From 5e87ba2cd16e07062dc1afb5853c8551391f39e3 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Tue, 7 Jul 2026 10:02:52 +0200 Subject: [PATCH] fix(checker): report predicate argument errors --- midas/checker/evaluator.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/midas/checker/evaluator.py b/midas/checker/evaluator.py index de8f9ad..baefc0d 100644 --- a/midas/checker/evaluator.py +++ b/midas/checker/evaluator.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from typing import Any, Callable, Optional import midas.ast.midas as m +from midas.ast.location import Location from midas.checker.preamble import Preamble from midas.checker.registry import TypesRegistry from midas.checker.reporter import FileReporter @@ -143,7 +144,7 @@ class Evaluator(m.Expr.Visitor[Any]): match callee: case Predicate(): - return self._evaluate_predicate(callee, args, kwargs) + return self._evaluate_predicate(expr.location, callee, args, kwargs) case _ if callable(callee): return callee(*args, **kwargs) case _: @@ -181,6 +182,7 @@ class Evaluator(m.Expr.Visitor[Any]): def _evaluate_predicate( self, + location: Location, predicate: Predicate, args: list[Any], kwargs: dict[str, Any], @@ -202,7 +204,7 @@ class Evaluator(m.Expr.Visitor[Any]): self.scopes.append({}) match predicate.type: case Function(returns=Function() as inner): - self._map_args(predicate.type, args, kwargs) + self._map_args(location, predicate.type, args, kwargs) res = PartialPredicate( type=inner, body=predicate.body, @@ -211,7 +213,7 @@ class Evaluator(m.Expr.Visitor[Any]): ) case Function(): - self._map_args(predicate.type, args, kwargs) + self._map_args(location, predicate.type, args, kwargs) res = self.evaluate(predicate.body) case _: @@ -219,7 +221,13 @@ class Evaluator(m.Expr.Visitor[Any]): self.scopes.pop() return res - def _map_args(self, function: Function, args: list[Any], kwargs: dict[str, Any]): + def _map_args( + self, + location: Location, + function: Function, + args: list[Any], + kwargs: dict[str, Any], + ): """Map call arguments to a function's parameters and set their values in context Each argument is mapped to a parameter of the function, then its value @@ -238,9 +246,20 @@ class Evaluator(m.Expr.Visitor[Any]): } for i, arg in enumerate(args): + if i >= len(positional): + if self.reporter is not None: + self.reporter.error( + location, + f"Too many positional arguments, expected at most {len(positional)}, got {len(args)}", + ) + break param: Function.Parameter = positional[i] self.set_value(param.name, arg) for name, arg in kwargs.items(): + if name not in keywords: + if self.reporter is not None: + self.reporter.error(location, f"Unknown keyword argument '{name}'") + break param: Function.Parameter = keywords[name] self.set_value(param.name, arg)