diff --git a/src/resolver.rs b/src/resolver.rs index 1bea277..5e97ac6 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -37,7 +37,7 @@ enum ClassType { Subclass, } -/// Resolve variable references and performs static analysis before interpretation. +/// Resolve variable references and perform static analysis before interpretation. #[derive(Debug)] pub struct Resolver<'a> { scopes: Vec>, @@ -47,6 +47,7 @@ pub struct Resolver<'a> { } impl<'a> Resolver<'a> { + /// Create a new resolver with a reference to the interpreter pub fn new(interpreter: &'a mut Interpreter) -> Self { Self { scopes: Vec::default(), @@ -56,6 +57,7 @@ impl<'a> Resolver<'a> { } } + /// Resolve all statements in a program pub fn resolve(&mut self, statements: &[Statement]) -> Result<(), ResolverError> { for stm in statements { self.resolve_statement(stm)?; @@ -63,6 +65,7 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a single statement. fn resolve_statement(&mut self, statement: &Statement) -> Result<(), ResolverError> { match statement { Statement::Block(statements) => self.resolve_block(statements), @@ -91,6 +94,7 @@ impl<'a> Resolver<'a> { } } + /// Resolve an expression. fn resolve_expression(&mut self, expr: &Expression) -> Result<(), ResolverError> { match expr { Expression::Assign { name, value } => self.resolve_assign_expr(expr, name, value), @@ -132,14 +136,19 @@ impl<'a> Resolver<'a> { } } + /// Create a new scope for variable declarations. fn begin_scope(&mut self) { self.scopes.push(HashMap::new()); } + /// Remove the current scope. fn end_scope(&mut self) { self.scopes.pop(); } + /// Declare a variable in the current scope and mark it as not initialized yet (false). + /// + /// Error if the variable is already declared in this scope. fn declare(&mut self, name: &Token) -> Result<(), ResolverError> { if let Some(scope) = self.scopes.last_mut() { if scope.contains_key(&name.lexeme) { @@ -152,12 +161,15 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Mark a variable as initialized (true) in the current scope. fn define(&mut self, name: &Token) { if let Some(scope) = self.scopes.last_mut() { scope.insert(name.lexeme.clone(), true); } } + /// Resolve a block statement by creating a new scope. + /// Resolve all statements in the block, then remove the scope. fn resolve_block(&mut self, statements: &[Statement]) -> Result<(), ResolverError> { self.begin_scope(); self.resolve(statements)?; @@ -166,6 +178,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a class declaration with methods and optional inheritance. + /// Handle special cases for 'this', 'super', and initializers. fn resolve_class_stmt( &mut self, name: &Token, @@ -225,6 +239,7 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a return statement, checking for invalid returns (top-level code and value returns from initializers). fn resolve_return_stmt( &mut self, keyword: &Token, @@ -243,6 +258,7 @@ impl<'a> Resolver<'a> { } } + /// Declare the variable, resolve its initializer if any, then define it. fn resolve_var( &mut self, name: &Token, @@ -258,6 +274,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a variable reference expression. + /// Check that the variable is not being used in its own initializer. fn resolve_var_expr(&mut self, expr: &Expression, name: &Token) -> Result<(), ResolverError> { if let Some(scope) = self.scopes.last() { if !scope.get(&name.lexeme).unwrap_or(&true) { @@ -268,6 +286,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve an assignment expression. + /// Resolve the value being assigned, then resolve the variable being assigned to. fn resolve_assign_expr( &mut self, expr: &Expression, @@ -279,6 +299,7 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a binary expression by resolving both operands. fn resolve_binary_expr( &mut self, left: &Expression, @@ -289,6 +310,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a function declaration. + /// Declare and define the function name, then resolve the function body. fn resolve_function_stmt( &mut self, name: &Token, @@ -302,6 +325,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a function call expression. + /// Resolve the callee and all arguments. fn resolve_call_expr( &mut self, callee: &Expression, @@ -316,6 +341,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a property assignment expression. + /// Resolve both the object and the value being assigned. fn resolve_set_expression( &mut self, object: &Expression, @@ -327,6 +354,7 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a super expression, checking for invalid uses (outside of classes, classes with no superclass). fn resolve_super_expression( &mut self, keyword: &Token, @@ -341,6 +369,7 @@ impl<'a> Resolver<'a> { self.resolve_local(expression, keyword) } + /// Resolve an if statement by resolving the condition and both branches. fn resolve_if_stmt( &mut self, condition: &Expression, @@ -357,6 +386,7 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a while statement by resolving the condition and body. fn resolve_while_stmt( &mut self, condition: &Expression, @@ -368,6 +398,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a function definition with parameters and body. + /// Create a new scope for the function body and declare all parameters. fn resolve_function( &mut self, params: &[Token], @@ -392,6 +424,8 @@ impl<'a> Resolver<'a> { Ok(()) } + /// Resolve a local variable reference by finding its scope. + /// Tell the interpreter the number of scopes between the reference and definition. fn resolve_local( &mut self, expression: &Expression,