make stdlib functions async (#672)

* wip

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

closer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* closer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* closer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* compiles

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* connection

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix wasm

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* timeout

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* remove the drop

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* drop handle

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2023-09-20 18:27:08 -07:00
committed by GitHub
parent 888104080e
commit 6cc8af5c23
24 changed files with 492 additions and 412 deletions

View File

@ -5,6 +5,9 @@ import {
EngineCommand, EngineCommand,
} from '../lang/std/engineConnection' } from '../lang/std/engineConnection'
import { SourceRange } from 'lang/executor' import { SourceRange } from 'lang/executor'
import { Models } from '@kittycad/lib'
type WebSocketResponse = Models['OkWebSocketResponseData_type']
class MockEngineCommandManager { class MockEngineCommandManager {
constructor(mockParams: { constructor(mockParams: {
@ -23,7 +26,13 @@ class MockEngineCommandManager {
range: SourceRange range: SourceRange
command: EngineCommand command: EngineCommand
}): Promise<any> { }): Promise<any> {
return Promise.resolve() const response: WebSocketResponse = {
type: 'modeling',
data: {
modeling_response: { type: 'empty' },
},
}
return Promise.resolve(JSON.stringify(response))
} }
sendModelingCommandFromWasm( sendModelingCommandFromWasm(
id: string, id: string,

View File

@ -148,6 +148,17 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "async-recursion"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.73" version = "0.1.73"
@ -1376,9 +1387,10 @@ dependencies = [
[[package]] [[package]]
name = "kcl-lib" name = "kcl-lib"
version = "0.1.30" version = "0.1.31"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-recursion",
"async-trait", "async-trait",
"bson", "bson",
"clap", "clap",

View File

@ -79,13 +79,6 @@ fn do_stdlib_inner(
)); ));
} }
if ast.sig.asyncness.is_some() {
errors.push(Error::new_spanned(
&ast.sig.fn_token,
"stdlib functions must not be async",
));
}
if ast.sig.unsafety.is_some() { if ast.sig.unsafety.is_some() {
errors.push(Error::new_spanned( errors.push(Error::new_spanned(
&ast.sig.unsafety, &ast.sig.unsafety,
@ -118,6 +111,7 @@ fn do_stdlib_inner(
let fn_name = &ast.sig.ident; let fn_name = &ast.sig.ident;
let fn_name_str = fn_name.to_string().replace("inner_", ""); let fn_name_str = fn_name.to_string().replace("inner_", "");
let fn_name_ident = format_ident!("{}", fn_name_str); let fn_name_ident = format_ident!("{}", fn_name_str);
let boxed_fn_name_ident = format_ident!("boxed_{}", fn_name_str);
let _visibility = &ast.vis; let _visibility = &ast.vis;
let (summary_text, description_text) = extract_doc_from_attrs(&ast.attrs); let (summary_text, description_text) = extract_doc_from_attrs(&ast.attrs);
@ -204,7 +198,10 @@ fn do_stdlib_inner(
syn::FnArg::Typed(pat) => pat.ty.as_ref().into_token_stream(), syn::FnArg::Typed(pat) => pat.ty.as_ref().into_token_stream(),
}; };
let ty_string = ty.to_string().replace('&', "").replace("mut", "").replace(' ', ""); let mut ty_string = ty.to_string().replace('&', "").replace("mut", "").replace(' ', "");
if ty_string.starts_with("Args") {
ty_string = "Args".to_string();
}
let ty_string = ty_string.trim().to_string(); let ty_string = ty_string.trim().to_string();
let ty_ident = if ty_string.starts_with("Vec<") { let ty_ident = if ty_string.starts_with("Vec<") {
let ty_string = ty_string.trim_start_matches("Vec<").trim_end_matches('>'); let ty_string = ty_string.trim_start_matches("Vec<").trim_end_matches('>');
@ -305,6 +302,14 @@ fn do_stdlib_inner(
#description_doc_comment #description_doc_comment
#const_struct #const_struct
fn #boxed_fn_name_ident(
args: crate::std::Args,
) -> std::pin::Pin<
Box<dyn std::future::Future<Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>>>,
> {
Box::pin(#fn_name_ident(args))
}
impl #docs_crate::StdLibFn for #name_ident impl #docs_crate::StdLibFn for #name_ident
{ {
fn name(&self) -> String { fn name(&self) -> String {
@ -348,7 +353,7 @@ fn do_stdlib_inner(
} }
fn std_lib_fn(&self) -> crate::std::StdFn { fn std_lib_fn(&self) -> crate::std::StdFn {
#fn_name_ident #boxed_fn_name_ident
} }
fn clone_box(&self) -> Box<dyn #docs_crate::StdLibFn> { fn clone_box(&self) -> Box<dyn #docs_crate::StdLibFn> {

View File

@ -7,6 +7,18 @@ pub(crate) struct Show {}
#[allow(non_upper_case_globals, missing_docs)] #[allow(non_upper_case_globals, missing_docs)]
#[doc = "Std lib function: show"] #[doc = "Std lib function: show"]
pub(crate) const Show: Show = Show {}; pub(crate) const Show: Show = Show {};
fn boxed_show(
args: crate::std::Args,
) -> std::pin::Pin<
Box<
dyn std::future::Future<
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
>,
>,
> {
Box::pin(show(args))
}
impl crate::docs::StdLibFn for Show { impl crate::docs::StdLibFn for Show {
fn name(&self) -> String { fn name(&self) -> String {
"show".to_string() "show".to_string()
@ -57,7 +69,7 @@ impl crate::docs::StdLibFn for Show {
} }
fn std_lib_fn(&self) -> crate::std::StdFn { fn std_lib_fn(&self) -> crate::std::StdFn {
show boxed_show
} }
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> { fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {

View File

@ -7,6 +7,18 @@ pub(crate) struct LineTo {}
#[allow(non_upper_case_globals, missing_docs)] #[allow(non_upper_case_globals, missing_docs)]
#[doc = "Std lib function: lineTo"] #[doc = "Std lib function: lineTo"]
pub(crate) const LineTo: LineTo = LineTo {}; pub(crate) const LineTo: LineTo = LineTo {};
fn boxed_line_to(
args: crate::std::Args,
) -> std::pin::Pin<
Box<
dyn std::future::Future<
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
>,
>,
> {
Box::pin(line_to(args))
}
impl crate::docs::StdLibFn for LineTo { impl crate::docs::StdLibFn for LineTo {
fn name(&self) -> String { fn name(&self) -> String {
"lineTo".to_string() "lineTo".to_string()
@ -65,7 +77,7 @@ impl crate::docs::StdLibFn for LineTo {
} }
fn std_lib_fn(&self) -> crate::std::StdFn { fn std_lib_fn(&self) -> crate::std::StdFn {
line_to boxed_line_to
} }
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> { fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {

View File

@ -7,6 +7,18 @@ pub(crate) struct Min {}
#[allow(non_upper_case_globals, missing_docs)] #[allow(non_upper_case_globals, missing_docs)]
#[doc = "Std lib function: min"] #[doc = "Std lib function: min"]
pub(crate) const Min: Min = Min {}; pub(crate) const Min: Min = Min {};
fn boxed_min(
args: crate::std::Args,
) -> std::pin::Pin<
Box<
dyn std::future::Future<
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
>,
>,
> {
Box::pin(min(args))
}
impl crate::docs::StdLibFn for Min { impl crate::docs::StdLibFn for Min {
fn name(&self) -> String { fn name(&self) -> String {
"min".to_string() "min".to_string()
@ -57,7 +69,7 @@ impl crate::docs::StdLibFn for Min {
} }
fn std_lib_fn(&self) -> crate::std::StdFn { fn std_lib_fn(&self) -> crate::std::StdFn {
min boxed_min
} }
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> { fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {

View File

@ -7,6 +7,18 @@ pub(crate) struct Show {}
#[allow(non_upper_case_globals, missing_docs)] #[allow(non_upper_case_globals, missing_docs)]
#[doc = "Std lib function: show"] #[doc = "Std lib function: show"]
pub(crate) const Show: Show = Show {}; pub(crate) const Show: Show = Show {};
fn boxed_show(
args: crate::std::Args,
) -> std::pin::Pin<
Box<
dyn std::future::Future<
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
>,
>,
> {
Box::pin(show(args))
}
impl crate::docs::StdLibFn for Show { impl crate::docs::StdLibFn for Show {
fn name(&self) -> String { fn name(&self) -> String {
"show".to_string() "show".to_string()
@ -52,7 +64,7 @@ impl crate::docs::StdLibFn for Show {
} }
fn std_lib_fn(&self) -> crate::std::StdFn { fn std_lib_fn(&self) -> crate::std::StdFn {
show boxed_show
} }
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> { fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {

View File

@ -1,7 +1,7 @@
[package] [package]
name = "kcl-lib" name = "kcl-lib"
description = "KittyCAD Language" description = "KittyCAD Language"
version = "0.1.30" version = "0.1.31"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
@ -9,6 +9,7 @@ license = "MIT"
[dependencies] [dependencies]
anyhow = { version = "1.0.75", features = ["backtrace"] } anyhow = { version = "1.0.75", features = ["backtrace"] }
async-recursion = "1.0.5"
async-trait = "0.1.73" async-trait = "0.1.73"
clap = { version = "4.4.3", features = ["cargo", "derive", "env", "unicode"], optional = true } clap = { version = "4.4.3", features = ["cargo", "derive", "env", "unicode"], optional = true }
dashmap = "5.5.3" dashmap = "5.5.3"

View File

@ -71,7 +71,7 @@ pub async fn modify_ast_for_sketch(
// Let's get the path info. // Let's get the path info.
let resp = engine let resp = engine
.send_modeling_cmd_get_response( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::PathGetInfo { path_id: sketch_id }, ModelingCmd::PathGetInfo { path_id: sketch_id },
@ -88,47 +88,6 @@ pub async fn modify_ast_for_sketch(
})); }));
}; };
/* // Let's try to get the children of the sketch.
let resp = engine
.send_modeling_cmd_get_response(
uuid::Uuid::new_v4(),
SourceRange::default(),
ModelingCmd::EntityGetAllChildUuids { entity_id: sketch_id },
)
.await?;
let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::EntityGetAllChildUuids { data: children_info },
} = &resp
else {
return Err(KclError::Engine(KclErrorDetails {
message: format!("Get child info response was not as expected: {:?}", resp),
source_ranges: vec![SourceRange::default()],
}));
};
println!("children_info: {:#?}", children_info);
// Let's try to get the parent id.
let resp = engine
.send_modeling_cmd_get_response(
uuid::Uuid::new_v4(),
SourceRange::default(),
ModelingCmd::EntityGetParentId { entity_id: sketch_id },
)
.await?;
let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::EntityGetParentId { data: parent_info },
} = &resp
else {
return Err(KclError::Engine(KclErrorDetails {
message: format!("Get parent id response was not as expected: {:?}", resp),
source_ranges: vec![SourceRange::default()],
}));
};
println!("parent_info: {:#?}", parent_info);*/
// Now let's get the control points for all the segments. // Now let's get the control points for all the segments.
// TODO: We should probably await all these at once so we aren't going one by one. // TODO: We should probably await all these at once so we aren't going one by one.
// But I guess this is fine for now. // But I guess this is fine for now.
@ -136,7 +95,7 @@ pub async fn modify_ast_for_sketch(
let mut control_points = Vec::new(); let mut control_points = Vec::new();
for segment in &path_info.segments { for segment in &path_info.segments {
if let Some(command_id) = &segment.command_id { if let Some(command_id) = &segment.command_id {
let h = engine.send_modeling_cmd_get_response( let h = engine.send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::CurveGetControlPoints { curve_id: *command_id }, ModelingCmd::CurveGetControlPoints { curve_id: *command_id },

View File

@ -571,11 +571,12 @@ impl BinaryPart {
} }
} }
pub fn get_result( #[async_recursion::async_recursion(?Send)]
pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this gloablly because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
@ -590,11 +591,13 @@ impl BinaryPart {
Ok(value.clone()) Ok(value.clone())
} }
BinaryPart::BinaryExpression(binary_expression) => { BinaryPart::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, &mut new_pipe_info, engine) binary_expression.get_result(memory, &mut new_pipe_info, engine).await
}
BinaryPart::CallExpression(call_expression) => {
call_expression.execute(memory, &mut new_pipe_info, engine).await
} }
BinaryPart::CallExpression(call_expression) => call_expression.execute(memory, &mut new_pipe_info, engine),
BinaryPart::UnaryExpression(unary_expression) => { BinaryPart::UnaryExpression(unary_expression) => {
unary_expression.get_result(memory, &mut new_pipe_info, engine) unary_expression.get_result(memory, &mut new_pipe_info, engine).await
} }
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(memory), BinaryPart::MemberExpression(member_expression) => member_expression.get_result(memory),
} }
@ -810,11 +813,12 @@ impl CallExpression {
) )
} }
pub fn execute( #[async_recursion::async_recursion(?Send)]
pub async fn execute(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
let fn_name = self.callee.name.clone(); let fn_name = self.callee.name.clone();
@ -828,7 +832,7 @@ impl CallExpression {
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, pipe_info, engine)? binary_expression.get_result(memory, pipe_info, engine).await?
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this gloablly because if we did and this was called inside a pipe it would
@ -836,11 +840,15 @@ impl CallExpression {
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
new_pipe_info.is_in_pipe = false; new_pipe_info.is_in_pipe = false;
call_expression.execute(memory, &mut new_pipe_info, engine)? call_expression.execute(memory, &mut new_pipe_info, engine).await?
} }
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?, Value::UnaryExpression(unary_expression) => {
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?, unary_expression.get_result(memory, pipe_info, engine).await?
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, engine)?, }
Value::ObjectExpression(object_expression) => {
object_expression.execute(memory, pipe_info, engine).await?
}
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, engine).await?,
Value::PipeExpression(pipe_expression) => { Value::PipeExpression(pipe_expression) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeExpression not implemented here: {:?}", pipe_expression), message: format!("PipeExpression not implemented here: {:?}", pipe_expression),
@ -877,20 +885,22 @@ impl CallExpression {
fn_name, source_range, fn_args fn_name, source_range, fn_args
);*/ );*/
// Attempt to call the function. // Attempt to call the function.
let mut args = crate::std::Args::new(fn_args, self.into(), engine); let args = crate::std::Args::new(fn_args, self.into(), engine.clone());
let result = func.std_lib_fn()(&mut args)?; let result = func.std_lib_fn()(args).await?;
if pipe_info.is_in_pipe { if pipe_info.is_in_pipe {
pipe_info.index += 1; pipe_info.index += 1;
pipe_info.previous_results.push(result); pipe_info.previous_results.push(result);
execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), engine) execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), engine).await
} else { } else {
Ok(result) Ok(result)
} }
} }
Function::InMemory => { Function::InMemory => {
let mem = memory.clone(); let func = memory.get(&fn_name, self.into())?;
let func = mem.get(&fn_name, self.into())?; let result = func
let result = func.call_fn(&fn_args, &mem, engine)?.ok_or_else(|| { .call_fn(fn_args, memory.clone(), engine.clone())
.await?
.ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails { KclError::UndefinedValue(KclErrorDetails {
message: format!("Result of function {} is undefined", fn_name), message: format!("Result of function {} is undefined", fn_name),
source_ranges: vec![self.into()], source_ranges: vec![self.into()],
@ -903,7 +913,7 @@ impl CallExpression {
pipe_info.index += 1; pipe_info.index += 1;
pipe_info.previous_results.push(result); pipe_info.previous_results.push(result);
execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), engine) execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), engine).await
} else { } else {
Ok(result) Ok(result)
} }
@ -1424,11 +1434,12 @@ impl ArrayExpression {
None None
} }
pub fn execute( #[async_recursion::async_recursion(?Send)]
pub async fn execute(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
let mut results = Vec::with_capacity(self.elements.len()); let mut results = Vec::with_capacity(self.elements.len());
@ -1440,7 +1451,7 @@ impl ArrayExpression {
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, pipe_info, engine)? binary_expression.get_result(memory, pipe_info, engine).await?
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this gloablly because if we did and this was called inside a pipe it would
@ -1448,12 +1459,16 @@ impl ArrayExpression {
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
new_pipe_info.is_in_pipe = false; new_pipe_info.is_in_pipe = false;
call_expression.execute(memory, &mut new_pipe_info, engine)? call_expression.execute(memory, &mut new_pipe_info, engine).await?
} }
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?, Value::UnaryExpression(unary_expression) => {
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?, unary_expression.get_result(memory, pipe_info, engine).await?
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, engine)?, }
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, engine)?, Value::ObjectExpression(object_expression) => {
object_expression.execute(memory, pipe_info, engine).await?
}
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, engine).await?,
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, engine).await?,
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
@ -1569,11 +1584,12 @@ impl ObjectExpression {
None None
} }
pub fn execute( #[async_recursion::async_recursion(?Send)]
pub async fn execute(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
let mut object = Map::new(); let mut object = Map::new();
for property in &self.properties { for property in &self.properties {
@ -1584,7 +1600,7 @@ impl ObjectExpression {
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, pipe_info, engine)? binary_expression.get_result(memory, pipe_info, engine).await?
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this gloablly because if we did and this was called inside a pipe it would
@ -1592,12 +1608,16 @@ impl ObjectExpression {
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
new_pipe_info.is_in_pipe = false; new_pipe_info.is_in_pipe = false;
call_expression.execute(memory, &mut new_pipe_info, engine)? call_expression.execute(memory, &mut new_pipe_info, engine).await?
} }
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?, Value::UnaryExpression(unary_expression) => {
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?, unary_expression.get_result(memory, pipe_info, engine).await?
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, engine)?, }
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, engine)?, Value::ObjectExpression(object_expression) => {
object_expression.execute(memory, pipe_info, engine).await?
}
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, engine).await?,
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, engine).await?,
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
@ -2005,11 +2025,12 @@ impl BinaryExpression {
None None
} }
pub fn get_result( #[async_recursion::async_recursion(?Send)]
pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this gloablly because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
@ -2019,11 +2040,13 @@ impl BinaryExpression {
let left_json_value = self let left_json_value = self
.left .left
.get_result(memory, &mut new_pipe_info, engine)? .get_result(memory, &mut new_pipe_info, engine)
.await?
.get_json_value()?; .get_json_value()?;
let right_json_value = self let right_json_value = self
.right .right
.get_result(memory, &mut new_pipe_info, engine)? .get_result(memory, &mut new_pipe_info, engine)
.await?
.get_json_value()?; .get_json_value()?;
// First check if we are doing string concatenation. // First check if we are doing string concatenation.
@ -2173,11 +2196,11 @@ impl UnaryExpression {
format!("{}{}", &self.operator, self.argument.recast(options, 0)) format!("{}{}", &self.operator, self.argument.recast(options, 0))
} }
pub fn get_result( pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this gloablly because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
@ -2188,7 +2211,8 @@ impl UnaryExpression {
let num = parse_json_number_as_f64( let num = parse_json_number_as_f64(
&self &self
.argument .argument
.get_result(memory, &mut new_pipe_info, engine)? .get_result(memory, &mut new_pipe_info, engine)
.await?
.get_json_value()?, .get_json_value()?,
self.into(), self.into(),
)?; )?;
@ -2310,16 +2334,16 @@ impl PipeExpression {
None None
} }
pub fn get_result( pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// Reset the previous results. // Reset the previous results.
pipe_info.previous_results = vec![]; pipe_info.previous_results = vec![];
pipe_info.index = 0; pipe_info.index = 0;
execute_pipe_body(memory, &self.body, pipe_info, self.into(), engine) execute_pipe_body(memory, &self.body, pipe_info, self.into(), engine).await
} }
/// Rename all identifiers that have the old name to the new given name. /// Rename all identifiers that have the old name to the new given name.
@ -2330,12 +2354,13 @@ impl PipeExpression {
} }
} }
fn execute_pipe_body( #[async_recursion::async_recursion(?Send)]
async fn execute_pipe_body(
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
body: &[Value], body: &[Value],
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
source_range: SourceRange, source_range: SourceRange,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
if pipe_info.index == body.len() { if pipe_info.index == body.len() {
pipe_info.is_in_pipe = false; pipe_info.is_in_pipe = false;
@ -2360,15 +2385,15 @@ fn execute_pipe_body(
match expression { match expression {
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
let result = binary_expression.get_result(memory, pipe_info, engine)?; let result = binary_expression.get_result(memory, pipe_info, engine).await?;
pipe_info.previous_results.push(result); pipe_info.previous_results.push(result);
pipe_info.index += 1; pipe_info.index += 1;
execute_pipe_body(memory, body, pipe_info, source_range, engine) execute_pipe_body(memory, body, pipe_info, source_range, engine).await
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
pipe_info.is_in_pipe = true; pipe_info.is_in_pipe = true;
pipe_info.body = body.to_vec(); pipe_info.body = body.to_vec();
call_expression.execute(memory, pipe_info, engine) call_expression.execute(memory, pipe_info, engine).await
} }
_ => { _ => {
// Return an error this should not happen. // Return an error this should not happen.

View File

@ -17,17 +17,11 @@ use crate::{
type WebSocketTcpWrite = futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>; type WebSocketTcpWrite = futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(dead_code)] // for the TcpReadHandle
pub struct EngineConnection { pub struct EngineConnection {
engine_req_tx: mpsc::Sender<ToEngineReq>, engine_req_tx: mpsc::Sender<ToEngineReq>,
tcp_read_handle: Arc<tokio::task::JoinHandle<Result<()>>>,
responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>, responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>,
} tcp_read_handle: Arc<TcpReadHandle>,
impl Drop for EngineConnection {
fn drop(&mut self) {
// Drop the read handle.
self.tcp_read_handle.abort();
}
} }
pub struct TcpRead { pub struct TcpRead {
@ -48,6 +42,18 @@ impl TcpRead {
} }
} }
#[derive(Debug)]
pub struct TcpReadHandle {
handle: Arc<tokio::task::JoinHandle<Result<()>>>,
}
impl Drop for TcpReadHandle {
fn drop(&mut self) {
// Drop the read handle.
self.handle.abort();
}
}
/// Requests to send to the engine, and a way to await a response. /// Requests to send to the engine, and a way to await a response.
struct ToEngineReq { struct ToEngineReq {
/// The request to send /// The request to send
@ -114,7 +120,9 @@ impl EngineConnection {
Ok(EngineConnection { Ok(EngineConnection {
engine_req_tx, engine_req_tx,
tcp_read_handle: Arc::new(tcp_read_handle), tcp_read_handle: Arc::new(TcpReadHandle {
handle: Arc::new(tcp_read_handle),
}),
responses, responses,
}) })
} }
@ -122,20 +130,7 @@ impl EngineConnection {
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl EngineManager for EngineConnection { impl EngineManager for EngineConnection {
/// Send a modeling command. async fn send_modeling_cmd(
/// Do not wait for the response message.
fn send_modeling_cmd(
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
) -> Result<(), KclError> {
futures::executor::block_on(self.send_modeling_cmd_get_response(id, source_range, cmd))?;
Ok(())
}
/// Send a modeling command and wait for the response message.
async fn send_modeling_cmd_get_response(
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
@ -146,7 +141,10 @@ impl EngineManager for EngineConnection {
// Send the request to the engine, via the actor. // Send the request to the engine, via the actor.
self.engine_req_tx self.engine_req_tx
.send(ToEngineReq { .send(ToEngineReq {
req: WebSocketRequest::ModelingCmdReq { cmd, cmd_id: id }, req: WebSocketRequest::ModelingCmdReq {
cmd: cmd.clone(),
cmd_id: id,
},
request_sent: tx, request_sent: tx,
}) })
.await .await
@ -173,8 +171,10 @@ impl EngineManager for EngineConnection {
})?; })?;
// Wait for the response. // Wait for the response.
loop { let current_time = std::time::Instant::now();
if let Some(resp) = self.responses.get(&id) { while current_time.elapsed().as_secs() < 60 {
// We pop off the responses to cleanup our mappings.
if let Some((_, resp)) = self.responses.remove(&id) {
return if let Some(data) = &resp.resp { return if let Some(data) = &resp.resp {
Ok(data.clone()) Ok(data.clone())
} else { } else {
@ -185,5 +185,10 @@ impl EngineManager for EngineConnection {
}; };
} }
} }
Err(KclError::Engine(KclErrorDetails {
message: format!("Modeling command timed out `{}`: {:?}", id, cmd),
source_ranges: vec![source_range],
}))
} }
} }

View File

@ -17,21 +17,14 @@ impl EngineConnection {
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl crate::engine::EngineManager for EngineConnection { impl crate::engine::EngineManager for EngineConnection {
fn send_modeling_cmd( async fn send_modeling_cmd(
&self,
_id: uuid::Uuid,
_source_range: crate::executor::SourceRange,
_cmd: kittycad::types::ModelingCmd,
) -> Result<(), KclError> {
Ok(())
}
async fn send_modeling_cmd_get_response(
&self, &self,
_id: uuid::Uuid, _id: uuid::Uuid,
_source_range: crate::executor::SourceRange, _source_range: crate::executor::SourceRange,
_cmd: kittycad::types::ModelingCmd, _cmd: kittycad::types::ModelingCmd,
) -> Result<OkWebSocketResponseData, KclError> { ) -> Result<OkWebSocketResponseData, KclError> {
todo!() Ok(OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {},
})
} }
} }

View File

@ -1,5 +1,6 @@
//! Functions for setting up our WebSocket and WebRTC connections for communications with the //! Functions for setting up our WebSocket and WebRTC connections for communications with the
//! engine. //! engine.
use std::sync::Arc;
use anyhow::Result; use anyhow::Result;
use kittycad::types::WebSocketRequest; use kittycad::types::WebSocketRequest;
@ -23,43 +24,20 @@ extern "C" {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EngineConnection { pub struct EngineConnection {
manager: EngineCommandManager, manager: Arc<EngineCommandManager>,
} }
impl EngineConnection { impl EngineConnection {
pub async fn new(manager: EngineCommandManager) -> Result<EngineConnection, JsValue> { pub async fn new(manager: EngineCommandManager) -> Result<EngineConnection, JsValue> {
Ok(EngineConnection { manager }) Ok(EngineConnection {
manager: Arc::new(manager),
})
} }
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl crate::engine::EngineManager for EngineConnection { impl crate::engine::EngineManager for EngineConnection {
fn send_modeling_cmd( async fn send_modeling_cmd(
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
) -> Result<(), KclError> {
let source_range_str = serde_json::to_string(&source_range).map_err(|e| {
KclError::Engine(KclErrorDetails {
message: format!("Failed to serialize source range: {:?}", e),
source_ranges: vec![source_range],
})
})?;
let ws_msg = WebSocketRequest::ModelingCmdReq { cmd, cmd_id: id };
let cmd_str = serde_json::to_string(&ws_msg).map_err(|e| {
KclError::Engine(KclErrorDetails {
message: format!("Failed to serialize modeling command: {:?}", e),
source_ranges: vec![source_range],
})
})?;
let _ = self
.manager
.sendModelingCommandFromWasm(id.to_string(), source_range_str, cmd_str);
Ok(())
}
async fn send_modeling_cmd_get_response(
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,

View File

@ -33,17 +33,8 @@ pub use conn_mock::EngineConnection;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait EngineManager: Clone { pub trait EngineManager: Clone {
/// Send a modeling command.
/// Do not wait for the response message.
fn send_modeling_cmd(
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
) -> Result<(), crate::errors::KclError>;
/// Send a modeling command and wait for the response message. /// Send a modeling command and wait for the response message.
async fn send_modeling_cmd_get_response( async fn send_modeling_cmd(
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,

View File

@ -104,7 +104,7 @@ pub enum MemoryItem {
SketchGroup(Box<SketchGroup>), SketchGroup(Box<SketchGroup>),
ExtrudeGroup(Box<ExtrudeGroup>), ExtrudeGroup(Box<ExtrudeGroup>),
#[ts(skip)] #[ts(skip)]
ExtrudeTransform(ExtrudeTransform), ExtrudeTransform(Box<ExtrudeTransform>),
#[ts(skip)] #[ts(skip)]
Function { Function {
#[serde(skip)] #[serde(skip)]
@ -134,13 +134,28 @@ pub struct ExtrudeTransform {
pub meta: Vec<Metadata>, pub meta: Vec<Metadata>,
} }
pub type MemoryFunction = fn( pub type MemoryFunction =
s: &[MemoryItem], fn(
memory: &ProgramMemory, s: Vec<MemoryItem>,
expression: &FunctionExpression, memory: ProgramMemory,
metadata: &[Metadata], expression: Box<FunctionExpression>,
engine: &mut EngineConnection, metadata: Vec<Metadata>,
) -> Result<Option<ProgramReturn>, KclError>; engine: EngineConnection,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>>>>;
fn force_memory_function<
F: Fn(
Vec<MemoryItem>,
ProgramMemory,
Box<FunctionExpression>,
Vec<Metadata>,
EngineConnection,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>>>>,
>(
f: F,
) -> F {
f
}
impl From<MemoryItem> for Vec<SourceRange> { impl From<MemoryItem> for Vec<SourceRange> {
fn from(item: MemoryItem) -> Self { fn from(item: MemoryItem) -> Self {
@ -168,24 +183,24 @@ impl MemoryItem {
} }
} }
pub fn call_fn( pub async fn call_fn(
&self, &self,
args: &[MemoryItem], args: Vec<MemoryItem>,
memory: &ProgramMemory, memory: ProgramMemory,
engine: &mut EngineConnection, engine: EngineConnection,
) -> Result<Option<ProgramReturn>, KclError> { ) -> Result<Option<ProgramReturn>, KclError> {
if let MemoryItem::Function { func, expression, meta } = self { if let MemoryItem::Function { func, expression, meta } = &self {
if let Some(func) = func { if let Some(func) = func {
func(args, memory, expression, meta, engine) func(args, memory, expression.clone(), meta.clone(), engine).await
} else { } else {
Err(KclError::Semantic(KclErrorDetails { Err(KclError::Semantic(KclErrorDetails {
message: format!("Not a function: {:?}", self), message: format!("Not a function: {:?}", expression),
source_ranges: vec![], source_ranges: vec![],
})) }))
} }
} else { } else {
Err(KclError::Semantic(KclErrorDetails { Err(KclError::Semantic(KclErrorDetails {
message: format!("not a function: {:?}", self), message: "not a in memory function".to_string(),
source_ranges: vec![], source_ranges: vec![],
})) }))
} }
@ -579,11 +594,11 @@ impl Default for PipeInfo {
} }
/// Execute a AST's program. /// Execute a AST's program.
pub fn execute( pub async fn execute(
program: crate::ast::types::Program, program: crate::ast::types::Program,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
options: BodyType, options: BodyType,
engine: &mut EngineConnection, engine: &EngineConnection,
) -> Result<ProgramMemory, KclError> { ) -> Result<ProgramMemory, KclError> {
let mut pipe_info = PipeInfo::default(); let mut pipe_info = PipeInfo::default();
@ -602,7 +617,7 @@ pub fn execute(
args.push(memory_item.clone()); args.push(memory_item.clone());
} }
Value::CallExpression(call_expr) => { Value::CallExpression(call_expr) => {
let result = call_expr.execute(memory, &mut pipe_info, engine)?; let result = call_expr.execute(memory, &mut pipe_info, engine).await?;
args.push(result); args.push(result);
} }
// We do nothing for the rest. // We do nothing for the rest.
@ -620,7 +635,7 @@ pub fn execute(
memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone())); memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
} else if let Some(func) = memory.clone().root.get(&fn_name) { } else if let Some(func) = memory.clone().root.get(&fn_name) {
let result = func.call_fn(&args, memory, engine)?; let result = func.call_fn(args.clone(), memory.clone(), engine.clone()).await?;
memory.return_ = result; memory.return_ = result;
} else { } else {
@ -646,22 +661,27 @@ pub fn execute(
memory.add(&var_name, value.clone(), source_range)?; memory.add(&var_name, value.clone(), source_range)?;
} }
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
let result = binary_expression.get_result(memory, &mut pipe_info, engine)?; let result = binary_expression.get_result(memory, &mut pipe_info, engine).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::FunctionExpression(function_expression) => { Value::FunctionExpression(function_expression) => {
memory.add( let mem_func = force_memory_function(
&var_name, |args: Vec<MemoryItem>,
MemoryItem::Function{ memory: ProgramMemory,
expression: function_expression.clone(), function_expression: Box<FunctionExpression>,
meta: vec![metadata], _metadata: Vec<Metadata>,
func: Some(|args: &[MemoryItem], memory: &ProgramMemory, function_expression: &FunctionExpression, _metadata: &[Metadata], engine: &mut EngineConnection| -> Result<Option<ProgramReturn>, KclError> { engine: EngineConnection| {
Box::pin(async move {
let mut fn_memory = memory.clone(); let mut fn_memory = memory.clone();
if args.len() != function_expression.params.len() { if args.len() != function_expression.params.len() {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("Expected {} arguments, got {}", function_expression.params.len(), args.len()), message: format!(
source_ranges: vec![function_expression.into()], "Expected {} arguments, got {}",
function_expression.params.len(),
args.len()
),
source_ranges: vec![(&function_expression).into()],
})); }));
} }
@ -674,20 +694,34 @@ pub fn execute(
)?; )?;
} }
let result = execute(function_expression.body.clone(), &mut fn_memory, BodyType::Block, engine)?; let result = execute(
function_expression.body.clone(),
&mut fn_memory,
BodyType::Block,
&engine,
)
.await?;
Ok(result.return_) Ok(result.return_)
}) })
}, },
);
memory.add(
&var_name,
MemoryItem::Function {
expression: function_expression.clone(),
meta: vec![metadata],
func: Some(mem_func),
},
source_range, source_range,
)?; )?;
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
let result = call_expression.execute(memory, &mut pipe_info, engine)?; let result = call_expression.execute(memory, &mut pipe_info, engine).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::PipeExpression(pipe_expression) => { Value::PipeExpression(pipe_expression) => {
let result = pipe_expression.get_result(memory, &mut pipe_info, engine)?; let result = pipe_expression.get_result(memory, &mut pipe_info, engine).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
@ -700,11 +734,11 @@ pub fn execute(
})); }));
} }
Value::ArrayExpression(array_expression) => { Value::ArrayExpression(array_expression) => {
let result = array_expression.execute(memory, &mut pipe_info, engine)?; let result = array_expression.execute(memory, &mut pipe_info, engine).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::ObjectExpression(object_expression) => { Value::ObjectExpression(object_expression) => {
let result = object_expression.execute(memory, &mut pipe_info, engine)?; let result = object_expression.execute(memory, &mut pipe_info, engine).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::MemberExpression(member_expression) => { Value::MemberExpression(member_expression) => {
@ -712,7 +746,7 @@ pub fn execute(
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::UnaryExpression(unary_expression) => { Value::UnaryExpression(unary_expression) => {
let result = unary_expression.get_result(memory, &mut pipe_info, engine)?; let result = unary_expression.get_result(memory, &mut pipe_info, engine).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
} }
@ -720,11 +754,11 @@ pub fn execute(
} }
BodyItem::ReturnStatement(return_statement) => match &return_statement.argument { BodyItem::ReturnStatement(return_statement) => match &return_statement.argument {
Value::BinaryExpression(bin_expr) => { Value::BinaryExpression(bin_expr) => {
let result = bin_expr.get_result(memory, &mut pipe_info, engine)?; let result = bin_expr.get_result(memory, &mut pipe_info, engine).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::UnaryExpression(unary_expr) => { Value::UnaryExpression(unary_expr) => {
let result = unary_expr.get_result(memory, &mut pipe_info, engine)?; let result = unary_expr.get_result(memory, &mut pipe_info, engine).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::Identifier(identifier) => { Value::Identifier(identifier) => {
@ -735,15 +769,15 @@ pub fn execute(
memory.return_ = Some(ProgramReturn::Value(literal.into())); memory.return_ = Some(ProgramReturn::Value(literal.into()));
} }
Value::ArrayExpression(array_expr) => { Value::ArrayExpression(array_expr) => {
let result = array_expr.execute(memory, &mut pipe_info, engine)?; let result = array_expr.execute(memory, &mut pipe_info, engine).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::ObjectExpression(obj_expr) => { Value::ObjectExpression(obj_expr) => {
let result = obj_expr.execute(memory, &mut pipe_info, engine)?; let result = obj_expr.execute(memory, &mut pipe_info, engine).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::CallExpression(call_expr) => { Value::CallExpression(call_expr) => {
let result = call_expr.execute(memory, &mut pipe_info, engine)?; let result = call_expr.execute(memory, &mut pipe_info, engine).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::MemberExpression(member_expr) => { Value::MemberExpression(member_expr) => {
@ -751,7 +785,7 @@ pub fn execute(
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeExpression(pipe_expr) => { Value::PipeExpression(pipe_expr) => {
let result = pipe_expr.get_result(memory, &mut pipe_info, engine)?; let result = pipe_expr.get_result(memory, &mut pipe_info, engine).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeSubstitution(_) => {} Value::PipeSubstitution(_) => {}
@ -774,8 +808,8 @@ mod tests {
let parser = crate::parser::Parser::new(tokens); let parser = crate::parser::Parser::new(tokens);
let program = parser.ast()?; let program = parser.ast()?;
let mut mem: ProgramMemory = Default::default(); let mut mem: ProgramMemory = Default::default();
let mut engine = EngineConnection::new().await?; let engine = EngineConnection::new().await?;
let memory = execute(program, &mut mem, BodyType::Root, &mut engine)?; let memory = execute(program, &mut mem, BodyType::Root, &engine).await?;
Ok(memory) Ok(memory)
} }

View File

@ -11,10 +11,10 @@ use crate::{
}; };
/// Extrudes by a given amount. /// Extrudes by a given amount.
pub fn extrude(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn extrude(args: Args) -> Result<MemoryItem, KclError> {
let (length, sketch_group) = args.get_number_sketch_group()?; let (length, sketch_group) = args.get_number_sketch_group()?;
let result = inner_extrude(length, sketch_group, args)?; let result = inner_extrude(length, sketch_group, args).await?;
Ok(MemoryItem::ExtrudeGroup(result)) Ok(MemoryItem::ExtrudeGroup(result))
} }
@ -23,7 +23,7 @@ pub fn extrude(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "extrude" name = "extrude"
}] }]
fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<ExtrudeGroup>, KclError> { async fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: Args) -> Result<Box<ExtrudeGroup>, KclError> {
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
let cmd = kittycad::types::ModelingCmd::Extrude { let cmd = kittycad::types::ModelingCmd::Extrude {
@ -31,7 +31,7 @@ fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: &mut Args) -
distance: length, distance: length,
cap: true, cap: true,
}; };
args.send_modeling_cmd(id, cmd)?; args.send_modeling_cmd(id, cmd).await?;
Ok(Box::new(ExtrudeGroup { Ok(Box::new(ExtrudeGroup {
id, id,
@ -46,7 +46,7 @@ fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: &mut Args) -
} }
/// Returns the extrude wall transform. /// Returns the extrude wall transform.
pub fn get_extrude_wall_transform(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn get_extrude_wall_transform(args: Args) -> Result<MemoryItem, KclError> {
let (surface_name, extrude_group) = args.get_path_name_extrude_group()?; let (surface_name, extrude_group) = args.get_path_name_extrude_group()?;
let result = inner_get_extrude_wall_transform(&surface_name, *extrude_group, args)?; let result = inner_get_extrude_wall_transform(&surface_name, *extrude_group, args)?;
Ok(MemoryItem::ExtrudeTransform(result)) Ok(MemoryItem::ExtrudeTransform(result))
@ -59,8 +59,8 @@ pub fn get_extrude_wall_transform(args: &mut Args) -> Result<MemoryItem, KclErro
fn inner_get_extrude_wall_transform( fn inner_get_extrude_wall_transform(
surface_name: &str, surface_name: &str,
extrude_group: ExtrudeGroup, extrude_group: ExtrudeGroup,
args: &mut Args, args: Args,
) -> Result<ExtrudeTransform, KclError> { ) -> Result<Box<ExtrudeTransform>, KclError> {
let surface = extrude_group.get_path_by_name(surface_name).ok_or_else(|| { let surface = extrude_group.get_path_by_name(surface_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!( message: format!(
@ -71,9 +71,9 @@ fn inner_get_extrude_wall_transform(
}) })
})?; })?;
Ok(ExtrudeTransform { Ok(Box::new(ExtrudeTransform {
position: surface.get_position(), position: surface.get_position(),
rotation: surface.get_rotation(), rotation: surface.get_rotation(),
meta: extrude_group.meta, meta: extrude_group.meta,
}) }))
} }

View File

@ -11,7 +11,7 @@ use crate::{
}; };
/// Computes the cosine of a number (in radians). /// Computes the cosine of a number (in radians).
pub fn cos(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn cos(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_cos(num)?; let result = inner_cos(num)?;
@ -27,7 +27,7 @@ fn inner_cos(num: f64) -> Result<f64, KclError> {
} }
/// Computes the sine of a number (in radians). /// Computes the sine of a number (in radians).
pub fn sin(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn sin(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_sin(num)?; let result = inner_sin(num)?;
@ -43,7 +43,7 @@ fn inner_sin(num: f64) -> Result<f64, KclError> {
} }
/// Computes the tangent of a number (in radians). /// Computes the tangent of a number (in radians).
pub fn tan(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn tan(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_tan(num)?; let result = inner_tan(num)?;
@ -59,7 +59,7 @@ fn inner_tan(num: f64) -> Result<f64, KclError> {
} }
/// Return the value of `pi`. Archimedes constant (π). /// Return the value of `pi`. Archimedes constant (π).
pub fn pi(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn pi(args: Args) -> Result<MemoryItem, KclError> {
let result = inner_pi()?; let result = inner_pi()?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
@ -74,7 +74,7 @@ fn inner_pi() -> Result<f64, KclError> {
} }
/// Computes the square root of a number. /// Computes the square root of a number.
pub fn sqrt(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn sqrt(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_sqrt(num)?; let result = inner_sqrt(num)?;
@ -90,7 +90,7 @@ fn inner_sqrt(num: f64) -> Result<f64, KclError> {
} }
/// Computes the absolute value of a number. /// Computes the absolute value of a number.
pub fn abs(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn abs(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_abs(num)?; let result = inner_abs(num)?;
@ -106,7 +106,7 @@ fn inner_abs(num: f64) -> Result<f64, KclError> {
} }
/// Computes the largest integer less than or equal to a number. /// Computes the largest integer less than or equal to a number.
pub fn floor(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn floor(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_floor(num)?; let result = inner_floor(num)?;
@ -122,7 +122,7 @@ fn inner_floor(num: f64) -> Result<f64, KclError> {
} }
/// Computes the smallest integer greater than or equal to a number. /// Computes the smallest integer greater than or equal to a number.
pub fn ceil(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn ceil(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_ceil(num)?; let result = inner_ceil(num)?;
@ -138,7 +138,7 @@ fn inner_ceil(num: f64) -> Result<f64, KclError> {
} }
/// Computes the minimum of the given arguments. /// Computes the minimum of the given arguments.
pub fn min(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn min(args: Args) -> Result<MemoryItem, KclError> {
let nums = args.get_number_array()?; let nums = args.get_number_array()?;
let result = inner_min(nums); let result = inner_min(nums);
@ -161,7 +161,7 @@ fn inner_min(args: Vec<f64>) -> f64 {
} }
/// Computes the maximum of the given arguments. /// Computes the maximum of the given arguments.
pub fn max(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn max(args: Args) -> Result<MemoryItem, KclError> {
let nums = args.get_number_array()?; let nums = args.get_number_array()?;
let result = inner_max(nums); let result = inner_max(nums);
@ -184,7 +184,7 @@ fn inner_max(args: Vec<f64>) -> f64 {
} }
/// Computes the number to a power. /// Computes the number to a power.
pub fn pow(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn pow(args: Args) -> Result<MemoryItem, KclError> {
let nums = args.get_number_array()?; let nums = args.get_number_array()?;
if nums.len() > 2 { if nums.len() > 2 {
return Err(KclError::Type(KclErrorDetails { return Err(KclError::Type(KclErrorDetails {
@ -214,7 +214,7 @@ fn inner_pow(num: f64, pow: f64) -> Result<f64, KclError> {
} }
/// Computes the arccosine of a number (in radians). /// Computes the arccosine of a number (in radians).
pub fn acos(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn acos(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_acos(num)?; let result = inner_acos(num)?;
@ -230,7 +230,7 @@ fn inner_acos(num: f64) -> Result<f64, KclError> {
} }
/// Computes the arcsine of a number (in radians). /// Computes the arcsine of a number (in radians).
pub fn asin(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn asin(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_asin(num)?; let result = inner_asin(num)?;
@ -246,7 +246,7 @@ fn inner_asin(num: f64) -> Result<f64, KclError> {
} }
/// Computes the arctangent of a number (in radians). /// Computes the arctangent of a number (in radians).
pub fn atan(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn atan(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_atan(num)?; let result = inner_atan(num)?;
@ -266,7 +266,7 @@ fn inner_atan(num: f64) -> Result<f64, KclError> {
/// The result might not be correctly rounded owing to implementation /// The result might not be correctly rounded owing to implementation
/// details; `log2()` can produce more accurate results for base 2, /// details; `log2()` can produce more accurate results for base 2,
/// and `log10()` can produce more accurate results for base 10. /// and `log10()` can produce more accurate results for base 10.
pub fn log(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn log(args: Args) -> Result<MemoryItem, KclError> {
let nums = args.get_number_array()?; let nums = args.get_number_array()?;
if nums.len() > 2 { if nums.len() > 2 {
return Err(KclError::Type(KclErrorDetails { return Err(KclError::Type(KclErrorDetails {
@ -299,7 +299,7 @@ fn inner_log(num: f64, base: f64) -> Result<f64, KclError> {
} }
/// Computes the base 2 logarithm of the number. /// Computes the base 2 logarithm of the number.
pub fn log2(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn log2(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_log2(num)?; let result = inner_log2(num)?;
@ -315,7 +315,7 @@ fn inner_log2(num: f64) -> Result<f64, KclError> {
} }
/// Computes the base 10 logarithm of the number. /// Computes the base 10 logarithm of the number.
pub fn log10(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn log10(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_log10(num)?; let result = inner_log10(num)?;
@ -331,7 +331,7 @@ fn inner_log10(num: f64) -> Result<f64, KclError> {
} }
/// Computes the natural logarithm of the number. /// Computes the natural logarithm of the number.
pub fn ln(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn ln(args: Args) -> Result<MemoryItem, KclError> {
let num = args.get_number()?; let num = args.get_number()?;
let result = inner_ln(num)?; let result = inner_ln(num)?;
@ -347,7 +347,7 @@ fn inner_ln(num: f64) -> Result<f64, KclError> {
} }
/// Return the value of Eulers number `e`. /// Return the value of Eulers number `e`.
pub fn e(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn e(args: Args) -> Result<MemoryItem, KclError> {
let result = inner_e()?; let result = inner_e()?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
@ -362,7 +362,7 @@ fn inner_e() -> Result<f64, KclError> {
} }
/// Return the value of `tau`. The full circle constant (τ). Equal to 2π. /// Return the value of `tau`. The full circle constant (τ). Equal to 2π.
pub fn tau(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn tau(args: Args) -> Result<MemoryItem, KclError> {
let result = inner_tau()?; let result = inner_tau()?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)

View File

@ -10,6 +10,7 @@ use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::OkWebSocketResponseData;
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -21,7 +22,7 @@ use crate::{
executor::{ExtrudeGroup, MemoryItem, Metadata, SketchGroup, SourceRange}, executor::{ExtrudeGroup, MemoryItem, Metadata, SketchGroup, SourceRange},
}; };
pub type StdFn = fn(&mut Args) -> Result<MemoryItem, KclError>; pub type StdFn = fn(Args) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<MemoryItem, KclError>>>>;
pub type FnMap = HashMap<String, StdFn>; pub type FnMap = HashMap<String, StdFn>;
pub struct StdLib { pub struct StdLib {
@ -102,15 +103,15 @@ impl Default for StdLib {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Args<'a> { pub struct Args {
pub args: Vec<MemoryItem>, pub args: Vec<MemoryItem>,
pub source_range: SourceRange, pub source_range: SourceRange,
engine: &'a mut EngineConnection, engine: EngineConnection,
} }
impl<'a> Args<'a> { impl Args {
pub fn new(args: Vec<MemoryItem>, source_range: SourceRange, engine: &'a mut EngineConnection) -> Self { pub fn new(args: Vec<MemoryItem>, source_range: SourceRange, engine: EngineConnection) -> Self {
Self { Self {
args, args,
source_range, source_range,
@ -118,8 +119,12 @@ impl<'a> Args<'a> {
} }
} }
pub fn send_modeling_cmd(&mut self, id: uuid::Uuid, cmd: kittycad::types::ModelingCmd) -> Result<(), KclError> { pub async fn send_modeling_cmd(
self.engine.send_modeling_cmd(id, self.source_range, cmd) &self,
id: uuid::Uuid,
cmd: kittycad::types::ModelingCmd,
) -> Result<OkWebSocketResponseData, KclError> {
self.engine.send_modeling_cmd(id, self.source_range, cmd).await
} }
fn make_user_val_from_json(&self, j: serde_json::Value) -> Result<MemoryItem, KclError> { fn make_user_val_from_json(&self, j: serde_json::Value) -> Result<MemoryItem, KclError> {
@ -443,7 +448,7 @@ impl<'a> Args<'a> {
/// Render a model. /// Render a model.
// This never actually gets called so this is fine. // This never actually gets called so this is fine.
pub fn show(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn show<'a>(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group = args.get_sketch_group()?; let sketch_group = args.get_sketch_group()?;
inner_show(sketch_group); inner_show(sketch_group);
@ -457,7 +462,7 @@ pub fn show(args: &mut Args) -> Result<MemoryItem, KclError> {
fn inner_show(_sketch: Box<SketchGroup>) {} fn inner_show(_sketch: Box<SketchGroup>) {}
/// Returns the length of the given leg. /// Returns the length of the given leg.
pub fn leg_length(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn leg_length(args: Args) -> Result<MemoryItem, KclError> {
let (hypotenuse, leg) = args.get_hypotenuse_leg()?; let (hypotenuse, leg) = args.get_hypotenuse_leg()?;
let result = inner_leg_length(hypotenuse, leg); let result = inner_leg_length(hypotenuse, leg);
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
@ -472,7 +477,7 @@ fn inner_leg_length(hypotenuse: f64, leg: f64) -> f64 {
} }
/// Returns the angle of the given leg for x. /// Returns the angle of the given leg for x.
pub fn leg_angle_x(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn leg_angle_x(args: Args) -> Result<MemoryItem, KclError> {
let (hypotenuse, leg) = args.get_hypotenuse_leg()?; let (hypotenuse, leg) = args.get_hypotenuse_leg()?;
let result = inner_leg_angle_x(hypotenuse, leg); let result = inner_leg_angle_x(hypotenuse, leg);
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
@ -487,7 +492,7 @@ fn inner_leg_angle_x(hypotenuse: f64, leg: f64) -> f64 {
} }
/// Returns the angle of the given leg for y. /// Returns the angle of the given leg for y.
pub fn leg_angle_y(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn leg_angle_y(args: Args) -> Result<MemoryItem, KclError> {
let (hypotenuse, leg) = args.get_hypotenuse_leg()?; let (hypotenuse, leg) = args.get_hypotenuse_leg()?;
let result = inner_leg_angle_y(hypotenuse, leg); let result = inner_leg_angle_y(hypotenuse, leg);
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)

View File

@ -11,9 +11,9 @@ use crate::{
}; };
/// Returns the segment end of x. /// Returns the segment end of x.
pub fn segment_end_x(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn segment_end_x(args: Args) -> Result<MemoryItem, KclError> {
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?; let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
let result = inner_segment_end_x(&segment_name, sketch_group, args)?; let result = inner_segment_end_x(&segment_name, sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -22,7 +22,7 @@ pub fn segment_end_x(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "segEndX", name = "segEndX",
}] }]
fn inner_segment_end_x(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> { fn inner_segment_end_x(segment_name: &str, sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| { let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!( message: format!(
@ -37,9 +37,9 @@ fn inner_segment_end_x(segment_name: &str, sketch_group: Box<SketchGroup>, args:
} }
/// Returns the segment end of y. /// Returns the segment end of y.
pub fn segment_end_y(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn segment_end_y(args: Args) -> Result<MemoryItem, KclError> {
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?; let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
let result = inner_segment_end_y(&segment_name, sketch_group, args)?; let result = inner_segment_end_y(&segment_name, sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -48,7 +48,7 @@ pub fn segment_end_y(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "segEndY", name = "segEndY",
}] }]
fn inner_segment_end_y(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> { fn inner_segment_end_y(segment_name: &str, sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| { let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!( message: format!(
@ -63,9 +63,9 @@ fn inner_segment_end_y(segment_name: &str, sketch_group: Box<SketchGroup>, args:
} }
/// Returns the last segment of x. /// Returns the last segment of x.
pub fn last_segment_x(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn last_segment_x(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group = args.get_sketch_group()?; let sketch_group = args.get_sketch_group()?;
let result = inner_last_segment_x(sketch_group, args)?; let result = inner_last_segment_x(sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -74,7 +74,7 @@ pub fn last_segment_x(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "lastSegX", name = "lastSegX",
}] }]
fn inner_last_segment_x(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> { fn inner_last_segment_x(sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
let last_line = sketch_group let last_line = sketch_group
.value .value
.last() .last()
@ -93,9 +93,9 @@ fn inner_last_segment_x(sketch_group: Box<SketchGroup>, args: &mut Args) -> Resu
} }
/// Returns the last segment of y. /// Returns the last segment of y.
pub fn last_segment_y(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn last_segment_y(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group = args.get_sketch_group()?; let sketch_group = args.get_sketch_group()?;
let result = inner_last_segment_y(sketch_group, args)?; let result = inner_last_segment_y(sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -104,7 +104,7 @@ pub fn last_segment_y(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "lastSegY", name = "lastSegY",
}] }]
fn inner_last_segment_y(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> { fn inner_last_segment_y(sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
let last_line = sketch_group let last_line = sketch_group
.value .value
.last() .last()
@ -123,9 +123,9 @@ fn inner_last_segment_y(sketch_group: Box<SketchGroup>, args: &mut Args) -> Resu
} }
/// Returns the length of the segment. /// Returns the length of the segment.
pub fn segment_length(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn segment_length(args: Args) -> Result<MemoryItem, KclError> {
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?; let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
let result = inner_segment_length(&segment_name, sketch_group, args)?; let result = inner_segment_length(&segment_name, sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -133,7 +133,7 @@ pub fn segment_length(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "segLen", name = "segLen",
}] }]
fn inner_segment_length(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> { fn inner_segment_length(segment_name: &str, sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| { let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!( message: format!(
@ -151,10 +151,10 @@ fn inner_segment_length(segment_name: &str, sketch_group: Box<SketchGroup>, args
} }
/// Returns the angle of the segment. /// Returns the angle of the segment.
pub fn segment_angle(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn segment_angle(args: Args) -> Result<MemoryItem, KclError> {
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?; let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
let result = inner_segment_angle(&segment_name, sketch_group, args)?; let result = inner_segment_angle(&segment_name, sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -162,7 +162,7 @@ pub fn segment_angle(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "segAng", name = "segAng",
}] }]
fn inner_segment_angle(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> { fn inner_segment_angle(segment_name: &str, sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| { let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!( message: format!(
@ -180,9 +180,9 @@ fn inner_segment_angle(segment_name: &str, sketch_group: Box<SketchGroup>, args:
} }
/// Returns the angle to match the given length for x. /// Returns the angle to match the given length for x.
pub fn angle_to_match_length_x(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angle_to_match_length_x(args: Args) -> Result<MemoryItem, KclError> {
let (segment_name, to, sketch_group) = args.get_segment_name_to_number_sketch_group()?; let (segment_name, to, sketch_group) = args.get_segment_name_to_number_sketch_group()?;
let result = inner_angle_to_match_length_x(&segment_name, to, sketch_group, args)?; let result = inner_angle_to_match_length_x(&segment_name, to, sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -194,7 +194,7 @@ fn inner_angle_to_match_length_x(
segment_name: &str, segment_name: &str,
to: f64, to: f64,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<f64, KclError> { ) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| { let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
@ -235,9 +235,9 @@ fn inner_angle_to_match_length_x(
} }
/// Returns the angle to match the given length for y. /// Returns the angle to match the given length for y.
pub fn angle_to_match_length_y(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angle_to_match_length_y(args: Args) -> Result<MemoryItem, KclError> {
let (segment_name, to, sketch_group) = args.get_segment_name_to_number_sketch_group()?; let (segment_name, to, sketch_group) = args.get_segment_name_to_number_sketch_group()?;
let result = inner_angle_to_match_length_y(&segment_name, to, sketch_group, args)?; let result = inner_angle_to_match_length_y(&segment_name, to, sketch_group, args.clone())?;
args.make_user_val_from_f64(result) args.make_user_val_from_f64(result)
} }
@ -249,7 +249,7 @@ fn inner_angle_to_match_length_y(
segment_name: &str, segment_name: &str,
to: f64, to: f64,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<f64, KclError> { ) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| { let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {

View File

@ -33,10 +33,10 @@ pub enum LineToData {
} }
/// Draw a line to a point. /// Draw a line to a point.
pub fn line_to(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn line_to(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (LineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (LineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_line_to(data, sketch_group, args)?; let new_sketch_group = inner_line_to(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -44,10 +44,10 @@ pub fn line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "lineTo", name = "lineTo",
}] }]
fn inner_line_to( async fn inner_line_to(
data: LineToData, data: LineToData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
let to = match data { let to = match data {
@ -70,7 +70,8 @@ fn inner_line_to(
relative: false, relative: false,
}, },
}, },
)?; )
.await?;
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
@ -111,10 +112,10 @@ pub enum AxisLineToData {
} }
/// Draw a line to a point on the x-axis. /// Draw a line to a point on the x-axis.
pub fn x_line_to(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn x_line_to(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AxisLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_x_line_to(data, sketch_group, args)?; let new_sketch_group = inner_x_line_to(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -122,10 +123,10 @@ pub fn x_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "xLineTo", name = "xLineTo",
}] }]
fn inner_x_line_to( async fn inner_x_line_to(
data: AxisLineToData, data: AxisLineToData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
@ -134,16 +135,16 @@ fn inner_x_line_to(
AxisLineToData::Point(data) => LineToData::Point([data, from.y]), AxisLineToData::Point(data) => LineToData::Point([data, from.y]),
}; };
let new_sketch_group = inner_line_to(line_to_data, sketch_group, args)?; let new_sketch_group = inner_line_to(line_to_data, sketch_group, args).await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
/// Draw a line to a point on the y-axis. /// Draw a line to a point on the y-axis.
pub fn y_line_to(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn y_line_to(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AxisLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_y_line_to(data, sketch_group, args)?; let new_sketch_group = inner_y_line_to(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -151,10 +152,10 @@ pub fn y_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "yLineTo", name = "yLineTo",
}] }]
fn inner_y_line_to( async fn inner_y_line_to(
data: AxisLineToData, data: AxisLineToData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
@ -163,7 +164,7 @@ fn inner_y_line_to(
AxisLineToData::Point(data) => LineToData::Point([from.x, data]), AxisLineToData::Point(data) => LineToData::Point([from.x, data]),
}; };
let new_sketch_group = inner_line_to(line_to_data, sketch_group, args)?; let new_sketch_group = inner_line_to(line_to_data, sketch_group, args).await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
@ -184,10 +185,10 @@ pub enum LineData {
} }
/// Draw a line. /// Draw a line.
pub fn line(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn line(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (LineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (LineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_line(data, sketch_group, args)?; let new_sketch_group = inner_line(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -195,7 +196,7 @@ pub fn line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "line", name = "line",
}] }]
fn inner_line(data: LineData, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<SketchGroup>, KclError> { async fn inner_line(data: LineData, sketch_group: Box<SketchGroup>, args: Args) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
let inner_args = match &data { let inner_args = match &data {
LineData::PointWithTag { to, .. } => *to, LineData::PointWithTag { to, .. } => *to,
@ -220,7 +221,8 @@ fn inner_line(data: LineData, sketch_group: Box<SketchGroup>, args: &mut Args) -
relative: true, relative: true,
}, },
}, },
)?; )
.await?;
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
@ -261,10 +263,10 @@ pub enum AxisLineData {
} }
/// Draw a line on the x-axis. /// Draw a line on the x-axis.
pub fn x_line(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn x_line(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AxisLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_x_line(data, sketch_group, args)?; let new_sketch_group = inner_x_line(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -272,25 +274,25 @@ pub fn x_line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "xLine", name = "xLine",
}] }]
fn inner_x_line( async fn inner_x_line(
data: AxisLineData, data: AxisLineData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let line_data = match data { let line_data = match data {
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag { to: [length, 0.0], tag }, AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag { to: [length, 0.0], tag },
AxisLineData::Length(length) => LineData::Point([length, 0.0]), AxisLineData::Length(length) => LineData::Point([length, 0.0]),
}; };
let new_sketch_group = inner_line(line_data, sketch_group, args)?; let new_sketch_group = inner_line(line_data, sketch_group, args).await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
/// Draw a line on the y-axis. /// Draw a line on the y-axis.
pub fn y_line(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn y_line(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AxisLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_y_line(data, sketch_group, args)?; let new_sketch_group = inner_y_line(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -298,17 +300,17 @@ pub fn y_line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "yLine", name = "yLine",
}] }]
fn inner_y_line( async fn inner_y_line(
data: AxisLineData, data: AxisLineData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let line_data = match data { let line_data = match data {
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag { to: [0.0, length], tag }, AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag { to: [0.0, length], tag },
AxisLineData::Length(length) => LineData::Point([0.0, length]), AxisLineData::Length(length) => LineData::Point([0.0, length]),
}; };
let new_sketch_group = inner_line(line_data, sketch_group, args)?; let new_sketch_group = inner_line(line_data, sketch_group, args).await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
@ -331,10 +333,10 @@ pub enum AngledLineData {
} }
/// Draw an angled line. /// Draw an angled line.
pub fn angled_line(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angled_line(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line(data, sketch_group, args)?; let new_sketch_group = inner_angled_line(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -342,10 +344,10 @@ pub fn angled_line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "angledLine", name = "angledLine",
}] }]
fn inner_angled_line( async fn inner_angled_line(
data: AngledLineData, data: AngledLineData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
let (angle, length) = match &data { let (angle, length) = match &data {
@ -393,7 +395,8 @@ fn inner_angled_line(
relative, relative,
}, },
}, },
)?; )
.await?;
let mut new_sketch_group = sketch_group.clone(); let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
@ -401,10 +404,10 @@ fn inner_angled_line(
} }
/// Draw an angled line of a given x length. /// Draw an angled line of a given x length.
pub fn angled_line_of_x_length(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angled_line_of_x_length(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_of_x_length(data, sketch_group, args)?; let new_sketch_group = inner_angled_line_of_x_length(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -412,10 +415,10 @@ pub fn angled_line_of_x_length(args: &mut Args) -> Result<MemoryItem, KclError>
#[stdlib { #[stdlib {
name = "angledLineOfXLength", name = "angledLineOfXLength",
}] }]
fn inner_angled_line_of_x_length( async fn inner_angled_line_of_x_length(
data: AngledLineData, data: AngledLineData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let (angle, length) = match &data { let (angle, length) = match &data {
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length), AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
@ -432,7 +435,8 @@ fn inner_angled_line_of_x_length(
}, },
sketch_group, sketch_group,
args, args,
)?; )
.await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
@ -456,10 +460,10 @@ pub enum AngledLineToData {
} }
/// Draw an angled line to a given x coordinate. /// Draw an angled line to a given x coordinate.
pub fn angled_line_to_x(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angled_line_to_x(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AngledLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_to_x(data, sketch_group, args)?; let new_sketch_group = inner_angled_line_to_x(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -467,10 +471,10 @@ pub fn angled_line_to_x(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "angledLineToX", name = "angledLineToX",
}] }]
fn inner_angled_line_to_x( async fn inner_angled_line_to_x(
data: AngledLineToData, data: AngledLineToData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
let (angle, x_to) = match &data { let (angle, x_to) = match &data {
@ -490,15 +494,16 @@ fn inner_angled_line_to_x(
}, },
sketch_group, sketch_group,
args, args,
)?; )
.await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
/// Draw an angled line of a given y length. /// Draw an angled line of a given y length.
pub fn angled_line_of_y_length(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angled_line_of_y_length(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_of_y_length(data, sketch_group, args)?; let new_sketch_group = inner_angled_line_of_y_length(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -507,10 +512,10 @@ pub fn angled_line_of_y_length(args: &mut Args) -> Result<MemoryItem, KclError>
#[stdlib { #[stdlib {
name = "angledLineOfYLength", name = "angledLineOfYLength",
}] }]
fn inner_angled_line_of_y_length( async fn inner_angled_line_of_y_length(
data: AngledLineData, data: AngledLineData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let (angle, length) = match &data { let (angle, length) = match &data {
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length), AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
@ -527,16 +532,17 @@ fn inner_angled_line_of_y_length(
}, },
sketch_group, sketch_group,
args, args,
)?; )
.await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
/// Draw an angled line to a given y coordinate. /// Draw an angled line to a given y coordinate.
pub fn angled_line_to_y(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angled_line_to_y(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AngledLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_to_y(data, sketch_group, args)?; let new_sketch_group = inner_angled_line_to_y(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -544,10 +550,10 @@ pub fn angled_line_to_y(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "angledLineToY", name = "angledLineToY",
}] }]
fn inner_angled_line_to_y( async fn inner_angled_line_to_y(
data: AngledLineToData, data: AngledLineToData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
let (angle, y_to) = match &data { let (angle, y_to) = match &data {
@ -567,7 +573,8 @@ fn inner_angled_line_to_y(
}, },
sketch_group, sketch_group,
args, args,
)?; )
.await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
@ -588,9 +595,9 @@ pub struct AngeledLineThatIntersectsData {
} }
/// Draw an angled line that intersects with a given line. /// Draw an angled line that intersects with a given line.
pub fn angled_line_that_intersects(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn angled_line_that_intersects(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngeledLineThatIntersectsData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (AngeledLineThatIntersectsData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, args)?; let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -598,10 +605,10 @@ pub fn angled_line_that_intersects(args: &mut Args) -> Result<MemoryItem, KclErr
#[stdlib { #[stdlib {
name = "angledLineThatIntersects", name = "angledLineThatIntersects",
}] }]
fn inner_angled_line_that_intersects( async fn inner_angled_line_that_intersects(
data: AngeledLineThatIntersectsData, data: AngeledLineThatIntersectsData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let intersect_path = sketch_group let intersect_path = sketch_group
.get_path_by_name(&data.intersect_tag) .get_path_by_name(&data.intersect_tag)
@ -630,15 +637,15 @@ fn inner_angled_line_that_intersects(
LineToData::Point(to.into()) LineToData::Point(to.into())
}; };
let new_sketch_group = inner_line_to(line_to_data, sketch_group, args)?; let new_sketch_group = inner_line_to(line_to_data, sketch_group, args).await?;
Ok(new_sketch_group) Ok(new_sketch_group)
} }
/// Start a sketch at a given point. /// Start a sketch at a given point.
pub fn start_sketch_at(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn start_sketch_at(args: Args) -> Result<MemoryItem, KclError> {
let data: LineData = args.get_data()?; let data: LineData = args.get_data()?;
let sketch_group = inner_start_sketch_at(data, args)?; let sketch_group = inner_start_sketch_at(data, args).await?;
Ok(MemoryItem::SketchGroup(sketch_group)) Ok(MemoryItem::SketchGroup(sketch_group))
} }
@ -646,7 +653,7 @@ pub fn start_sketch_at(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "startSketchAt", name = "startSketchAt",
}] }]
fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<Box<SketchGroup>, KclError> { async fn inner_start_sketch_at(data: LineData, args: Args) -> Result<Box<SketchGroup>, KclError> {
let to = match &data { let to = match &data {
LineData::PointWithTag { to, .. } => *to, LineData::PointWithTag { to, .. } => *to,
LineData::Point(to) => *to, LineData::Point(to) => *to,
@ -655,7 +662,7 @@ fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<Box<SketchGr
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
let path_id = uuid::Uuid::new_v4(); let path_id = uuid::Uuid::new_v4();
args.send_modeling_cmd(path_id, ModelingCmd::StartPath {})?; args.send_modeling_cmd(path_id, ModelingCmd::StartPath {}).await?;
args.send_modeling_cmd( args.send_modeling_cmd(
id, id,
ModelingCmd::MovePathPen { ModelingCmd::MovePathPen {
@ -666,7 +673,8 @@ fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<Box<SketchGr
z: 0.0, z: 0.0,
}, },
}, },
)?; )
.await?;
let current_path = BasePath { let current_path = BasePath {
from: to, from: to,
@ -694,10 +702,10 @@ fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<Box<SketchGr
} }
/// Close the current sketch. /// Close the current sketch.
pub fn close(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn close(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group = args.get_sketch_group()?; let sketch_group = args.get_sketch_group()?;
let new_sketch_group = inner_close(sketch_group, args)?; let new_sketch_group = inner_close(sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -706,7 +714,7 @@ pub fn close(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "close", name = "close",
}] }]
fn inner_close(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<SketchGroup>, KclError> { async fn inner_close(sketch_group: Box<SketchGroup>, args: Args) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
let to: Point2d = sketch_group.start.from.into(); let to: Point2d = sketch_group.start.from.into();
@ -717,7 +725,8 @@ fn inner_close(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<Sk
ModelingCmd::ClosePath { ModelingCmd::ClosePath {
path_id: sketch_group.id, path_id: sketch_group.id,
}, },
)?; )
.await?;
let mut new_sketch_group = sketch_group.clone(); let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(Path::ToPoint { new_sketch_group.value.push(Path::ToPoint {
@ -784,10 +793,10 @@ pub enum ArcData {
} }
/// Draw an arc. /// Draw an arc.
pub fn arc(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn arc(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (ArcData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (ArcData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_arc(data, sketch_group, args)?; let new_sketch_group = inner_arc(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -795,7 +804,7 @@ pub fn arc(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "arc", name = "arc",
}] }]
fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<SketchGroup>, KclError> { async fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: Args) -> Result<Box<SketchGroup>, KclError> {
let from: Point2d = sketch_group.get_coords_from_paths()?; let from: Point2d = sketch_group.get_coords_from_paths()?;
let (center, angle_start, angle_end, radius, end) = match &data { let (center, angle_start, angle_end, radius, end) = match &data {
@ -844,7 +853,8 @@ fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: &mut Args) ->
relative: false, relative: false,
}, },
}, },
)?; )
.await?;
// TODO: Dont do this (move path pen) - mike // TODO: Dont do this (move path pen) - mike
// lets review what the needs are here and see if any existing arc endpoints can accomplish this // lets review what the needs are here and see if any existing arc endpoints can accomplish this
@ -863,7 +873,8 @@ fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: &mut Args) ->
z: 0.0, z: 0.0,
}, },
}, },
)?; )
.await?;
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
@ -916,10 +927,10 @@ pub enum BezierData {
} }
/// Draw a bezier curve. /// Draw a bezier curve.
pub fn bezier_curve(args: &mut Args) -> Result<MemoryItem, KclError> { pub async fn bezier_curve(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (BezierData, Box<SketchGroup>) = args.get_data_and_sketch_group()?; let (data, sketch_group): (BezierData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_bezier_curve(data, sketch_group, args)?; let new_sketch_group = inner_bezier_curve(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group)) Ok(MemoryItem::SketchGroup(new_sketch_group))
} }
@ -927,10 +938,10 @@ pub fn bezier_curve(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "bezierCurve", name = "bezierCurve",
}] }]
fn inner_bezier_curve( async fn inner_bezier_curve(
data: BezierData, data: BezierData,
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
args: &mut Args, args: Args,
) -> Result<Box<SketchGroup>, KclError> { ) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?; let from = sketch_group.get_coords_from_paths()?;
@ -970,7 +981,8 @@ fn inner_bezier_curve(
relative, relative,
}, },
}, },
)?; )
.await?;
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {

View File

@ -21,11 +21,12 @@ pub async fn execute_wasm(
let program: kcl_lib::ast::types::Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?; let program: kcl_lib::ast::types::Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
let mut mem: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?; let mut mem: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
let mut engine = kcl_lib::engine::EngineConnection::new(manager) let engine = kcl_lib::engine::EngineConnection::new(manager)
.await .await
.map_err(|e| format!("{:?}", e))?; .map_err(|e| format!("{:?}", e))?;
let memory = kcl_lib::executor::execute(program, &mut mem, kcl_lib::executor::BodyType::Root, &mut engine) let memory = kcl_lib::executor::execute(program, &mut mem, kcl_lib::executor::BodyType::Root, &engine)
.await
.map_err(String::from)?; .map_err(String::from)?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the // The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead. // gloo-serialize crate instead.

View File

@ -35,12 +35,12 @@ async fn execute_and_snapshot(code: &str) -> Result<image::DynamicImage> {
let parser = kcl_lib::parser::Parser::new(tokens); let parser = kcl_lib::parser::Parser::new(tokens);
let program = parser.ast()?; let program = parser.ast()?;
let mut mem: kcl_lib::executor::ProgramMemory = Default::default(); let mut mem: kcl_lib::executor::ProgramMemory = Default::default();
let mut engine = kcl_lib::engine::EngineConnection::new(ws).await?; let engine = kcl_lib::engine::EngineConnection::new(ws).await?;
let _ = kcl_lib::executor::execute(program, &mut mem, kcl_lib::executor::BodyType::Root, &mut engine)?; let _ = kcl_lib::executor::execute(program, &mut mem, kcl_lib::executor::BodyType::Root, &engine).await?;
// Send a snapshot request to the engine. // Send a snapshot request to the engine.
let resp = engine let resp = engine
.send_modeling_cmd_get_response( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
kcl_lib::executor::SourceRange::default(), kcl_lib::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot { kittycad::types::ModelingCmd::TakeSnapshot {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -37,13 +37,9 @@ async fn setup(code: &str, name: &str) -> Result<(EngineConnection, Program, uui
let parser = kcl_lib::parser::Parser::new(tokens); let parser = kcl_lib::parser::Parser::new(tokens);
let program = parser.ast()?; let program = parser.ast()?;
let mut mem: kcl_lib::executor::ProgramMemory = Default::default(); let mut mem: kcl_lib::executor::ProgramMemory = Default::default();
let mut engine = kcl_lib::engine::EngineConnection::new(ws).await?; let engine = kcl_lib::engine::EngineConnection::new(ws).await?;
let memory = kcl_lib::executor::execute( let memory =
program.clone(), kcl_lib::executor::execute(program.clone(), &mut mem, kcl_lib::executor::BodyType::Root, &engine).await?;
&mut mem,
kcl_lib::executor::BodyType::Root,
&mut engine,
)?;
// We need to get the sketch ID. // We need to get the sketch ID.
// Get the sketch group ID from memory. // Get the sketch group ID from memory.
@ -53,7 +49,8 @@ async fn setup(code: &str, name: &str) -> Result<(EngineConnection, Program, uui
let sketch_id = sketch_group.id; let sketch_id = sketch_group.id;
let plane_id = uuid::Uuid::new_v4(); let plane_id = uuid::Uuid::new_v4();
engine.send_modeling_cmd( engine
.send_modeling_cmd(
plane_id, plane_id,
SourceRange::default(), SourceRange::default(),
ModelingCmd::MakePlane { ModelingCmd::MakePlane {
@ -63,12 +60,14 @@ async fn setup(code: &str, name: &str) -> Result<(EngineConnection, Program, uui
x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 }, x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 },
y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 }, y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
}, },
)?; )
.await?;
// Enter sketch mode. // Enter sketch mode.
// We can't get control points without being in sketch mode. // We can't get control points without being in sketch mode.
// You can however get path info without sketch mode. // You can however get path info without sketch mode.
engine.send_modeling_cmd( engine
.send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::SketchModeEnable { ModelingCmd::SketchModeEnable {
@ -76,15 +75,18 @@ async fn setup(code: &str, name: &str) -> Result<(EngineConnection, Program, uui
ortho: true, ortho: true,
plane_id, plane_id,
}, },
)?; )
.await?;
// Enter edit mode. // Enter edit mode.
// We can't get control points of an existing sketch without being in edit mode. // We can't get control points of an existing sketch without being in edit mode.
engine.send_modeling_cmd( engine
.send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::EditModeEnter { target: sketch_id }, ModelingCmd::EditModeEnter { target: sketch_id },
)?; )
.await?;
Ok((engine, program, sketch_id)) Ok((engine, program, sketch_id))
} }