diff --git a/src/interpreter.rs b/src/interpreter.rs index 7176892..0388687 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -49,8 +49,11 @@ pub enum InterpreterError { /// Interpreter for the Lox language that executes statements and evaluates expressions. #[derive(Debug)] pub struct Interpreter { + /// Global environment containing built-in functions and top-level variables pub globals: Rc>, + /// Current environment for variable lookups and assignments environment: Rc>, + /// Map of expressions to their lexical distance for variable resolution locals: HashMap, } @@ -76,7 +79,8 @@ impl Default for Interpreter { } impl Interpreter { - /// Try to evaluate an expression and return its result. + /// Execute a list of statements in sequence. + /// Log errors but continue execution. pub fn run(&mut self, statements: Vec) -> Result<(), InterpreterError> { for stmt in statements { match self.execute(&stmt) { @@ -88,11 +92,12 @@ impl Interpreter { Ok(()) } + /// Record the resolved lexical depth for a variable reference. pub fn resolve(&mut self, expression: Expression, depth: usize) { self.locals.insert(expression, depth); } - ///Execute a statement. + /// Execute a statement and return its result value, if any. fn execute(&mut self, statement: &Statement) -> Result, InterpreterError> { match statement { Statement::Block(statements) => { @@ -154,6 +159,8 @@ impl Interpreter { Ok(None) } + /// Define a new class with methods and optional inheritance. + /// Handle superclass setup and method capturing. fn class( &mut self, name: &Token, @@ -259,6 +266,7 @@ impl Interpreter { /// Call a callable if it is one (meaning it starts with a LeftParen after an identifier), /// otherwise evaluate the expression. + /// Evaluate the callee and all arguments before making the call. fn call( &mut self, callee: &Expression, @@ -280,6 +288,8 @@ impl Interpreter { } } + /// Get a property from an object instance. + /// Properties can be fields or methods. fn get(&mut self, object: &Expression, name: &Token) -> Result { match self.evaluate(object)? { Value::Instance(instance) => Ok(instance.borrow().get(name, instance.clone())?), @@ -287,6 +297,7 @@ impl Interpreter { } } + /// Set a property on an object instance to a new value. fn set( &mut self, object: &Expression, @@ -304,6 +315,7 @@ impl Interpreter { } } + /// Handle super expressions to access methods from a superclass. fn super_expr( &mut self, expression: &Expression, @@ -423,7 +435,7 @@ impl Interpreter { Ok(None) } - /// Execute the body as long as the condition evaluates to true. + /// Execute the body as long as the loop condition evaluates to true. fn while_statement( &mut self, condition: &Expression, @@ -513,7 +525,7 @@ impl Interpreter { } } - /// Get the value of a variable. + /// Evaluate a variable reference expression. fn var_expression( &mut self, name: &Token, @@ -522,6 +534,8 @@ impl Interpreter { self.lookup_var(name, expression) } + /// Look up a variable's value using static analysis information. + /// Use the resolved lexical distance if available, otherwise check globals. fn lookup_var( &mut self, name: &Token, diff --git a/src/parser.rs b/src/parser.rs index 04a0809..4e60e49 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -81,6 +81,7 @@ struct Parser { impl Parser { /// Create a new parser instance, fail if the tokens vector is empty. + /// Initialize the current token to the first token in the list. fn new(tokens: Vec) -> Result { let current_token = tokens.first().ok_or(ParserError::NoTokens)?.clone(); @@ -92,6 +93,8 @@ impl Parser { } /// Parse all tokens to a list of statements for execution. + /// Continue parsing until reaching the end of the token stream. + /// Handle errors by logging them and synchronizing to continue parsing. fn run(&mut self) -> Result, ParserError> { let mut statements = Vec::new(); @@ -110,7 +113,8 @@ impl Parser { /// Check if any of the provided types match the type of the current token. /// - /// If so, advance the current token. + /// If so, advance the current token and return true. + /// Otherwise, return false without advancing. fn matches(&mut self, types: &[TokenType]) -> bool { let matches = types.iter().any(|x| self.check(x)); matches.then(|| self.advance()); @@ -151,7 +155,7 @@ impl Parser { } /// Consume the current token if its token type matches the provided token_type and advance the - /// current token. Otherwise return None.. + /// current token. Otherwise return None. fn consume(&mut self, token_type: &TokenType) -> Option<&Token> { if self.check(token_type) { self.advance().ok() @@ -185,6 +189,7 @@ impl Parser { self.assignment() } + /// Parse a declaration. fn declaration(&mut self) -> Result { if self.matches(&[Class]) { self.class_declaration() @@ -197,6 +202,7 @@ impl Parser { } } + /// Parse a statement. fn statement(&mut self) -> Result { if self.matches(&[For]) { self.for_statement() @@ -215,7 +221,7 @@ impl Parser { } } - /// Build up a while statement from a for statement. + /// Parse a for statement by desugaring it into a while loop. fn for_statement(&mut self) -> Result { let line = self.current_token.line; self.consume(&LeftParen) @@ -264,6 +270,8 @@ impl Parser { Ok(body) } + /// Parse an if statement with a condition, then branch, and optional else branch. + /// The condition must be enclosed in parentheses. fn if_statement(&mut self) -> Result { let line = self.current_token.line; self.consume(&LeftParen) @@ -288,6 +296,8 @@ impl Parser { }) } + /// Parse a print statement, which consists of an expression followed by a semicolon. + /// The expression's value will be printed during execution. fn print_statement(&mut self) -> Result { let value = self.expression()?; let line = self.current_token.line; @@ -297,6 +307,8 @@ impl Parser { Ok(Statement::Print(value)) } + /// Parse a return statement, which may include a return value expression. + /// The return value is optional - if not provided, nil is returned implicitly. fn return_statement(&mut self) -> Result { let keyword = self.previous()?.clone(); let value = if self.check(&Semicolon) { @@ -311,6 +323,8 @@ impl Parser { Ok(Statement::Return { keyword, value }) } + /// Parse a class declaration with a name, optional superclass, and methods. + /// A class can inherit from a superclass using the '<' operator. fn class_declaration(&mut self) -> Result { let line = self.current_token.line; let name = self @@ -347,6 +361,8 @@ impl Parser { }) } + /// Parse a variable declaration with a name and optional initializer. + /// If no initializer is provided, the variable is initialized to nil. fn var_declaration(&mut self) -> Result { let line = self.current_token.line; let name = self @@ -369,6 +385,8 @@ impl Parser { }) } + /// Parse a while statement with a condition and body. + /// The condition must be enclosed in parentheses. fn while_statement(&mut self) -> Result { let line = self.current_token.line; self.consume(&LeftParen) @@ -387,6 +405,8 @@ impl Parser { }) } + /// Parse an expression statement, which is an expression followed by a semicolon. + /// The expression is evaluated for its side effects. fn expression_statement(&mut self) -> Result { let expr = self.expression()?; let line = self.current_token.line; @@ -396,6 +416,8 @@ impl Parser { Ok(Statement::Expression(expr)) } + /// Parse a function declaration with a name, parameters, and body. + /// Used for both standalone functions and class methods. fn function(&mut self) -> Result { let line = self.current_token.line; let name = self @@ -433,6 +455,8 @@ impl Parser { Ok(Statement::Function { name, params, body }) } + /// Parse a block of statements enclosed in braces. + /// A block creates a new scope for variable declarations. fn block(&mut self) -> Result, ParserError> { let mut statements = Vec::new(); @@ -447,6 +471,8 @@ impl Parser { Ok(statements) } + /// Parse an assignment expression, which can assign to a variable or object property. + /// Assignment is right-associative, so we recursively parse the right side. fn assignment(&mut self) -> Result { let expr = self.or()?; @@ -473,6 +499,7 @@ impl Parser { } } + /// Parse a logical expression with a specific operator (AND or OR). fn logical_operator( &mut self, operator: TokenType, @@ -497,10 +524,12 @@ impl Parser { Ok(expr) } + /// Parse a logical OR expression. fn or(&mut self) -> Result { self.logical_operator(Or, Self::and) } + /// Parse a logical AND expression. fn and(&mut self) -> Result { self.logical_operator(And, Self::equality) } @@ -540,6 +569,7 @@ impl Parser { } } + /// Parse a call expression or property access. fn call(&mut self) -> Result { let mut expr = self.primary()?; @@ -565,6 +595,8 @@ impl Parser { Ok(expr) } + /// Complete parsing a function call after seeing the opening parenthesis. + /// Parse the arguments and closing parenthesis. fn finish_call(&mut self, callee: Expression) -> Result { let mut args = Vec::new(); @@ -643,6 +675,8 @@ impl Parser { } } + /// Synchronize the parser after an error by advancing to the next statement boundary. + /// This allows parsing to continue after encountering a syntax error. fn synchronize(&mut self) { let _ = self.advance(); while !self.is_at_end() 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,