Grackle: lineTo stdlib function
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -33,6 +33,7 @@ src/wasm-lib/bindings
|
||||
src/wasm-lib/kcl/bindings
|
||||
public/wasm_lib_bg.wasm
|
||||
src/wasm-lib/lcov.info
|
||||
src/wasm-lib/grackle/*.test.json
|
||||
|
||||
e2e/playwright/playwright-secrets.env
|
||||
e2e/playwright/temp1.png
|
||||
|
||||
@ -105,6 +105,10 @@ impl BindingScope {
|
||||
"startSketchAt".into(),
|
||||
EpBinding::from(KclFunction::StartSketchAt(native_functions::sketch::StartSketchAt)),
|
||||
),
|
||||
(
|
||||
"lineTo".into(),
|
||||
EpBinding::from(KclFunction::LineTo(native_functions::sketch::LineTo)),
|
||||
),
|
||||
]),
|
||||
parent: None,
|
||||
}
|
||||
|
||||
@ -252,6 +252,7 @@ impl Planner {
|
||||
} = match callee {
|
||||
KclFunction::Id(f) => f.call(&mut self.next_addr, args)?,
|
||||
KclFunction::StartSketchAt(f) => f.call(&mut self.next_addr, args)?,
|
||||
KclFunction::LineTo(f) => f.call(&mut self.next_addr, args)?,
|
||||
KclFunction::Add(f) => f.call(&mut self.next_addr, args)?,
|
||||
KclFunction::UserDefined(f) => {
|
||||
let UserDefinedFunction {
|
||||
@ -619,6 +620,7 @@ impl Eq for UserDefinedFunction {}
|
||||
enum KclFunction {
|
||||
Id(native_functions::Id),
|
||||
StartSketchAt(native_functions::sketch::StartSketchAt),
|
||||
LineTo(native_functions::sketch::LineTo),
|
||||
Add(native_functions::Add),
|
||||
UserDefined(UserDefinedFunction),
|
||||
}
|
||||
|
||||
@ -4,4 +4,4 @@ pub mod helpers;
|
||||
pub mod stdlib_functions;
|
||||
pub mod types;
|
||||
|
||||
pub use stdlib_functions::StartSketchAt;
|
||||
pub use stdlib_functions::{LineTo, StartSketchAt};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use kittycad_execution_plan::{api_request::ApiRequest, Instruction};
|
||||
use kittycad_execution_plan::{api_request::ApiRequest, Destination, Instruction};
|
||||
use kittycad_execution_plan_traits::{Address, InMemory, Value};
|
||||
use kittycad_modeling_cmds::{
|
||||
shared::{Point3d, Point4d},
|
||||
@ -12,6 +12,82 @@ use super::{
|
||||
};
|
||||
use crate::{binding_scope::EpBinding, error::CompileError, native_functions::Callable, EvalPlan};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(Eq, PartialEq))]
|
||||
pub struct LineTo;
|
||||
|
||||
impl Callable for LineTo {
|
||||
fn call(&self, next_addr: &mut Address, args: Vec<EpBinding>) -> Result<EvalPlan, CompileError> {
|
||||
let mut instructions = Vec::new();
|
||||
let fn_name = "lineTo";
|
||||
// Get both required params.
|
||||
let mut args_iter = args.into_iter();
|
||||
let Some(to) = args_iter.next() else {
|
||||
return Err(CompileError::NotEnoughArgs {
|
||||
fn_name: fn_name.into(),
|
||||
required: 2,
|
||||
actual: 0,
|
||||
});
|
||||
};
|
||||
let Some(sketch_group) = args_iter.next() else {
|
||||
return Err(CompileError::NotEnoughArgs {
|
||||
fn_name: fn_name.into(),
|
||||
required: 2,
|
||||
actual: 1,
|
||||
});
|
||||
};
|
||||
// Check the type of both required params.
|
||||
let to = arg_point2d(to, fn_name, &mut instructions, next_addr, 0)?;
|
||||
let sg = single_binding(sketch_group, fn_name, "sketch group", 1)?;
|
||||
let id = Uuid::new_v4();
|
||||
let start_of_line = next_addr.offset(1);
|
||||
let length_of_3d_point = Point3d::<f64>::default().into_parts().len();
|
||||
instructions.extend([
|
||||
// Push the `to` 2D point onto the stack.
|
||||
Instruction::Copy {
|
||||
source: to,
|
||||
length: 2,
|
||||
destination: Destination::StackPush,
|
||||
},
|
||||
// Make it a 3D point.
|
||||
Instruction::StackExtend { data: vec![0.0.into()] },
|
||||
// Append the new path segment to memory.
|
||||
// First comes its tag.
|
||||
Instruction::SetPrimitive {
|
||||
address: start_of_line,
|
||||
value: "Line".to_owned().into(),
|
||||
},
|
||||
// Then its end
|
||||
Instruction::StackPop {
|
||||
destination: Some(start_of_line + 1),
|
||||
},
|
||||
// Then its `relative` field.
|
||||
Instruction::SetPrimitive {
|
||||
address: start_of_line + 1 + length_of_3d_point,
|
||||
value: false.into(),
|
||||
},
|
||||
// Send the ExtendPath request
|
||||
Instruction::ApiRequest(ApiRequest {
|
||||
endpoint: ModelingCmdEndpoint::ExtendPath,
|
||||
store_response: None,
|
||||
arguments: vec![
|
||||
// Path ID
|
||||
InMemory::Address(sg + SketchGroup::path_id_offset()),
|
||||
// Segment
|
||||
InMemory::Address(start_of_line),
|
||||
],
|
||||
cmd_id: id.into(),
|
||||
}),
|
||||
]);
|
||||
|
||||
// TODO: Create a new SketchGroup from the old one + add the new path, then store it.
|
||||
Ok(EvalPlan {
|
||||
instructions,
|
||||
binding: EpBinding::Single(Address::ZERO + 9999),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(Eq, PartialEq))]
|
||||
pub struct StartSketchAt;
|
||||
|
||||
@ -7,6 +7,8 @@ use uuid::Uuid;
|
||||
/// A sketch group is a collection of paths.
|
||||
#[derive(Clone, ExecutionPlanValue)]
|
||||
pub struct SketchGroup {
|
||||
// NOTE to developers
|
||||
// Do NOT reorder these fields without updating the _offset() methods below.
|
||||
/// The id of the sketch group.
|
||||
pub id: Uuid,
|
||||
/// What the sketch is on (can be a plane or a face).
|
||||
@ -26,6 +28,10 @@ pub struct SketchGroup {
|
||||
}
|
||||
|
||||
impl SketchGroup {
|
||||
/// Get the offset for the `id` field.
|
||||
pub fn path_id_offset() -> usize {
|
||||
0
|
||||
}
|
||||
pub fn set_base_path(&self, sketch_group: Address, start_point: Address, tag: Option<Address>) -> Vec<Instruction> {
|
||||
let base_path_addr = sketch_group
|
||||
+ self.id.into_parts().len()
|
||||
|
||||
@ -1048,15 +1048,35 @@ fn store_object_with_array_property() {
|
||||
#[tokio::test]
|
||||
async fn stdlib_cube_partial() {
|
||||
let program = r#"
|
||||
let cube = startSketchAt([22.0, 33.0])
|
||||
let cube = startSketchAt([0.0, 0.0])
|
||||
|> lineTo([4.0, 0.0], %)
|
||||
"#;
|
||||
let (plan, _scope) = must_plan(program);
|
||||
std::fs::write("stdlib_cube_partial.json", serde_json::to_string_pretty(&plan).unwrap()).unwrap();
|
||||
std::fs::write(
|
||||
"stdlib_cube_partial.test.json",
|
||||
serde_json::to_string_pretty(&plan).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program))
|
||||
.ast()
|
||||
.unwrap();
|
||||
let mem = crate::execute(ast, Some(test_client().await)).await.unwrap();
|
||||
dbg!(mem);
|
||||
let client = test_client().await;
|
||||
let _mem = crate::execute(ast, Some(client)).await.unwrap();
|
||||
// use kittycad_modeling_cmds::{each_cmd, ok_response::OkModelingCmdResponse, ImageFormat, ModelingCmd};
|
||||
// let out = client
|
||||
// .run_command(
|
||||
// uuid::Uuid::new_v4().into(),
|
||||
// each_cmd::TakeSnapshot {
|
||||
// format: ImageFormat::Png,
|
||||
// },
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
// let out = match out {
|
||||
// OkModelingCmdResponse::TakeSnapshot(b) => b,
|
||||
// other => panic!("wrong output: {other:?}"),
|
||||
// };
|
||||
// let out: Vec<u8> = out.contents.into();
|
||||
}
|
||||
|
||||
async fn test_client() -> Session {
|
||||
|
||||
Reference in New Issue
Block a user