Refactor environment to use stack-based scoping

The commit rewrites the environment to use a stack of hash maps for
managing variable scopes. This replaces the old parent-reference
approach with a simpler and more efficient stack-based model.

Key changes: - Rename Environment to EnvironmentStack - Store scopes in
a Vec of HashMaps - Add push/pop scope operations for block handling -
Update interpreter to properly manage scope lifetimes - Clean up error
handling with helper functions
This commit is contained in:
Giulio Agostini
2025-10-04 21:05:00 +02:00
parent 41253e932a
commit 827349cbad
11 changed files with 165 additions and 243 deletions
+44 -1
View File
@@ -5,7 +5,7 @@ use crate::{
tokens::{LiteralValue, Token, TokenType},
},
logging::display_ast::{pretty_print_with_config, PrettyConfig},
result::{LoxError, LoxResult},
result::{parse_error, LoxError, LoxResult},
};
pub struct Parser {
@@ -65,10 +65,53 @@ impl Parser {
(TokenType::Identifier, TokenType::Equal) => self.assignment_statement(),
(TokenType::If, _) => self.if_statement(),
(TokenType::While, _) => self.while_statement(),
(TokenType::For, _) => self.for_statement(),
_ => self.expression_statement(),
}
}
fn for_statement(&mut self) -> LoxResult<AstNode<Stmt>> {
let start_slice = self.peek().source_slice.clone();
self.advance();
let variable = if let Token {
token_type: TokenType::Identifier,
literal: Some(variable_name),
source_slice,
..
} = self.peek()
{
AstNode {
node: Expr::Literal {
value: variable_name.clone(),
},
source_slice: source_slice.clone(),
}
} else {
return parse_error(
self.peek().source_slice.clone(),
"Expect variable name after 'for' keyword.",
);
};
self.advance();
self.consume(TokenType::In, "Expect 'in' after for variable.")?;
let iterable = self.expression()?;
let body = self.statement()?;
let end_slice = body.source_slice.clone();
let combined_slice = SourceSlice::from_positions(
start_slice.source_id,
start_slice.start_position,
end_slice.end_position,
);
Ok(AstNode::new(
Stmt::For {
variable: Box::new(variable),
iterable: Box::new(iterable),
body: Box::new(body),
},
combined_slice,
))
}
fn while_statement(&mut self) -> LoxResult<AstNode<Stmt>> {
let start_slice = self.peek().source_slice.clone();
self.advance();