Compare commits

..

No commits in common. "734060193976afedd2eabfaed90b8db554102ed1" and "f59e6a5fd5e25f35116b6360ca33aa150ad7d1c6" have entirely different histories.

3 changed files with 8 additions and 90 deletions

View file

@ -49,11 +49,8 @@ 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<RefCell<Environment>>,
/// Current environment for variable lookups and assignments
environment: Rc<RefCell<Environment>>,
/// Map of expressions to their lexical distance for variable resolution
locals: HashMap<Expression, usize>,
}
@ -79,8 +76,7 @@ impl Default for Interpreter {
}
impl Interpreter {
/// Execute a list of statements in sequence.
/// Log errors but continue execution.
/// Try to evaluate an expression and return its result.
pub fn run(&mut self, statements: Vec<Statement>) -> Result<(), InterpreterError> {
for stmt in statements {
match self.execute(&stmt) {
@ -92,12 +88,11 @@ 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 and return its result value, if any.
///Execute a statement.
fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, InterpreterError> {
match statement {
Statement::Block(statements) => {
@ -159,8 +154,6 @@ 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,
@ -266,7 +259,6 @@ 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,
@ -288,8 +280,6 @@ 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> {
match self.evaluate(object)? {
Value::Instance(instance) => Ok(instance.borrow().get(name, instance.clone())?),
@ -297,7 +287,6 @@ impl Interpreter {
}
}
/// Set a property on an object instance to a new value.
fn set(
&mut self,
object: &Expression,
@ -315,7 +304,6 @@ impl Interpreter {
}
}
/// Handle super expressions to access methods from a superclass.
fn super_expr(
&mut self,
expression: &Expression,
@ -435,7 +423,7 @@ impl Interpreter {
Ok(None)
}
/// Execute the body as long as the loop condition evaluates to true.
/// Execute the body as long as the condition evaluates to true.
fn while_statement(
&mut self,
condition: &Expression,
@ -525,7 +513,7 @@ impl Interpreter {
}
}
/// Evaluate a variable reference expression.
/// Get the value of a variable.
fn var_expression(
&mut self,
name: &Token,
@ -534,8 +522,6 @@ 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,

View file

@ -81,7 +81,6 @@ 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<Token>) -> Result<Self, ParserError> {
let current_token = tokens.first().ok_or(ParserError::NoTokens)?.clone();
@ -93,8 +92,6 @@ 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<Vec<Statement>, ParserError> {
let mut statements = Vec::new();
@ -113,8 +110,7 @@ impl Parser {
/// Check if any of the provided types match the type of the current token.
///
/// If so, advance the current token and return true.
/// Otherwise, return false without advancing.
/// If so, advance the current token.
fn matches(&mut self, types: &[TokenType]) -> bool {
let matches = types.iter().any(|x| self.check(x));
matches.then(|| self.advance());
@ -155,7 +151,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()
@ -189,7 +185,6 @@ impl Parser {
self.assignment()
}
/// Parse a declaration.
fn declaration(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[Class]) {
self.class_declaration()
@ -202,7 +197,6 @@ impl Parser {
}
}
/// Parse a statement.
fn statement(&mut self) -> Result<Statement, ParserError> {
if self.matches(&[For]) {
self.for_statement()
@ -221,7 +215,7 @@ impl Parser {
}
}
/// Parse a for statement by desugaring it into a while loop.
/// Build up a while statement from a for statement.
fn for_statement(&mut self) -> Result<Statement, ParserError> {
let line = self.current_token.line;
self.consume(&LeftParen)
@ -270,8 +264,6 @@ 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<Statement, ParserError> {
let line = self.current_token.line;
self.consume(&LeftParen)
@ -296,8 +288,6 @@ 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> {
let value = self.expression()?;
let line = self.current_token.line;
@ -307,8 +297,6 @@ 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<Statement, ParserError> {
let keyword = self.previous()?.clone();
let value = if self.check(&Semicolon) {
@ -323,8 +311,6 @@ 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<Statement, ParserError> {
let line = self.current_token.line;
let name = self
@ -361,8 +347,6 @@ 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> {
let line = self.current_token.line;
let name = self
@ -385,8 +369,6 @@ 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> {
let line = self.current_token.line;
self.consume(&LeftParen)
@ -405,8 +387,6 @@ 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> {
let expr = self.expression()?;
let line = self.current_token.line;
@ -416,8 +396,6 @@ 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<Statement, ParserError> {
let line = self.current_token.line;
let name = self
@ -455,8 +433,6 @@ 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<Vec<Statement>, ParserError> {
let mut statements = Vec::new();
@ -471,8 +447,6 @@ 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<Expression, ParserError> {
let expr = self.or()?;
@ -499,7 +473,6 @@ impl Parser {
}
}
/// Parse a logical expression with a specific operator (AND or OR).
fn logical_operator<F>(
&mut self,
operator: TokenType,
@ -524,12 +497,10 @@ impl Parser {
Ok(expr)
}
/// Parse a logical OR expression.
fn or(&mut self) -> Result<Expression, ParserError> {
self.logical_operator(Or, Self::and)
}
/// Parse a logical AND expression.
fn and(&mut self) -> Result<Expression, ParserError> {
self.logical_operator(And, Self::equality)
}
@ -569,7 +540,6 @@ impl Parser {
}
}
/// Parse a call expression or property access.
fn call(&mut self) -> Result<Expression, ParserError> {
let mut expr = self.primary()?;
@ -595,8 +565,6 @@ 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<Expression, ParserError> {
let mut args = Vec::new();
@ -675,8 +643,6 @@ 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()

View file

@ -37,7 +37,7 @@ enum ClassType {
Subclass,
}
/// Resolve variable references and perform static analysis before interpretation.
/// Resolve variable references and performs static analysis before interpretation.
#[derive(Debug)]
pub struct Resolver<'a> {
scopes: Vec<HashMap<String, bool>>,
@ -47,7 +47,6 @@ 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(),
@ -57,7 +56,6 @@ 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)?;
@ -65,7 +63,6 @@ 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),
@ -94,7 +91,6 @@ 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),
@ -136,19 +132,14 @@ 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) {
@ -161,15 +152,12 @@ 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)?;
@ -178,8 +166,6 @@ 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,
@ -239,7 +225,6 @@ 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,
@ -258,7 +243,6 @@ impl<'a> Resolver<'a> {
}
}
/// Declare the variable, resolve its initializer if any, then define it.
fn resolve_var(
&mut self,
name: &Token,
@ -274,8 +258,6 @@ 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) {
@ -286,8 +268,6 @@ 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,
@ -299,7 +279,6 @@ impl<'a> Resolver<'a> {
Ok(())
}
/// Resolve a binary expression by resolving both operands.
fn resolve_binary_expr(
&mut self,
left: &Expression,
@ -310,8 +289,6 @@ 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,
@ -325,8 +302,6 @@ impl<'a> Resolver<'a> {
Ok(())
}
/// Resolve a function call expression.
/// Resolve the callee and all arguments.
fn resolve_call_expr(
&mut self,
callee: &Expression,
@ -341,8 +316,6 @@ 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,
@ -354,7 +327,6 @@ 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,
@ -369,7 +341,6 @@ 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,
@ -386,7 +357,6 @@ impl<'a> Resolver<'a> {
Ok(())
}
/// Resolve a while statement by resolving the condition and body.
fn resolve_while_stmt(
&mut self,
condition: &Expression,
@ -398,8 +368,6 @@ 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],
@ -424,8 +392,6 @@ 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,