fix(checker): handle returns outside functions
This commit is contained in:
@@ -48,7 +48,9 @@ TypedExpr = tuple[p.Expr, Type]
|
|||||||
|
|
||||||
|
|
||||||
class ReturnException(Exception):
|
class ReturnException(Exception):
|
||||||
pass
|
def __init__(self, stmt: p.Stmt):
|
||||||
|
super().__init__()
|
||||||
|
self.stmt: p.Stmt = stmt
|
||||||
|
|
||||||
|
|
||||||
class UndefinedMethodException(Exception):
|
class UndefinedMethodException(Exception):
|
||||||
@@ -116,7 +118,10 @@ class PythonTyper(
|
|||||||
self.judgements = []
|
self.judgements = []
|
||||||
self.evaluated_casts = []
|
self.evaluated_casts = []
|
||||||
|
|
||||||
self.check(stmts)
|
try:
|
||||||
|
self.check(stmts)
|
||||||
|
except ReturnException as e:
|
||||||
|
self.reporter.error(e.stmt.location, "Return statement outside of function")
|
||||||
|
|
||||||
return TypedAST(
|
return TypedAST(
|
||||||
stmts=stmts,
|
stmts=stmts,
|
||||||
@@ -576,7 +581,7 @@ class PythonTyper(
|
|||||||
def visit_return_stmt(self, stmt: p.ReturnStmt) -> None:
|
def visit_return_stmt(self, stmt: p.ReturnStmt) -> None:
|
||||||
type: Type = self.type_of(stmt.value) if stmt.value is not None else UnitType()
|
type: Type = self.type_of(stmt.value) if stmt.value is not None else UnitType()
|
||||||
self.env.return_types.append(type)
|
self.env.return_types.append(type)
|
||||||
raise ReturnException()
|
raise ReturnException(stmt)
|
||||||
|
|
||||||
def visit_if_stmt(self, stmt: p.IfStmt) -> None:
|
def visit_if_stmt(self, stmt: p.IfStmt) -> None:
|
||||||
# Not evaluated in sub-environment because assignments in the test leak out of the if
|
# Not evaluated in sub-environment because assignments in the test leak out of the if
|
||||||
@@ -599,7 +604,7 @@ class PythonTyper(
|
|||||||
else_returned: bool = self.process_block(stmt.orelse, env)
|
else_returned: bool = self.process_block(stmt.orelse, env)
|
||||||
self.env.return_types.extend(env.return_types)
|
self.env.return_types.extend(env.return_types)
|
||||||
if body_returned and else_returned:
|
if body_returned and else_returned:
|
||||||
raise ReturnException()
|
raise ReturnException(stmt)
|
||||||
|
|
||||||
def visit_pass(self, stmt: p.Pass) -> None:
|
def visit_pass(self, stmt: p.Pass) -> None:
|
||||||
pass
|
pass
|
||||||
@@ -627,7 +632,7 @@ class PythonTyper(
|
|||||||
self.env = outer_env
|
self.env = outer_env
|
||||||
|
|
||||||
if body_returned:
|
if body_returned:
|
||||||
raise ReturnException()
|
raise ReturnException(stmt)
|
||||||
|
|
||||||
def visit_import_stmt(self, stmt: p.ImportStmt) -> None:
|
def visit_import_stmt(self, stmt: p.ImportStmt) -> None:
|
||||||
self._visit_imports(stmt.location, stmt.imports)
|
self._visit_imports(stmt.location, stmt.imports)
|
||||||
|
|||||||
Reference in New Issue
Block a user