feat(tvix/compiler): implement -> (implication) operator

Similar to `||`, but inverting the left-hand side.

In other words, `a -> b` is essentially rewritten as `!a || b`.

Change-Id: I8a62da65ff070b389e46048d047a54279060a97b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6152
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2022-08-11 14:54:34 +03:00 committed by tazjin
parent c7c7ab9bd4
commit 63a0cc83d1

View file

@ -149,7 +149,7 @@ impl Compiler {
match op.operator().unwrap() {
BinOpKind::And => return self.compile_and(op),
BinOpKind::Or => return self.compile_or(op),
BinOpKind::Implication => todo!(),
BinOpKind::Implication => return self.compile_implication(op),
_ => {}
};
@ -374,6 +374,26 @@ impl Compiler {
Ok(())
}
fn compile_implication(&mut self, node: rnix::types::BinOp) -> EvalResult<()> {
debug_assert!(
matches!(node.operator(), Some(BinOpKind::Implication)),
"compile_implication called with wrong operator kind: {:?}",
node.operator(),
);
// Leave left-hand side value on the stack and invert it.
self.compile(node.lhs().unwrap())?;
self.chunk.add_op(OpCode::OpInvert);
// Exactly as `||` (because `a -> b` = `!a || b`).
let end_idx = self.chunk.add_op(OpCode::OpJumpIfTrue(0));
self.chunk.add_op(OpCode::OpPop);
self.compile(node.rhs().unwrap())?;
self.patch_jump(end_idx);
Ok(())
}
fn patch_jump(&mut self, idx: CodeIdx) {
let offset = self.chunk.code.len() - 1 - idx.0;