diff options
-rw-r--r-- | tvix/eval/src/compiler.rs | 18 | ||||
-rw-r--r-- | tvix/eval/src/opcode.rs | 6 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 12 |
3 files changed, 35 insertions, 1 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs index 65b97cd56ccc..d71eda43aa36 100644 --- a/tvix/eval/src/compiler.rs +++ b/tvix/eval/src/compiler.rs @@ -31,6 +31,11 @@ impl Compiler { self.compile_binop(op) } + rnix::SyntaxKind::NODE_UNARY_OP => { + let op = rnix::types::UnaryOp::cast(node).expect("TODO: (should not be possible)"); + self.compile_unary_op(op) + } + kind => { println!("visiting unsupported node: {:?}", kind); Ok(()) @@ -77,6 +82,19 @@ impl Compiler { self.chunk.add_op(opcode); Ok(()) } + + fn compile_unary_op(&mut self, op: rnix::types::UnaryOp) -> EvalResult<()> { + self.compile(op.value().unwrap())?; + + use rnix::types::UnaryOpKind; + let opcode = match op.operator() { + UnaryOpKind::Invert => OpCode::OpInvert, + UnaryOpKind::Negate => OpCode::OpNegate, + }; + + self.chunk.add_op(opcode); + Ok(()) + } } pub fn compile(ast: rnix::AST) -> EvalResult<Chunk> { diff --git a/tvix/eval/src/opcode.rs b/tvix/eval/src/opcode.rs index 307b695f6d9b..0aa252c4cc08 100644 --- a/tvix/eval/src/opcode.rs +++ b/tvix/eval/src/opcode.rs @@ -17,9 +17,13 @@ pub enum OpCode { OpTrue, OpFalse, - // Simple binary operators + // Arithmetic binary operators OpAdd, OpSub, OpMul, OpDiv, + + // Unary operators + OpInvert, + OpNegate, } diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 077acfcc1b8d..da79867ef3f0 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -81,6 +81,18 @@ impl VM { NumberPair::Integer(i1, i2) => self.push(Value::Integer(i1 / i2)), }, + OpCode::OpNegate => match self.pop() { + Value::Integer(i) => self.push(Value::Integer(-i)), + Value::Float(f) => self.push(Value::Float(-f)), + v => { + return Err(Error::TypeError { + expected: "number (either int or float)", + actual: v.type_of(), + }) + } + }, + + OpCode::OpInvert => todo!(), OpCode::OpNull => todo!(), OpCode::OpTrue => todo!(), OpCode::OpFalse => todo!(), |