closure
This commit is contained in:
+73
-50
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user