diff options
Diffstat (limited to 'tvix/eval')
-rw-r--r-- | tvix/eval/src/compiler.rs | 54 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp | 1 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix | 8 |
3 files changed, 49 insertions, 14 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs index 11bd649f71df..2f48a1cea8af 100644 --- a/tvix/eval/src/compiler.rs +++ b/tvix/eval/src/compiler.rs @@ -688,9 +688,36 @@ impl Compiler { // // Unless in a non-standard scope, the encountered values are // simply pushed on the stack and their indices noted in the + // entries vector. fn compile_let_in(&mut self, node: rnix::types::LetIn) -> Result<(), Error> { self.begin_scope(); let mut entries = vec![]; + let mut from_inherits = vec![]; + + for inherit in node.inherits() { + match inherit.from() { + // Within a `let` binding, inheriting from the outer + // scope is practically a no-op. + None => { + self.warnings.push(EvalWarning { + node: inherit.node().clone(), + kind: WarningKind::UselessInherit, + }); + + continue; + } + + Some(_) => { + for ident in inherit.idents() { + self.locals.locals.push(Local { + name: ident.as_str().to_string(), + depth: self.locals.scope_depth, + }); + } + from_inherits.push(inherit); + } + } + } // Before compiling the values of a let expression, all keys // need to already be added to the known locals. This is @@ -712,24 +739,23 @@ impl Compiler { }); } - for inherit in node.inherits() { - match inherit.from() { - // Within a `let` binding, inheriting from the outer - // scope is practically a no-op. - None => { - self.warnings.push(EvalWarning { - node: inherit.node().clone(), - kind: WarningKind::UselessInherit, - }); + // Now we can add instructions to look up each inherited value + // ... + for inherit in from_inherits { + let from = inherit + .from() + .expect("only inherits with `from` are pushed here"); - continue; - } - Some(_) => todo!("let inherit from attrs"), + for ident in inherit.idents() { + // TODO: Optimised multi-select instruction? + self.compile(from.inner().unwrap())?; + self.emit_literal_ident(&ident); + self.chunk.push_op(OpCode::OpAttrsSelect); } } - // Now we can compile each expression, leaving the values on - // the stack in the right order. + // ... and finally each expression, leaving the values on the + // stack in the right order. for value in entries { self.compile(value)?; } diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp @@ -0,0 +1 @@ +1 diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix new file mode 100644 index 000000000000..12eed10e13fc --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix @@ -0,0 +1,8 @@ +let + set = { + a = 1; + }; +in + let + inherit (set) a; + in a |