Issue: Closure Scoping Bug
We’ve encountered a scoping issue in our interpreter due to how closures capture environments. Initially, our scoping rules worked fine, but when we introduced closures, we accidentally allowed later-declared variables to be visible inside previously captured environments. This means our lexical scoping behaves incorrectly, making our language unintentionally leak dynamic scoping.
Expected Behavior
A function should retain access to the environment as it was at the moment of declaration, meaning it should not see variables declared after it was created.
Current Behavior (Bug)
Right now, functions capture a reference to a mutable environment, so when a variable is declared later in the same block, the closure mistakenly sees that new variable instead of the original scope at the time of function creation.
var a = "global";
{
fun showA() {
print a;
}
showA(); // Expected: "global"
var a = "block";
showA(); // Expected: "global", but prints "block"
}
Instead of printing global twice, the second call prints block because showA() captures a mutable environment instead of a frozen snapshot of its lexical scope.
Next Steps
We need to properly resolve variable bindings statically instead of relying on dynamic lookups at runtime. Implementing a semantic analysis phase for variable resolution will help enforce correct lexical scoping and prevent these issues.

Issue: Closure Scoping Bug
We’ve encountered a scoping issue in our interpreter due to how closures capture environments. Initially, our scoping rules worked fine, but when we introduced closures, we accidentally allowed later-declared variables to be visible inside previously captured environments. This means our lexical scoping behaves incorrectly, making our language unintentionally leak dynamic scoping.
Expected Behavior
A function should retain access to the environment as it was at the moment of declaration, meaning it should not see variables declared after it was created.
Current Behavior (Bug)
Right now, functions capture a reference to a mutable environment, so when a variable is declared later in the same block, the closure mistakenly sees that new variable instead of the original scope at the time of function creation.
Instead of printing
globaltwice, the second call printsblockbecauseshowA()captures a mutable environment instead of a frozen snapshot of its lexical scope.Next Steps
We need to properly resolve variable bindings statically instead of relying on dynamic lookups at runtime. Implementing a semantic analysis phase for variable resolution will help enforce correct lexical scoping and prevent these issues.