Compare commits

...

3 commits

Author SHA1 Message Date
7340601939
documentation run 2025-05-26 12:53:52 +02:00
3cbeab3434
documentation run 2025-05-26 12:53:40 +02:00
eefbcc8ae2
documentation run 2025-05-26 12:31:51 +02:00
3 changed files with 90 additions and 8 deletions

View file

@ -49,8 +49,11 @@ pub enum InterpreterError {
/// Interpreter for the Lox language that executes statements and evaluates expressions. /// Interpreter for the Lox language that executes statements and evaluates expressions.
#[derive(Debug)] #[derive(Debug)]
pub struct Interpreter { pub struct Interpreter {
/// Global environment containing built-in functions and top-level variables
pub globals: Rc<RefCell<Environment>>, pub globals: Rc<RefCell<Environment>>,
/// Current environment for variable lookups and assignments
environment: Rc<RefCell<Environment>>, environment: Rc<RefCell<Environment>>,
/// Map of expressions to their lexical distance for variable resolution
locals: HashMap<Expression, usize>, locals: HashMap<Expression, usize>,
} }
@ -76,7 +79,8 @@ impl Default for Interpreter {
} }
impl 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<Statement>) -> Result<(), InterpreterError> { pub fn run(&mut self, statements: Vec<Statement>) -> Result<(), InterpreterError> {
for stmt in statements { for stmt in statements {
match self.execute(&stmt) { match self.execute(&stmt) {
@ -88,11 +92,12 @@ impl Interpreter {
Ok(()) Ok(())
} }
/// Record the resolved lexical depth for a variable reference.
pub fn resolve(&mut self, expression: Expression, depth: usize) { pub fn resolve(&mut self, expression: Expression, depth: usize) {
self.locals.insert(expression, depth); 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<Option<Value>, InterpreterError> { fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, InterpreterError> {
match statement { match statement {
Statement::Block(statements) => { Statement::Block(statements) => {
@ -154,6 +159,8 @@ impl Interpreter {
Ok(None) Ok(None)
} }
/// Define a new class with methods and optional inheritance.
/// Handle superclass setup and method capturing.
fn class( fn class(
&mut self, &mut self,
name: &Token, name: &Token,
@ -259,6 +266,7 @@ impl Interpreter {
/// Call a callable if it is one (meaning it starts with a LeftParen after an identifier), /// Call a callable if it is one (meaning it starts with a LeftParen after an identifier),
/// otherwise evaluate the expression. /// otherwise evaluate the expression.
/// Evaluate the callee and all arguments before making the call.
fn call( fn call(
&mut self, &mut self,
callee: &Expression, 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<Value, InterpreterError> { fn get(&mut self, object: &Expression, name: &Token) -> Result<Value, InterpreterError> {
match self.evaluate(object)? { match self.evaluate(object)? {
Value::Instance(instance) => Ok(instance.borrow().get(name, instance.clone())?), 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( fn set(
&mut self, &mut self,
object: &Expression, object: &Expression,
@ -304,6 +315,7 @@ impl Interpreter {
} }
} }
/// Handle super expressions to access methods from a superclass.
fn super_expr( fn super_expr(
&mut self, &mut self,
expression: &Expression, expression: &Expression,
@ -423,7 +435,7 @@ impl Interpreter {
Ok(None) 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( fn while_statement(
&mut self, &mut self,
condition: &Expression, condition: &Expression,
@ -513,7 +525,7 @@ impl Interpreter {
} }
} }
/// Get the value of a variable. /// Evaluate a variable reference expression.
fn var_expression( fn var_expression(
&mut self, &mut self,
name: &Token, name: &Token,
@ -522,6 +534,8 @@ impl Interpreter {
self.lookup_var(name, expression) 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( fn lookup_var(
&mut self, &mut self,
name: &Token, name: &Token,

View file

@ -81,6 +81,7 @@ struct Parser {
impl Parser { impl Parser {
/// Create a new parser instance, fail if the tokens vector is empty. /// 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<Token>) -> Result<Self, ParserError> { fn new(tokens: Vec<Token>) -> Result<Self, ParserError> {
let current_token = tokens.first().ok_or(ParserError::NoTokens)?.clone(); 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. /// 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<Vec<Statement>, ParserError> { fn run(&mut self) -> Result<Vec<Statement>, ParserError> {
let mut statements = Vec::new(); 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. /// 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 { fn matches(&mut self, types: &[TokenType]) -> bool {
let matches = types.iter().any(|x| self.check(x)); let matches = types.iter().any(|x| self.check(x));
matches.then(|| self.advance()); 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 /// 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> { fn consume(&mut self, token_type: &TokenType) -> Option<&Token> {
if self.check(token_type) { if self.check(token_type) {
self.advance().ok() self.advance().ok()
@ -185,6 +189,7 @@ impl Parser {
self.assignment() self.assignment()
} }
/// Parse a declaration.
fn declaration(&mut self) -> Result<Statement, ParserError> { fn declaration(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[Class]) { if self.matches(&[Class]) {
self.class_declaration() self.class_declaration()
@ -197,6 +202,7 @@ impl Parser {
} }
} }
/// Parse a statement.
fn statement(&mut self) -> Result<Statement, ParserError> { fn statement(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[For]) { if self.matches(&[For]) {
self.for_statement() 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<Statement, ParserError> { fn for_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line; let line = self.current_token.line;
self.consume(&LeftParen) self.consume(&LeftParen)
@ -264,6 +270,8 @@ impl Parser {
Ok(body) 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<Statement, ParserError> { fn if_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line; let line = self.current_token.line;
self.consume(&LeftParen) 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<Statement, ParserError> { fn print_statement(&mut self) -> Result<Statement, ParserError> {
let value = self.expression()?; let value = self.expression()?;
let line = self.current_token.line; let line = self.current_token.line;
@ -297,6 +307,8 @@ impl Parser {
Ok(Statement::Print(value)) 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<Statement, ParserError> { fn return_statement(&mut self) -> Result<Statement, ParserError> {
let keyword = self.previous()?.clone(); let keyword = self.previous()?.clone();
let value = if self.check(&Semicolon) { let value = if self.check(&Semicolon) {
@ -311,6 +323,8 @@ impl Parser {
Ok(Statement::Return { keyword, value }) 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<Statement, ParserError> { fn class_declaration(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line; let line = self.current_token.line;
let name = self 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<Statement, ParserError> { fn var_declaration(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line; let line = self.current_token.line;
let name = self 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<Statement, ParserError> { fn while_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line; let line = self.current_token.line;
self.consume(&LeftParen) 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<Statement, ParserError> { fn expression_statement(&mut self) -> Result<Statement, ParserError> {
let expr = self.expression()?; let expr = self.expression()?;
let line = self.current_token.line; let line = self.current_token.line;
@ -396,6 +416,8 @@ impl Parser {
Ok(Statement::Expression(expr)) 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<Statement, ParserError> { fn function(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line; let line = self.current_token.line;
let name = self let name = self
@ -433,6 +455,8 @@ impl Parser {
Ok(Statement::Function { name, params, body }) 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<Vec<Statement>, ParserError> { fn block(&mut self) -> Result<Vec<Statement>, ParserError> {
let mut statements = Vec::new(); let mut statements = Vec::new();
@ -447,6 +471,8 @@ impl Parser {
Ok(statements) 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<Expression, ParserError> { fn assignment(&mut self) -> Result<Expression, ParserError> {
let expr = self.or()?; let expr = self.or()?;
@ -473,6 +499,7 @@ impl Parser {
} }
} }
/// Parse a logical expression with a specific operator (AND or OR).
fn logical_operator<F>( fn logical_operator<F>(
&mut self, &mut self,
operator: TokenType, operator: TokenType,
@ -497,10 +524,12 @@ impl Parser {
Ok(expr) Ok(expr)
} }
/// Parse a logical OR expression.
fn or(&mut self) -> Result<Expression, ParserError> { fn or(&mut self) -> Result<Expression, ParserError> {
self.logical_operator(Or, Self::and) self.logical_operator(Or, Self::and)
} }
/// Parse a logical AND expression.
fn and(&mut self) -> Result<Expression, ParserError> { fn and(&mut self) -> Result<Expression, ParserError> {
self.logical_operator(And, Self::equality) self.logical_operator(And, Self::equality)
} }
@ -540,6 +569,7 @@ impl Parser {
} }
} }
/// Parse a call expression or property access.
fn call(&mut self) -> Result<Expression, ParserError> { fn call(&mut self) -> Result<Expression, ParserError> {
let mut expr = self.primary()?; let mut expr = self.primary()?;
@ -565,6 +595,8 @@ impl Parser {
Ok(expr) 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<Expression, ParserError> { fn finish_call(&mut self, callee: Expression) -> Result<Expression, ParserError> {
let mut args = Vec::new(); 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) { fn synchronize(&mut self) {
let _ = self.advance(); let _ = self.advance();
while !self.is_at_end() while !self.is_at_end()

View file

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