feat(tvix/eval): implement inherit
in attribute set literals
Straightforward implementation, evaluating the elements of an inherit and preparing the stack so that `OpAttrs` sees all relevant values when constructing the attribute set itself. The emitted instructions for inheriting a lot of values from the same attribute set are inefficient, but it's too early to say whether this actually matters. Change-Id: Icb55a20936d4ef77173f34433811c5fa5d2c9ecc Reviewed-on: https://cl.tvl.fyi/c/depot/+/6214 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
This commit is contained in:
parent
7db4f8d774
commit
8c1c9aee3c
5 changed files with 39 additions and 12 deletions
|
@ -152,10 +152,7 @@ impl Compiler {
|
||||||
fn compile_with_literal_ident(&mut self, node: rnix::SyntaxNode) -> EvalResult<()> {
|
fn compile_with_literal_ident(&mut self, node: rnix::SyntaxNode) -> EvalResult<()> {
|
||||||
if node.kind() == rnix::SyntaxKind::NODE_IDENT {
|
if node.kind() == rnix::SyntaxKind::NODE_IDENT {
|
||||||
let ident = rnix::types::Ident::cast(node).unwrap();
|
let ident = rnix::types::Ident::cast(node).unwrap();
|
||||||
let idx = self
|
self.emit_literal_ident(&ident);
|
||||||
.chunk
|
|
||||||
.push_constant(Value::String(ident.as_str().into()));
|
|
||||||
self.chunk.push_op(OpCode::OpConstant(idx));
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,17 +360,31 @@ impl Compiler {
|
||||||
// inherit "from the outside").
|
// inherit "from the outside").
|
||||||
for inherit in node.inherits() {
|
for inherit in node.inherits() {
|
||||||
match inherit.from() {
|
match inherit.from() {
|
||||||
Some(_from) => todo!("inherit from attrs not implemented"),
|
Some(from) => {
|
||||||
None => {
|
|
||||||
for ident in inherit.idents() {
|
for ident in inherit.idents() {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
// Leave the identifier on the stack (never
|
// First emit the identifier itself
|
||||||
// nested in case of inherits!)
|
self.emit_literal_ident(&ident);
|
||||||
let idx = self
|
|
||||||
.chunk
|
// Then emit the node that we're inheriting
|
||||||
.push_constant(Value::String(ident.as_str().into()));
|
// from.
|
||||||
self.chunk.push_op(OpCode::OpConstant(idx));
|
//
|
||||||
|
// TODO: Likely significant optimisation
|
||||||
|
// potential in having a multi-select
|
||||||
|
// instruction followed by a merge, rather
|
||||||
|
// than pushing/popping the same attrs
|
||||||
|
// potentially a lot of times.
|
||||||
|
self.compile(from.inner().unwrap())?;
|
||||||
|
self.emit_literal_ident(&ident);
|
||||||
|
self.chunk.push_op(OpCode::OpAttrsSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None => {
|
||||||
|
for ident in inherit.idents() {
|
||||||
|
count += 1;
|
||||||
|
self.emit_literal_ident(&ident);
|
||||||
|
|
||||||
match self.resolve_local(ident.as_str()) {
|
match self.resolve_local(ident.as_str()) {
|
||||||
Some(idx) => self.chunk.push_op(OpCode::OpGetLocal(idx)),
|
Some(idx) => self.chunk.push_op(OpCode::OpGetLocal(idx)),
|
||||||
|
@ -729,6 +740,16 @@ impl Compiler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit the literal string value of an identifier. Required for
|
||||||
|
// several operations related to attribute sets, where identifiers
|
||||||
|
// are used as string keys.
|
||||||
|
fn emit_literal_ident(&mut self, ident: &rnix::types::Ident) {
|
||||||
|
let idx = self
|
||||||
|
.chunk
|
||||||
|
.push_constant(Value::String(ident.as_str().into()));
|
||||||
|
self.chunk.push_op(OpCode::OpConstant(idx));
|
||||||
|
}
|
||||||
|
|
||||||
fn patch_jump(&mut self, idx: CodeIdx) {
|
fn patch_jump(&mut self, idx: CodeIdx) {
|
||||||
let offset = self.chunk.code.len() - 1 - idx.0;
|
let offset = self.chunk.code.len() - 1 - idx.0;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
15
|
|
@ -0,0 +1,2 @@
|
||||||
|
# the 'from' part of an `inherit` can be any expression.
|
||||||
|
{ inherit ({a = 15;}) a; }.a
|
|
@ -0,0 +1 @@
|
||||||
|
{ a = 15; }
|
|
@ -0,0 +1,2 @@
|
||||||
|
let a = 15;
|
||||||
|
in { inherit a; }
|
Loading…
Reference in a new issue