diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-11T14·23+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-08-26T15·06+0000 |
commit | dd8f5f1dc8e314b1908d90620f69efed2b284072 (patch) | |
tree | c056a2489c8fd95dd15dc44fb8c5b944945be768 /tvix | |
parent | cf3e3b784bc322c7e2f032b0c803e42524bede38 (diff) |
feat(tvix/eval): implement nested '?' operator r/4496
Implements the nested presence check operator for attribuet sets by traversing the chain of lookups through instructions that push/pop sequentially deeper attribute sets onto the stack. Note that this commit introduces a bug in case of nested attributes not being found, which is fixed in a later commit. Change-Id: Ic8b4c8648736f6cb048e3aa52592e4d075bf0544 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6163 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org> Reviewed-by: grfn <grfn@gws.fyi>
Diffstat (limited to 'tvix')
-rw-r--r-- | tvix/eval/src/compiler.rs | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs index 1d56e227f41d..b9e850a36b7e 100644 --- a/tvix/eval/src/compiler.rs +++ b/tvix/eval/src/compiler.rs @@ -448,22 +448,34 @@ impl Compiler { // // Otherwise, the right hand side is the (only) key expression // itself and can be compiled directly. - let rhs = node.rhs().unwrap(); + let mut next = node.rhs().unwrap(); + let mut fragments = vec![]; + + loop { + if matches!(next.kind(), rnix::SyntaxKind::NODE_SELECT) { + // Keep nesting deeper until we encounter something + // different than `NODE_SELECT` on the left side. This is + // required because `rnix` parses nested keys as select + // expressions, instead of as a key expression. + // + // The parsed tree will nest something like `a.b.c.d.e.f` + // as (((((a, b), c), d), e), f). + fragments.push(next.last_child().unwrap()); + next = next.first_child().unwrap(); + } else { + self.compile_with_literal_ident(next)?; + + for fragment in fragments.into_iter().rev() { + println!("fragment: {}", fragment); + self.chunk.add_op(OpCode::OpAttrsSelect); + self.compile_with_literal_ident(fragment)?; + } - if matches!(rhs.kind(), rnix::SyntaxKind::NODE_SELECT) { - // Keep nesting deeper until we encounter something - // different than `NODE_SELECT` on the left side. This is - // required because `rnix` parses nested keys as select - // expressions, instead of as a key expression. - // - // The parsed tree will nest something like `a.b.c.d.e.f` - // as (((((a, b), c), d), e), f). - todo!("nested '?' check") - } else { - self.compile_with_literal_ident(rhs)?; + self.chunk.add_op(OpCode::OpAttrsIsSet); + break; + } } - self.chunk.add_op(OpCode::OpAttrsIsSet); Ok(()) } |