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

View File

@ -133,6 +133,30 @@ impl Planner {
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) => {
let l = self.plan_to_compute_single(SingleValue::from(expr.left))?;
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);
plan.extend(l.instructions);
plan.extend(r.instructions);
plan.push(Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
plan.push(Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: match expr.operator {
ast::types::BinaryOperator::Add => ep::Operation::Add,
ast::types::BinaryOperator::Sub => ep::Operation::Sub,
ast::types::BinaryOperator::Mul => ep::Operation::Mul,
ast::types::BinaryOperator::Div => ep::Operation::Div,
ast::types::BinaryOperator::Add => ep::BinaryOperation::Add,
ast::types::BinaryOperator::Sub => ep::BinaryOperation::Sub,
ast::types::BinaryOperator::Mul => ep::BinaryOperation::Mul,
ast::types::BinaryOperator::Div => ep::BinaryOperation::Div,
ast::types::BinaryOperator::Mod => {
todo!("execution plan instruction set doesn't support Mod yet")
}
@ -300,7 +324,6 @@ impl Planner {
})
}
SingleValue::PipeExpression(_) => todo!(),
SingleValue::UnaryExpression(_) => todo!(),
}
}

View File

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

View File

@ -1,3 +1,4 @@
use ep::UnaryArithmetic;
use pretty_assertions::assert_eq;
use super::*;
@ -157,9 +158,9 @@ fn use_native_function_add() {
address: Address::ZERO.offset(1),
value: 2i64.into()
},
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Add,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(Address::ZERO),
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]
fn add_literals() {
let program = "let x = 1 + 2";
@ -278,9 +300,9 @@ fn add_literals() {
address: Address::ZERO.offset(1),
value: 2i64.into()
},
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Add,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO.offset(1)),
},
@ -310,9 +332,9 @@ fn add_vars() {
address: addr1,
value: 2i64.into(),
},
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Add,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(addr0),
operand1: ep::Operand::Reference(addr1),
},
@ -351,18 +373,18 @@ fn composite_binary_exprs() {
value: 3i64.into(),
},
// Adds 1 + 2
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Add,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(addr0),
operand1: ep::Operand::Reference(addr1),
},
destination: addr3,
},
// Adds `x` + 3, where `x` is (1 + 2)
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Add,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Add,
operand0: ep::Operand::Reference(addr3),
operand1: ep::Operand::Reference(addr2),
},
@ -419,9 +441,9 @@ fn use_kcl_functions_with_optional_params() {
address: Address::ZERO + 2,
value: 3i64.into(),
},
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Mul,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Mul,
operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO + 2)
},
@ -540,9 +562,9 @@ fn use_kcl_functions_with_params() {
address: Address::ZERO + 1,
value: 3i64.into(),
},
Instruction::Arithmetic {
arithmetic: ep::Arithmetic {
operation: ep::Operation::Mul,
Instruction::BinaryArithmetic {
arithmetic: ep::BinaryArithmetic {
operation: ep::BinaryOperation::Mul,
operand0: ep::Operand::Reference(Address::ZERO),
operand1: ep::Operand::Reference(Address::ZERO.offset(1))
},