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:
parent
d35ecc0caf
commit
72be759e1e
3 changed files with 35 additions and 1 deletions
|
@ -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> {
|
||||
|
|
|
@ -17,9 +17,13 @@ pub enum OpCode {
|
|||
OpTrue,
|
||||
OpFalse,
|
||||
|
||||
// Simple binary operators
|
||||
// Arithmetic binary operators
|
||||
OpAdd,
|
||||
OpSub,
|
||||
OpMul,
|
||||
OpDiv,
|
||||
|
||||
// Unary operators
|
||||
OpInvert,
|
||||
OpNegate,
|
||||
}
|
||||
|
|
|
@ -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!(),
|
||||
|
|
Loading…
Reference in a new issue