refactor(tvix/eval): extract attribute set inherit into helper

This will be re-used between the code paths for
recursive/non-recursive sets, and it might even be possible to unify
it with the logic for compiling `let inherit ...`.

Change-Id: I960a061048ac583a6e932e11ff6e642d9fc3093e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6464
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2022-09-05 15:46:21 +03:00 committed by tazjin
parent 5eda0fbd86
commit bb34665abd

View file

@ -17,7 +17,7 @@ mod scope;
use path_clean::PathClean;
use rnix::ast::{self, AstToken, HasEntry};
use rowan::ast::AstNode;
use rowan::ast::{AstChildren, AstNode};
use smol_str::SmolStr;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
@ -451,25 +451,20 @@ impl Compiler<'_, '_> {
self.push_op(OpCode::OpList(Count(count)), &node);
}
/// Compile attribute set literals into equivalent bytecode.
///
/// This is complicated by a number of features specific to Nix
/// attribute sets, most importantly:
///
/// 1. Keys can be dynamically constructed through interpolation.
/// 2. Keys can refer to nested attribute sets.
/// 3. Attribute sets can (optionally) be recursive.
fn compile_attr_set(&mut self, slot: LocalIdx, node: ast::AttrSet) {
if node.rec_token().is_some() {
todo!("recursive attribute sets are not yet implemented")
}
/// Compiles inherited values in an attribute set. Inherited
/// values are *always* inherited from the outer scope, even if
/// there is a matching name within a recursive attribute set.
fn compile_inherit_attrs(
&mut self,
slot: LocalIdx,
inherits: AstChildren<ast::Inherit>,
) -> usize {
// Count the number of inherited values, so that the outer
// constructor can emit the correct number of pairs when
// constructing attribute sets.
let mut count = 0;
// Inherits have to be evaluated before entering the scope of
// a potentially recursive attribute sets (i.e. we always
// inherit "from the outside").
for inherit in node.inherits() {
for inherit in inherits {
match inherit.from() {
Some(from) => {
for ident in inherit.idents() {
@ -508,6 +503,24 @@ impl Compiler<'_, '_> {
}
}
count
}
/// Compile attribute set literals into equivalent bytecode.
///
/// This is complicated by a number of features specific to Nix
/// attribute sets, most importantly:
///
/// 1. Keys can be dynamically constructed through interpolation.
/// 2. Keys can refer to nested attribute sets.
/// 3. Attribute sets can (optionally) be recursive.
fn compile_attr_set(&mut self, slot: LocalIdx, node: ast::AttrSet) {
if node.rec_token().is_some() {
todo!("recursive attribute sets are not yet implemented")
}
let mut count = self.compile_inherit_attrs(slot, node.inherits());
for kv in node.attrpath_values() {
count += 1;