diff --git a/src/wasm-lib/grackle/src/error.rs b/src/wasm-lib/grackle/src/error.rs new file mode 100644 index 000000000..44e51bebe --- /dev/null +++ b/src/wasm-lib/grackle/src/error.rs @@ -0,0 +1,56 @@ +use kcl_lib::ast::types::RequiredParamAfterOptionalParam; +use kittycad_execution_plan::ExecutionError; + +use crate::String2; + +#[derive(Debug, thiserror::Error, PartialEq, Clone)] +pub enum CompileError { + #[error("the name {name} was not defined")] + Undefined { name: String }, + #[error("the function {fn_name} requires at least {required} arguments but you only supplied {actual}")] + NotEnoughArgs { + fn_name: String2, + required: usize, + actual: usize, + }, + #[error("the function {fn_name} accepts at most {maximum} arguments but you supplied {actual}")] + TooManyArgs { + fn_name: String2, + maximum: usize, + actual: usize, + }, + #[error("you tried to call {name} but it's not a function")] + NotCallable { name: String }, + #[error("you're trying to use an operand that isn't compatible with the given arithmetic operator: {0}")] + InvalidOperand(&'static str), + #[error("you cannot use the value {0} as an index")] + InvalidIndex(String), + #[error("you tried to index into a value that isn't an array. Only arrays have numeric indices!")] + CannotIndex, + #[error("you tried to get the element {i} but that index is out of bounds. The array only has a length of {len}")] + IndexOutOfBounds { i: usize, len: usize }, + #[error("you tried to access the property of a value that doesn't have any properties")] + NoProperties, + #[error("you tried to access a property of an array, but arrays don't have properties. They do have numeric indexes though, try using an index e.g. [0]")] + ArrayDoesNotHaveProperties, + #[error( + "you tried to read the '.{property}' of an object, but the object doesn't have any properties with that key" + )] + UndefinedProperty { property: String }, + #[error("{0}")] + BadParamOrder(RequiredParamAfterOptionalParam), + #[error("A KCL function cannot have anything after its return value")] + MultipleReturns, + #[error("A KCL function must end with a return statement, but your function doesn't have one.")] + NoReturnStmt, + #[error("You used the %, which means \"substitute this argument for the value to the left in this |> pipeline\". But there is no such value, because you're not calling a pipeline.")] + NotInPipeline, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0}")] + Compile(#[from] CompileError), + #[error("{0}")] + Execution(#[from] ExecutionError), +} diff --git a/src/wasm-lib/grackle/src/lib.rs b/src/wasm-lib/grackle/src/lib.rs index 11f97309c..3a73c9905 100644 --- a/src/wasm-lib/grackle/src/lib.rs +++ b/src/wasm-lib/grackle/src/lib.rs @@ -1,4 +1,5 @@ mod binding_scope; +mod error; mod kcl_value_group; mod native_functions; #[cfg(test)] @@ -8,15 +9,16 @@ use std::collections::HashMap; use kcl_lib::{ ast, - ast::types::{BodyItem, FunctionExpressionParts, KclNone, LiteralValue, Program, RequiredParamAfterOptionalParam}, + ast::types::{BodyItem, FunctionExpressionParts, KclNone, LiteralValue, Program}, }; use kittycad_execution_plan as ep; -use kittycad_execution_plan::{Address, ExecutionError, Instruction}; +use kittycad_execution_plan::{Address, Instruction}; use kittycad_execution_plan_traits as ept; use kittycad_execution_plan_traits::NumericPrimitive; use kittycad_modeling_session::Session; use self::binding_scope::{BindingScope, EpBinding, GetFnResult}; +use self::error::{CompileError, Error}; use self::kcl_value_group::{KclValueGroup, SingleValue}; /// Execute a KCL program by compiling into an execution plan, then running that. @@ -540,58 +542,6 @@ impl Planner { } } -#[derive(Debug, thiserror::Error, PartialEq, Clone)] -pub enum CompileError { - #[error("the name {name} was not defined")] - Undefined { name: String }, - #[error("the function {fn_name} requires at least {required} arguments but you only supplied {actual}")] - NotEnoughArgs { - fn_name: String2, - required: usize, - actual: usize, - }, - #[error("the function {fn_name} accepts at most {maximum} arguments but you supplied {actual}")] - TooManyArgs { - fn_name: String2, - maximum: usize, - actual: usize, - }, - #[error("you tried to call {name} but it's not a function")] - NotCallable { name: String }, - #[error("you're trying to use an operand that isn't compatible with the given arithmetic operator: {0}")] - InvalidOperand(&'static str), - #[error("you cannot use the value {0} as an index")] - InvalidIndex(String), - #[error("you tried to index into a value that isn't an array. Only arrays have numeric indices!")] - CannotIndex, - #[error("you tried to get the element {i} but that index is out of bounds. The array only has a length of {len}")] - IndexOutOfBounds { i: usize, len: usize }, - #[error("you tried to access the property of a value that doesn't have any properties")] - NoProperties, - #[error("you tried to access a property of an array, but arrays don't have properties. They do have numeric indexes though, try using an index e.g. [0]")] - ArrayDoesNotHaveProperties, - #[error( - "you tried to read the '.{property}' of an object, but the object doesn't have any properties with that key" - )] - UndefinedProperty { property: String }, - #[error("{0}")] - BadParamOrder(RequiredParamAfterOptionalParam), - #[error("A KCL function cannot have anything after its return value")] - MultipleReturns, - #[error("A KCL function must end with a return statement, but your function doesn't have one.")] - NoReturnStmt, - #[error("You used the %, which means \"substitute this argument for the value to the left in this |> pipeline\". But there is no such value, because you're not calling a pipeline.")] - NotInPipeline, -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("{0}")] - Compile(#[from] CompileError), - #[error("{0}")] - Execution(#[from] ExecutionError), -} - /// Every KCL literal value is equivalent to an Execution Plan value, and therefore can be /// bound to some KCL name and Execution Plan address. fn kcl_literal_to_kcep_literal(expr: LiteralValue) -> ept::Primitive {