wip: i dont rembemer

This commit is contained in:
2026-07-11 18:07:07 +02:00
parent 4e2645e12d
commit 6bf255668a
8 changed files with 253 additions and 29 deletions
+15
View File
@@ -10,3 +10,18 @@ end
internal := closure(); internal := closure();
internal(); internal();
a := "Global";
b := a;
c := b;
c = b = a;
d := c = b = a;
do
showA :: fn() do
print a;
end
showA();
a := "Local";
showA();
end
+23 -12
View File
@@ -1,34 +1,45 @@
use std::collections::HashMap;
use crate::{ use crate::{
common::{ common::lox_result::{runtime_error, LoxResult},
base_value::BaseValue,
lox_result::{runtime_error, LoxResult},
},
frontend::source_registry::SourceSlice, frontend::source_registry::SourceSlice,
}; };
use std::collections::HashMap;
use std::fmt::Debug;
pub type Environment<T> = HashMap<String, T>;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct EnvironmentStack { pub struct EnvironmentStack<T: Clone + Debug + PartialEq> {
stack: Vec<HashMap<String, BaseValue>>, stack: Vec<HashMap<String, T>>,
} }
impl EnvironmentStack { impl<T: Clone + Debug + PartialEq> EnvironmentStack<T> {
pub fn new() -> Self { pub fn new() -> Self {
EnvironmentStack { EnvironmentStack {
stack: vec![HashMap::new()], stack: vec![HashMap::new()],
} }
} }
pub fn is_empty(&self) -> bool {
self.stack.is_empty()
}
pub fn push_new_scope(&mut self) { pub fn push_new_scope(&mut self) {
self.stack.push(HashMap::new()); self.stack.push(HashMap::new());
} }
pub fn push_existing_scope(&mut self, scope: HashMap<String, T>) {
self.stack.push(scope);
}
pub fn pop_scope(&mut self) { pub fn pop_scope(&mut self) {
self.stack.pop(); self.stack.pop();
} }
pub fn get(&self, name: &str) -> LoxResult<BaseValue> { pub fn clone_last_scope(&mut self) -> HashMap<String, T> {
self.stack.last().unwrap().clone()
}
pub fn get(&self, name: &str) -> LoxResult<T> {
let size = self.stack.len(); let size = self.stack.len();
for i in (0..size).rev() { for i in (0..size).rev() {
@@ -42,12 +53,12 @@ impl EnvironmentStack {
) )
} }
pub fn declare(&mut self, name: String, value: BaseValue) -> LoxResult<BaseValue> { pub fn declare(&mut self, name: String, value: T) -> LoxResult<T> {
self.stack.last_mut().unwrap().insert(name, value.clone()); self.stack.last_mut().unwrap().insert(name, value.clone());
Ok(value) Ok(value)
} }
pub fn set(&mut self, name: String, value: BaseValue) -> LoxResult<BaseValue> { pub fn set(&mut self, name: String, value: T) -> LoxResult<T> {
let size = self.stack.len(); let size = self.stack.len();
for i in (0..size).rev() { for i in (0..size).rev() {
+2 -6
View File
@@ -10,14 +10,14 @@ use crate::{
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
pub struct Interpreter { pub struct Interpreter {
enviorment: EnvironmentStack, enviorment: EnvironmentStack<BaseValue>,
} }
pub trait EvaluateInterpreter<T> { pub trait EvaluateInterpreter<T> {
fn evaluate(&mut self, stmt: T) -> LoxResult<BaseValue>; fn evaluate(&mut self, stmt: T) -> LoxResult<BaseValue>;
} }
impl<'a, R: AstNodeKind + Clone + Debug + Display> EvaluateInterpreter<AstNode<R>> for Interpreter impl<R: AstNodeKind + Clone + Debug + Display> EvaluateInterpreter<AstNode<R>> for Interpreter
where where
Interpreter: EvaluateInterpreter<R>, Interpreter: EvaluateInterpreter<R>,
{ {
@@ -36,8 +36,6 @@ impl EvaluateInterpreter<Expr> for Interpreter {
Expr::Literal { value } => match value { Expr::Literal { value } => match value {
BaseValue::Function(mut func) => { BaseValue::Function(mut func) => {
func.closure = Some(self.enviorment.clone()); func.closure = Some(self.enviorment.clone());
println!("Closure created");
println!("current enviorment: {:?}", self.enviorment);
Ok(BaseValue::Function(func)) Ok(BaseValue::Function(func))
} }
_ => Ok(value), _ => Ok(value),
@@ -128,9 +126,7 @@ impl Interpreter {
match function { match function {
BaseValue::NativeFunction(func) => Ok((func.function)(&evaluated_arguments)), BaseValue::NativeFunction(func) => Ok((func.function)(&evaluated_arguments)),
BaseValue::Function(func) => { BaseValue::Function(func) => {
// Save the current environment
let saved_env = self.enviorment.clone(); let saved_env = self.enviorment.clone();
// If the function captured a closure, use it as the base environment // If the function captured a closure, use it as the base environment
if let Some(closure_env) = func.closure { if let Some(closure_env) = func.closure {
self.enviorment = closure_env; self.enviorment = closure_env;
+3 -2
View File
@@ -2,6 +2,7 @@ use core::fmt;
use std::fmt::Display; use std::fmt::Display;
use std::ops::{Add, Div, Mul, Not, Rem, Sub}; use std::ops::{Add, Div, Mul, Not, Rem, Sub};
use crate::backend::environment::Environment;
use crate::common::lox_result::{runtime_error, LoxResult}; use crate::common::lox_result::{runtime_error, LoxResult};
use crate::{ use crate::{
backend::environment::EnvironmentStack, backend::environment::EnvironmentStack,
@@ -312,7 +313,7 @@ pub struct LoxFunction {
pub parameters: Vec<(String, String)>, pub parameters: Vec<(String, String)>,
pub return_type: Option<String>, pub return_type: Option<String>,
pub body: AstNode<Stmt>, pub body: AstNode<Stmt>,
pub closure: Option<EnvironmentStack>, pub closure: Option<EnvironmentStack<BaseValue>>,
pub guard: Option<Box<Expr>>, pub guard: Option<Box<Expr>>,
} }
@@ -320,7 +321,7 @@ impl LoxFunction {
pub fn new( pub fn new(
parameters: Vec<(String, String)>, parameters: Vec<(String, String)>,
body: AstNode<Stmt>, body: AstNode<Stmt>,
closure: Option<EnvironmentStack>, closure: Option<EnvironmentStack<BaseValue>>,
guard: Option<Box<Expr>>, guard: Option<Box<Expr>>,
) -> Self { ) -> Self {
LoxFunction { LoxFunction {
+1 -5
View File
@@ -106,11 +106,7 @@ impl LoxError {
LoxError::ParseError { source_slice, .. } => Some(source_slice.clone()), LoxError::ParseError { source_slice, .. } => Some(source_slice.clone()),
LoxError::IoError { .. } => None, LoxError::IoError { .. } => None,
LoxError::TypeMismatch { source_slice, .. } => Some(source_slice.clone()), LoxError::TypeMismatch { source_slice, .. } => Some(source_slice.clone()),
LoxError::Return { LoxError::Return { .. } => None,
value,
return_label,
..
} => None,
} }
} }
+1
View File
@@ -2,3 +2,4 @@ pub mod lexer;
pub mod parser; pub mod parser;
pub mod source_registry; pub mod source_registry;
pub mod tokens; pub mod tokens;
pub mod variable_resolution;
+4 -4
View File
@@ -205,6 +205,10 @@ impl Parser {
let mut _type_annotation = BaseValue::Nil; let mut _type_annotation = BaseValue::Nil;
self.consume(TokenType::Colon, "Expect column")?; self.consume(TokenType::Colon, "Expect column")?;
if self.peek().token_type == TokenType::Identifier {
// TODO manage type annotation
self.consume(TokenType::Identifier, "Expect type name.")?;
}
match self.peek().token_type { match self.peek().token_type {
TokenType::Equal | TokenType::Identifier => { TokenType::Equal | TokenType::Identifier => {
@@ -374,11 +378,7 @@ impl Parser {
while self.peek().token_type != TokenType::EndBlock && !self.is_at_end() { while self.peek().token_type != TokenType::EndBlock && !self.is_at_end() {
let stmt = self.statement(label.clone())?; let stmt = self.statement(label.clone())?;
let should_break = matches!(stmt.node, Stmt::Expression { .. });
statements.push(stmt); statements.push(stmt);
if should_break {
break;
}
} }
let end_token = self.consume(TokenType::EndBlock, "Expect 'end' after block.")?; let end_token = self.consume(TokenType::EndBlock, "Expect 'end' after block.")?;
let end_slice = end_token.source_slice.clone(); let end_slice = end_token.source_slice.clone();
+204
View File
@@ -0,0 +1,204 @@
use crate::{
backend::environment::EnvironmentStack,
common::{
ast::{AstNode, AstNodeKind, Expr, Stmt},
lox_result::{runtime_error, LoxError, LoxResult},
},
frontend::source_registry::SourceSlice,
};
use std::fmt::{Debug, Display};
struct Resolver {
scopes: EnvironmentStack<bool>,
}
impl Resolver {
pub fn new() -> Self {
Resolver {
scopes: EnvironmentStack::new(),
}
}
fn declare(&mut self, name: &String) {
if self.scopes.is_empty() {
return;
}
let _ = self.scopes.set(name.clone(), false);
}
fn define(&mut self, name: &String) {
if self.scopes.is_empty() {
return;
}
let _ = self.scopes.set(name.clone(), true);
}
}
pub trait StaticAnalyzer<T> {
fn resolve(&mut self, node: &T) -> LoxResult<bool>;
}
impl<R: AstNodeKind + Clone + Debug + Display> StaticAnalyzer<AstNode<R>> for Resolver
where
Resolver: StaticAnalyzer<R>,
{
fn resolve(&mut self, node: &AstNode<R>) -> LoxResult<bool> {
self.resolve(&node.node)
}
}
impl StaticAnalyzer<Stmt> for Resolver {
fn resolve(&mut self, node: &Stmt) -> LoxResult<bool> {
match node {
Stmt::Expression { expression, .. } => {
// Visit the expression
self.resolve(expression.as_ref())
}
Stmt::Print { expression, .. } => {
// Visit the expression
self.resolve(expression.as_ref())
}
Stmt::VarDeclaration {
initializer, name, ..
} => {
self.declare(name);
// Visit the initializer if present
if let Some(init) = initializer {
self.resolve(init.as_ref())?;
}
self.define(name);
Ok(true)
}
Stmt::VarAssigment { value, name, .. } => {
match self.scopes.get(name) {
Ok(true) => (),
Ok(false) => {
return Err(LoxError::RuntimeError {
source_slice: SourceSlice::default(),
message: "Cant read loac variable in it own lintilizer".to_string(),
})
}
Err(err) => return Err(err),
}
self.resolve(value.as_ref())
}
Stmt::Return { expression, .. } => {
// Visit the return expression
self.resolve(expression.as_ref())
}
Stmt::Block { statements, .. } => {
self.scopes.push_new_scope();
// Visit all statements in the block
for stmt in statements.iter() {
self.resolve(stmt)?;
}
self.scopes.pop_scope();
Ok(true)
}
Stmt::If {
condition,
then_branch,
elif_branch,
else_branch,
..
} => {
// Visit the condition
self.resolve(condition.as_ref())?;
// Visit the then branch
self.resolve(then_branch.as_ref())?;
// Visit all elif branches
for (elif_condition, elif_stmt) in elif_branch.iter() {
self.resolve(elif_condition.as_ref())?;
self.resolve(elif_stmt.as_ref())?;
}
// Visit the else branch if present
if let Some(else_stmt) = else_branch {
self.resolve(else_stmt.as_ref())?;
}
Ok(true)
}
Stmt::While {
condition, body, ..
} => {
// Visit the condition
self.resolve(condition.as_ref())?;
// Visit the body
self.resolve(body.as_ref())?;
Ok(true)
}
Stmt::For {
variable,
condition,
increment,
body,
..
} => {
// Visit the variable initialization
self.resolve(variable.as_ref())?;
// Visit the condition
self.resolve(condition.as_ref())?;
// Visit the increment
self.resolve(increment.as_ref())?;
// Visit the body
self.resolve(body.as_ref())?;
Ok(true)
}
}
}
}
impl StaticAnalyzer<Expr> for Resolver {
fn resolve(&mut self, node: &Expr) -> LoxResult<bool> {
match node {
Expr::Literal { .. } => {
// Leaf node - no children to visit
Ok(true)
}
Expr::Binary { left, right, .. } => {
// Visit left operand
self.resolve(left.as_ref())?;
// Visit right operand
self.resolve(right.as_ref())
}
Expr::Unary { operand, .. } => {
// Visit the operand
self.resolve(operand.as_ref())
}
Expr::Grouping { expression } => {
// Visit the grouped expression
self.resolve(expression.as_ref())
}
Expr::Identifier { name, .. } => {
if !self.scopes.is_empty() && self.scopes.get(name).is_ok() {
return Err(LoxError::ParseError {
source_slice: SourceSlice::default(),
message: "Cant read local varialbe in it own initializer".to_string(),
});
}
Ok(true)
}
Expr::Call {
callee, arguments, ..
} => {
// Visit the callee
self.resolve(callee.as_ref())?;
// Visit all arguments
for arg in arguments.iter() {
self.resolve(arg)?;
}
Ok(true)
}
}
}
}