implement WithLookup
This commit is contained in:
+54
-2
@@ -891,8 +891,60 @@ impl Runtime {
|
|||||||
root.with_scope = scope.prev;
|
root.with_scope = scope.prev;
|
||||||
}),
|
}),
|
||||||
WithLookup => {
|
WithLookup => {
|
||||||
let _name = self.read_string_id();
|
let name = self.read_string_id();
|
||||||
todo!("implement WithLookup (force with_scope)");
|
let mut depth = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let found_scope = self.arena.mutate_root(|_, root| {
|
||||||
|
let mut cur = root.with_scope;
|
||||||
|
for _ in 0..depth {
|
||||||
|
if let Some(s) = cur {
|
||||||
|
cur = s.prev;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(scope) = cur {
|
||||||
|
root.push_stack(scope.env);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if !found_scope {
|
||||||
|
let name_str = self.strings.resolve(name.0).unwrap_or("«unknown»");
|
||||||
|
return Runtime::handle_vm_error(
|
||||||
|
self,
|
||||||
|
vm_err(format!("undefined variable '{name_str}'")),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let err @ Action::Done(Err(_)) = self.force_tos() {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lookup_result = self.arena.mutate_root(|_, root| {
|
||||||
|
let val = root.pop_stack();
|
||||||
|
let Some(attrs) = val.as_gc::<AttrSet<'_>>() else {
|
||||||
|
return Err(vm_err("value in 'with' scope must be a set"));
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(v) = attrs.lookup(name) {
|
||||||
|
root.push_stack(v);
|
||||||
|
Ok(true) // Found it
|
||||||
|
} else {
|
||||||
|
Ok(false) // Not in this scope, try the next one
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match lookup_result {
|
||||||
|
Ok(true) => break, // Successfully resolved and pushed to stack
|
||||||
|
Ok(false) => depth += 1, // Move to the parent 'with' scope
|
||||||
|
Err(e) => return Runtime::handle_vm_error(self, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadBuiltins => {
|
LoadBuiltins => {
|
||||||
|
|||||||
Reference in New Issue
Block a user