3 Commits
Author SHA1 Message Date
HEL 7c96f7a19f Merge pull request 'Undefined variables and column aggregations' (#43) from fix/undefined-variable into main
Tests / tests (push) Successful in 6s
Reviewed-on: #43
2026-07-23 23:36:12 +00:00
HEL e37432ad57 fix(checker): correct return type for column aggregation
Tests / tests (pull_request) Successful in 10s
2026-07-24 00:03:26 +02:00
HEL 3ab0dda682 fix(resolver): check undefined varaible in parent scopes 2026-07-19 15:51:46 +02:00
4 changed files with 33 additions and 47 deletions
@@ -13,7 +13,6 @@ from midas.checker.types import (
Function,
ParamSpec,
Type,
UnknownType,
)
if TYPE_CHECKING:
@@ -97,11 +96,9 @@ class ColumnGroupByMethodRegistry(MethodRegistry[Call]):
positional=[],
keywords={},
)
if not isinstance(returns, ColumnType):
returns = ColumnType(type=UnknownType())
signature = Function(
params=ParamSpec(mixed=real_params),
returns=returns,
returns=ColumnType(type=returns),
)
result: CallResult = self.dispatcher.get_result(
+4 -6
View File
@@ -364,13 +364,11 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
Type: the result type
"""
returns: Type = ColumnType(type=TopType())
returns: Type = TopType()
if formula:
returns = ColumnType(
type=self._resolve_formula_type(
call,
formula(call.column.type),
)
returns = self._resolve_formula_type(
call,
formula(call.column.type),
)
signature = Function(
params=ParamSpec(
+16 -1
View File
@@ -97,6 +97,21 @@ class Resolver(p.Stmt.Visitor[None], p.Expr.Visitor[None]):
return True
return False
def is_defined(self, name: str) -> bool:
"""Check whether the given variable is defined
Args:
name (str): the name of the variable
Returns:
bool: `True` if the variable is defined in the closest scope where it
is declared, `False` otherwise
"""
for scope in reversed(self.scopes):
if name in scope:
return scope[name]
return False
def resolve_function(self, function: p.Function) -> None:
"""Resolve a function definition
@@ -230,7 +245,7 @@ class Resolver(p.Stmt.Visitor[None], p.Expr.Visitor[None]):
pass
def visit_variable_expr(self, expr: p.VariableExpr) -> None:
if len(self.scopes) != 0 and self.scopes[-1].get(expr.name) is False:
if self.is_declared(expr.name) and not self.is_defined(expr.name):
self.reporter.error(
expr.location,
f"Variable '{expr.name}' is declared but may not be defined",
+12 -36
View File
@@ -4305,9 +4305,7 @@
"arguments": [],
"keywords": {}
},
"type": {
"type": {}
}
"type": {}
},
{
"location": {
@@ -4342,9 +4340,7 @@
"arguments": [],
"keywords": {}
},
"type": {
"type": {}
}
"type": {}
},
{
"location": {
@@ -4380,9 +4376,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4419,9 +4413,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "float"
}
"name": "float"
}
},
{
@@ -4458,9 +4450,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4497,9 +4487,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4536,9 +4524,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4575,9 +4561,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4614,9 +4598,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4652,9 +4634,7 @@
"arguments": [],
"keywords": {}
},
"type": {
"type": {}
}
"type": {}
},
{
"location": {
@@ -4690,9 +4670,7 @@
"keywords": {}
},
"type": {
"type": {
"name": "int"
}
"name": "int"
}
},
{
@@ -4728,9 +4706,7 @@
"arguments": [],
"keywords": {}
},
"type": {
"type": {}
}
"type": {}
},
{
"location": {