feat(resolver): add error to prevent returning value from init

This commit is contained in:
2026-02-06 23:07:17 +01:00
parent 00055fc5ed
commit 97f05848d9

View File

@@ -7,6 +7,7 @@ from src.ast.expr import Expr, LogicalExpr, VariableExpr, LiteralExpr, GroupingE
AssignExpr, GetExpr, SetExpr, ThisExpr AssignExpr, GetExpr, SetExpr, ThisExpr
from src.ast.stmt import Stmt, ForStmt, WhileStmt, LetStmt, ReturnStmt, IfStmt, FunctionStmt, \ from src.ast.stmt import Stmt, ForStmt, WhileStmt, LetStmt, ReturnStmt, IfStmt, FunctionStmt, \
ExpressionStmt, BlockStmt, BreakStmt, ContinueStmt, ClassStmt ExpressionStmt, BlockStmt, BreakStmt, ContinueStmt, ClassStmt
from src.consts import CONSTRUCTOR_NAME
from src.pebble import Pebble from src.pebble import Pebble
from src.token import Token from src.token import Token
@@ -17,6 +18,7 @@ if TYPE_CHECKING:
class FunctionType(Enum): class FunctionType(Enum):
NONE = auto() NONE = auto()
FUNCTION = auto() FUNCTION = auto()
INITIALIZER = auto()
METHOD = auto() METHOD = auto()
@@ -136,7 +138,10 @@ class Resolver(Expr.Visitor[None], Stmt.Visitor[None]):
self.scopes[-1]["this"] = True self.scopes[-1]["this"] = True
for method in stmt.methods: for method in stmt.methods:
self.resolve_function(method, FunctionType.METHOD) declaration: FunctionType = FunctionType.METHOD
if method.name.lexeme == CONSTRUCTOR_NAME:
declaration = FunctionType.INITIALIZER
self.resolve_function(method, declaration)
self.end_scope() self.end_scope()
self.current_class = enclosing_class self.current_class = enclosing_class
@@ -160,6 +165,8 @@ class Resolver(Expr.Visitor[None], Stmt.Visitor[None]):
Pebble.token_error(stmt.keyword, "Cannot return from top-level scope.") Pebble.token_error(stmt.keyword, "Cannot return from top-level scope.")
if stmt.value is not None: if stmt.value is not None:
if self.current_func == FunctionType.INITIALIZER:
Pebble.token_error(stmt.keyword, "Cannot return a value from an initializer.")
self.resolve(stmt.value) self.resolve(stmt.value)
def visit_let_stmt(self, stmt: LetStmt) -> None: def visit_let_stmt(self, stmt: LetStmt) -> None: