Refactor: move point-parsing into its own function (#1590)
This will be reused in future stdlib functions. Also, add a field for argument number to the "invalid argument type" error message.
This commit is contained in:
@ -45,11 +45,12 @@ pub enum CompileError {
|
||||
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,
|
||||
#[error("The function '{fn_name}' expects a parameter of type {expected} but you supplied {actual}")]
|
||||
#[error("The function '{fn_name}' expects a parameter of type {expected} as argument number {arg_number} but you supplied {actual}")]
|
||||
ArgWrongType {
|
||||
fn_name: &'static str,
|
||||
expected: &'static str,
|
||||
actual: String,
|
||||
arg_number: usize,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -35,23 +35,31 @@ pub fn stack_api_call<const N: usize>(
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn single_binding(b: EpBinding, fn_name: &'static str, expected: &'static str) -> Result<Address, CompileError> {
|
||||
pub fn single_binding(
|
||||
b: EpBinding,
|
||||
fn_name: &'static str,
|
||||
expected: &'static str,
|
||||
arg_number: usize,
|
||||
) -> Result<Address, CompileError> {
|
||||
match b {
|
||||
EpBinding::Single(a) => Ok(a),
|
||||
EpBinding::Sequence { .. } => Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: "array".to_owned(),
|
||||
arg_number,
|
||||
}),
|
||||
EpBinding::Map { .. } => Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: "object".to_owned(),
|
||||
arg_number,
|
||||
}),
|
||||
EpBinding::Function(_) => Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: "function".to_owned(),
|
||||
arg_number,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -60,6 +68,7 @@ pub fn sequence_binding(
|
||||
b: EpBinding,
|
||||
fn_name: &'static str,
|
||||
expected: &'static str,
|
||||
arg_number: usize,
|
||||
) -> Result<Vec<EpBinding>, CompileError> {
|
||||
match b {
|
||||
EpBinding::Sequence { elements, .. } => Ok(elements),
|
||||
@ -67,16 +76,60 @@ pub fn sequence_binding(
|
||||
fn_name,
|
||||
expected,
|
||||
actual: "single".to_owned(),
|
||||
arg_number,
|
||||
}),
|
||||
EpBinding::Map { .. } => Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: "object".to_owned(),
|
||||
arg_number,
|
||||
}),
|
||||
EpBinding::Function(_) => Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: "function".to_owned(),
|
||||
arg_number,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract a 2D point from an argument to a Cabble.
|
||||
pub fn arg_point2d(
|
||||
arg: EpBinding,
|
||||
fn_name: &'static str,
|
||||
instructions: &mut Vec<Instruction>,
|
||||
next_addr: &mut Address,
|
||||
arg_number: usize,
|
||||
) -> Result<Address, CompileError> {
|
||||
let expected = "2D point (array with length 2)";
|
||||
let elements = sequence_binding(arg, "startSketchAt", "an array of length 2", arg_number)?;
|
||||
if elements.len() != 2 {
|
||||
return Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: format!("array of length {}", elements.len()),
|
||||
arg_number: 0,
|
||||
});
|
||||
}
|
||||
// KCL stores points as an array.
|
||||
// KC API stores them as Rust objects laid flat out in memory.
|
||||
let start = next_addr.offset_by(2);
|
||||
let start_x = start;
|
||||
let start_y = start + 1;
|
||||
let start_z = start + 2;
|
||||
instructions.extend([
|
||||
Instruction::Copy {
|
||||
source: single_binding(elements[0].clone(), "startSketchAt", "number", arg_number)?,
|
||||
destination: start_x,
|
||||
},
|
||||
Instruction::Copy {
|
||||
source: single_binding(elements[1].clone(), "startSketchAt", "number", arg_number)?,
|
||||
destination: start_y,
|
||||
},
|
||||
Instruction::SetPrimitive {
|
||||
address: start_z,
|
||||
value: 0.0.into(),
|
||||
},
|
||||
]);
|
||||
Ok(start)
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ use kittycad_modeling_cmds::{
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{
|
||||
helpers::{no_arg_api_call, sequence_binding, single_binding, stack_api_call},
|
||||
helpers::{arg_point2d, no_arg_api_call, single_binding, stack_api_call},
|
||||
types::{Axes, BasePath, Plane, SketchGroup},
|
||||
};
|
||||
use crate::{binding_scope::EpBinding, error::CompileError, native_functions::Callable, EvalPlan};
|
||||
@ -28,42 +28,10 @@ impl Callable for StartSketchAt {
|
||||
actual: 0,
|
||||
});
|
||||
};
|
||||
let start_point = {
|
||||
let expected = "2D point (array with length 2)";
|
||||
let fn_name = "startSketchAt";
|
||||
let elements = sequence_binding(start, "startSketchAt", "an array of length 2")?;
|
||||
if elements.len() != 2 {
|
||||
return Err(CompileError::ArgWrongType {
|
||||
fn_name,
|
||||
expected,
|
||||
actual: format!("array of length {}", elements.len()),
|
||||
});
|
||||
}
|
||||
// KCL stores points as an array.
|
||||
// KC API stores them as Rust objects laid flat out in memory.
|
||||
let start = next_addr.offset_by(2);
|
||||
let start_x = start;
|
||||
let start_y = start + 1;
|
||||
let start_z = start + 2;
|
||||
instructions.extend([
|
||||
Instruction::Copy {
|
||||
source: single_binding(elements[0].clone(), "startSketchAt (first parameter, elem 0)", "number")?,
|
||||
destination: start_x,
|
||||
},
|
||||
Instruction::Copy {
|
||||
source: single_binding(elements[1].clone(), "startSketchAt (first parameter, elem 1)", "number")?,
|
||||
destination: start_y,
|
||||
},
|
||||
Instruction::SetPrimitive {
|
||||
address: start_z,
|
||||
value: 0.0.into(),
|
||||
},
|
||||
]);
|
||||
start
|
||||
};
|
||||
let start_point = arg_point2d(start, "startSketchAt", &mut instructions, next_addr, 0)?;
|
||||
let tag = match args_iter.next() {
|
||||
None => None,
|
||||
Some(b) => Some(single_binding(b, "startSketchAt", "a single string")?),
|
||||
Some(b) => Some(single_binding(b, "startSketchAt", "a single string", 1)?),
|
||||
};
|
||||
|
||||
// Define some constants:
|
||||
|
||||
Reference in New Issue
Block a user