fix(checker): report predicate argument errors
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user