@@ -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}
0 commit comments