Skip to content

Commit 7e68645

Browse files
Fix misplaced pop in execute_block and add exec_if_block for conditional block execution
Fixes a scoping bug in execute_block where pop() was applied to the wrong environment. Previously, in function `exec`: - The environment `env` was cloned into a variable `new_env`. - In the `Statement::Block` match arm, the returned environment was actually wrapped inside the variable `result`, of type `Computation`. - However, `pop()` was mistakenly called on `new_env`, which was discarded afterward. - As a result, the environment inside `result` — the one that was actually returned — remained unmodified, and the pushed scope was never popped. This commit fixes the issue by: - Moving the push/pop operations into the `execute_block` function itself, so that scope management is handled consistently before wrapping the result in a `Computation`. Additionally, it introduces the `exec_if_block` function: - A simplified version of `execute_block` that executes a list of statements without pushing or popping a new scope. - Intended for use in the body of `if` clauses These changes improve correctness and modularity in the interpreter's handling of scope and control flow.
1 parent d488d84 commit 7e68645

1 file changed

Lines changed: 39 additions & 7 deletions

File tree

src/interpreter/statement_execute.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
7979

8080
match value {
8181
Expression::CTrue => match *stmt_then {
82-
Statement::Block(stmts) => execute_block(stmts, &new_env),
82+
Statement::Block(stmts) => execute_if_block(stmts, &new_env),
8383
_ => execute(*stmt_then, &new_env),
8484
},
8585
Expression::CFalse => match stmt_else {
8686
Some(else_stmt) => match *else_stmt {
87-
Statement::Block(stmts) => execute_block(stmts, &new_env),
87+
Statement::Block(stmts) => execute_if_block(stmts, &new_env),
8888
_ => execute(*else_stmt, &new_env),
8989
},
9090
None => Ok(Computation::Continue(new_env)),
@@ -94,9 +94,14 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
9494
}
9595

9696
Statement::Block(stmts) => {
97-
new_env.push();
97+
// new_env.push(); <- removing push()
9898
let result = execute_block(stmts, &new_env);
99-
new_env.pop();
99+
// new_env.pop(); <- removing pop()
100+
// `result` already encapsulates the updated environment,
101+
// So popping would have no effect on the final outcome
102+
// Therefore, push and pop operations will be handled in function 'execute_block'
103+
// A new function `execute_if_block` will be created specifically for executing blocks
104+
// without performing push/pop operations
100105
result
101106
}
102107

@@ -201,13 +206,40 @@ pub fn execute_block(
201206
env: &Environment<Expression>,
202207
) -> Result<Computation, String> {
203208
let mut current_env = env.clone();
209+
current_env.push();
204210

205211
for stmt in stmts {
206212
match execute(stmt, &current_env)? {
207213
Computation::Continue(new_env) => current_env = new_env,
208-
Computation::Return(expr, env) => return Ok(Computation::Return(expr, env)),
209-
Computation::PropagateError(expr, env) => {
210-
return Ok(Computation::PropagateError(expr, env))
214+
Computation::Return(expr, mut new_env) =>
215+
{
216+
new_env.pop(); //expr has already been evaluated, so it is safe to pop here
217+
return Ok(Computation::Return(expr, new_env));
218+
}
219+
Computation::PropagateError(expr, new_env) => {
220+
return Ok(Computation::PropagateError(expr, new_env))
221+
}
222+
}
223+
}
224+
current_env.pop();
225+
Ok(Computation::Continue(current_env))
226+
}
227+
228+
pub fn execute_if_block(
229+
stmts: Vec<Statement>,
230+
env: &Environment<Expression>,
231+
) -> Result<Computation, String> {
232+
let mut current_env = env.clone();
233+
234+
for stmt in stmts {
235+
match execute(stmt, &current_env)? {
236+
Computation::Continue(new_env) => current_env = new_env,
237+
Computation::Return(expr, new_env) =>
238+
{
239+
return Ok(Computation::Return(expr, new_env));
240+
}
241+
Computation::PropagateError(expr, new_env) => {
242+
return Ok(Computation::PropagateError(expr, new_env))
211243
}
212244
}
213245
}

0 commit comments

Comments
 (0)