diff options
author | Vincent Ambo <mail@tazj.in> | 2022-09-16T16·35+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-16T18·12+0000 |
commit | 20230e1e2ddea5fd6e65d6d263444c46dc5e43db (patch) | |
tree | a301f194c26d595308ae72f9669aebcf9031aeb8 /tvix/eval/src/compiler/attrs.rs | |
parent | a7e280ec004df8c9f38afa5cc3629b632e2b55ca (diff) |
feat(tvix/eval): implement recursive attribute sets r/4876
Yep. This is kind of ugly right now. The idea is that the recursive_scope compilation function is used for recursive sets as well by emitting the keys. The rest of the logic is pretty much identical. There is quite a lot of code here that can be cleaned up (duplication between attrs and let, duplication inside of the recursive scope compilation function etc.), but I'd like to get it working first and then make it nice. Note that nested keys are *not* supported yet. Change-Id: I45c7cdd5f0e1d35fd94797093904740af3a97134 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6610 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/compiler/attrs.rs')
-rw-r--r-- | tvix/eval/src/compiler/attrs.rs | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/tvix/eval/src/compiler/attrs.rs b/tvix/eval/src/compiler/attrs.rs index b5ebfe23998f..e2e932953b7c 100644 --- a/tvix/eval/src/compiler/attrs.rs +++ b/tvix/eval/src/compiler/attrs.rs @@ -215,25 +215,23 @@ impl Compiler<'_, '_> { /// 2. Keys can refer to nested attribute sets. /// 3. Attribute sets can (optionally) be recursive. pub(super) fn compile_attr_set(&mut self, slot: LocalIdx, node: ast::AttrSet) { - if node.rec_token().is_some() { - let span = self.span_for(&node); - self.emit_warning( - span, - WarningKind::NotImplemented("recursive attribute sets"), - ); - } - // Open a scope to track the positions of the temporaries used // by the `OpAttrs` instruction. self.scope_mut().begin_scope(); - let mut count = self.compile_inherit_attrs(slot, node.inherits()); + if node.rec_token().is_some() { + self.compile_recursive_scope(slot, true, &node); + self.push_op(OpCode::OpAttrs(Count(node.entries().count())), &node); + } else { + let mut count = self.compile_inherit_attrs(slot, node.inherits()); - let dynamic_entries = self.compile_static_attr_entries(&mut count, node.attrpath_values()); + let dynamic_entries = + self.compile_static_attr_entries(&mut count, node.attrpath_values()); - self.compile_dynamic_attr_entries(&mut count, dynamic_entries); + self.compile_dynamic_attr_entries(&mut count, dynamic_entries); - self.push_op(OpCode::OpAttrs(Count(count)), &node); + self.push_op(OpCode::OpAttrs(Count(count)), &node); + } // Remove the temporary scope, but do not emit any additional // cleanup (OpAttrs consumes all of these locals). |