about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-09T14·37+0300
committertazjin <tazjin@tvl.su>2022-08-13T18·28+0000
commit3577841bdedddffb411c07ed050b25b986d1d0d6 (patch)
tree42213c84158d4263966ad91fc43ba71faae69d18
parent72863d81fcf51aed0fd5b4cffd378c30d7fbfb43 (diff)
feat(tvix/compiler): compile non-interpolated string literals r/4433
This sets up the scaffolding for compiling interpolation, but those
instructions do not yet exist.

Change-Id: Ife41bbbf432d9661abe566c92437409dd0da44e7
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6097
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
-rw-r--r--tvix/eval/src/compiler.rs35
1 files changed, 35 insertions, 0 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs
index ce3642b585..5ad8215b10 100644
--- a/tvix/eval/src/compiler.rs
+++ b/tvix/eval/src/compiler.rs
@@ -27,6 +27,11 @@ impl Compiler {
                 self.compile_literal(value.to_value().expect("TODO"))
             }
 
+            rnix::SyntaxKind::NODE_STRING => {
+                let op = rnix::types::Str::cast(node).unwrap();
+                self.compile_string(op)
+            }
+
             rnix::SyntaxKind::NODE_BIN_OP => {
                 let op = rnix::types::BinOp::cast(node).expect("TODO (should not be possible)");
                 self.compile_binop(op)
@@ -83,6 +88,36 @@ impl Compiler {
         }
     }
 
+    fn compile_string(&mut self, string: rnix::types::Str) -> EvalResult<()> {
+        let mut count = 0;
+
+        // The string parts are produced in literal order, however
+        // they need to be reversed on the stack in order to
+        // efficiently create the real string in case of
+        // interpolation.
+        for part in string.parts().into_iter().rev() {
+            count += 1;
+
+            match part {
+                // Interpolated expressions are compiled as normal and
+                // dealt with by the VM before being assembled into
+                // the final string.
+                rnix::StrPart::Ast(node) => self.compile(node)?,
+
+                rnix::StrPart::Literal(lit) => {
+                    let idx = self.chunk.add_constant(Value::String(NixString(lit)));
+                    self.chunk.add_op(OpCode::OpConstant(idx));
+                }
+            }
+        }
+
+        if count != 1 {
+            todo!("assemble string interpolation instruction")
+        }
+
+        Ok(())
+    }
+
     fn compile_binop(&mut self, op: rnix::types::BinOp) -> EvalResult<()> {
         self.compile(op.lhs().unwrap())?;
         self.compile(op.rhs().unwrap())?;