about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval')
-rw-r--r--tvix/eval/src/compiler.rs22
1 files changed, 21 insertions, 1 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs
index b8ade621743c..90a6155b6b62 100644
--- a/tvix/eval/src/compiler.rs
+++ b/tvix/eval/src/compiler.rs
@@ -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;