diff options
Diffstat (limited to 'tvix/eval/src')
-rw-r--r-- | tvix/eval/src/compiler.rs | 3 | ||||
-rw-r--r-- | tvix/eval/src/opcode.rs | 3 | ||||
-rw-r--r-- | tvix/eval/src/value/mod.rs | 4 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 14 |
4 files changed, 24 insertions, 0 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs index 90a6155b6b62..1bfd765a07cd 100644 --- a/tvix/eval/src/compiler.rs +++ b/tvix/eval/src/compiler.rs @@ -350,6 +350,7 @@ impl Compiler { self.compile(node.rhs().unwrap())?; self.patch_jump(end_idx); + self.chunk.add_op(OpCode::OpAssertBool); Ok(()) } @@ -370,6 +371,7 @@ impl Compiler { self.chunk.add_op(OpCode::OpPop); self.compile(node.rhs().unwrap())?; self.patch_jump(end_idx); + self.chunk.add_op(OpCode::OpAssertBool); Ok(()) } @@ -390,6 +392,7 @@ impl Compiler { self.chunk.add_op(OpCode::OpPop); self.compile(node.rhs().unwrap())?; self.patch_jump(end_idx); + self.chunk.add_op(OpCode::OpAssertBool); Ok(()) } diff --git a/tvix/eval/src/opcode.rs b/tvix/eval/src/opcode.rs index f577bc985d3a..4831a71ebd6e 100644 --- a/tvix/eval/src/opcode.rs +++ b/tvix/eval/src/opcode.rs @@ -53,4 +53,7 @@ pub enum OpCode { // Strings OpInterpolate(usize), + + // Type assertion operators + OpAssertBool, } diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 4a343797480e..99eb4c657ba5 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -91,6 +91,10 @@ impl Value { }), } } + + pub fn is_bool(&self) -> bool { + matches!(self, Value::Bool(_)) + } } impl Display for Value { diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index ed040cf91743..3e8509187b4d 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -187,6 +187,20 @@ impl VM { self.ip += offset; } } + + // These assertion operations error out if the stack + // top is not of the expected type. This is necessary + // to implement some specific behaviours of Nix + // exactly. + OpCode::OpAssertBool => { + let val = self.peek(0); + if !val.is_bool() { + return Err(Error::TypeError { + expected: "bool", + actual: val.type_of(), + }); + } + } } if self.ip == self.chunk.code.len() { |