From dd8f5f1dc8e314b1908d90620f69efed2b284072 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Thu, 11 Aug 2022 17:23:08 +0300 Subject: feat(tvix/eval): implement nested '?' operator 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 Reviewed-by: grfn --- tvix/eval/src/compiler.rs | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'tvix/eval/src/compiler.rs') diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs index 1d56e227f4..b9e850a36b 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(()) } -- cgit 1.4.1