From ee54ab88955657cdb86f564d35ee7da2658eaf18 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sat, 4 Apr 2026 09:51:57 +0800 Subject: [PATCH] implement WithLookup --- fix/src/runtime/vm.rs | 56 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/fix/src/runtime/vm.rs b/fix/src/runtime/vm.rs index 5e533b2..d596a5a 100644 --- a/fix/src/runtime/vm.rs +++ b/fix/src/runtime/vm.rs @@ -891,8 +891,60 @@ impl Runtime { root.with_scope = scope.prev; }), WithLookup => { - let _name = self.read_string_id(); - todo!("implement WithLookup (force with_scope)"); + let name = self.read_string_id(); + 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::>() 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 => {