feat(tvix/compiler): compile non-interpolated string literals

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>
This commit is contained in:
Vincent Ambo 2022-08-09 17:37:38 +03:00 committed by tazjin
parent 72863d81fc
commit 3577841bde

View file

@ -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())?;