documentation run

This commit is contained in:
Sebastian Hugentobler 2025-05-26 12:53:52 +02:00
parent 3cbeab3434
commit 7340601939
Signed by: shu
SSH key fingerprint: SHA256:ppcx6MlixdNZd5EUM1nkHOKoyQYoJwzuQKXM6J/t66M

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,