feat(tvix/eval): Implement OpResolveWith instruction
Change-Id: I4d2a69f28a6b6199b3ff48ef81135e7da9fe1c3b Reviewed-on: https://cl.tvl.fyi/c/depot/+/6222 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org> Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
parent
911fb96eca
commit
59f50dc81a
3 changed files with 24 additions and 1 deletions
|
@ -28,6 +28,9 @@ pub enum Error {
|
||||||
|
|
||||||
// Unknown variable in statically known scope.
|
// Unknown variable in statically known scope.
|
||||||
UnknownStaticVariable(rnix::types::Ident),
|
UnknownStaticVariable(rnix::types::Ident),
|
||||||
|
|
||||||
|
// Unknown variable in dynamic scope (with, rec, ...).
|
||||||
|
UnknownDynamicVariable(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
|
|
|
@ -55,6 +55,7 @@ pub enum OpCode {
|
||||||
// `with`-handling
|
// `with`-handling
|
||||||
OpPushWith(usize),
|
OpPushWith(usize),
|
||||||
OpPopWith,
|
OpPopWith,
|
||||||
|
OpResolveWith,
|
||||||
|
|
||||||
// Lists
|
// Lists
|
||||||
OpList(usize),
|
OpList(usize),
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl VM {
|
||||||
#[cfg(feature = "disassembler")]
|
#[cfg(feature = "disassembler")]
|
||||||
let mut tracer = Tracer::new();
|
let mut tracer = Tracer::new();
|
||||||
|
|
||||||
loop {
|
'dispatch: loop {
|
||||||
let op = self.inc_ip();
|
let op = self.inc_ip();
|
||||||
match op {
|
match op {
|
||||||
OpCode::OpConstant(idx) => {
|
OpCode::OpConstant(idx) => {
|
||||||
|
@ -285,6 +285,25 @@ impl VM {
|
||||||
OpCode::OpPopWith => {
|
OpCode::OpPopWith => {
|
||||||
self.with_stack.pop();
|
self.with_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(Error::UnknownDynamicVariable(ident.to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "disassembler")]
|
#[cfg(feature = "disassembler")]
|
||||||
|
|
Loading…
Reference in a new issue