diff options
author | Vincent Ambo <mail@tazj.in> | 2022-09-05T12·46+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-11T12·04+0000 |
commit | bb34665abdf82227abdf0fc726abe2df57f3193e (patch) | |
tree | bca576028e5eda7fcd5ba00d6425ade847657712 /tvix/eval/src/compiler/mod.rs | |
parent | 5eda0fbd8668fceb9bfa01a03990b573e59cc17b (diff) |
refactor(tvix/eval): extract attribute set inherit into helper r/4792
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>
Diffstat (limited to '')
-rw-r--r-- | tvix/eval/src/compiler/mod.rs | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index 3fd43db53c93..6be2a1fb05a5 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -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; |