feat(tvix/eval): implement unary negation operator

Change-Id: I5d012cc073e55d79d7b34b88283aab3164864293
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6075
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
Vincent Ambo 2022-08-08 02:32:07 +03:00 committed by tazjin
parent d35ecc0caf
commit 72be759e1e
3 changed files with 35 additions and 1 deletions

View file

@ -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> {

View file

@ -17,9 +17,13 @@ pub enum OpCode {
OpTrue,
OpFalse,
// Simple binary operators
// Arithmetic binary operators
OpAdd,
OpSub,
OpMul,
OpDiv,
// Unary operators
OpInvert,
OpNegate,
}

View file

@ -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!(),