feat(tvix/eval): implement simple arithmetic binary operations
Implements simple arithmetic operations (+, -, *, /). There is some scaffolding included to pop and coerce pairs of numbers, as the Nix language will let arithmetic operators apply to arbitrary pairs of number types (always resulting in floats if the types are mixed). Change-Id: I5f62c363bdea8baa6ef812cc64c5406759d257cf Reviewed-on: https://cl.tvl.fyi/c/depot/+/6074 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
parent
e96a2934ad
commit
d35ecc0caf
5 changed files with 110 additions and 5 deletions
|
|
@ -6,17 +6,18 @@ use crate::errors::EvalResult;
|
|||
use crate::opcode::OpCode;
|
||||
use crate::value::Value;
|
||||
use rnix;
|
||||
use rnix::types::TypedNode;
|
||||
|
||||
struct Compiler {
|
||||
chunk: Chunk,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
fn compile(&mut self, node: &rnix::SyntaxNode) -> EvalResult<()> {
|
||||
fn compile(&mut self, node: rnix::SyntaxNode) -> EvalResult<()> {
|
||||
match node.kind() {
|
||||
// Root of a file contains no content, it's just a marker
|
||||
// type.
|
||||
rnix::SyntaxKind::NODE_ROOT => self.compile(&node.first_child().expect("TODO")),
|
||||
rnix::SyntaxKind::NODE_ROOT => self.compile(node.first_child().expect("TODO")),
|
||||
|
||||
// Literals contain a single token comprising of the
|
||||
// literal itself.
|
||||
|
|
@ -25,6 +26,11 @@ impl Compiler {
|
|||
self.compile_literal(token)
|
||||
}
|
||||
|
||||
rnix::SyntaxKind::NODE_BIN_OP => {
|
||||
let op = rnix::types::BinOp::cast(node).expect("TODO (should not be possible)");
|
||||
self.compile_binop(op)
|
||||
}
|
||||
|
||||
kind => {
|
||||
println!("visiting unsupported node: {:?}", kind);
|
||||
Ok(())
|
||||
|
|
@ -52,6 +58,25 @@ impl Compiler {
|
|||
rnix::NixValue::Path(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_binop(&mut self, op: rnix::types::BinOp) -> EvalResult<()> {
|
||||
self.compile(op.lhs().unwrap())?;
|
||||
self.compile(op.rhs().unwrap())?;
|
||||
|
||||
use rnix::types::BinOpKind;
|
||||
|
||||
let opcode = match op.operator().unwrap() {
|
||||
BinOpKind::Add => OpCode::OpAdd,
|
||||
BinOpKind::Sub => OpCode::OpSub,
|
||||
BinOpKind::Mul => OpCode::OpMul,
|
||||
BinOpKind::Div => OpCode::OpDiv,
|
||||
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
self.chunk.add_op(opcode);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile(ast: rnix::AST) -> EvalResult<Chunk> {
|
||||
|
|
@ -59,7 +84,7 @@ pub fn compile(ast: rnix::AST) -> EvalResult<Chunk> {
|
|||
chunk: Chunk::default(),
|
||||
};
|
||||
|
||||
c.compile(&ast.node())?;
|
||||
c.compile(ast.node())?;
|
||||
|
||||
Ok(c.chunk)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue