Environment class
Represents a scope for variable bindings in the interpreter.
An Environment maintains a mapping of variable names to their values and can be chained to parent environments to implement lexical scoping. It supports variable definition, assignment, and lookup through the scope chain.
Variable Management Methods Overview
This class provides four main methods for variable operations, each serving specific use cases to correctly implement Lua's variable scoping semantics:
1. get(name) - Variable Lookup
- Purpose: Read variable values
- Behavior: Searches environment chain from current to root
- Usage:
xin expressions likeprint(x)ory = x + 1
2. declare(name, value) - Local Variable Declaration
- Purpose: Create new local variables (
local x = value) - Behavior: Always creates new binding with
isLocal: true, shadows existing variables - Usage: Local variable declarations in Lua code
3. updateLocal(name, value) - Local Variable Assignment
- Purpose: Update existing local variables only
- Behavior: Searches for
isLocal: truevariables, updates first match - Returns:
trueif local found and updated,falseotherwise - Usage: Assignments when local variable should take precedence
- Why needed: Prevents accidental global creation when local exists
4. defineGlobal(name, value) - Global Variable Assignment
- Purpose: Create/update global variables specifically
- Behavior: Always operates on root environment, ignores local variables
- Usage: When assignment should target global environment
- Why needed: Ensures globals can be created even when locals exist
5. define(name, value) - Legacy General Assignment
- Purpose: Original assignment method (has scoping issues)
- Behavior: Searches chain, updates first match, creates in root if none found
- Status: Still used but being phased out in favor of precise methods
Design Rationale
The multiple methods exist because Lua has complex variable scoping rules:
- Local variables shadow globals with the same name
- Assignments to existing locals should update the local, not create globals
- Assignments when no local exists should create/update globals
- Environment isolation (like
load()with custom env) needs special handling
The original define() method couldn't distinguish these cases correctly,
leading to bugs where local variables in main scripts affected globals.
The newer methods provide precise control over each scenario.
Constructors
- Environment({Environment? parent, LuaRuntime? interpreter, bool isClosure = false, bool isLoadIsolated = false})
- Creates a new Environment.
Properties
-
declaredGlobals
→ Map<
String, Box> -
Names explicitly declared as globals in this lexical scope.
final
- estimatedSize → int
-
Estimated memory footprint for this object expressed in GC "credits".
no setter
- gcSpace ↔ GCGenerationSpace?
-
Which GC generation space this object is tracked in, or null if untracked.
Stored directly on the object to avoid Expando lookups on hot paths.
getter/setter pairinherited
- hashCode → int
-
The hash code for this object.
no setterinherited
-
implicitToBeClosedValues
→ List<
Value> -
Stores implicit to-be-closed resources that must stay GC-reachable even
when they are not ordinary local bindings.
final
- interpreter ↔ LuaRuntime?
-
The interpreter associated with this environment.
getter/setter pair
- isClosure → bool
-
Whether this environment represents a closure scope.
final
- isLoadIsolated ↔ bool
-
Whether this environment was created by load() with a custom environment.
getter/setter pair
- isOld ↔ bool
-
Whether this object belongs to the old generation.
Used in generational collection to determine which generation the object belongs to.
getter/setter pairinherited
- marked ↔ bool
-
Whether this object has been marked during the current GC cycle.
Used in mark-and-sweep collection to identify live objects.
getter/setter pairinherited
- parent → Environment?
-
The parent environment in the scope chain, if any.
final
- pendingImplicitToBeClosed ↔ int
-
Tracks pending implicit to-be-closed resources that are active for this
scope but are not represented as normal local bindings.
getter/setter pair
- root → Environment
-
Gets the root environment (the one with no parent).
no setter
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
toBeClosedVars
→ List<
String> -
Tracks the order in which to-be-closed variables were declared
final
-
values
→ Map<
String, Box> -
Storage for variable bindings in this scope.
final
Methods
-
clearGlobal(
String name) → void -
Removes the root global binding for
nameand keeps the backing_Gtable in sync. -
clone(
{LuaRuntime? interpreter}) → Environment - Creates a clone of this environment
-
closeVariables(
[dynamic error]) → Future< void> - Closes all to-be-closed variables in this environment in reverse order of declaration.
-
contains(
String name) → bool - Checks if a variable exists in this environment or any of its ancestors.
-
declare(
String name, dynamic value, {bool trackToBeClosed = false}) → void - Declares a new local variable in the current environment.
-
declareGlobalBinding(
String name) → void -
Declares
nameas an explicit global in this lexical scope. -
define(
String name, dynamic value) → void -
Defines or updates a variable named
namewithvalue. -
defineAll(
Map< String, dynamic> values) → void - Defines multiple variables in the current environment.
-
defineGlobal(
String name, dynamic value) → void - Defines or updates a global variable in the root environment.
-
findBox(
String name) → Box? -
Finds the Box associated with
namein this environment chain. Returns null if no binding exists. -
findDeclaredGlobalBox(
String name) → Box? -
Finds the nearest explicit-global binding for
namein this lexical chain. -
free(
) → void -
Free any resources (for debugging or finalization).
inherited
-
get(
String name) → dynamic -
Looks up the value of a variable named
namein this environment. -
getReferences(
) → List< GCObject> - Return direct references so the GC can traverse the object graph.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
readRootGlobal(
String name) → dynamic -
Reads the root global binding for
name, ignoring local variables. -
resolvesThroughDeclaredGlobal(
String name) → bool -
Returns whether
nameresolves through an explicit global declaration before any local binding when walking the lexical scope chain. -
toString(
) → String -
A string representation of this object.
inherited
-
updateLocal(
String name, dynamic value) → bool - Updates only local variables in the current scope chain.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Properties
- maxActive ↔ int
-
getter/setter pair
- totalCreated ↔ int
-
getter/setter pair
- totalFreed ↔ int
-
getter/setter pair
Static Methods
-
createModuleEnvironment(
Environment globalEnv) → Environment - Creates a new module environment.