Grackle: unary operations (#1308)

Support compiling logical not and sign-flipping negation.
This commit is contained in:
Adam Chalmers
2024-01-23 13:57:09 +11:00
committed by GitHub
parent 4903f6b9fc
commit e04b09fcd8
4 changed files with 82 additions and 37 deletions

View File

@ -1943,7 +1943,7 @@ dependencies = [
[[package]] [[package]]
name = "kittycad-execution-plan" name = "kittycad-execution-plan"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#9200b9540fa5ae99b692db276c625223116f467f" source = "git+https://github.com/KittyCAD/modeling-api?branch=main#935256e4a7080ea130b09b578e16820dc96e78e4"
dependencies = [ dependencies = [
"bytes", "bytes",
"insta", "insta",
@ -1972,7 +1972,7 @@ dependencies = [
[[package]] [[package]]
name = "kittycad-execution-plan-macros" name = "kittycad-execution-plan-macros"
version = "0.1.2" version = "0.1.2"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#9200b9540fa5ae99b692db276c625223116f467f" source = "git+https://github.com/KittyCAD/modeling-api?branch=main#935256e4a7080ea130b09b578e16820dc96e78e4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1992,8 +1992,8 @@ dependencies = [
[[package]] [[package]]
name = "kittycad-modeling-cmds" name = "kittycad-modeling-cmds"
version = "0.1.11" version = "0.1.12"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#9200b9540fa5ae99b692db276c625223116f467f" source = "git+https://github.com/KittyCAD/modeling-api?branch=main#935256e4a7080ea130b09b578e16820dc96e78e4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -2020,7 +2020,7 @@ dependencies = [
[[package]] [[package]]
name = "kittycad-modeling-session" name = "kittycad-modeling-session"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#9200b9540fa5ae99b692db276c625223116f467f" source = "git+https://github.com/KittyCAD/modeling-api?branch=main#935256e4a7080ea130b09b578e16820dc96e78e4"
dependencies = [ dependencies = [
"futures", "futures",
"kittycad", "kittycad",

View File

@ -133,6 +133,30 @@ impl Planner {
binding: previously_bound_to.clone(), binding: previously_bound_to.clone(),
}) })
} }
SingleValue::UnaryExpression(expr) => {
let operand = self.plan_to_compute_single(SingleValue::from(expr.argument))?;
let EpBinding::Single(binding) = operand.binding else {
return Err(CompileError::InvalidOperand(
"you tried to use a composite value (e.g. array or object) as the operand to some math",
));
};
let destination = self.next_addr.offset_by(1);
let mut plan = operand.instructions;
plan.push(Instruction::UnaryArithmetic {
arithmetic: ep::UnaryArithmetic {
operation: match expr.operator {
ast::types::UnaryOperator::Neg => ep::UnaryOperation::Neg,
ast::types::UnaryOperator::Not => ep::UnaryOperation::Not,
},
operand: ep::Operand::Reference(binding),
},
destination,
});
Ok(EvalPlan {
instructions: plan,
binding: EpBinding::Single(destination),
})
}
SingleValue::BinaryExpression(expr) => { SingleValue::BinaryExpression(expr) => {
let l = self.plan_to_compute_single(SingleValue::from(expr.left))?; let l = self.plan_to_compute_single(SingleValue::from(expr.left))?;
let r = self.plan_to_compute_single(SingleValue::from(expr.right))?; let r = self.plan_to_compute_single(SingleValue::from(expr.right))?;
@ -150,13 +174,13 @@ impl Planner {
let mut plan = Vec::with_capacity(l.instructions.len() + r.instructions.len() + 1); let mut plan = Vec::with_capacity(l.instructions.len() + r.instructions.len() + 1);
plan.extend(l.instructions); plan.extend(l.instructions);
plan.extend(r.instructions); plan.extend(r.instructions);
plan.push(Instruction::Arithmetic { plan.push(Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: match expr.operator { operation: match expr.operator {
ast::types::BinaryOperator::Add => ep::Operation::Add, ast::types::BinaryOperator::Add => ep::BinaryOperation::Add,
ast::types::BinaryOperator::Sub => ep::Operation::Sub, ast::types::BinaryOperator::Sub => ep::BinaryOperation::Sub,
ast::types::BinaryOperator::Mul => ep::Operation::Mul, ast::types::BinaryOperator::Mul => ep::BinaryOperation::Mul,
ast::types::BinaryOperator::Div => ep::Operation::Div, ast::types::BinaryOperator::Div => ep::BinaryOperation::Div,
ast::types::BinaryOperator::Mod => { ast::types::BinaryOperator::Mod => {
todo!("execution plan instruction set doesn't support Mod yet") todo!("execution plan instruction set doesn't support Mod yet")
} }
@ -300,7 +324,6 @@ impl Planner {
}) })
} }
SingleValue::PipeExpression(_) => todo!(), SingleValue::PipeExpression(_) => todo!(),
SingleValue::UnaryExpression(_) => todo!(),
} }
} }

View File

@ -3,7 +3,7 @@
//! But some other stdlib functions will be written in KCL. //! But some other stdlib functions will be written in KCL.
use kcl_lib::std::sketch::PlaneData; use kcl_lib::std::sketch::PlaneData;
use kittycad_execution_plan::{Address, Arithmetic, Instruction}; use kittycad_execution_plan::{Address, BinaryArithmetic, Instruction};
use kittycad_execution_plan_traits::Value; use kittycad_execution_plan_traits::Value;
use crate::{CompileError, EpBinding, EvalPlan}; use crate::{CompileError, EpBinding, EvalPlan};
@ -98,9 +98,9 @@ impl Callable for Add {
}; };
let destination = next_address.offset_by(1); let destination = next_address.offset_by(1);
Ok(EvalPlan { Ok(EvalPlan {
instructions: vec![Instruction::Arithmetic { instructions: vec![Instruction::BinaryArithmetic {
arithmetic: Arithmetic { arithmetic: BinaryArithmetic {
operation: kittycad_execution_plan::Operation::Add, operation: kittycad_execution_plan::BinaryOperation::Add,
operand0: kittycad_execution_plan::Operand::Reference(arg0), operand0: kittycad_execution_plan::Operand::Reference(arg0),
operand1: kittycad_execution_plan::Operand::Reference(arg1), operand1: kittycad_execution_plan::Operand::Reference(arg1),
}, },

View File

@ -1,3 +1,4 @@
use ep::UnaryArithmetic;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use super::*; use super::*;
@ -157,9 +158,9 @@ fn use_native_function_add() {
address: Address::ZERO.offset(1), address: Address::ZERO.offset(1),
value: 2i64.into() value: 2i64.into()
}, },
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Add, operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(Address::ZERO), operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO.offset(1)) operand1: ep::Operand::Reference(Address::ZERO.offset(1))
}, },
@ -263,6 +264,27 @@ fn member_expressions_array() {
} }
} }
#[test]
fn compile_flipped_sign() {
let program = "let x = 3
let y = -x";
let (plan, _scope) = must_plan(program);
let expected = vec![
Instruction::SetPrimitive {
address: Address::ZERO,
value: 3i64.into(),
},
Instruction::UnaryArithmetic {
arithmetic: UnaryArithmetic {
operation: ep::UnaryOperation::Neg,
operand: ep::Operand::Reference(Address::ZERO),
},
destination: Address::ZERO + 1,
},
];
assert_eq!(plan, expected);
}
#[test] #[test]
fn add_literals() { fn add_literals() {
let program = "let x = 1 + 2"; let program = "let x = 1 + 2";
@ -278,9 +300,9 @@ fn add_literals() {
address: Address::ZERO.offset(1), address: Address::ZERO.offset(1),
value: 2i64.into() value: 2i64.into()
}, },
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Add, operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(Address::ZERO), operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO.offset(1)), operand1: ep::Operand::Reference(Address::ZERO.offset(1)),
}, },
@ -310,9 +332,9 @@ fn add_vars() {
address: addr1, address: addr1,
value: 2i64.into(), value: 2i64.into(),
}, },
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Add, operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(addr0), operand0: ep::Operand::Reference(addr0),
operand1: ep::Operand::Reference(addr1), operand1: ep::Operand::Reference(addr1),
}, },
@ -351,18 +373,18 @@ fn composite_binary_exprs() {
value: 3i64.into(), value: 3i64.into(),
}, },
// Adds 1 + 2 // Adds 1 + 2
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Add, operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(addr0), operand0: ep::Operand::Reference(addr0),
operand1: ep::Operand::Reference(addr1), operand1: ep::Operand::Reference(addr1),
}, },
destination: addr3, destination: addr3,
}, },
// Adds `x` + 3, where `x` is (1 + 2) // Adds `x` + 3, where `x` is (1 + 2)
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Add, operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(addr3), operand0: ep::Operand::Reference(addr3),
operand1: ep::Operand::Reference(addr2), operand1: ep::Operand::Reference(addr2),
}, },
@ -419,9 +441,9 @@ fn use_kcl_functions_with_optional_params() {
address: Address::ZERO + 2, address: Address::ZERO + 2,
value: 3i64.into(), value: 3i64.into(),
}, },
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Mul, operation: ep::BinaryOperation::Mul,
operand0: ep::Operand::Reference(Address::ZERO), operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO + 2) operand1: ep::Operand::Reference(Address::ZERO + 2)
}, },
@ -540,9 +562,9 @@ fn use_kcl_functions_with_params() {
address: Address::ZERO + 1, address: Address::ZERO + 1,
value: 3i64.into(), value: 3i64.into(),
}, },
Instruction::Arithmetic { Instruction::BinaryArithmetic {
arithmetic: ep::Arithmetic { arithmetic: ep::BinaryArithmetic {
operation: ep::Operation::Mul, operation: ep::BinaryOperation::Mul,
operand0: ep::Operand::Reference(Address::ZERO), operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO.offset(1)) operand1: ep::Operand::Reference(Address::ZERO.offset(1))
}, },