diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-27T00·17+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-04T17·40+0000 |
commit | 10b0879c009098d3c5f9fe21067ff656a29442a5 (patch) | |
tree | 1e38d06f69e690571032135c9890efe4430907f3 /tvix | |
parent | 7c2fdefcd8ff693be1afd15a08958f09d07a0e91 (diff) |
fix(tvix/eval): ensure OpResolveWith can be traced r/4634
The previous implementation of OpResolveWith manually controlled the loop iteration, which skipped over the disassembler's tracing instruction. Instead, the resolution of dynamic variables has been delegated to a new helper function. This has the additional benefit that the loop labels are no longer required, making things a bit cleaner. Change-Id: If22b74c3d49c74bf3a1ec4497cb761a9ee6cf2a4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6298 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix')
-rw-r--r-- | tvix/eval/src/vm.rs | 32 |
1 files changed, 16 insertions, 16 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index c851ad83ccad..4ce3505cdb9a 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -126,7 +126,7 @@ impl VM { #[cfg(feature = "disassembler")] let mut tracer = Tracer::new(); - 'dispatch: loop { + loop { if self.frame().ip == self.chunk().code.len() { // If this is the end of the top-level function, // return, otherwise pop the call frame. @@ -330,21 +330,8 @@ impl VM { OpCode::OpResolveWith => { let ident = self.pop().to_string()?; - - // Attempt to resolve the variable, starting at - // the back of the with_stack. - 'with: for idx in self.with_stack.iter().rev() { - let with = self.stack[*idx].as_attrs()?; - match with.select(ident.as_str()) { - None => continue 'with, - Some(val) => { - self.push(val.clone()); - continue 'dispatch; - } - } - } - - return Err(ErrorKind::UnknownDynamicVariable(ident.to_string()).into()); + let value = self.resolve_with(ident.as_str())?; + self.push(value) } OpCode::OpAssert => { @@ -450,6 +437,19 @@ impl VM { self.push(Value::String(out.into())); Ok(()) } + + /// Resolve a dynamic identifier through the with-stack at runtime. + fn resolve_with(&self, ident: &str) -> EvalResult<Value> { + for idx in self.with_stack.iter().rev() { + let with = self.stack[*idx].as_attrs()?; + match with.select(ident) { + None => continue, + Some(val) => return Ok(val.clone()), + } + } + + Err(ErrorKind::UnknownDynamicVariable(ident.to_string()).into()) + } } // TODO: use Rc::unwrap_or_clone once it is stabilised. |