feat(tvix/eval): implement inherit in let expressions
Note that at this point recursive bindings do not yet work in either attrsets or let, so inheriting from the same scope is generally not possible yet. Change-Id: I6ca820d04b8ded5c22fb7ea18e2ec203bcaa8e9c Reviewed-on: https://cl.tvl.fyi/c/depot/+/6215 Reviewed-by: sterni <sternenseemann@systemli.org> Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
This commit is contained in:
parent
8c1c9aee3c
commit
f173161f4c
3 changed files with 49 additions and 14 deletions
|
@ -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)?;
|
||||
}
|
||||
|
|
1
tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp
Normal file
1
tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
8
tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix
Normal file
8
tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
let
|
||||
set = {
|
||||
a = 1;
|
||||
};
|
||||
in
|
||||
let
|
||||
inherit (set) a;
|
||||
in a
|
Loading…
Reference in a new issue