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
|
from typing import Any, Callable, Optional
|
||||||
|
|
||||||
import midas.ast.midas as m
|
import midas.ast.midas as m
|
||||||
|
from midas.ast.location import Location
|
||||||
from midas.checker.preamble import Preamble
|
from midas.checker.preamble import Preamble
|
||||||
from midas.checker.registry import TypesRegistry
|
from midas.checker.registry import TypesRegistry
|
||||||
from midas.checker.reporter import FileReporter
|
from midas.checker.reporter import FileReporter
|
||||||
@@ -143,7 +144,7 @@ class Evaluator(m.Expr.Visitor[Any]):
|
|||||||
|
|
||||||
match callee:
|
match callee:
|
||||||
case Predicate():
|
case Predicate():
|
||||||
return self._evaluate_predicate(callee, args, kwargs)
|
return self._evaluate_predicate(expr.location, callee, args, kwargs)
|
||||||
case _ if callable(callee):
|
case _ if callable(callee):
|
||||||
return callee(*args, **kwargs)
|
return callee(*args, **kwargs)
|
||||||
case _:
|
case _:
|
||||||
@@ -181,6 +182,7 @@ class Evaluator(m.Expr.Visitor[Any]):
|
|||||||
|
|
||||||
def _evaluate_predicate(
|
def _evaluate_predicate(
|
||||||
self,
|
self,
|
||||||
|
location: Location,
|
||||||
predicate: Predicate,
|
predicate: Predicate,
|
||||||
args: list[Any],
|
args: list[Any],
|
||||||
kwargs: dict[str, Any],
|
kwargs: dict[str, Any],
|
||||||
@@ -202,7 +204,7 @@ class Evaluator(m.Expr.Visitor[Any]):
|
|||||||
self.scopes.append({})
|
self.scopes.append({})
|
||||||
match predicate.type:
|
match predicate.type:
|
||||||
case Function(returns=Function() as inner):
|
case Function(returns=Function() as inner):
|
||||||
self._map_args(predicate.type, args, kwargs)
|
self._map_args(location, predicate.type, args, kwargs)
|
||||||
res = PartialPredicate(
|
res = PartialPredicate(
|
||||||
type=inner,
|
type=inner,
|
||||||
body=predicate.body,
|
body=predicate.body,
|
||||||
@@ -211,7 +213,7 @@ class Evaluator(m.Expr.Visitor[Any]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
case Function():
|
case Function():
|
||||||
self._map_args(predicate.type, args, kwargs)
|
self._map_args(location, predicate.type, args, kwargs)
|
||||||
res = self.evaluate(predicate.body)
|
res = self.evaluate(predicate.body)
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
@@ -219,7 +221,13 @@ class Evaluator(m.Expr.Visitor[Any]):
|
|||||||
self.scopes.pop()
|
self.scopes.pop()
|
||||||
return res
|
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
|
"""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
|
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):
|
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]
|
param: Function.Parameter = positional[i]
|
||||||
self.set_value(param.name, arg)
|
self.set_value(param.name, arg)
|
||||||
|
|
||||||
for name, arg in kwargs.items():
|
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]
|
param: Function.Parameter = keywords[name]
|
||||||
self.set_value(param.name, arg)
|
self.set_value(param.name, arg)
|
||||||
|
|||||||
Reference in New Issue
Block a user