createModuleEnvironment static method
Creates a new module environment.
This creates an environment suitable for module execution, where local variables are scoped to the module but globals are inherited.
Implementation
static Environment createModuleEnvironment(Environment globalEnv) {
final rootEnv = globalEnv.root;
Logger.debugLazy(
() =>
"Creating new module environment with global env (${rootEnv.hashCode})",
category: 'Env',
);
final moduleEnv = Environment(parent: rootEnv, interpreter: null);
final envTable = <dynamic, dynamic>{};
final envValue = Value(envTable, interpreter: rootEnv.interpreter);
final inheritedEnvValue = switch (globalEnv.get('_ENV')) {
final Value value => value,
final Object? value? => cachedPrimitiveOrValue(
rootEnv.interpreter,
value,
),
_ => null,
};
final proxyHandler = <String, Function>{
'__index': (List<Object?> args) {
final key = args[1] as Value;
final keyStr = rawLuaSlot(key).toString();
Logger.debugLazy(
() => "Module env __index: looking up '$keyStr'",
category: 'Env',
);
if (envTable.containsKey(keyStr)) {
return envTable[keyStr];
}
final inheritedRaw = rawLuaSlot(inheritedEnvValue);
if (inheritedEnvValue != null && inheritedRaw is Map) {
final inheritedTable = inheritedRaw;
if (inheritedTable.containsKey(keyStr)) {
return inheritedTable[keyStr];
}
}
return rootEnv.get(keyStr);
},
'__newindex': (List<Object?> args) {
final key = args[1] as Value;
final value = args[2] as Value;
final keyStr = rawLuaSlot(key).toString();
final gc = rootEnv.interpreter?.gc ?? GCAccess.defaultManager;
Logger.debugLazy(
() => "Module env __newindex: setting '$keyStr' to $value",
category: 'Env',
);
envTable[keyStr] = value;
gc?.ensureTracked(value);
gc?.noteReferenceWrite(envValue, keyStr);
gc?.noteReferenceWrite(envValue, value);
envValue.markTableModified();
final inheritedRaw = rawLuaSlot(inheritedEnvValue);
if (inheritedEnvValue != null && inheritedRaw is Map) {
final inheritedTable = inheritedRaw;
inheritedTable[keyStr] = value;
gc?.noteReferenceWrite(inheritedEnvValue, keyStr);
gc?.noteReferenceWrite(inheritedEnvValue, value);
inheritedEnvValue.markTableModified();
} else {
rootEnv.defineGlobal(keyStr, value);
}
return rootEnv.interpreter?.constantPrimitiveValue(null) ??
Value.primitive(null);
},
};
envValue.setMetatable(proxyHandler);
moduleEnv.declare("_ENV", envValue);
Logger.debugLazy(
() => "Module environment created with id (${moduleEnv.hashCode})",
category: 'Env',
);
return moduleEnv;
}