This commit is contained in:
2026-02-11 16:35:05 +01:00
parent ee279425f2
commit 4e2645e12d
13 changed files with 229 additions and 176 deletions
+73 -50
View File
@@ -33,7 +33,15 @@ where
impl EvaluateInterpreter<Expr> for Interpreter {
fn evaluate(&mut self, expr: Expr) -> LoxResult<BaseValue> {
match expr {
Expr::Literal { value } => Ok(value),
Expr::Literal { value } => match value {
BaseValue::Function(mut func) => {
func.closure = Some(self.enviorment.clone());
println!("Closure created");
println!("current enviorment: {:?}", self.enviorment);
Ok(BaseValue::Function(func))
}
_ => Ok(value),
},
Expr::Identifier { name } => self.enviorment.get(&name),
Expr::Binary {
left,
@@ -120,15 +128,34 @@ impl Interpreter {
match function {
BaseValue::NativeFunction(func) => Ok((func.function)(&evaluated_arguments)),
BaseValue::Function(func) => {
func.parameters
.iter()
.enumerate()
.map(|(index, par)| {
let value = evaluated_arguments.get(index).unwrap();
self.enviorment.declare(par.0.clone(), value.clone())
})
.collect::<LoxResult<Vec<BaseValue>>>()?;
self.evaluate(func.body)
// Save the current environment
let saved_env = self.enviorment.clone();
// If the function captured a closure, use it as the base environment
if let Some(closure_env) = func.closure {
self.enviorment = closure_env;
}
// Push a new scope for the function's parameters
self.enviorment.push_new_scope();
// Declare parameters in the new scope
for (index, par) in func.parameters.iter().enumerate() {
let value = evaluated_arguments.get(index).unwrap();
self.enviorment.declare(par.0.clone(), value.clone())?;
}
// Execute the function body
let result = match self.evaluate(func.body) {
Ok(value) => Ok(value),
Err(LoxError::Return { value, .. }) => Ok(value),
Err(err) => Err(err),
};
// Restore the original environment (cleanup is automatic)
self.enviorment = saved_env;
result
}
_ => runtime_error(
source_slice.clone(),
@@ -194,21 +221,11 @@ impl Interpreter {
name, initializer, ..
} => {
let value = match initializer {
Some(expr_node) => match &expr_node.node {
Expr::Literal { value } => {
if value.is_callable() {
value.clone()
} else {
value.clone()
}
}
_ => self.evaluate(*expr_node)?,
},
Some(expr_node) => self.evaluate(*expr_node)?,
None => BaseValue::Nil,
};
self.enviorment.declare(name.clone(), value)
}
Stmt::VarAssigment { name, value, .. } => {
let result = self.evaluate(*value)?;
self.enviorment.set(name.clone(), result)
@@ -223,10 +240,18 @@ impl Interpreter {
Stmt::While {
condition, body, ..
} => {
let mut ret = BaseValue::Nil;
while self.evaluate(*condition.clone())?.is_truthy() {
self.evaluate(*body.clone())?;
match self.evaluate(*body.clone()) {
Ok(val) => ret = val,
Err(LoxError::Return { value, .. }) => {
ret = value;
break;
}
Err(err) => return Err(err),
};
}
Ok(BaseValue::Nil)
Ok(ret)
}
Stmt::For {
variable,
@@ -235,7 +260,6 @@ impl Interpreter {
body,
..
} => {
self.enviorment.push_new_scope();
let source_slice = variable.source_slice.clone();
let val = self.evaluate(*variable)?;
if !matches!(val, BaseValue::Number(..)) {
@@ -243,7 +267,14 @@ impl Interpreter {
}
let mut ret = BaseValue::Nil;
while self.evaluate(*condition.clone())?.is_truthy() {
ret = self.evaluate(*body.clone())?;
match self.evaluate(*body.clone()) {
Ok(val) => ret = val,
Err(LoxError::Return { value, .. }) => {
ret = value;
break;
}
Err(err) => return Err(err),
};
self.evaluate(*increment.clone())?;
}
@@ -294,34 +325,26 @@ impl Interpreter {
fn evaluate_block(&mut self, statements: Vec<AstNode<Stmt>>) -> LoxResult<BaseValue> {
self.enviorment.push_new_scope();
let (elements, final_expr) = match statements.split_last() {
Some((stmt, body)) => match &stmt.node {
Stmt::Expression { expression, .. } => (body, Some(expression)),
Stmt::Return { expression, .. } => (body, Some(expression)),
_ => (statements.as_slice(), None),
},
None => {
(&[][..], None) // Blocco vuoto
}
};
// Ora elements è sempre disponibile
for statement in elements.iter() {
self.evaluate((*statement).clone())?;
}
let mut result = Ok(BaseValue::Nil);
for statement in statements.iter() {
let node = statement.node.clone();
match node {
Stmt::Return { expression, .. } => {
let value = self.evaluate(*expression)?;
// Gestisci l'espressione finale se presente
match final_expr {
Some(expr) => {
let res = self.evaluate(*expr.clone());
self.enviorment.pop_scope();
res
}
None => {
self.enviorment.pop_scope();
Ok(BaseValue::Nil)
}
result = Err(LoxError::Return {
source_slice: statement.source_slice.clone(),
value: value,
return_label: "Hi".to_string(),
});
break;
}
_ => result = self.evaluate((*statement).clone()),
};
}
self.enviorment.pop_scope();
result
}
}