documentation run
This commit is contained in:
parent
3cbeab3434
commit
7340601939
1 changed files with 35 additions and 1 deletions
|
@ -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<HashMap<String, bool>>,
|
||||
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue