Skip to content

Commit f1b28f8

Browse files
committed
test: garantir isolamento de escopo léxico entre funções (issue #44)
1 parent 248c7aa commit f1b28f8

File tree

2 files changed

+50
-149
lines changed

2 files changed

+50
-149
lines changed

src/interpreter/statement_execute.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
393393
Ok(Computation::Continue(new_env))
394394
}
395395

396-
// Tupla (assumindo que você tem Expression::Tuple)
396+
// Tupla
397397
Expression::Tuple(items) => {
398398
for item in items {
399399
let prev = new_env.lookup(&var.clone());
@@ -415,7 +415,7 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
415415
Ok(Computation::Continue(new_env))
416416
}
417417

418-
// Constructor (já existia)
418+
// Constructor
419419
Expression::Constructor(_, items) => {
420420
for item_expr in items {
421421
let item_value = *item_expr.clone();
@@ -1538,4 +1538,52 @@ mod tests {
15381538
assert_eq!(r2.error, Some("Variable 'x' not found".to_string())); // Erro é propagado de Expression::Var
15391539
}
15401540
}
1541+
1542+
// Escopo léxico entre funções (issue #44)
1543+
mod scoping_tests {
1544+
use super::*;
1545+
1546+
#[test]
1547+
fn top_level_function_cannot_see_caller_local_variable() {
1548+
let env = create_test_env();
1549+
1550+
// outer() tenta acessar a variável local `x`, que só existe dentro de inner()
1551+
let outer_func = Function {
1552+
name: "outer".to_string(),
1553+
kind: Type::TInteger,
1554+
params: vec![],
1555+
body: Some(Box::new(Statement::Block(vec![Statement::Return(
1556+
Box::new(Expression::Var("x".to_string())),
1557+
)]))),
1558+
};
1559+
1560+
// inner() declara x localmente e chama outer()
1561+
let inner_func = Function {
1562+
name: "inner".to_string(),
1563+
kind: Type::TInteger,
1564+
params: vec![],
1565+
body: Some(Box::new(Statement::Block(vec![
1566+
Statement::VarDeclaration("x".to_string(), Box::new(Expression::CInt(42))),
1567+
Statement::Return(Box::new(Expression::FuncCall("outer".to_string(), vec![]))),
1568+
]))),
1569+
};
1570+
1571+
let program = Statement::Block(vec![
1572+
Statement::FuncDef(outer_func),
1573+
Statement::FuncDef(inner_func),
1574+
// Executa inner(); durante a chamada, outer() não deve enxergar `x`
1575+
Statement::ExprStmt(Box::new(Expression::FuncCall("inner".to_string(), vec![]))),
1576+
]);
1577+
1578+
let result = execute(program, &env);
1579+
1580+
// O cenário problemático descrito na issue #44 seria a chamada ter sucesso
1581+
// usando o valor de `x` definido em `inner` (escopo dinâmico).
1582+
// Aqui garantimos que a chamada falha (não há captura de `x`).
1583+
assert!(
1584+
result.is_err(),
1585+
"Programa deveria falhar por falta de escopo léxico"
1586+
);
1587+
}
1588+
}
15411589
}

src/pretty_print/README.md

Lines changed: 0 additions & 147 deletions
This file was deleted.

0 commit comments

Comments
 (0)