///|
pub(all) struct Environment {
loader : ((String) -> String raise Error)? // host-provided: module name -> source
module_cache : Map[String, Map[String, @value.Value]] // cached module globals
predeclared : Map[String, @value.Value] // built-in functions
}
///|
pub fn Environment::new(
loader? : ((String) -> String raise Error)? = None,
) -> Environment {
{ loader, module_cache: {}, predeclared: predeclared_builtins() }
}
///|
pub(all) struct Scope {
bindings : Map[String, @value.Value]
parent : Scope?
env : Environment? // only set at root scope
}
///|
pub fn Scope::new(parent? : Scope, env? : Environment) -> Scope {
{ bindings: {}, parent, env }
}
///|
pub fn Scope::get(self : Scope, name : String) -> @value.Value? {
match self.bindings.get(name) {
Some(v) => Some(v)
None =>
match self.parent {
Some(parent) => parent.get(name)
None => None
}
}
}
///|
pub fn Scope::set(self : Scope, name : String, value : @value.Value) -> Unit {
self.bindings.set(name, value)
}
///|
/// Walk up the scope chain to find the Environment.
pub fn Scope::get_env(self : Scope) -> Environment? {
match self.env {
Some(e) => Some(e)
None =>
match self.parent {
Some(parent) => parent.get_env()
None => None
}
}
}
///|
pub fn Scope::with_builtins(
loader? : ((String) -> String raise Error)? = None,
) -> Scope {
let env = Environment::new(loader~)
let scope = Scope::new(env~)
for name, value in env.predeclared {
scope.set(name, value)
}
scope
}