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