Unify execution state into a single struct (#3877)
* Add ExecState that combines ProgramMemory and DynamicState * Remove unneeded clones * Add exec_state parameter to all KCL stdlib functions * Move pipe value into ExecState * Add test for pipe substitution not leaking into function calls * KCL: Better message on assertEqual function Also add a new no-visual test for performance testing. * Fix new array module to use ExecState --------- Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
This commit is contained in:
@ -269,7 +269,7 @@ fn do_stdlib_inner(
|
|||||||
let ty_string = rust_type_to_openapi_type(&ty_string);
|
let ty_string = rust_type_to_openapi_type(&ty_string);
|
||||||
let required = !ty_ident.to_string().starts_with("Option <");
|
let required = !ty_ident.to_string().starts_with("Option <");
|
||||||
|
|
||||||
if ty_string != "Args" {
|
if ty_string != "ExecState" && ty_string != "Args" {
|
||||||
let schema = if ty_ident.to_string().starts_with("Vec < ")
|
let schema = if ty_ident.to_string().starts_with("Vec < ")
|
||||||
|| ty_ident.to_string().starts_with("Option <")
|
|| ty_ident.to_string().starts_with("Option <")
|
||||||
|| ty_ident.to_string().starts_with('[')
|
|| ty_ident.to_string().starts_with('[')
|
||||||
@ -387,11 +387,12 @@ fn do_stdlib_inner(
|
|||||||
#const_struct
|
#const_struct
|
||||||
|
|
||||||
fn #boxed_fn_name_ident(
|
fn #boxed_fn_name_ident(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<dyn std::future::Future<Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>> + Send>,
|
Box<dyn std::future::Future<Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>> + Send + '_>,
|
||||||
> {
|
> {
|
||||||
Box::pin(#fn_name_ident(args))
|
Box::pin(#fn_name_ident(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #docs_crate::StdLibFn for #name_ident
|
impl #docs_crate::StdLibFn for #name_ident
|
||||||
@ -662,6 +663,9 @@ fn clean_ty_string(t: &str) -> (String, proc_macro2::TokenStream) {
|
|||||||
.replace("mut", "")
|
.replace("mut", "")
|
||||||
.replace("< 'a >", "")
|
.replace("< 'a >", "")
|
||||||
.replace(' ', "");
|
.replace(' ', "");
|
||||||
|
if ty_string.starts_with("ExecState") {
|
||||||
|
ty_string = "ExecState".to_string();
|
||||||
|
}
|
||||||
if ty_string.starts_with("Args") {
|
if ty_string.starts_with("Args") {
|
||||||
ty_string = "Args".to_string();
|
ty_string = "Args".to_string();
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,32 @@ fn test_args_with_lifetime() {
|
|||||||
expectorate::assert_contents("tests/args_with_lifetime.gen", &get_text_fmt(&item).unwrap());
|
expectorate::assert_contents("tests/args_with_lifetime.gen", &get_text_fmt(&item).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_args_with_exec_state() {
|
||||||
|
let (item, mut errors) = do_stdlib(
|
||||||
|
quote! {
|
||||||
|
name = "someFunction",
|
||||||
|
},
|
||||||
|
quote! {
|
||||||
|
/// Docs
|
||||||
|
/// ```
|
||||||
|
/// someFunction()
|
||||||
|
/// ```
|
||||||
|
fn inner_some_function<'a>(
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: &Args,
|
||||||
|
) -> i32 {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
if let Some(e) = errors.pop() {
|
||||||
|
panic!("{e}");
|
||||||
|
}
|
||||||
|
expectorate::assert_contents("tests/test_args_with_exec_state.gen", &get_text_fmt(&item).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stdlib_line_to() {
|
fn test_stdlib_line_to() {
|
||||||
let (item, errors) = do_stdlib(
|
let (item, errors) = do_stdlib(
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct SomeFn {}
|
|||||||
#[doc = "Std lib function: someFn\nDocs"]
|
#[doc = "Std lib function: someFn\nDocs"]
|
||||||
pub(crate) const SomeFn: SomeFn = SomeFn {};
|
pub(crate) const SomeFn: SomeFn = SomeFn {};
|
||||||
fn boxed_someFn(
|
fn boxed_someFn(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(someFn(args))
|
Box::pin(someFn(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for SomeFn {
|
impl crate::docs::StdLibFn for SomeFn {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct SomeFn {}
|
|||||||
#[doc = "Std lib function: someFn\nDocs"]
|
#[doc = "Std lib function: someFn\nDocs"]
|
||||||
pub(crate) const SomeFn: SomeFn = SomeFn {};
|
pub(crate) const SomeFn: SomeFn = SomeFn {};
|
||||||
fn boxed_someFn(
|
fn boxed_someFn(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(someFn(args))
|
Box::pin(someFn(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for SomeFn {
|
impl crate::docs::StdLibFn for SomeFn {
|
||||||
|
@ -77,15 +77,17 @@ pub(crate) struct Show {}
|
|||||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Show: Show = Show {};
|
pub(crate) const Show: Show = Show {};
|
||||||
fn boxed_show(
|
fn boxed_show(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(show(args))
|
Box::pin(show(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Show {
|
impl crate::docs::StdLibFn for Show {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct Show {}
|
|||||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Show: Show = Show {};
|
pub(crate) const Show: Show = Show {};
|
||||||
fn boxed_show(
|
fn boxed_show(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(show(args))
|
Box::pin(show(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Show {
|
impl crate::docs::StdLibFn for Show {
|
||||||
|
@ -78,15 +78,17 @@ pub(crate) struct MyFunc {}
|
|||||||
#[doc = "Std lib function: myFunc\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: myFunc\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const MyFunc: MyFunc = MyFunc {};
|
pub(crate) const MyFunc: MyFunc = MyFunc {};
|
||||||
fn boxed_my_func(
|
fn boxed_my_func(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(my_func(args))
|
Box::pin(my_func(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for MyFunc {
|
impl crate::docs::StdLibFn for MyFunc {
|
||||||
|
@ -78,15 +78,17 @@ pub(crate) struct LineTo {}
|
|||||||
#[doc = "Std lib function: lineTo\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: lineTo\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const LineTo: LineTo = LineTo {};
|
pub(crate) const LineTo: LineTo = LineTo {};
|
||||||
fn boxed_line_to(
|
fn boxed_line_to(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(line_to(args))
|
Box::pin(line_to(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for LineTo {
|
impl crate::docs::StdLibFn for LineTo {
|
||||||
|
@ -77,15 +77,17 @@ pub(crate) struct Min {}
|
|||||||
#[doc = "Std lib function: min\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: min\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Min: Min = Min {};
|
pub(crate) const Min: Min = Min {};
|
||||||
fn boxed_min(
|
fn boxed_min(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(min(args))
|
Box::pin(min(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Min {
|
impl crate::docs::StdLibFn for Min {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct Show {}
|
|||||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Show: Show = Show {};
|
pub(crate) const Show: Show = Show {};
|
||||||
fn boxed_show(
|
fn boxed_show(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(show(args))
|
Box::pin(show(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Show {
|
impl crate::docs::StdLibFn for Show {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct Import {}
|
|||||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Import: Import = Import {};
|
pub(crate) const Import: Import = Import {};
|
||||||
fn boxed_import(
|
fn boxed_import(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(import(args))
|
Box::pin(import(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Import {
|
impl crate::docs::StdLibFn for Import {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct Import {}
|
|||||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Import: Import = Import {};
|
pub(crate) const Import: Import = Import {};
|
||||||
fn boxed_import(
|
fn boxed_import(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(import(args))
|
Box::pin(import(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Import {
|
impl crate::docs::StdLibFn for Import {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct Import {}
|
|||||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Import: Import = Import {};
|
pub(crate) const Import: Import = Import {};
|
||||||
fn boxed_import(
|
fn boxed_import(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(import(args))
|
Box::pin(import(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Import {
|
impl crate::docs::StdLibFn for Import {
|
||||||
|
@ -44,15 +44,17 @@ pub(crate) struct Show {}
|
|||||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||||
pub(crate) const Show: Show = Show {};
|
pub(crate) const Show: Show = Show {};
|
||||||
fn boxed_show(
|
fn boxed_show(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
args: crate::std::Args,
|
args: crate::std::Args,
|
||||||
) -> std::pin::Pin<
|
) -> std::pin::Pin<
|
||||||
Box<
|
Box<
|
||||||
dyn std::future::Future<
|
dyn std::future::Future<
|
||||||
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
> + Send,
|
> + Send
|
||||||
|
+ '_,
|
||||||
>,
|
>,
|
||||||
> {
|
> {
|
||||||
Box::pin(show(args))
|
Box::pin(show(exec_state, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::docs::StdLibFn for Show {
|
impl crate::docs::StdLibFn for Show {
|
||||||
|
134
src/wasm-lib/derive-docs/tests/test_args_with_exec_state.gen
Normal file
134
src/wasm-lib/derive-docs/tests/test_args_with_exec_state.gen
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod test_examples_some_function {
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_mock_example_some_function0() {
|
||||||
|
let tokens = crate::token::lexer("someFunction()").unwrap();
|
||||||
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
|
let program = parser.ast().unwrap();
|
||||||
|
let ctx = crate::executor::ExecutorContext {
|
||||||
|
engine: std::sync::Arc::new(Box::new(
|
||||||
|
crate::engine::conn_mock::EngineConnection::new()
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
)),
|
||||||
|
fs: std::sync::Arc::new(crate::fs::FileManager::new()),
|
||||||
|
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||||
|
settings: Default::default(),
|
||||||
|
is_mock: true,
|
||||||
|
};
|
||||||
|
ctx.run(&program, None).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||||
|
async fn kcl_test_example_some_function0() {
|
||||||
|
let code = "someFunction()";
|
||||||
|
let result =
|
||||||
|
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
twenty_twenty::assert_image(
|
||||||
|
&format!("tests/outputs/{}.png", "serial_test_example_some_function0"),
|
||||||
|
&result,
|
||||||
|
0.99,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types, missing_docs)]
|
||||||
|
#[doc = "Std lib function: someFunction\nDocs"]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||||
|
#[ts(export)]
|
||||||
|
pub(crate) struct SomeFunction {}
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals, missing_docs)]
|
||||||
|
#[doc = "Std lib function: someFunction\nDocs"]
|
||||||
|
pub(crate) const SomeFunction: SomeFunction = SomeFunction {};
|
||||||
|
fn boxed_some_function(
|
||||||
|
exec_state: &mut crate::executor::ExecState,
|
||||||
|
args: crate::std::Args,
|
||||||
|
) -> std::pin::Pin<
|
||||||
|
Box<
|
||||||
|
dyn std::future::Future<
|
||||||
|
Output = anyhow::Result<crate::executor::KclValue, crate::errors::KclError>,
|
||||||
|
> + Send
|
||||||
|
+ '_,
|
||||||
|
>,
|
||||||
|
> {
|
||||||
|
Box::pin(some_function(exec_state, args))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::docs::StdLibFn for SomeFunction {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"someFunction".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn summary(&self) -> String {
|
||||||
|
"Docs".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> String {
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tags(&self) -> Vec<String> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||||
|
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||||
|
settings.inline_subschemas = true;
|
||||||
|
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||||
|
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||||
|
settings.inline_subschemas = true;
|
||||||
|
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||||
|
Some(crate::docs::StdLibFnArg {
|
||||||
|
name: "".to_string(),
|
||||||
|
type_: "i32".to_string(),
|
||||||
|
schema: <i32>::json_schema(&mut generator),
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unpublished(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deprecated(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<String> {
|
||||||
|
let code_blocks = vec!["someFunction()"];
|
||||||
|
code_blocks
|
||||||
|
.iter()
|
||||||
|
.map(|cb| {
|
||||||
|
let tokens = crate::token::lexer(cb).unwrap();
|
||||||
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
|
let program = parser.ast().unwrap();
|
||||||
|
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||||
|
options.insert_final_newline = false;
|
||||||
|
program.recast(&options, 0)
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||||
|
boxed_some_function
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = r" Docs"]
|
||||||
|
#[doc = r" ```"]
|
||||||
|
#[doc = r" someFunction()"]
|
||||||
|
#[doc = r" ```"]
|
||||||
|
fn inner_some_function<'a>(exec_state: &mut ExecState, args: &Args) -> i32 {
|
||||||
|
3
|
||||||
|
}
|
@ -7,6 +7,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use async_recursion::async_recursion;
|
||||||
use databake::*;
|
use databake::*;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
@ -22,8 +23,8 @@ use crate::{
|
|||||||
docs::StdLibFn,
|
docs::StdLibFn,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
BodyType, DynamicState, ExecutorContext, KclValue, Metadata, PipeInfo, ProgramMemory, SketchGroup, SourceRange,
|
BodyType, ExecState, ExecutorContext, KclValue, Metadata, SketchGroup, SourceRange, StatementKind,
|
||||||
StatementKind, TagEngineInfo, TagIdentifier, UserVal,
|
TagEngineInfo, TagIdentifier, UserVal,
|
||||||
},
|
},
|
||||||
parser::PIPE_OPERATOR,
|
parser::PIPE_OPERATOR,
|
||||||
std::{kcl_stdlib::KclStdLibFn, FunctionKind},
|
std::{kcl_stdlib::KclStdLibFn, FunctionKind},
|
||||||
@ -797,31 +798,17 @@ impl BinaryPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
pub async fn get_result(
|
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
&self,
|
|
||||||
memory: &mut ProgramMemory,
|
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
match self {
|
match self {
|
||||||
BinaryPart::Literal(literal) => Ok(literal.into()),
|
BinaryPart::Literal(literal) => Ok(literal.into()),
|
||||||
BinaryPart::Identifier(identifier) => {
|
BinaryPart::Identifier(identifier) => {
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
}
|
}
|
||||||
BinaryPart::BinaryExpression(binary_expression) => {
|
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
||||||
binary_expression
|
BinaryPart::CallExpression(call_expression) => call_expression.execute(exec_state, ctx).await,
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
BinaryPart::UnaryExpression(unary_expression) => unary_expression.get_result(exec_state, ctx).await,
|
||||||
.await
|
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(exec_state),
|
||||||
}
|
|
||||||
BinaryPart::CallExpression(call_expression) => {
|
|
||||||
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await
|
|
||||||
}
|
|
||||||
BinaryPart::UnaryExpression(unary_expression) => {
|
|
||||||
unary_expression.get_result(memory, dynamic_state, pipe_info, ctx).await
|
|
||||||
}
|
|
||||||
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(memory),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1192,30 +1179,17 @@ impl CallExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
pub async fn execute(
|
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
&self,
|
let fn_name = &self.callee.name;
|
||||||
memory: &mut ProgramMemory,
|
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
let fn_name = self.callee.name.clone();
|
|
||||||
|
|
||||||
let mut fn_args: Vec<KclValue> = Vec::with_capacity(self.arguments.len());
|
let mut fn_args: Vec<KclValue> = Vec::with_capacity(self.arguments.len());
|
||||||
|
|
||||||
for arg in &self.arguments {
|
for arg in &self.arguments {
|
||||||
let metadata = Metadata {
|
let metadata = Metadata {
|
||||||
source_range: SourceRange([arg.start(), arg.end()]),
|
source_range: SourceRange::from(arg),
|
||||||
};
|
};
|
||||||
let result = ctx
|
let result = ctx
|
||||||
.execute_expr(
|
.execute_expr(arg, exec_state, &metadata, StatementKind::Expression)
|
||||||
arg,
|
|
||||||
memory,
|
|
||||||
dynamic_state,
|
|
||||||
pipe_info,
|
|
||||||
&metadata,
|
|
||||||
StatementKind::Expression,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
fn_args.push(result);
|
fn_args.push(result);
|
||||||
}
|
}
|
||||||
@ -1223,9 +1197,8 @@ impl CallExpression {
|
|||||||
match ctx.stdlib.get_either(&self.callee.name) {
|
match ctx.stdlib.get_either(&self.callee.name) {
|
||||||
FunctionKind::Core(func) => {
|
FunctionKind::Core(func) => {
|
||||||
// Attempt to call the function.
|
// Attempt to call the function.
|
||||||
let args =
|
let args = crate::std::Args::new(fn_args, self.into(), ctx.clone());
|
||||||
crate::std::Args::new(fn_args, self.into(), ctx.clone(), memory.clone(), dynamic_state.clone());
|
let mut result = func.std_lib_fn()(exec_state, args).await?;
|
||||||
let mut result = func.std_lib_fn()(args).await?;
|
|
||||||
|
|
||||||
// If the return result is a sketch group or extrude group, we want to update the
|
// If the return result is a sketch group or extrude group, we want to update the
|
||||||
// memory for the tags of the group.
|
// memory for the tags of the group.
|
||||||
@ -1235,7 +1208,7 @@ impl CallExpression {
|
|||||||
KclValue::UserVal(ref mut uval) => {
|
KclValue::UserVal(ref mut uval) => {
|
||||||
uval.mutate(|sketch_group: &mut SketchGroup| {
|
uval.mutate(|sketch_group: &mut SketchGroup| {
|
||||||
for (_, tag) in sketch_group.tags.iter() {
|
for (_, tag) in sketch_group.tags.iter() {
|
||||||
memory.update_tag(&tag.value, tag.clone())?;
|
exec_state.memory.update_tag(&tag.value, tag.clone())?;
|
||||||
}
|
}
|
||||||
Ok::<_, KclError>(())
|
Ok::<_, KclError>(())
|
||||||
})?;
|
})?;
|
||||||
@ -1275,7 +1248,7 @@ impl CallExpression {
|
|||||||
info.sketch_group = extrude_group.id;
|
info.sketch_group = extrude_group.id;
|
||||||
t.info = Some(info);
|
t.info = Some(info);
|
||||||
|
|
||||||
memory.update_tag(&tag.name, t.clone())?;
|
exec_state.memory.update_tag(&tag.name, t.clone())?;
|
||||||
|
|
||||||
// update the sketch group tags.
|
// update the sketch group tags.
|
||||||
extrude_group.sketch_group.tags.insert(tag.name.clone(), t);
|
extrude_group.sketch_group.tags.insert(tag.name.clone(), t);
|
||||||
@ -1283,7 +1256,11 @@ impl CallExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the stale sketch group in memory and update it.
|
// Find the stale sketch group in memory and update it.
|
||||||
if let Some(current_env) = memory.environments.get_mut(memory.current_env.index()) {
|
if let Some(current_env) = exec_state
|
||||||
|
.memory
|
||||||
|
.environments
|
||||||
|
.get_mut(exec_state.memory.current_env.index())
|
||||||
|
{
|
||||||
current_env.update_sketch_group_tags(&extrude_group.sketch_group);
|
current_env.update_sketch_group_tags(&extrude_group.sketch_group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1294,17 +1271,18 @@ impl CallExpression {
|
|||||||
}
|
}
|
||||||
FunctionKind::Std(func) => {
|
FunctionKind::Std(func) => {
|
||||||
let function_expression = func.function();
|
let function_expression = func.function();
|
||||||
let parts = function_expression.clone().into_parts().map_err(|e| {
|
let (required_params, optional_params) =
|
||||||
KclError::Semantic(KclErrorDetails {
|
function_expression.required_and_optional_params().map_err(|e| {
|
||||||
message: format!("Error getting parts of function: {}", e),
|
KclError::Semantic(KclErrorDetails {
|
||||||
source_ranges: vec![self.into()],
|
message: format!("Error getting parts of function: {}", e),
|
||||||
})
|
source_ranges: vec![self.into()],
|
||||||
})?;
|
})
|
||||||
if fn_args.len() < parts.params_required.len() || fn_args.len() > function_expression.params.len() {
|
})?;
|
||||||
|
if fn_args.len() < required_params.len() || fn_args.len() > function_expression.params.len() {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
"this function expected {} arguments, got {}",
|
"this function expected {} arguments, got {}",
|
||||||
parts.params_required.len(),
|
required_params.len(),
|
||||||
fn_args.len(),
|
fn_args.len(),
|
||||||
),
|
),
|
||||||
source_ranges: vec![self.into()],
|
source_ranges: vec![self.into()],
|
||||||
@ -1312,8 +1290,8 @@ impl CallExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the arguments to the memory.
|
// Add the arguments to the memory.
|
||||||
let mut fn_memory = memory.clone();
|
let mut fn_memory = exec_state.memory.clone();
|
||||||
for (index, param) in parts.params_required.iter().enumerate() {
|
for (index, param) in required_params.iter().enumerate() {
|
||||||
fn_memory.add(
|
fn_memory.add(
|
||||||
¶m.identifier.name,
|
¶m.identifier.name,
|
||||||
fn_args.get(index).unwrap().clone(),
|
fn_args.get(index).unwrap().clone(),
|
||||||
@ -1321,8 +1299,8 @@ impl CallExpression {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
// Add the optional arguments to the memory.
|
// Add the optional arguments to the memory.
|
||||||
for (index, param) in parts.params_optional.iter().enumerate() {
|
for (index, param) in optional_params.iter().enumerate() {
|
||||||
if let Some(arg) = fn_args.get(index + parts.params_required.len()) {
|
if let Some(arg) = fn_args.get(index + required_params.len()) {
|
||||||
fn_memory.add(¶m.identifier.name, arg.clone(), param.identifier.clone().into())?;
|
fn_memory.add(¶m.identifier.name, arg.clone(), param.identifier.clone().into())?;
|
||||||
} else {
|
} else {
|
||||||
fn_memory.add(
|
fn_memory.add(
|
||||||
@ -1336,22 +1314,31 @@ impl CallExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut fn_dynamic_state = dynamic_state.clone();
|
let fn_dynamic_state = exec_state.dynamic_state.clone();
|
||||||
|
// TODO: Shouldn't we merge program memory into fn_dynamic_state
|
||||||
|
// here?
|
||||||
|
|
||||||
// Call the stdlib function
|
// Call the stdlib function
|
||||||
let p = func.function().clone().body;
|
let p = &func.function().body;
|
||||||
let results = match ctx
|
|
||||||
.inner_execute(&p, &mut fn_memory, &mut fn_dynamic_state, BodyType::Block)
|
let (exec_result, fn_memory) = {
|
||||||
.await
|
let previous_memory = std::mem::replace(&mut exec_state.memory, fn_memory);
|
||||||
{
|
let previous_dynamic_state = std::mem::replace(&mut exec_state.dynamic_state, fn_dynamic_state);
|
||||||
Ok(results) => results,
|
let result = ctx.inner_execute(p, exec_state, BodyType::Block).await;
|
||||||
|
exec_state.dynamic_state = previous_dynamic_state;
|
||||||
|
let fn_memory = std::mem::replace(&mut exec_state.memory, previous_memory);
|
||||||
|
(result, fn_memory)
|
||||||
|
};
|
||||||
|
|
||||||
|
match exec_result {
|
||||||
|
Ok(()) => {}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// We need to override the source ranges so we don't get the embedded kcl
|
// We need to override the source ranges so we don't get the embedded kcl
|
||||||
// function from the stdlib.
|
// function from the stdlib.
|
||||||
return Err(err.override_source_ranges(vec![self.into()]));
|
return Err(err.override_source_ranges(vec![self.into()]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let out = results.return_;
|
let out = fn_memory.return_;
|
||||||
let result = out.ok_or_else(|| {
|
let result = out.ok_or_else(|| {
|
||||||
KclError::UndefinedValue(KclErrorDetails {
|
KclError::UndefinedValue(KclErrorDetails {
|
||||||
message: format!("Result of stdlib function {} is undefined", fn_name),
|
message: format!("Result of stdlib function {} is undefined", fn_name),
|
||||||
@ -1361,18 +1348,24 @@ impl CallExpression {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
FunctionKind::UserDefined => {
|
FunctionKind::UserDefined => {
|
||||||
let func = memory.get(&fn_name, self.into())?;
|
let source_range = SourceRange::from(self);
|
||||||
let fn_dynamic_state = dynamic_state.merge(memory);
|
// Clone the function so that we can use a mutable reference to
|
||||||
let result = func
|
// exec_state.
|
||||||
.call_fn(fn_args, &fn_dynamic_state, ctx.clone())
|
let func = exec_state.memory.get(fn_name, source_range)?.clone();
|
||||||
.await
|
let fn_dynamic_state = exec_state.dynamic_state.merge(&exec_state.memory);
|
||||||
.map_err(|e| {
|
|
||||||
// Add the call expression to the source ranges.
|
|
||||||
e.add_source_ranges(vec![self.into()])
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let result = result.ok_or_else(|| {
|
let return_value = {
|
||||||
let mut source_ranges: Vec<SourceRange> = vec![self.into()];
|
let previous_dynamic_state = std::mem::replace(&mut exec_state.dynamic_state, fn_dynamic_state);
|
||||||
|
let result = func.call_fn(fn_args, exec_state, ctx.clone()).await.map_err(|e| {
|
||||||
|
// Add the call expression to the source ranges.
|
||||||
|
e.add_source_ranges(vec![source_range])
|
||||||
|
});
|
||||||
|
exec_state.dynamic_state = previous_dynamic_state;
|
||||||
|
result?
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = return_value.ok_or_else(move || {
|
||||||
|
let mut source_ranges: Vec<SourceRange> = vec![source_range];
|
||||||
// We want to send the source range of the original function.
|
// We want to send the source range of the original function.
|
||||||
if let KclValue::Function { meta, .. } = func {
|
if let KclValue::Function { meta, .. } = func {
|
||||||
source_ranges = meta.iter().map(|m| m.source_range).collect();
|
source_ranges = meta.iter().map(|m| m.source_range).collect();
|
||||||
@ -1990,7 +1983,7 @@ impl TagDeclarator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute(&self, memory: &mut ProgramMemory) -> Result<KclValue, KclError> {
|
pub async fn execute(&self, exec_state: &mut ExecState) -> Result<KclValue, KclError> {
|
||||||
let memory_item = KclValue::TagIdentifier(Box::new(TagIdentifier {
|
let memory_item = KclValue::TagIdentifier(Box::new(TagIdentifier {
|
||||||
value: self.name.clone(),
|
value: self.name.clone(),
|
||||||
info: None,
|
info: None,
|
||||||
@ -1999,7 +1992,7 @@ impl TagDeclarator {
|
|||||||
}],
|
}],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
memory.add(&self.name, memory_item.clone(), self.into())?;
|
exec_state.memory.add(&self.name, memory_item.clone(), self.into())?;
|
||||||
|
|
||||||
Ok(self.into())
|
Ok(self.into())
|
||||||
}
|
}
|
||||||
@ -2136,65 +2129,18 @@ impl ArrayExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
pub async fn execute(
|
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
&self,
|
|
||||||
memory: &mut ProgramMemory,
|
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
let mut results = Vec::with_capacity(self.elements.len());
|
let mut results = Vec::with_capacity(self.elements.len());
|
||||||
|
|
||||||
for element in &self.elements {
|
for element in &self.elements {
|
||||||
let result = match element {
|
let metadata = Metadata::from(element);
|
||||||
Expr::Literal(literal) => literal.into(),
|
// TODO: Carry statement kind here so that we know if we're
|
||||||
Expr::TagDeclarator(tag) => tag.execute(memory).await?,
|
// inside a variable declaration.
|
||||||
Expr::None(none) => none.into(),
|
let value = ctx
|
||||||
Expr::Identifier(identifier) => {
|
.execute_expr(element, exec_state, &metadata, StatementKind::Expression)
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
.await?;
|
||||||
value.clone()
|
|
||||||
}
|
|
||||||
Expr::BinaryExpression(binary_expression) => {
|
|
||||||
binary_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::CallExpression(call_expression) => {
|
|
||||||
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
|
|
||||||
}
|
|
||||||
Expr::UnaryExpression(unary_expression) => {
|
|
||||||
unary_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::ObjectExpression(object_expression) => {
|
|
||||||
object_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
|
|
||||||
}
|
|
||||||
Expr::ArrayExpression(array_expression) => {
|
|
||||||
array_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
|
|
||||||
}
|
|
||||||
Expr::PipeExpression(pipe_expression) => {
|
|
||||||
pipe_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::PipeSubstitution(pipe_substitution) => {
|
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
|
|
||||||
source_ranges: vec![pipe_substitution.into()],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
Expr::MemberExpression(member_expression) => member_expression.get_result(memory)?,
|
|
||||||
Expr::FunctionExpression(function_expression) => {
|
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
message: format!("FunctionExpression not implemented here: {:?}", function_expression),
|
|
||||||
source_ranges: vec![function_expression.into()],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.get_json_value()?;
|
|
||||||
|
|
||||||
results.push(result);
|
results.push(value.get_json_value()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(KclValue::UserVal(UserVal {
|
Ok(KclValue::UserVal(UserVal {
|
||||||
@ -2279,61 +2225,13 @@ impl ObjectExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
pub async fn execute(
|
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
&self,
|
|
||||||
memory: &mut ProgramMemory,
|
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
let mut object = Map::new();
|
let mut object = Map::new();
|
||||||
for property in &self.properties {
|
for property in &self.properties {
|
||||||
let result = match &property.value {
|
let metadata = Metadata::from(&property.value);
|
||||||
Expr::Literal(literal) => literal.into(),
|
let result = ctx
|
||||||
Expr::TagDeclarator(tag) => tag.execute(memory).await?,
|
.execute_expr(&property.value, exec_state, &metadata, StatementKind::Expression)
|
||||||
Expr::None(none) => none.into(),
|
.await?;
|
||||||
Expr::Identifier(identifier) => {
|
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
|
||||||
value.clone()
|
|
||||||
}
|
|
||||||
Expr::BinaryExpression(binary_expression) => {
|
|
||||||
binary_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::CallExpression(call_expression) => {
|
|
||||||
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
|
|
||||||
}
|
|
||||||
Expr::UnaryExpression(unary_expression) => {
|
|
||||||
unary_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::ObjectExpression(object_expression) => {
|
|
||||||
object_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
|
|
||||||
}
|
|
||||||
Expr::ArrayExpression(array_expression) => {
|
|
||||||
array_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
|
|
||||||
}
|
|
||||||
Expr::PipeExpression(pipe_expression) => {
|
|
||||||
pipe_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::MemberExpression(member_expression) => member_expression.get_result(memory)?,
|
|
||||||
Expr::PipeSubstitution(pipe_substitution) => {
|
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
|
|
||||||
source_ranges: vec![pipe_substitution.into()],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
Expr::FunctionExpression(function_expression) => {
|
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
message: format!("FunctionExpression not implemented here: {:?}", function_expression),
|
|
||||||
source_ranges: vec![function_expression.into()],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
object.insert(property.key.name.clone(), result.get_json_value()?);
|
object.insert(property.key.name.clone(), result.get_json_value()?);
|
||||||
}
|
}
|
||||||
@ -2545,11 +2443,11 @@ impl MemberExpression {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_result_array(&self, memory: &mut ProgramMemory, index: usize) -> Result<KclValue, KclError> {
|
pub fn get_result_array(&self, exec_state: &mut ExecState, index: usize) -> Result<KclValue, KclError> {
|
||||||
let array = match &self.object {
|
let array = match &self.object {
|
||||||
MemberObject::MemberExpression(member_expr) => member_expr.get_result(memory)?,
|
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
||||||
MemberObject::Identifier(identifier) => {
|
MemberObject::Identifier(identifier) => {
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
||||||
value.clone()
|
value.clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2578,7 +2476,7 @@ impl MemberExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_result(&self, memory: &mut ProgramMemory) -> Result<KclValue, KclError> {
|
pub fn get_result(&self, exec_state: &mut ExecState) -> Result<KclValue, KclError> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Property {
|
enum Property {
|
||||||
Number(usize),
|
Number(usize),
|
||||||
@ -2605,7 +2503,7 @@ impl MemberExpression {
|
|||||||
Property::String(name.to_string())
|
Property::String(name.to_string())
|
||||||
} else {
|
} else {
|
||||||
// Actually evaluate memory to compute the property.
|
// Actually evaluate memory to compute the property.
|
||||||
let prop = memory.get(&name, property_src)?;
|
let prop = exec_state.memory.get(&name, property_src)?;
|
||||||
let KclValue::UserVal(prop) = prop else {
|
let KclValue::UserVal(prop) = prop else {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
source_ranges: property_sr,
|
source_ranges: property_sr,
|
||||||
@ -2667,9 +2565,9 @@ impl MemberExpression {
|
|||||||
|
|
||||||
let object = match &self.object {
|
let object = match &self.object {
|
||||||
// TODO: Don't use recursion here, use a loop.
|
// TODO: Don't use recursion here, use a loop.
|
||||||
MemberObject::MemberExpression(member_expr) => member_expr.get_result(memory)?,
|
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
||||||
MemberObject::Identifier(identifier) => {
|
MemberObject::Identifier(identifier) => {
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
||||||
value.clone()
|
value.clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2827,23 +2725,9 @@ impl BinaryExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
pub async fn get_result(
|
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
&self,
|
let left_json_value = self.left.get_result(exec_state, ctx).await?.get_json_value()?;
|
||||||
memory: &mut ProgramMemory,
|
let right_json_value = self.right.get_result(exec_state, ctx).await?.get_json_value()?;
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
let left_json_value = self
|
|
||||||
.left
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
.get_json_value()?;
|
|
||||||
let right_json_value = self
|
|
||||||
.right
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
.get_json_value()?;
|
|
||||||
|
|
||||||
// First check if we are doing string concatenation.
|
// First check if we are doing string concatenation.
|
||||||
if self.operator == BinaryOperator::Add {
|
if self.operator == BinaryOperator::Add {
|
||||||
@ -3043,19 +2927,9 @@ impl UnaryExpression {
|
|||||||
self.argument.get_constraint_level()
|
self.argument.get_constraint_level()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_result(
|
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
&self,
|
|
||||||
memory: &mut ProgramMemory,
|
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
if self.operator == UnaryOperator::Not {
|
if self.operator == UnaryOperator::Not {
|
||||||
let value = self
|
let value = self.argument.get_result(exec_state, ctx).await?.get_json_value()?;
|
||||||
.argument
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
.get_json_value()?;
|
|
||||||
let Some(bool_value) = json_as_bool(&value) else {
|
let Some(bool_value) = json_as_bool(&value) else {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!("Cannot apply unary operator ! to non-boolean value: {}", value),
|
message: format!("Cannot apply unary operator ! to non-boolean value: {}", value),
|
||||||
@ -3072,11 +2946,7 @@ impl UnaryExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let num = parse_json_number_as_f64(
|
let num = parse_json_number_as_f64(
|
||||||
&self
|
&self.argument.get_result(exec_state, ctx).await?.get_json_value()?,
|
||||||
.argument
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
|
||||||
.await?
|
|
||||||
.get_json_value()?,
|
|
||||||
self.into(),
|
self.into(),
|
||||||
)?;
|
)?;
|
||||||
Ok(KclValue::UserVal(UserVal {
|
Ok(KclValue::UserVal(UserVal {
|
||||||
@ -3204,14 +3074,9 @@ impl PipeExpression {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_result(
|
#[async_recursion]
|
||||||
&self,
|
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||||
memory: &mut ProgramMemory,
|
execute_pipe_body(exec_state, &self.body, self.into(), ctx).await
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
ctx: &ExecutorContext,
|
|
||||||
) -> Result<KclValue, KclError> {
|
|
||||||
execute_pipe_body(memory, dynamic_state, &self.body, pipe_info, self.into(), ctx).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.
|
||||||
@ -3222,45 +3087,49 @@ impl PipeExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
|
||||||
async fn execute_pipe_body(
|
async fn execute_pipe_body(
|
||||||
memory: &mut ProgramMemory,
|
exec_state: &mut ExecState,
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
body: &[Expr],
|
body: &[Expr],
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
ctx: &ExecutorContext,
|
ctx: &ExecutorContext,
|
||||||
) -> Result<KclValue, KclError> {
|
) -> Result<KclValue, KclError> {
|
||||||
let mut body = body.iter();
|
let Some((first, body)) = body.split_first() else {
|
||||||
let first = body.next().ok_or_else(|| {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
KclError::Semantic(KclErrorDetails {
|
|
||||||
message: "Pipe expressions cannot be empty".to_owned(),
|
message: "Pipe expressions cannot be empty".to_owned(),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
})
|
}));
|
||||||
})?;
|
};
|
||||||
// Evaluate the first element in the pipeline.
|
// Evaluate the first element in the pipeline.
|
||||||
// They use the `pipe_info` from some AST node above this, so that if pipe expression is nested in a larger pipe expression,
|
// They use the pipe_value from some AST node above this, so that if pipe expression is nested in a larger pipe expression,
|
||||||
// they use the % from the parent. After all, this pipe expression hasn't been executed yet, so it doesn't have any % value
|
// they use the % from the parent. After all, this pipe expression hasn't been executed yet, so it doesn't have any % value
|
||||||
// of its own.
|
// of its own.
|
||||||
let meta = Metadata {
|
let meta = Metadata {
|
||||||
source_range: SourceRange([first.start(), first.end()]),
|
source_range: SourceRange([first.start(), first.end()]),
|
||||||
};
|
};
|
||||||
let output = ctx
|
let output = ctx
|
||||||
.execute_expr(
|
.execute_expr(first, exec_state, &meta, StatementKind::Expression)
|
||||||
first,
|
|
||||||
memory,
|
|
||||||
dynamic_state,
|
|
||||||
pipe_info,
|
|
||||||
&meta,
|
|
||||||
StatementKind::Expression,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Now that we've evaluated the first child expression in the pipeline, following child expressions
|
// Now that we've evaluated the first child expression in the pipeline, following child expressions
|
||||||
// should use the previous child expression for %.
|
// should use the previous child expression for %.
|
||||||
// This means there's no more need for the previous `pipe_info` from the parent AST node above this one.
|
// This means there's no more need for the previous pipe_value from the parent AST node above this one.
|
||||||
let mut new_pipe_info = PipeInfo::new();
|
let previous_pipe_value = std::mem::replace(&mut exec_state.pipe_value, Some(output));
|
||||||
new_pipe_info.previous_results = Some(output);
|
|
||||||
// Evaluate remaining elements.
|
// Evaluate remaining elements.
|
||||||
|
let result = inner_execute_pipe_body(exec_state, body, ctx).await;
|
||||||
|
// Restore the previous pipe value.
|
||||||
|
exec_state.pipe_value = previous_pipe_value;
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Execute the tail of a pipe expression. exec_state.pipe_value must be set by
|
||||||
|
/// the caller.
|
||||||
|
#[async_recursion]
|
||||||
|
async fn inner_execute_pipe_body(
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
body: &[Expr],
|
||||||
|
ctx: &ExecutorContext,
|
||||||
|
) -> Result<KclValue, KclError> {
|
||||||
for expression in body {
|
for expression in body {
|
||||||
match expression {
|
match expression {
|
||||||
Expr::TagDeclarator(_) => {
|
Expr::TagDeclarator(_) => {
|
||||||
@ -3286,19 +3155,12 @@ async fn execute_pipe_body(
|
|||||||
source_range: SourceRange([expression.start(), expression.end()]),
|
source_range: SourceRange([expression.start(), expression.end()]),
|
||||||
};
|
};
|
||||||
let output = ctx
|
let output = ctx
|
||||||
.execute_expr(
|
.execute_expr(expression, exec_state, &metadata, StatementKind::Expression)
|
||||||
expression,
|
|
||||||
memory,
|
|
||||||
dynamic_state,
|
|
||||||
&new_pipe_info,
|
|
||||||
&metadata,
|
|
||||||
StatementKind::Expression,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
new_pipe_info.previous_results = Some(output);
|
exec_state.pipe_value = Some(output);
|
||||||
}
|
}
|
||||||
// Safe to unwrap here, because `newpipe_info` always has something pushed in when the `match first` executes.
|
// Safe to unwrap here, because pipe_value always has something pushed in when the `match first` executes.
|
||||||
let final_output = new_pipe_info.previous_results.unwrap();
|
let final_output = exec_state.pipe_value.take().unwrap();
|
||||||
Ok(final_output)
|
Ok(final_output)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3430,14 +3292,6 @@ pub struct FunctionExpression {
|
|||||||
|
|
||||||
impl_value_meta!(FunctionExpression);
|
impl_value_meta!(FunctionExpression);
|
||||||
|
|
||||||
pub struct FunctionExpressionParts {
|
|
||||||
pub start: usize,
|
|
||||||
pub end: usize,
|
|
||||||
pub params_required: Vec<Parameter>,
|
|
||||||
pub params_optional: Vec<Parameter>,
|
|
||||||
pub body: Program,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct RequiredParamAfterOptionalParam(pub Parameter);
|
pub struct RequiredParamAfterOptionalParam(pub Parameter);
|
||||||
|
|
||||||
@ -3472,36 +3326,28 @@ impl FunctionExpression {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn into_parts(self) -> Result<FunctionExpressionParts, RequiredParamAfterOptionalParam> {
|
pub fn required_and_optional_params(
|
||||||
|
&self,
|
||||||
|
) -> Result<(&[Parameter], &[Parameter]), RequiredParamAfterOptionalParam> {
|
||||||
let Self {
|
let Self {
|
||||||
start,
|
start: _,
|
||||||
end,
|
end: _,
|
||||||
params,
|
params,
|
||||||
body,
|
body: _,
|
||||||
digest: _,
|
digest: _,
|
||||||
return_type: _,
|
return_type: _,
|
||||||
} = self;
|
} = self;
|
||||||
let mut params_required = Vec::with_capacity(params.len());
|
let mut found_optional = false;
|
||||||
let mut params_optional = Vec::with_capacity(params.len());
|
|
||||||
for param in params {
|
for param in params {
|
||||||
if param.optional {
|
if param.optional {
|
||||||
params_optional.push(param);
|
found_optional = true;
|
||||||
} else {
|
} else if found_optional {
|
||||||
if !params_optional.is_empty() {
|
return Err(RequiredParamAfterOptionalParam(param.clone()));
|
||||||
return Err(RequiredParamAfterOptionalParam(param));
|
|
||||||
}
|
|
||||||
params_required.push(param);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
params_required.shrink_to_fit();
|
let boundary = self.params.partition_point(|param| !param.optional);
|
||||||
params_optional.shrink_to_fit();
|
// SAFETY: split_at panics if the boundary is greater than the length.
|
||||||
Ok(FunctionExpressionParts {
|
Ok(self.params.split_at(boundary))
|
||||||
start,
|
|
||||||
end,
|
|
||||||
params_required,
|
|
||||||
params_optional,
|
|
||||||
body,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Required parameters must be declared before optional parameters.
|
/// Required parameters must be declared before optional parameters.
|
||||||
|
@ -23,6 +23,20 @@ use crate::{
|
|||||||
std::{FnAsArg, StdLib},
|
std::{FnAsArg, StdLib},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// State for executing a program.
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ExecState {
|
||||||
|
/// Program variable bindings.
|
||||||
|
pub memory: ProgramMemory,
|
||||||
|
/// Dynamic state that follows dynamic flow of the program.
|
||||||
|
pub dynamic_state: DynamicState,
|
||||||
|
/// The current value of the pipe operator returned from the previous
|
||||||
|
/// expression. If we're not currently in a pipeline, this will be None.
|
||||||
|
pub pipe_value: Option<KclValue>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@ -227,7 +241,7 @@ impl Environment {
|
|||||||
/// Dynamic state that depends on the dynamic flow of the program, like the call
|
/// Dynamic state that depends on the dynamic flow of the program, like the call
|
||||||
/// stack. If the language had exceptions, for example, you could store the
|
/// stack. If the language had exceptions, for example, you could store the
|
||||||
/// stack of exception handlers here.
|
/// stack of exception handlers here.
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
|
||||||
pub struct DynamicState {
|
pub struct DynamicState {
|
||||||
pub extrude_group_ids: Vec<ExtrudeGroupLazyIds>,
|
pub extrude_group_ids: Vec<ExtrudeGroupLazyIds>,
|
||||||
}
|
}
|
||||||
@ -730,25 +744,10 @@ pub type MemoryFunction =
|
|||||||
memory: ProgramMemory,
|
memory: ProgramMemory,
|
||||||
expression: Box<FunctionExpression>,
|
expression: Box<FunctionExpression>,
|
||||||
metadata: Vec<Metadata>,
|
metadata: Vec<Metadata>,
|
||||||
dynamic_state: DynamicState,
|
exec_state: &ExecState,
|
||||||
ctx: ExecutorContext,
|
ctx: ExecutorContext,
|
||||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<KclValue>, KclError>> + Send>>;
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<KclValue>, KclError>> + Send>>;
|
||||||
|
|
||||||
fn force_memory_function<
|
|
||||||
F: Fn(
|
|
||||||
Vec<KclValue>,
|
|
||||||
ProgramMemory,
|
|
||||||
Box<FunctionExpression>,
|
|
||||||
Vec<Metadata>,
|
|
||||||
DynamicState,
|
|
||||||
ExecutorContext,
|
|
||||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<KclValue>, KclError>> + Send>>,
|
|
||||||
>(
|
|
||||||
f: F,
|
|
||||||
) -> F {
|
|
||||||
f
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<KclValue> for Vec<SourceRange> {
|
impl From<KclValue> for Vec<SourceRange> {
|
||||||
fn from(item: KclValue) -> Self {
|
fn from(item: KclValue) -> Self {
|
||||||
match item {
|
match item {
|
||||||
@ -848,9 +847,8 @@ impl KclValue {
|
|||||||
else {
|
else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let func = func.as_ref()?;
|
|
||||||
Some(FnAsArg {
|
Some(FnAsArg {
|
||||||
func,
|
func: func.as_ref(),
|
||||||
expr: expression.to_owned(),
|
expr: expression.to_owned(),
|
||||||
memory: memory.to_owned(),
|
memory: memory.to_owned(),
|
||||||
})
|
})
|
||||||
@ -904,7 +902,7 @@ impl KclValue {
|
|||||||
pub async fn call_fn(
|
pub async fn call_fn(
|
||||||
&self,
|
&self,
|
||||||
args: Vec<KclValue>,
|
args: Vec<KclValue>,
|
||||||
dynamic_state: &DynamicState,
|
exec_state: &mut ExecState,
|
||||||
ctx: ExecutorContext,
|
ctx: ExecutorContext,
|
||||||
) -> Result<Option<KclValue>, KclError> {
|
) -> Result<Option<KclValue>, KclError> {
|
||||||
let KclValue::Function {
|
let KclValue::Function {
|
||||||
@ -919,21 +917,19 @@ impl KclValue {
|
|||||||
source_ranges: vec![],
|
source_ranges: vec![],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
let Some(func) = func else {
|
if let Some(func) = func {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
func(
|
||||||
message: format!("Not a function: {:?}", expression),
|
args,
|
||||||
source_ranges: vec![],
|
closure_memory.as_ref().clone(),
|
||||||
}));
|
expression.clone(),
|
||||||
};
|
meta.clone(),
|
||||||
func(
|
exec_state,
|
||||||
args,
|
ctx,
|
||||||
closure_memory.as_ref().clone(),
|
)
|
||||||
expression.clone(),
|
.await
|
||||||
meta.clone(),
|
} else {
|
||||||
dynamic_state.clone(),
|
call_user_defined_function(args, closure_memory.as_ref(), expression.as_ref(), exec_state, &ctx).await
|
||||||
ctx,
|
}
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1356,6 +1352,14 @@ impl From<&ReturnStatement> for Metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&Expr> for Metadata {
|
||||||
|
fn from(expr: &Expr) -> Self {
|
||||||
|
Self {
|
||||||
|
source_range: SourceRange::from(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A base path.
|
/// A base path.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
@ -1573,25 +1577,6 @@ impl ExtrudeSurface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct PipeInfo {
|
|
||||||
pub previous_results: Option<KclValue>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PipeInfo {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { previous_results: None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PipeInfo {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The executor context.
|
/// The executor context.
|
||||||
/// Cloning will return another handle to the same engine connection/session,
|
/// Cloning will return another handle to the same engine connection/session,
|
||||||
/// as this uses `Arc` under the hood.
|
/// as this uses `Arc` under the hood.
|
||||||
@ -1773,7 +1758,7 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
program: &crate::ast::types::Program,
|
program: &crate::ast::types::Program,
|
||||||
memory: Option<ProgramMemory>,
|
memory: Option<ProgramMemory>,
|
||||||
) -> Result<ProgramMemory, KclError> {
|
) -> Result<ExecState, KclError> {
|
||||||
self.run_with_session_data(program, memory).await.map(|x| x.0)
|
self.run_with_session_data(program, memory).await.map(|x| x.0)
|
||||||
}
|
}
|
||||||
/// Perform the execution of a program.
|
/// Perform the execution of a program.
|
||||||
@ -1783,7 +1768,7 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
program: &crate::ast::types::Program,
|
program: &crate::ast::types::Program,
|
||||||
memory: Option<ProgramMemory>,
|
memory: Option<ProgramMemory>,
|
||||||
) -> Result<(ProgramMemory, Option<ModelingSessionData>), KclError> {
|
) -> Result<(ExecState, Option<ModelingSessionData>), KclError> {
|
||||||
// Before we even start executing the program, set the units.
|
// Before we even start executing the program, set the units.
|
||||||
self.engine
|
self.engine
|
||||||
.batch_modeling_cmd(
|
.batch_modeling_cmd(
|
||||||
@ -1794,22 +1779,19 @@ impl ExecutorContext {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let mut memory = if let Some(memory) = memory {
|
let memory = if let Some(memory) = memory {
|
||||||
memory.clone()
|
memory.clone()
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Default::default()
|
||||||
};
|
};
|
||||||
let mut dynamic_state = DynamicState::default();
|
let mut exec_state = ExecState {
|
||||||
let final_memory = self
|
memory,
|
||||||
.inner_execute(
|
..Default::default()
|
||||||
program,
|
};
|
||||||
&mut memory,
|
self.inner_execute(program, &mut exec_state, crate::executor::BodyType::Root)
|
||||||
&mut dynamic_state,
|
|
||||||
crate::executor::BodyType::Root,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
let session_data = self.engine.get_session_data();
|
let session_data = self.engine.get_session_data();
|
||||||
Ok((final_memory, session_data))
|
Ok((exec_state, session_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute an AST's program.
|
/// Execute an AST's program.
|
||||||
@ -1817,12 +1799,9 @@ impl ExecutorContext {
|
|||||||
pub(crate) async fn inner_execute(
|
pub(crate) async fn inner_execute(
|
||||||
&self,
|
&self,
|
||||||
program: &crate::ast::types::Program,
|
program: &crate::ast::types::Program,
|
||||||
memory: &mut ProgramMemory,
|
exec_state: &mut ExecState,
|
||||||
dynamic_state: &mut DynamicState,
|
|
||||||
body_type: BodyType,
|
body_type: BodyType,
|
||||||
) -> Result<ProgramMemory, KclError> {
|
) -> Result<(), KclError> {
|
||||||
let pipe_info = PipeInfo::default();
|
|
||||||
|
|
||||||
// Iterate over the body of the program.
|
// Iterate over the body of the program.
|
||||||
for statement in &program.body {
|
for statement in &program.body {
|
||||||
match statement {
|
match statement {
|
||||||
@ -1831,9 +1810,7 @@ impl ExecutorContext {
|
|||||||
// Discard return value.
|
// Discard return value.
|
||||||
self.execute_expr(
|
self.execute_expr(
|
||||||
&expression_statement.expression,
|
&expression_statement.expression,
|
||||||
memory,
|
exec_state,
|
||||||
dynamic_state,
|
|
||||||
&pipe_info,
|
|
||||||
&metadata,
|
&metadata,
|
||||||
StatementKind::Expression,
|
StatementKind::Expression,
|
||||||
)
|
)
|
||||||
@ -1848,14 +1825,12 @@ impl ExecutorContext {
|
|||||||
let memory_item = self
|
let memory_item = self
|
||||||
.execute_expr(
|
.execute_expr(
|
||||||
&declaration.init,
|
&declaration.init,
|
||||||
memory,
|
exec_state,
|
||||||
dynamic_state,
|
|
||||||
&pipe_info,
|
|
||||||
&metadata,
|
&metadata,
|
||||||
StatementKind::Declaration { name: &var_name },
|
StatementKind::Declaration { name: &var_name },
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
memory.add(&var_name, memory_item, source_range)?;
|
exec_state.memory.add(&var_name, memory_item, source_range)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BodyItem::ReturnStatement(return_statement) => {
|
BodyItem::ReturnStatement(return_statement) => {
|
||||||
@ -1863,14 +1838,12 @@ impl ExecutorContext {
|
|||||||
let value = self
|
let value = self
|
||||||
.execute_expr(
|
.execute_expr(
|
||||||
&return_statement.argument,
|
&return_statement.argument,
|
||||||
memory,
|
exec_state,
|
||||||
dynamic_state,
|
|
||||||
&pipe_info,
|
|
||||||
&metadata,
|
&metadata,
|
||||||
StatementKind::Expression,
|
StatementKind::Expression,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
memory.return_ = Some(value);
|
exec_state.memory.return_ = Some(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1887,81 +1860,38 @@ impl ExecutorContext {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(memory.clone())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_expr<'a>(
|
pub async fn execute_expr<'a>(
|
||||||
&self,
|
&self,
|
||||||
init: &Expr,
|
init: &Expr,
|
||||||
memory: &mut ProgramMemory,
|
exec_state: &mut ExecState,
|
||||||
dynamic_state: &DynamicState,
|
|
||||||
pipe_info: &PipeInfo,
|
|
||||||
metadata: &Metadata,
|
metadata: &Metadata,
|
||||||
statement_kind: StatementKind<'a>,
|
statement_kind: StatementKind<'a>,
|
||||||
) -> Result<KclValue, KclError> {
|
) -> Result<KclValue, KclError> {
|
||||||
let item = match init {
|
let item = match init {
|
||||||
Expr::None(none) => KclValue::from(none),
|
Expr::None(none) => KclValue::from(none),
|
||||||
Expr::Literal(literal) => KclValue::from(literal),
|
Expr::Literal(literal) => KclValue::from(literal),
|
||||||
Expr::TagDeclarator(tag) => tag.execute(memory).await?,
|
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
|
||||||
Expr::Identifier(identifier) => {
|
Expr::Identifier(identifier) => {
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
||||||
value.clone()
|
value.clone()
|
||||||
}
|
}
|
||||||
Expr::BinaryExpression(binary_expression) => {
|
Expr::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, self).await?,
|
||||||
binary_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, self)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::FunctionExpression(function_expression) => {
|
Expr::FunctionExpression(function_expression) => {
|
||||||
let mem_func = force_memory_function(
|
|
||||||
|args: Vec<KclValue>,
|
|
||||||
memory: ProgramMemory,
|
|
||||||
function_expression: Box<FunctionExpression>,
|
|
||||||
_metadata: Vec<Metadata>,
|
|
||||||
mut dynamic_state: DynamicState,
|
|
||||||
ctx: ExecutorContext| {
|
|
||||||
Box::pin(async move {
|
|
||||||
// Create a new environment to execute the function
|
|
||||||
// body in so that local variables shadow variables
|
|
||||||
// in the parent scope. The new environment's
|
|
||||||
// parent should be the environment of the closure.
|
|
||||||
let mut body_memory = memory.clone();
|
|
||||||
let closure_env = memory.current_env;
|
|
||||||
let body_env = body_memory.new_env_for_call(closure_env);
|
|
||||||
body_memory.current_env = body_env;
|
|
||||||
let mut fn_memory = assign_args_to_params(&function_expression, args, body_memory)?;
|
|
||||||
|
|
||||||
let result = ctx
|
|
||||||
.inner_execute(
|
|
||||||
&function_expression.body,
|
|
||||||
&mut fn_memory,
|
|
||||||
&mut dynamic_state,
|
|
||||||
BodyType::Block,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(result.return_)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
);
|
|
||||||
// Cloning memory here is crucial for semantics so that we close
|
// Cloning memory here is crucial for semantics so that we close
|
||||||
// over variables. Variables defined lexically later shouldn't
|
// over variables. Variables defined lexically later shouldn't
|
||||||
// be available to the function body.
|
// be available to the function body.
|
||||||
KclValue::Function {
|
KclValue::Function {
|
||||||
expression: function_expression.clone(),
|
expression: function_expression.clone(),
|
||||||
meta: vec![metadata.to_owned()],
|
meta: vec![metadata.to_owned()],
|
||||||
func: Some(mem_func),
|
func: None,
|
||||||
memory: Box::new(memory.clone()),
|
memory: Box::new(exec_state.memory.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::CallExpression(call_expression) => {
|
Expr::CallExpression(call_expression) => call_expression.execute(exec_state, self).await?,
|
||||||
call_expression.execute(memory, dynamic_state, pipe_info, self).await?
|
Expr::PipeExpression(pipe_expression) => pipe_expression.get_result(exec_state, self).await?,
|
||||||
}
|
|
||||||
Expr::PipeExpression(pipe_expression) => {
|
|
||||||
pipe_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, self)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::PipeSubstitution(pipe_substitution) => match statement_kind {
|
Expr::PipeSubstitution(pipe_substitution) => match statement_kind {
|
||||||
StatementKind::Declaration { name } => {
|
StatementKind::Declaration { name } => {
|
||||||
let message = format!(
|
let message = format!(
|
||||||
@ -1973,7 +1903,7 @@ impl ExecutorContext {
|
|||||||
source_ranges: vec![pipe_substitution.into()],
|
source_ranges: vec![pipe_substitution.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
StatementKind::Expression => match pipe_info.previous_results.clone() {
|
StatementKind::Expression => match exec_state.pipe_value.clone() {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => {
|
None => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
@ -1983,20 +1913,10 @@ impl ExecutorContext {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Expr::ArrayExpression(array_expression) => {
|
Expr::ArrayExpression(array_expression) => array_expression.execute(exec_state, self).await?,
|
||||||
array_expression.execute(memory, dynamic_state, pipe_info, self).await?
|
Expr::ObjectExpression(object_expression) => object_expression.execute(exec_state, self).await?,
|
||||||
}
|
Expr::MemberExpression(member_expression) => member_expression.get_result(exec_state)?,
|
||||||
Expr::ObjectExpression(object_expression) => {
|
Expr::UnaryExpression(unary_expression) => unary_expression.get_result(exec_state, self).await?,
|
||||||
object_expression
|
|
||||||
.execute(memory, dynamic_state, pipe_info, self)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
Expr::MemberExpression(member_expression) => member_expression.get_result(memory)?,
|
|
||||||
Expr::UnaryExpression(unary_expression) => {
|
|
||||||
unary_expression
|
|
||||||
.get_result(memory, dynamic_state, pipe_info, self)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok(item)
|
Ok(item)
|
||||||
}
|
}
|
||||||
@ -2097,6 +2017,36 @@ fn assign_args_to_params(
|
|||||||
Ok(fn_memory)
|
Ok(fn_memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn call_user_defined_function(
|
||||||
|
args: Vec<KclValue>,
|
||||||
|
memory: &ProgramMemory,
|
||||||
|
function_expression: &FunctionExpression,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
ctx: &ExecutorContext,
|
||||||
|
) -> Result<Option<KclValue>, KclError> {
|
||||||
|
// Create a new environment to execute the function body in so that local
|
||||||
|
// variables shadow variables in the parent scope. The new environment's
|
||||||
|
// parent should be the environment of the closure.
|
||||||
|
let mut body_memory = memory.clone();
|
||||||
|
let body_env = body_memory.new_env_for_call(memory.current_env);
|
||||||
|
body_memory.current_env = body_env;
|
||||||
|
let fn_memory = assign_args_to_params(function_expression, args, body_memory)?;
|
||||||
|
|
||||||
|
// Execute the function body using the memory we just created.
|
||||||
|
let (result, fn_memory) = {
|
||||||
|
let previous_memory = std::mem::replace(&mut exec_state.memory, fn_memory);
|
||||||
|
let result = ctx
|
||||||
|
.inner_execute(&function_expression.body, exec_state, BodyType::Block)
|
||||||
|
.await;
|
||||||
|
// Restore the previous memory.
|
||||||
|
let fn_memory = std::mem::replace(&mut exec_state.memory, previous_memory);
|
||||||
|
|
||||||
|
(result, fn_memory)
|
||||||
|
};
|
||||||
|
|
||||||
|
result.map(|()| fn_memory.return_)
|
||||||
|
}
|
||||||
|
|
||||||
pub enum StatementKind<'a> {
|
pub enum StatementKind<'a> {
|
||||||
Declaration { name: &'a str },
|
Declaration { name: &'a str },
|
||||||
Expression,
|
Expression,
|
||||||
@ -2122,9 +2072,9 @@ mod tests {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
};
|
};
|
||||||
let memory = ctx.run(&program, None).await?;
|
let exec_state = ctx.run(&program, None).await?;
|
||||||
|
|
||||||
Ok(memory)
|
Ok(exec_state.memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to get a JSON value from memory and unwrap.
|
/// Convenience function to get a JSON value from memory and unwrap.
|
||||||
|
@ -3,30 +3,36 @@ use schemars::JsonSchema;
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::types::FunctionExpression,
|
ast::types::FunctionExpression,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
executor::{DynamicState, ExecutorContext, KclValue, MemoryFunction, Metadata, ProgramMemory},
|
executor::{
|
||||||
|
call_user_defined_function, ExecState, ExecutorContext, KclValue, MemoryFunction, Metadata, ProgramMemory,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A function being used as a parameter into a stdlib function.
|
/// A function being used as a parameter into a stdlib function. This is a
|
||||||
|
/// closure, plus everything needed to execute it.
|
||||||
pub struct FunctionParam<'a> {
|
pub struct FunctionParam<'a> {
|
||||||
pub inner: &'a MemoryFunction,
|
pub inner: Option<&'a MemoryFunction>,
|
||||||
pub memory: ProgramMemory,
|
pub memory: ProgramMemory,
|
||||||
pub dynamic_state: DynamicState,
|
|
||||||
pub fn_expr: Box<FunctionExpression>,
|
pub fn_expr: Box<FunctionExpression>,
|
||||||
pub meta: Vec<Metadata>,
|
pub meta: Vec<Metadata>,
|
||||||
pub ctx: ExecutorContext,
|
pub ctx: ExecutorContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FunctionParam<'a> {
|
impl<'a> FunctionParam<'a> {
|
||||||
pub async fn call(&self, args: Vec<KclValue>) -> Result<Option<KclValue>, KclError> {
|
pub async fn call(&self, exec_state: &mut ExecState, args: Vec<KclValue>) -> Result<Option<KclValue>, KclError> {
|
||||||
(self.inner)(
|
if let Some(inner) = self.inner {
|
||||||
args,
|
inner(
|
||||||
self.memory.clone(),
|
args,
|
||||||
self.fn_expr.clone(),
|
self.memory.clone(),
|
||||||
self.meta.clone(),
|
self.fn_expr.clone(),
|
||||||
self.dynamic_state.clone(),
|
self.meta.clone(),
|
||||||
self.ctx.clone(),
|
exec_state,
|
||||||
)
|
self.ctx.clone(),
|
||||||
.await
|
)
|
||||||
|
.await
|
||||||
|
} else {
|
||||||
|
call_user_defined_function(args, &self.memory, self.fn_expr.as_ref(), exec_state, &self.ctx).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,8 +591,8 @@ impl Backend {
|
|||||||
// Clear the scene, before we execute so it's not fugly as shit.
|
// Clear the scene, before we execute so it's not fugly as shit.
|
||||||
executor_ctx.engine.clear_scene(SourceRange::default()).await?;
|
executor_ctx.engine.clear_scene(SourceRange::default()).await?;
|
||||||
|
|
||||||
let memory = match executor_ctx.run(ast, None).await {
|
let exec_state = match executor_ctx.run(ast, None).await {
|
||||||
Ok(memory) => memory,
|
Ok(exec_state) => exec_state,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.memory_map.remove(params.uri.as_str());
|
self.memory_map.remove(params.uri.as_str());
|
||||||
self.add_to_diagnostics(params, &[err], false).await;
|
self.add_to_diagnostics(params, &[err], false).await;
|
||||||
@ -603,11 +603,12 @@ impl Backend {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.memory_map.insert(params.uri.to_string(), memory.clone());
|
self.memory_map
|
||||||
|
.insert(params.uri.to_string(), exec_state.memory.clone());
|
||||||
|
|
||||||
// Send the notification to the client that the memory was updated.
|
// Send the notification to the client that the memory was updated.
|
||||||
self.client
|
self.client
|
||||||
.send_notification::<custom_notifications::MemoryUpdated>(memory)
|
.send_notification::<custom_notifications::MemoryUpdated>(exec_state.memory)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -8,8 +8,8 @@ use crate::{
|
|||||||
ast::types::{parse_json_number_as_f64, TagDeclarator},
|
ast::types::{parse_json_number_as_f64, TagDeclarator},
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
DynamicState, ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, KclValue, Metadata,
|
ExecState, ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, KclValue, Metadata, SketchGroup,
|
||||||
ProgramMemory, SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier,
|
SketchGroupSet, SketchSurface, SourceRange, TagIdentifier,
|
||||||
},
|
},
|
||||||
std::{shapes::SketchSurfaceOrGroup, sketch::FaceTag, FnAsArg},
|
std::{shapes::SketchSurfaceOrGroup, sketch::FaceTag, FnAsArg},
|
||||||
};
|
};
|
||||||
@ -19,24 +19,14 @@ pub struct Args {
|
|||||||
pub args: Vec<KclValue>,
|
pub args: Vec<KclValue>,
|
||||||
pub source_range: SourceRange,
|
pub source_range: SourceRange,
|
||||||
pub ctx: ExecutorContext,
|
pub ctx: ExecutorContext,
|
||||||
pub current_program_memory: ProgramMemory,
|
|
||||||
pub dynamic_state: DynamicState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
pub fn new(
|
pub fn new(args: Vec<KclValue>, source_range: SourceRange, ctx: ExecutorContext) -> Self {
|
||||||
args: Vec<KclValue>,
|
|
||||||
source_range: SourceRange,
|
|
||||||
ctx: ExecutorContext,
|
|
||||||
current_program_memory: ProgramMemory,
|
|
||||||
dynamic_state: DynamicState,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
args,
|
args,
|
||||||
source_range,
|
source_range,
|
||||||
ctx,
|
ctx,
|
||||||
current_program_memory,
|
|
||||||
dynamic_state,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +44,6 @@ impl Args {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
is_mock: true,
|
is_mock: true,
|
||||||
},
|
},
|
||||||
current_program_memory: ProgramMemory::default(),
|
|
||||||
dynamic_state: DynamicState::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +76,12 @@ impl Args {
|
|||||||
self.ctx.engine.send_modeling_cmd(id, self.source_range, cmd).await
|
self.ctx.engine.send_modeling_cmd(id, self.source_range, cmd).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tag_info_from_memory<'a>(
|
fn get_tag_info_from_memory<'a, 'e>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
exec_state: &'e mut ExecState,
|
||||||
tag: &'a TagIdentifier,
|
tag: &'a TagIdentifier,
|
||||||
) -> Result<&'a crate::executor::TagEngineInfo, KclError> {
|
) -> Result<&'e crate::executor::TagEngineInfo, KclError> {
|
||||||
if let KclValue::TagIdentifier(t) = self.current_program_memory.get(&tag.value, self.source_range)? {
|
if let KclValue::TagIdentifier(t) = exec_state.memory.get(&tag.value, self.source_range)? {
|
||||||
Ok(t.info.as_ref().ok_or_else(|| {
|
Ok(t.info.as_ref().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Tag `{}` does not have engine info", tag.value),
|
message: format!("Tag `{}` does not have engine info", tag.value),
|
||||||
@ -107,34 +96,43 @@ impl Args {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_tag_engine_info<'a>(
|
pub(crate) fn get_tag_engine_info<'a, 'e>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
exec_state: &'e mut ExecState,
|
||||||
tag: &'a TagIdentifier,
|
tag: &'a TagIdentifier,
|
||||||
) -> Result<&'a crate::executor::TagEngineInfo, KclError> {
|
) -> Result<&'a crate::executor::TagEngineInfo, KclError>
|
||||||
|
where
|
||||||
|
'e: 'a,
|
||||||
|
{
|
||||||
if let Some(info) = &tag.info {
|
if let Some(info) = &tag.info {
|
||||||
return Ok(info);
|
return Ok(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get_tag_info_from_memory(tag)
|
self.get_tag_info_from_memory(exec_state, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tag_engine_info_check_surface<'a>(
|
fn get_tag_engine_info_check_surface<'a, 'e>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
exec_state: &'e mut ExecState,
|
||||||
tag: &'a TagIdentifier,
|
tag: &'a TagIdentifier,
|
||||||
) -> Result<&'a crate::executor::TagEngineInfo, KclError> {
|
) -> Result<&'a crate::executor::TagEngineInfo, KclError>
|
||||||
|
where
|
||||||
|
'e: 'a,
|
||||||
|
{
|
||||||
if let Some(info) = &tag.info {
|
if let Some(info) = &tag.info {
|
||||||
if info.surface.is_some() {
|
if info.surface.is_some() {
|
||||||
return Ok(info);
|
return Ok(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get_tag_info_from_memory(tag)
|
self.get_tag_info_from_memory(exec_state, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush just the fillets and chamfers for this specific ExtrudeGroupSet.
|
/// Flush just the fillets and chamfers for this specific ExtrudeGroupSet.
|
||||||
#[allow(clippy::vec_box)]
|
#[allow(clippy::vec_box)]
|
||||||
pub(crate) async fn flush_batch_for_extrude_group_set(
|
pub(crate) async fn flush_batch_for_extrude_group_set(
|
||||||
&self,
|
&self,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
extrude_groups: Vec<Box<ExtrudeGroup>>,
|
extrude_groups: Vec<Box<ExtrudeGroup>>,
|
||||||
) -> Result<(), KclError> {
|
) -> Result<(), KclError> {
|
||||||
// Make sure we don't traverse sketch_groups more than once.
|
// Make sure we don't traverse sketch_groups more than once.
|
||||||
@ -148,12 +146,13 @@ impl Args {
|
|||||||
if !traversed_sketch_groups.contains(&sketch_group_id) {
|
if !traversed_sketch_groups.contains(&sketch_group_id) {
|
||||||
// Find all the extrude groups on the same shared sketch group.
|
// Find all the extrude groups on the same shared sketch group.
|
||||||
ids.extend(
|
ids.extend(
|
||||||
self.current_program_memory
|
exec_state
|
||||||
|
.memory
|
||||||
.find_extrude_groups_on_sketch_group(extrude_group.sketch_group.id)
|
.find_extrude_groups_on_sketch_group(extrude_group.sketch_group.id)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|eg| eg.get_all_edge_cut_ids()),
|
.flat_map(|eg| eg.get_all_edge_cut_ids()),
|
||||||
);
|
);
|
||||||
ids.extend(self.dynamic_state.edge_cut_ids_on_sketch_group(sketch_group_id));
|
ids.extend(exec_state.dynamic_state.edge_cut_ids_on_sketch_group(sketch_group_id));
|
||||||
traversed_sketch_groups.push(sketch_group_id);
|
traversed_sketch_groups.push(sketch_group_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,6 +379,7 @@ impl Args {
|
|||||||
|
|
||||||
pub(crate) async fn get_adjacent_face_to_tag(
|
pub(crate) async fn get_adjacent_face_to_tag(
|
||||||
&self,
|
&self,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
tag: &TagIdentifier,
|
tag: &TagIdentifier,
|
||||||
must_be_planar: bool,
|
must_be_planar: bool,
|
||||||
) -> Result<uuid::Uuid, KclError> {
|
) -> Result<uuid::Uuid, KclError> {
|
||||||
@ -390,7 +390,7 @@ impl Args {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let engine_info = self.get_tag_engine_info_check_surface(tag)?;
|
let engine_info = self.get_tag_engine_info_check_surface(exec_state, tag)?;
|
||||||
|
|
||||||
let surface = engine_info.surface.as_ref().ok_or_else(|| {
|
let surface = engine_info.surface.as_ref().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
|
@ -3,14 +3,14 @@ use schemars::JsonSchema;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{KclValue, SketchGroup, SourceRange, UserVal},
|
executor::{ExecState, KclValue, SketchGroup, SourceRange, UserVal},
|
||||||
function_param::FunctionParam,
|
function_param::FunctionParam,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{args::FromArgs, Args, FnAsArg};
|
use super::{args::FromArgs, Args, FnAsArg};
|
||||||
|
|
||||||
/// For each item in an array, update a value.
|
/// For each item in an array, update a value.
|
||||||
pub async fn array_reduce(args: Args) -> Result<KclValue, KclError> {
|
pub async fn array_reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (array, start, f): (Vec<u64>, SketchGroup, FnAsArg<'_>) = FromArgs::from_args(&args, 0)?;
|
let (array, start, f): (Vec<u64>, SketchGroup, FnAsArg<'_>) = FromArgs::from_args(&args, 0)?;
|
||||||
let reduce_fn = FunctionParam {
|
let reduce_fn = FunctionParam {
|
||||||
inner: f.func,
|
inner: f.func,
|
||||||
@ -18,9 +18,8 @@ pub async fn array_reduce(args: Args) -> Result<KclValue, KclError> {
|
|||||||
meta: vec![args.source_range.into()],
|
meta: vec![args.source_range.into()],
|
||||||
ctx: args.ctx.clone(),
|
ctx: args.ctx.clone(),
|
||||||
memory: *f.memory,
|
memory: *f.memory,
|
||||||
dynamic_state: args.dynamic_state.clone(),
|
|
||||||
};
|
};
|
||||||
inner_array_reduce(array, start, reduce_fn, &args)
|
inner_array_reduce(array, start, reduce_fn, exec_state, &args)
|
||||||
.await
|
.await
|
||||||
.map(|sg| KclValue::UserVal(UserVal::set(sg.meta.clone(), sg)))
|
.map(|sg| KclValue::UserVal(UserVal::set(sg.meta.clone(), sg)))
|
||||||
}
|
}
|
||||||
@ -46,11 +45,12 @@ async fn inner_array_reduce<'a>(
|
|||||||
array: Vec<u64>,
|
array: Vec<u64>,
|
||||||
start: SketchGroup,
|
start: SketchGroup,
|
||||||
reduce_fn: FunctionParam<'a>,
|
reduce_fn: FunctionParam<'a>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: &'a Args,
|
args: &'a Args,
|
||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
let mut reduced = start;
|
let mut reduced = start;
|
||||||
for i in array {
|
for i in array {
|
||||||
reduced = call_reduce_closure(i, reduced, &reduce_fn, args.source_range).await?;
|
reduced = call_reduce_closure(i, reduced, &reduce_fn, args.source_range, exec_state).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(reduced)
|
Ok(reduced)
|
||||||
@ -61,6 +61,7 @@ async fn call_reduce_closure<'a>(
|
|||||||
start: SketchGroup,
|
start: SketchGroup,
|
||||||
reduce_fn: &FunctionParam<'a>,
|
reduce_fn: &FunctionParam<'a>,
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
// Call the reduce fn for this repetition.
|
// Call the reduce fn for this repetition.
|
||||||
let reduce_fn_args = vec![
|
let reduce_fn_args = vec![
|
||||||
@ -70,7 +71,7 @@ async fn call_reduce_closure<'a>(
|
|||||||
}),
|
}),
|
||||||
KclValue::new_user_val(start.meta.clone(), start),
|
KclValue::new_user_val(start.meta.clone(), start),
|
||||||
];
|
];
|
||||||
let transform_fn_return = reduce_fn.call(reduce_fn_args).await?;
|
let transform_fn_return = reduce_fn.call(exec_state, reduce_fn_args).await?;
|
||||||
|
|
||||||
// Unpack the returned transform object.
|
// Unpack the returned transform object.
|
||||||
let source_ranges = vec![source_range];
|
let source_ranges = vec![source_range];
|
||||||
|
@ -6,7 +6,7 @@ use schemars::JsonSchema;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::KclValue,
|
executor::{ExecState, KclValue},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ async fn _assert(value: bool, message: &str, args: &Args) -> Result<(), KclError
|
|||||||
|
|
||||||
/// Check that the provided value is true, or raise a [KclError]
|
/// Check that the provided value is true, or raise a [KclError]
|
||||||
/// with the provided description.
|
/// with the provided description.
|
||||||
pub async fn assert(args: Args) -> Result<KclValue, KclError> {
|
pub async fn assert(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, description): (bool, String) = args.get_data()?;
|
let (data, description): (bool, String) = args.get_data()?;
|
||||||
inner_assert(data, &description, &args).await?;
|
inner_assert(data, &description, &args).await?;
|
||||||
args.make_null_user_val()
|
args.make_null_user_val()
|
||||||
@ -42,7 +42,7 @@ async fn inner_assert(data: bool, message: &str, args: &Args) -> Result<(), KclE
|
|||||||
_assert(data, message, args).await
|
_assert(data, message, args).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_lt(args: Args) -> Result<KclValue, KclError> {
|
pub async fn assert_lt(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
||||||
inner_assert_lt(left, right, &description, &args).await?;
|
inner_assert_lt(left, right, &description, &args).await?;
|
||||||
args.make_null_user_val()
|
args.make_null_user_val()
|
||||||
@ -61,7 +61,7 @@ async fn inner_assert_lt(left: f64, right: f64, message: &str, args: &Args) -> R
|
|||||||
_assert(left < right, message, args).await
|
_assert(left < right, message, args).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_gt(args: Args) -> Result<KclValue, KclError> {
|
pub async fn assert_gt(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
||||||
inner_assert_gt(left, right, &description, &args).await?;
|
inner_assert_gt(left, right, &description, &args).await?;
|
||||||
args.make_null_user_val()
|
args.make_null_user_val()
|
||||||
@ -89,7 +89,7 @@ async fn inner_assert_equal(left: f64, right: f64, epsilon: f64, message: &str,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_equal(args: Args) -> Result<KclValue, KclError> {
|
pub async fn assert_equal(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (left, right, epsilon, description): (f64, f64, f64, String) = args.get_data()?;
|
let (left, right, epsilon, description): (f64, f64, f64, String) = args.get_data()?;
|
||||||
inner_assert_equal(left, right, epsilon, &description, &args).await?;
|
inner_assert_equal(left, right, epsilon, &description, &args).await?;
|
||||||
args.make_null_user_val()
|
args.make_null_user_val()
|
||||||
@ -108,7 +108,7 @@ async fn inner_assert_gt(left: f64, right: f64, message: &str, args: &Args) -> R
|
|||||||
_assert(left > right, message, args).await
|
_assert(left > right, message, args).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_lte(args: Args) -> Result<KclValue, KclError> {
|
pub async fn assert_lte(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
||||||
inner_assert_lte(left, right, &description, &args).await?;
|
inner_assert_lte(left, right, &description, &args).await?;
|
||||||
args.make_null_user_val()
|
args.make_null_user_val()
|
||||||
@ -128,7 +128,7 @@ async fn inner_assert_lte(left: f64, right: f64, message: &str, args: &Args) ->
|
|||||||
_assert(left <= right, message, args).await
|
_assert(left <= right, message, args).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_gte(args: Args) -> Result<KclValue, KclError> {
|
pub async fn assert_gte(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
let (left, right, description): (f64, f64, String) = args.get_data()?;
|
||||||
inner_assert_gte(left, right, &description, &args).await?;
|
inner_assert_gte(left, right, &description, &args).await?;
|
||||||
args.make_null_user_val()
|
args.make_null_user_val()
|
||||||
|
@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::types::TagDeclarator,
|
ast::types::TagDeclarator,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ChamferSurface, EdgeCut, ExtrudeGroup, ExtrudeSurface, GeoMeta, KclValue},
|
executor::{ChamferSurface, EdgeCut, ExecState, ExtrudeGroup, ExtrudeSurface, GeoMeta, KclValue},
|
||||||
std::{fillet::EdgeReference, Args},
|
std::{fillet::EdgeReference, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,11 +27,11 @@ pub struct ChamferData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create chamfers on tagged paths.
|
/// Create chamfers on tagged paths.
|
||||||
pub async fn chamfer(args: Args) -> Result<KclValue, KclError> {
|
pub async fn chamfer(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group, tag): (ChamferData, Box<ExtrudeGroup>, Option<TagDeclarator>) =
|
let (data, extrude_group, tag): (ChamferData, Box<ExtrudeGroup>, Option<TagDeclarator>) =
|
||||||
args.get_data_and_extrude_group_and_tag()?;
|
args.get_data_and_extrude_group_and_tag()?;
|
||||||
|
|
||||||
let extrude_group = inner_chamfer(data, extrude_group, tag, args).await?;
|
let extrude_group = inner_chamfer(data, extrude_group, tag, exec_state, args).await?;
|
||||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +103,7 @@ async fn inner_chamfer(
|
|||||||
data: ChamferData,
|
data: ChamferData,
|
||||||
extrude_group: Box<ExtrudeGroup>,
|
extrude_group: Box<ExtrudeGroup>,
|
||||||
tag: Option<TagDeclarator>,
|
tag: Option<TagDeclarator>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
// Check if tags contains any duplicate values.
|
// Check if tags contains any duplicate values.
|
||||||
@ -130,7 +131,7 @@ async fn inner_chamfer(
|
|||||||
for edge_tag in data.tags {
|
for edge_tag in data.tags {
|
||||||
let edge_id = match edge_tag {
|
let edge_id = match edge_tag {
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
EdgeReference::Uuid(uuid) => uuid,
|
||||||
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(&edge_tag)?.id,
|
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
@ -5,7 +5,7 @@ use schemars::JsonSchema;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{KclValue, SourceRange},
|
executor::{ExecState, KclValue, SourceRange},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ impl ConversionError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a number to integer.
|
/// Converts a number to integer.
|
||||||
pub async fn int(args: Args) -> Result<KclValue, KclError> {
|
pub async fn int(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let converted = inner_int(num).map_err(|err| err.into_kcl_error(args.source_range))?;
|
let converted = inner_int(num).map_err(|err| err.into_kcl_error(args.source_range))?;
|
||||||
|
|
||||||
|
@ -11,14 +11,14 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup, SketchGroupSet,
|
ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup, SketchGroupSet,
|
||||||
SketchSurface,
|
SketchSurface,
|
||||||
},
|
},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Extrudes by a given amount.
|
/// Extrudes by a given amount.
|
||||||
pub async fn extrude(args: Args) -> Result<KclValue, KclError> {
|
pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (length, sketch_group_set) = args.get_number_sketch_group_set()?;
|
let (length, sketch_group_set) = args.get_number_sketch_group_set()?;
|
||||||
|
|
||||||
let result = inner_extrude(length, sketch_group_set, args).await?;
|
let result = inner_extrude(length, sketch_group_set, args).await?;
|
||||||
|
@ -10,7 +10,9 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::types::TagDeclarator,
|
ast::types::TagDeclarator,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{EdgeCut, ExtrudeGroup, ExtrudeSurface, FilletSurface, GeoMeta, KclValue, TagIdentifier, UserVal},
|
executor::{
|
||||||
|
EdgeCut, ExecState, ExtrudeGroup, ExtrudeSurface, FilletSurface, GeoMeta, KclValue, TagIdentifier, UserVal,
|
||||||
|
},
|
||||||
settings::types::UnitLength,
|
settings::types::UnitLength,
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
@ -41,11 +43,11 @@ pub enum EdgeReference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create fillets on tagged paths.
|
/// Create fillets on tagged paths.
|
||||||
pub async fn fillet(args: Args) -> Result<KclValue, KclError> {
|
pub async fn fillet(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group, tag): (FilletData, Box<ExtrudeGroup>, Option<TagDeclarator>) =
|
let (data, extrude_group, tag): (FilletData, Box<ExtrudeGroup>, Option<TagDeclarator>) =
|
||||||
args.get_data_and_extrude_group_and_tag()?;
|
args.get_data_and_extrude_group_and_tag()?;
|
||||||
|
|
||||||
let extrude_group = inner_fillet(data, extrude_group, tag, args).await?;
|
let extrude_group = inner_fillet(data, extrude_group, tag, exec_state, args).await?;
|
||||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +114,7 @@ async fn inner_fillet(
|
|||||||
data: FilletData,
|
data: FilletData,
|
||||||
extrude_group: Box<ExtrudeGroup>,
|
extrude_group: Box<ExtrudeGroup>,
|
||||||
tag: Option<TagDeclarator>,
|
tag: Option<TagDeclarator>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
// Check if tags contains any duplicate values.
|
// Check if tags contains any duplicate values.
|
||||||
@ -130,7 +133,7 @@ async fn inner_fillet(
|
|||||||
for edge_tag in data.tags {
|
for edge_tag in data.tags {
|
||||||
let edge_id = match edge_tag {
|
let edge_id = match edge_tag {
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
EdgeReference::Uuid(uuid) => uuid,
|
||||||
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(&edge_tag)?.id,
|
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
@ -172,10 +175,10 @@ async fn inner_fillet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the opposite edge to the edge given.
|
/// Get the opposite edge to the edge given.
|
||||||
pub async fn get_opposite_edge(args: Args) -> Result<KclValue, KclError> {
|
pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
|
|
||||||
let edge = inner_get_opposite_edge(tag, args.clone()).await?;
|
let edge = inner_get_opposite_edge(tag, exec_state, args.clone()).await?;
|
||||||
Ok(KclValue::UserVal(UserVal {
|
Ok(KclValue::UserVal(UserVal {
|
||||||
value: serde_json::to_value(edge).map_err(|e| {
|
value: serde_json::to_value(edge).map_err(|e| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
@ -217,13 +220,13 @@ pub async fn get_opposite_edge(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "getOppositeEdge",
|
name = "getOppositeEdge",
|
||||||
}]
|
}]
|
||||||
async fn inner_get_opposite_edge(tag: TagIdentifier, args: Args) -> Result<Uuid, KclError> {
|
async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<Uuid, KclError> {
|
||||||
if args.ctx.is_mock {
|
if args.ctx.is_mock {
|
||||||
return Ok(Uuid::new_v4());
|
return Ok(Uuid::new_v4());
|
||||||
}
|
}
|
||||||
let tagged_path = args.get_tag_engine_info(&tag)?;
|
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||||
|
|
||||||
let face_id = args.get_adjacent_face_to_tag(&tag, false).await?;
|
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
@ -249,10 +252,10 @@ async fn inner_get_opposite_edge(tag: TagIdentifier, args: Args) -> Result<Uuid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next adjacent edge to the edge given.
|
/// Get the next adjacent edge to the edge given.
|
||||||
pub async fn get_next_adjacent_edge(args: Args) -> Result<KclValue, KclError> {
|
pub async fn get_next_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
|
|
||||||
let edge = inner_get_next_adjacent_edge(tag, args.clone()).await?;
|
let edge = inner_get_next_adjacent_edge(tag, exec_state, args.clone()).await?;
|
||||||
Ok(KclValue::UserVal(UserVal {
|
Ok(KclValue::UserVal(UserVal {
|
||||||
value: serde_json::to_value(edge).map_err(|e| {
|
value: serde_json::to_value(edge).map_err(|e| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
@ -294,13 +297,17 @@ pub async fn get_next_adjacent_edge(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "getNextAdjacentEdge",
|
name = "getNextAdjacentEdge",
|
||||||
}]
|
}]
|
||||||
async fn inner_get_next_adjacent_edge(tag: TagIdentifier, args: Args) -> Result<Uuid, KclError> {
|
async fn inner_get_next_adjacent_edge(
|
||||||
|
tag: TagIdentifier,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<Uuid, KclError> {
|
||||||
if args.ctx.is_mock {
|
if args.ctx.is_mock {
|
||||||
return Ok(Uuid::new_v4());
|
return Ok(Uuid::new_v4());
|
||||||
}
|
}
|
||||||
let tagged_path = args.get_tag_engine_info(&tag)?;
|
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||||
|
|
||||||
let face_id = args.get_adjacent_face_to_tag(&tag, false).await?;
|
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
@ -331,10 +338,10 @@ async fn inner_get_next_adjacent_edge(tag: TagIdentifier, args: Args) -> Result<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the previous adjacent edge to the edge given.
|
/// Get the previous adjacent edge to the edge given.
|
||||||
pub async fn get_previous_adjacent_edge(args: Args) -> Result<KclValue, KclError> {
|
pub async fn get_previous_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
|
|
||||||
let edge = inner_get_previous_adjacent_edge(tag, args.clone()).await?;
|
let edge = inner_get_previous_adjacent_edge(tag, exec_state, args.clone()).await?;
|
||||||
Ok(KclValue::UserVal(UserVal {
|
Ok(KclValue::UserVal(UserVal {
|
||||||
value: serde_json::to_value(edge).map_err(|e| {
|
value: serde_json::to_value(edge).map_err(|e| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
@ -376,13 +383,17 @@ pub async fn get_previous_adjacent_edge(args: Args) -> Result<KclValue, KclError
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "getPreviousAdjacentEdge",
|
name = "getPreviousAdjacentEdge",
|
||||||
}]
|
}]
|
||||||
async fn inner_get_previous_adjacent_edge(tag: TagIdentifier, args: Args) -> Result<Uuid, KclError> {
|
async fn inner_get_previous_adjacent_edge(
|
||||||
|
tag: TagIdentifier,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<Uuid, KclError> {
|
||||||
if args.ctx.is_mock {
|
if args.ctx.is_mock {
|
||||||
return Ok(Uuid::new_v4());
|
return Ok(Uuid::new_v4());
|
||||||
}
|
}
|
||||||
let tagged_path = args.get_tag_engine_info(&tag)?;
|
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||||
|
|
||||||
let face_id = args.get_adjacent_face_to_tag(&tag, false).await?;
|
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
executor::{ExtrudeGroup, KclValue},
|
executor::{ExecState, ExtrudeGroup, KclValue},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ pub struct HelixData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a helix on a cylinder.
|
/// Create a helix on a cylinder.
|
||||||
pub async fn helix(args: Args) -> Result<KclValue, KclError> {
|
pub async fn helix(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group): (HelixData, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
let (data, extrude_group): (HelixData, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
||||||
|
|
||||||
let extrude_group = inner_helix(data, extrude_group, args).await?;
|
let extrude_group = inner_helix(data, extrude_group, args).await?;
|
||||||
|
@ -9,7 +9,7 @@ use schemars::JsonSchema;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ImportedGeometry, KclValue},
|
executor::{ExecState, ImportedGeometry, KclValue},
|
||||||
fs::FileSystem,
|
fs::FileSystem,
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
@ -117,7 +117,7 @@ impl From<ImportFormat> for kittycad::types::InputFormat {
|
|||||||
///
|
///
|
||||||
/// Import paths are relative to the current project directory. This only works in the desktop app
|
/// Import paths are relative to the current project directory. This only works in the desktop app
|
||||||
/// not in browser.
|
/// not in browser.
|
||||||
pub async fn import(args: Args) -> Result<KclValue, KclError> {
|
pub async fn import(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (file_path, options): (String, Option<ImportFormat>) = args.get_import_data()?;
|
let (file_path, options): (String, Option<ImportFormat>) = args.get_import_data()?;
|
||||||
|
|
||||||
let imported_geometry = inner_import(file_path, options, args).await?;
|
let imported_geometry = inner_import(file_path, options, args).await?;
|
||||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ExtrudeGroup, KclValue, SketchGroup},
|
executor::{ExecState, ExtrudeGroup, KclValue, SketchGroup},
|
||||||
std::{extrude::do_post_extrude, fillet::default_tolerance, Args},
|
std::{extrude::do_post_extrude, fillet::default_tolerance, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ impl Default for LoftData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a 3D surface or solid by interpolating between two or more sketches.
|
/// Create a 3D surface or solid by interpolating between two or more sketches.
|
||||||
pub async fn loft(args: Args) -> Result<KclValue, KclError> {
|
pub async fn loft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (sketch_groups, data): (Vec<SketchGroup>, Option<LoftData>) = args.get_sketch_groups_and_data()?;
|
let (sketch_groups, data): (Vec<SketchGroup>, Option<LoftData>) = args.get_sketch_groups_and_data()?;
|
||||||
|
|
||||||
let extrude_group = inner_loft(sketch_groups, data, args).await?;
|
let extrude_group = inner_loft(sketch_groups, data, args).await?;
|
||||||
|
@ -6,12 +6,12 @@ use schemars::JsonSchema;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::KclValue,
|
executor::{ExecState, KclValue},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Compute the cosine of a number (in radians).
|
/// Compute the cosine of a number (in radians).
|
||||||
pub async fn cos(args: Args) -> Result<KclValue, KclError> {
|
pub async fn cos(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_cos(num)?;
|
let result = inner_cos(num)?;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ fn inner_cos(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the sine of a number (in radians).
|
/// Compute the sine of a number (in radians).
|
||||||
pub async fn sin(args: Args) -> Result<KclValue, KclError> {
|
pub async fn sin(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_sin(num)?;
|
let result = inner_sin(num)?;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ fn inner_sin(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the tangent of a number (in radians).
|
/// Compute the tangent of a number (in radians).
|
||||||
pub async fn tan(args: Args) -> Result<KclValue, KclError> {
|
pub async fn tan(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_tan(num)?;
|
let result = inner_tan(num)?;
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ fn inner_tan(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the value of `pi`. Archimedes’ constant (π).
|
/// Return the value of `pi`. Archimedes’ constant (π).
|
||||||
pub async fn pi(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pi(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_pi()?;
|
let result = inner_pi()?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -126,7 +126,7 @@ fn inner_pi() -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the square root of a number.
|
/// Compute the square root of a number.
|
||||||
pub async fn sqrt(args: Args) -> Result<KclValue, KclError> {
|
pub async fn sqrt(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_sqrt(num)?;
|
let result = inner_sqrt(num)?;
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ fn inner_sqrt(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the absolute value of a number.
|
/// Compute the absolute value of a number.
|
||||||
pub async fn abs(args: Args) -> Result<KclValue, KclError> {
|
pub async fn abs(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_abs(num)?;
|
let result = inner_abs(num)?;
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ fn inner_abs(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the largest integer less than or equal to a number.
|
/// Compute the largest integer less than or equal to a number.
|
||||||
pub async fn floor(args: Args) -> Result<KclValue, KclError> {
|
pub async fn floor(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_floor(num)?;
|
let result = inner_floor(num)?;
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ fn inner_floor(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the smallest integer greater than or equal to a number.
|
/// Compute the smallest integer greater than or equal to a number.
|
||||||
pub async fn ceil(args: Args) -> Result<KclValue, KclError> {
|
pub async fn ceil(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_ceil(num)?;
|
let result = inner_ceil(num)?;
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ fn inner_ceil(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the minimum of the given arguments.
|
/// Compute the minimum of the given arguments.
|
||||||
pub async fn min(args: Args) -> Result<KclValue, KclError> {
|
pub async fn min(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let nums = args.get_number_array()?;
|
let nums = args.get_number_array()?;
|
||||||
let result = inner_min(nums);
|
let result = inner_min(nums);
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ fn inner_min(args: Vec<f64>) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the maximum of the given arguments.
|
/// Compute the maximum of the given arguments.
|
||||||
pub async fn max(args: Args) -> Result<KclValue, KclError> {
|
pub async fn max(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let nums = args.get_number_array()?;
|
let nums = args.get_number_array()?;
|
||||||
let result = inner_max(nums);
|
let result = inner_max(nums);
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ fn inner_max(args: Vec<f64>) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the number to a power.
|
/// Compute the number to a power.
|
||||||
pub async fn pow(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pow(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, 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 {
|
||||||
@ -367,7 +367,7 @@ fn inner_pow(num: f64, pow: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the arccosine of a number (in radians).
|
/// Compute the arccosine of a number (in radians).
|
||||||
pub async fn acos(args: Args) -> Result<KclValue, KclError> {
|
pub async fn acos(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_acos(num)?;
|
let result = inner_acos(num)?;
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ fn inner_acos(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the arcsine of a number (in radians).
|
/// Compute the arcsine of a number (in radians).
|
||||||
pub async fn asin(args: Args) -> Result<KclValue, KclError> {
|
pub async fn asin(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_asin(num)?;
|
let result = inner_asin(num)?;
|
||||||
|
|
||||||
@ -428,7 +428,7 @@ fn inner_asin(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the arctangent of a number (in radians).
|
/// Compute the arctangent of a number (in radians).
|
||||||
pub async fn atan(args: Args) -> Result<KclValue, KclError> {
|
pub async fn atan(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_atan(num)?;
|
let result = inner_atan(num)?;
|
||||||
|
|
||||||
@ -462,7 +462,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 async fn log(args: Args) -> Result<KclValue, KclError> {
|
pub async fn log(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, 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 {
|
||||||
@ -507,7 +507,7 @@ fn inner_log(num: f64, base: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the base 2 logarithm of the number.
|
/// Compute the base 2 logarithm of the number.
|
||||||
pub async fn log2(args: Args) -> Result<KclValue, KclError> {
|
pub async fn log2(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_log2(num)?;
|
let result = inner_log2(num)?;
|
||||||
|
|
||||||
@ -535,7 +535,7 @@ fn inner_log2(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the base 10 logarithm of the number.
|
/// Compute the base 10 logarithm of the number.
|
||||||
pub async fn log10(args: Args) -> Result<KclValue, KclError> {
|
pub async fn log10(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_log10(num)?;
|
let result = inner_log10(num)?;
|
||||||
|
|
||||||
@ -563,7 +563,7 @@ fn inner_log10(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the natural logarithm of the number.
|
/// Compute the natural logarithm of the number.
|
||||||
pub async fn ln(args: Args) -> Result<KclValue, KclError> {
|
pub async fn ln(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_ln(num)?;
|
let result = inner_ln(num)?;
|
||||||
|
|
||||||
@ -591,7 +591,7 @@ fn inner_ln(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the value of Euler’s number `e`.
|
/// Return the value of Euler’s number `e`.
|
||||||
pub async fn e(args: Args) -> Result<KclValue, KclError> {
|
pub async fn e(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_e()?;
|
let result = inner_e()?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -620,7 +620,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 async fn tau(args: Args) -> Result<KclValue, KclError> {
|
pub async fn tau(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_tau()?;
|
let result = inner_tau()?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -649,7 +649,7 @@ fn inner_tau() -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a number from degrees to radians.
|
/// Converts a number from degrees to radians.
|
||||||
pub async fn to_radians(args: Args) -> Result<KclValue, KclError> {
|
pub async fn to_radians(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_to_radians(num)?;
|
let result = inner_to_radians(num)?;
|
||||||
|
|
||||||
@ -679,7 +679,7 @@ fn inner_to_radians(num: f64) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a number from radians to degrees.
|
/// Converts a number from radians to degrees.
|
||||||
pub async fn to_degrees(args: Args) -> Result<KclValue, KclError> {
|
pub async fn to_degrees(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let num = args.get_number()?;
|
let num = args.get_number()?;
|
||||||
let result = inner_to_degrees(num)?;
|
let result = inner_to_degrees(num)?;
|
||||||
|
|
||||||
|
@ -38,11 +38,14 @@ use crate::{
|
|||||||
ast::types::FunctionExpression,
|
ast::types::FunctionExpression,
|
||||||
docs::StdLibFn,
|
docs::StdLibFn,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
executor::{KclValue, ProgramMemory, SketchGroup, SketchSurface},
|
executor::{ExecState, KclValue, ProgramMemory, SketchGroup, SketchSurface},
|
||||||
std::kcl_stdlib::KclStdLibFn,
|
std::kcl_stdlib::KclStdLibFn,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type StdFn = fn(Args) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<KclValue, KclError>> + Send>>;
|
pub type StdFn = fn(
|
||||||
|
&mut ExecState,
|
||||||
|
Args,
|
||||||
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<KclValue, KclError>> + Send + '_>>;
|
||||||
|
|
||||||
pub type FnMap = HashMap<String, StdFn>;
|
pub type FnMap = HashMap<String, StdFn>;
|
||||||
|
|
||||||
@ -228,7 +231,7 @@ pub enum FunctionKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the length of the given leg.
|
/// Compute the length of the given leg.
|
||||||
pub async fn leg_length(args: Args) -> Result<KclValue, KclError> {
|
pub async fn leg_length(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, 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)
|
||||||
@ -248,7 +251,7 @@ fn inner_leg_length(hypotenuse: f64, leg: f64) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the angle of the given leg for x.
|
/// Compute the angle of the given leg for x.
|
||||||
pub async fn leg_angle_x(args: Args) -> Result<KclValue, KclError> {
|
pub async fn leg_angle_x(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, 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)
|
||||||
@ -268,7 +271,7 @@ fn inner_leg_angle_x(hypotenuse: f64, leg: f64) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the angle of the given leg for y.
|
/// Compute the angle of the given leg for y.
|
||||||
pub async fn leg_angle_y(args: Args) -> Result<KclValue, KclError> {
|
pub async fn leg_angle_y(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, 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)
|
||||||
@ -302,8 +305,9 @@ pub enum Primitive {
|
|||||||
Uuid,
|
Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A closure used as an argument to a stdlib function.
|
||||||
pub struct FnAsArg<'a> {
|
pub struct FnAsArg<'a> {
|
||||||
pub func: &'a crate::executor::MemoryFunction,
|
pub func: Option<&'a crate::executor::MemoryFunction>,
|
||||||
pub expr: Box<FunctionExpression>,
|
pub expr: Box<FunctionExpression>,
|
||||||
pub memory: Box<ProgramMemory>,
|
pub memory: Box<ProgramMemory>,
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
ExtrudeGroup, ExtrudeGroupSet, Geometries, Geometry, KclValue, Point3d, SketchGroup, SketchGroupSet,
|
ExecState, ExtrudeGroup, ExtrudeGroupSet, Geometries, Geometry, KclValue, Point3d, SketchGroup, SketchGroupSet,
|
||||||
SourceRange, UserVal,
|
SourceRange, UserVal,
|
||||||
},
|
},
|
||||||
function_param::FunctionParam,
|
function_param::FunctionParam,
|
||||||
@ -77,7 +77,7 @@ impl LinearPattern {
|
|||||||
/// A linear pattern
|
/// A linear pattern
|
||||||
/// Each element in the pattern repeats a particular piece of geometry.
|
/// Each element in the pattern repeats a particular piece of geometry.
|
||||||
/// The repetitions can be transformed by the `transform` parameter.
|
/// The repetitions can be transformed by the `transform` parameter.
|
||||||
pub async fn pattern_transform(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pattern_transform(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (num_repetitions, transform, extr) = args.get_pattern_transform_args()?;
|
let (num_repetitions, transform, extr) = args.get_pattern_transform_args()?;
|
||||||
|
|
||||||
let extrude_groups = inner_pattern_transform(
|
let extrude_groups = inner_pattern_transform(
|
||||||
@ -88,9 +88,9 @@ pub async fn pattern_transform(args: Args) -> Result<KclValue, KclError> {
|
|||||||
meta: vec![args.source_range.into()],
|
meta: vec![args.source_range.into()],
|
||||||
ctx: args.ctx.clone(),
|
ctx: args.ctx.clone(),
|
||||||
memory: *transform.memory,
|
memory: *transform.memory,
|
||||||
dynamic_state: args.dynamic_state.clone(),
|
|
||||||
},
|
},
|
||||||
extr,
|
extr,
|
||||||
|
exec_state,
|
||||||
&args,
|
&args,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@ -131,18 +131,19 @@ async fn inner_pattern_transform<'a>(
|
|||||||
num_repetitions: u32,
|
num_repetitions: u32,
|
||||||
transform_function: FunctionParam<'a>,
|
transform_function: FunctionParam<'a>,
|
||||||
extrude_group_set: ExtrudeGroupSet,
|
extrude_group_set: ExtrudeGroupSet,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: &'a Args,
|
args: &'a Args,
|
||||||
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
|
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
|
||||||
// Build the vec of transforms, one for each repetition.
|
// Build the vec of transforms, one for each repetition.
|
||||||
let mut transform = Vec::with_capacity(usize::try_from(num_repetitions).unwrap());
|
let mut transform = Vec::with_capacity(usize::try_from(num_repetitions).unwrap());
|
||||||
for i in 0..num_repetitions {
|
for i in 0..num_repetitions {
|
||||||
let t = make_transform(i, &transform_function, args.source_range).await?;
|
let t = make_transform(i, &transform_function, args.source_range, exec_state).await?;
|
||||||
transform.push(t);
|
transform.push(t);
|
||||||
}
|
}
|
||||||
// Flush the batch for our fillets/chamfers if there are any.
|
// Flush the batch for our fillets/chamfers if there are any.
|
||||||
// If we do not flush these, then you won't be able to pattern something with fillets.
|
// If we do not flush these, then you won't be able to pattern something with fillets.
|
||||||
// Flush just the fillets/chamfers that apply to these extrude groups.
|
// Flush just the fillets/chamfers that apply to these extrude groups.
|
||||||
args.flush_batch_for_extrude_group_set(extrude_group_set.clone().into())
|
args.flush_batch_for_extrude_group_set(exec_state, extrude_group_set.clone().into())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let starting_extrude_groups: Vec<Box<ExtrudeGroup>> = extrude_group_set.into();
|
let starting_extrude_groups: Vec<Box<ExtrudeGroup>> = extrude_group_set.into();
|
||||||
@ -201,6 +202,7 @@ async fn make_transform<'a>(
|
|||||||
i: u32,
|
i: u32,
|
||||||
transform_function: &FunctionParam<'a>,
|
transform_function: &FunctionParam<'a>,
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
) -> Result<kittycad::types::Transform, KclError> {
|
) -> Result<kittycad::types::Transform, KclError> {
|
||||||
// Call the transform fn for this repetition.
|
// Call the transform fn for this repetition.
|
||||||
let repetition_num = KclValue::UserVal(UserVal {
|
let repetition_num = KclValue::UserVal(UserVal {
|
||||||
@ -208,7 +210,7 @@ async fn make_transform<'a>(
|
|||||||
meta: vec![source_range.into()],
|
meta: vec![source_range.into()],
|
||||||
});
|
});
|
||||||
let transform_fn_args = vec![repetition_num];
|
let transform_fn_args = vec![repetition_num];
|
||||||
let transform_fn_return = transform_function.call(transform_fn_args).await?;
|
let transform_fn_return = transform_function.call(exec_state, transform_fn_args).await?;
|
||||||
|
|
||||||
// Unpack the returned transform object.
|
// Unpack the returned transform object.
|
||||||
let source_ranges = vec![source_range];
|
let source_ranges = vec![source_range];
|
||||||
@ -299,7 +301,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A linear pattern on a 2D sketch.
|
/// A linear pattern on a 2D sketch.
|
||||||
pub async fn pattern_linear_2d(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pattern_linear_2d(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group_set): (LinearPattern2dData, SketchGroupSet) = args.get_data_and_sketch_group_set()?;
|
let (data, sketch_group_set): (LinearPattern2dData, SketchGroupSet) = args.get_data_and_sketch_group_set()?;
|
||||||
|
|
||||||
if data.axis == [0.0, 0.0] {
|
if data.axis == [0.0, 0.0] {
|
||||||
@ -366,7 +368,7 @@ async fn inner_pattern_linear_2d(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A linear pattern on a 3D model.
|
/// A linear pattern on a 3D model.
|
||||||
pub async fn pattern_linear_3d(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group_set): (LinearPattern3dData, ExtrudeGroupSet) = args.get_data_and_extrude_group_set()?;
|
let (data, extrude_group_set): (LinearPattern3dData, ExtrudeGroupSet) = args.get_data_and_extrude_group_set()?;
|
||||||
|
|
||||||
if data.axis == [0.0, 0.0, 0.0] {
|
if data.axis == [0.0, 0.0, 0.0] {
|
||||||
@ -378,7 +380,7 @@ pub async fn pattern_linear_3d(args: Args) -> Result<KclValue, KclError> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let extrude_groups = inner_pattern_linear_3d(data, extrude_group_set, args).await?;
|
let extrude_groups = inner_pattern_linear_3d(data, extrude_group_set, exec_state, args).await?;
|
||||||
Ok(extrude_groups.into())
|
Ok(extrude_groups.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,12 +408,13 @@ pub async fn pattern_linear_3d(args: Args) -> Result<KclValue, KclError> {
|
|||||||
async fn inner_pattern_linear_3d(
|
async fn inner_pattern_linear_3d(
|
||||||
data: LinearPattern3dData,
|
data: LinearPattern3dData,
|
||||||
extrude_group_set: ExtrudeGroupSet,
|
extrude_group_set: ExtrudeGroupSet,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
|
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
|
||||||
// Flush the batch for our fillets/chamfers if there are any.
|
// Flush the batch for our fillets/chamfers if there are any.
|
||||||
// If we do not flush these, then you won't be able to pattern something with fillets.
|
// If we do not flush these, then you won't be able to pattern something with fillets.
|
||||||
// Flush just the fillets/chamfers that apply to these extrude groups.
|
// Flush just the fillets/chamfers that apply to these extrude groups.
|
||||||
args.flush_batch_for_extrude_group_set(extrude_group_set.clone().into())
|
args.flush_batch_for_extrude_group_set(exec_state, extrude_group_set.clone().into())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let starting_extrude_groups: Vec<Box<ExtrudeGroup>> = extrude_group_set.into();
|
let starting_extrude_groups: Vec<Box<ExtrudeGroup>> = extrude_group_set.into();
|
||||||
@ -574,7 +577,7 @@ impl CircularPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A circular pattern on a 2D sketch.
|
/// A circular pattern on a 2D sketch.
|
||||||
pub async fn pattern_circular_2d(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pattern_circular_2d(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group_set): (CircularPattern2dData, SketchGroupSet) = args.get_data_and_sketch_group_set()?;
|
let (data, sketch_group_set): (CircularPattern2dData, SketchGroupSet) = args.get_data_and_sketch_group_set()?;
|
||||||
|
|
||||||
let sketch_groups = inner_pattern_circular_2d(data, sketch_group_set, args).await?;
|
let sketch_groups = inner_pattern_circular_2d(data, sketch_group_set, args).await?;
|
||||||
@ -639,10 +642,10 @@ async fn inner_pattern_circular_2d(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A circular pattern on a 3D model.
|
/// A circular pattern on a 3D model.
|
||||||
pub async fn pattern_circular_3d(args: Args) -> Result<KclValue, KclError> {
|
pub async fn pattern_circular_3d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group_set): (CircularPattern3dData, ExtrudeGroupSet) = args.get_data_and_extrude_group_set()?;
|
let (data, extrude_group_set): (CircularPattern3dData, ExtrudeGroupSet) = args.get_data_and_extrude_group_set()?;
|
||||||
|
|
||||||
let extrude_groups = inner_pattern_circular_3d(data, extrude_group_set, args).await?;
|
let extrude_groups = inner_pattern_circular_3d(data, extrude_group_set, exec_state, args).await?;
|
||||||
Ok(extrude_groups.into())
|
Ok(extrude_groups.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,12 +673,13 @@ pub async fn pattern_circular_3d(args: Args) -> Result<KclValue, KclError> {
|
|||||||
async fn inner_pattern_circular_3d(
|
async fn inner_pattern_circular_3d(
|
||||||
data: CircularPattern3dData,
|
data: CircularPattern3dData,
|
||||||
extrude_group_set: ExtrudeGroupSet,
|
extrude_group_set: ExtrudeGroupSet,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
|
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
|
||||||
// Flush the batch for our fillets/chamfers if there are any.
|
// Flush the batch for our fillets/chamfers if there are any.
|
||||||
// If we do not flush these, then you won't be able to pattern something with fillets.
|
// If we do not flush these, then you won't be able to pattern something with fillets.
|
||||||
// Flush just the fillets/chamfers that apply to these extrude groups.
|
// Flush just the fillets/chamfers that apply to these extrude groups.
|
||||||
args.flush_batch_for_extrude_group_set(extrude_group_set.clone().into())
|
args.flush_batch_for_extrude_group_set(exec_state, extrude_group_set.clone().into())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let starting_extrude_groups: Vec<Box<ExtrudeGroup>> = extrude_group_set.into();
|
let starting_extrude_groups: Vec<Box<ExtrudeGroup>> = extrude_group_set.into();
|
||||||
|
@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
executor::{KclValue, Metadata, Plane, UserVal},
|
executor::{ExecState, KclValue, Metadata, Plane, UserVal},
|
||||||
std::{sketch::PlaneData, Args},
|
std::{sketch::PlaneData, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ impl From<StandardPlane> for PlaneData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Offset a plane by a distance along its normal.
|
/// Offset a plane by a distance along its normal.
|
||||||
pub async fn offset_plane(args: Args) -> Result<KclValue, KclError> {
|
pub async fn offset_plane(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (std_plane, offset): (StandardPlane, f64) = args.get_data_and_float()?;
|
let (std_plane, offset): (StandardPlane, f64) = args.get_data_and_float()?;
|
||||||
|
|
||||||
let plane = inner_offset_plane(std_plane, offset).await?;
|
let plane = inner_offset_plane(std_plane, offset).await?;
|
||||||
|
@ -5,7 +5,11 @@ use derive_docs::stdlib;
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{errors::KclError, executor::KclValue, std::Args};
|
use crate::{
|
||||||
|
errors::KclError,
|
||||||
|
executor::{ExecState, KclValue},
|
||||||
|
std::Args,
|
||||||
|
};
|
||||||
|
|
||||||
/// Data for polar coordinates.
|
/// Data for polar coordinates.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
@ -19,7 +23,7 @@ pub struct PolarCoordsData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert from polar/sphere coordinates to cartesian coordinates.
|
/// Convert from polar/sphere coordinates to cartesian coordinates.
|
||||||
pub async fn polar(args: Args) -> Result<KclValue, KclError> {
|
pub async fn polar(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let data: PolarCoordsData = args.get_data()?;
|
let data: PolarCoordsData = args.get_data()?;
|
||||||
let result = inner_polar(&data)?;
|
let result = inner_polar(&data)?;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ExtrudeGroup, KclValue, SketchGroup},
|
executor::{ExecState, ExtrudeGroup, KclValue, SketchGroup},
|
||||||
std::{
|
std::{
|
||||||
extrude::do_post_extrude,
|
extrude::do_post_extrude,
|
||||||
fillet::{default_tolerance, EdgeReference},
|
fillet::{default_tolerance, EdgeReference},
|
||||||
@ -101,10 +101,10 @@ impl RevolveAxisAndOrigin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Revolve a sketch around an axis.
|
/// Revolve a sketch around an axis.
|
||||||
pub async fn revolve(args: Args) -> Result<KclValue, KclError> {
|
pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group): (RevolveData, SketchGroup) = args.get_data_and_sketch_group()?;
|
let (data, sketch_group): (RevolveData, SketchGroup) = args.get_data_and_sketch_group()?;
|
||||||
|
|
||||||
let extrude_group = inner_revolve(data, sketch_group, args).await?;
|
let extrude_group = inner_revolve(data, sketch_group, exec_state, args).await?;
|
||||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +250,7 @@ pub async fn revolve(args: Args) -> Result<KclValue, KclError> {
|
|||||||
async fn inner_revolve(
|
async fn inner_revolve(
|
||||||
data: RevolveData,
|
data: RevolveData,
|
||||||
sketch_group: SketchGroup,
|
sketch_group: SketchGroup,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
if let Some(angle) = data.angle {
|
if let Some(angle) = data.angle {
|
||||||
@ -284,7 +285,7 @@ async fn inner_revolve(
|
|||||||
RevolveAxis::Edge(edge) => {
|
RevolveAxis::Edge(edge) => {
|
||||||
let edge_id = match edge {
|
let edge_id = match edge {
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
EdgeReference::Uuid(uuid) => uuid,
|
||||||
EdgeReference::Tag(tag) => args.get_tag_engine_info(&tag)?.id,
|
EdgeReference::Tag(tag) => args.get_tag_engine_info(exec_state, &tag)?.id,
|
||||||
};
|
};
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
|
@ -6,14 +6,14 @@ use schemars::JsonSchema;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{KclValue, SketchGroup, TagIdentifier},
|
executor::{ExecState, KclValue, SketchGroup, TagIdentifier},
|
||||||
std::{utils::between, Args},
|
std::{utils::between, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns the segment end of x.
|
/// Returns the segment end of x.
|
||||||
pub async fn segment_end_x(args: Args) -> Result<KclValue, KclError> {
|
pub async fn segment_end_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
let result = inner_segment_end_x(&tag, args.clone())?;
|
let result = inner_segment_end_x(&tag, exec_state, args.clone())?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
}
|
}
|
||||||
@ -34,8 +34,8 @@ pub async fn segment_end_x(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segEndX",
|
name = "segEndX",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_end_x(tag: &TagIdentifier, args: Args) -> Result<f64, KclError> {
|
fn inner_segment_end_x(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<f64, KclError> {
|
||||||
let line = args.get_tag_engine_info(tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
||||||
@ -47,9 +47,9 @@ fn inner_segment_end_x(tag: &TagIdentifier, args: Args) -> Result<f64, KclError>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the segment end of y.
|
/// Returns the segment end of y.
|
||||||
pub async fn segment_end_y(args: Args) -> Result<KclValue, KclError> {
|
pub async fn segment_end_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
let result = inner_segment_end_y(&tag, args.clone())?;
|
let result = inner_segment_end_y(&tag, exec_state, args.clone())?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
}
|
}
|
||||||
@ -71,8 +71,8 @@ pub async fn segment_end_y(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segEndY",
|
name = "segEndY",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_end_y(tag: &TagIdentifier, args: Args) -> Result<f64, KclError> {
|
fn inner_segment_end_y(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<f64, KclError> {
|
||||||
let line = args.get_tag_engine_info(tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
||||||
@ -84,7 +84,7 @@ fn inner_segment_end_y(tag: &TagIdentifier, args: Args) -> Result<f64, KclError>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last segment of x.
|
/// Returns the last segment of x.
|
||||||
pub async fn last_segment_x(args: Args) -> Result<KclValue, KclError> {
|
pub async fn last_segment_x(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let sketch_group = args.get_sketch_group()?;
|
let sketch_group = args.get_sketch_group()?;
|
||||||
let result = inner_last_segment_x(sketch_group, args.clone())?;
|
let result = inner_last_segment_x(sketch_group, args.clone())?;
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ fn inner_last_segment_x(sketch_group: SketchGroup, args: Args) -> Result<f64, Kc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last segment of y.
|
/// Returns the last segment of y.
|
||||||
pub async fn last_segment_y(args: Args) -> Result<KclValue, KclError> {
|
pub async fn last_segment_y(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let sketch_group = args.get_sketch_group()?;
|
let sketch_group = args.get_sketch_group()?;
|
||||||
let result = inner_last_segment_y(sketch_group, args.clone())?;
|
let result = inner_last_segment_y(sketch_group, args.clone())?;
|
||||||
|
|
||||||
@ -170,9 +170,9 @@ fn inner_last_segment_y(sketch_group: SketchGroup, args: Args) -> Result<f64, Kc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the segment.
|
/// Returns the length of the segment.
|
||||||
pub async fn segment_length(args: Args) -> Result<KclValue, KclError> {
|
pub async fn segment_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
let result = inner_segment_length(&tag, args.clone())?;
|
let result = inner_segment_length(&tag, exec_state, args.clone())?;
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +200,8 @@ pub async fn segment_length(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segLen",
|
name = "segLen",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_length(tag: &TagIdentifier, args: Args) -> Result<f64, KclError> {
|
fn inner_segment_length(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<f64, KclError> {
|
||||||
let line = args.get_tag_engine_info(tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
||||||
@ -215,10 +215,10 @@ fn inner_segment_length(tag: &TagIdentifier, args: Args) -> Result<f64, KclError
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the angle of the segment.
|
/// Returns the angle of the segment.
|
||||||
pub async fn segment_angle(args: Args) -> Result<KclValue, KclError> {
|
pub async fn segment_angle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let tag: TagIdentifier = args.get_data()?;
|
let tag: TagIdentifier = args.get_data()?;
|
||||||
|
|
||||||
let result = inner_segment_angle(&tag, args.clone())?;
|
let result = inner_segment_angle(&tag, exec_state, args.clone())?;
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,8 +240,8 @@ pub async fn segment_angle(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segAng",
|
name = "segAng",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_angle(tag: &TagIdentifier, args: Args) -> Result<f64, KclError> {
|
fn inner_segment_angle(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<f64, KclError> {
|
||||||
let line = args.get_tag_engine_info(tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
||||||
@ -255,9 +255,9 @@ fn inner_segment_angle(tag: &TagIdentifier, args: Args) -> Result<f64, KclError>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the angle to match the given length for x.
|
/// Returns the angle to match the given length for x.
|
||||||
pub async fn angle_to_match_length_x(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angle_to_match_length_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (tag, to, sketch_group) = args.get_tag_to_number_sketch_group()?;
|
let (tag, to, sketch_group) = args.get_tag_to_number_sketch_group()?;
|
||||||
let result = inner_angle_to_match_length_x(&tag, to, sketch_group, args.clone())?;
|
let result = inner_angle_to_match_length_x(&tag, to, sketch_group, exec_state, args.clone())?;
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,9 +282,10 @@ fn inner_angle_to_match_length_x(
|
|||||||
tag: &TagIdentifier,
|
tag: &TagIdentifier,
|
||||||
to: f64,
|
to: f64,
|
||||||
sketch_group: SketchGroup,
|
sketch_group: SketchGroup,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<f64, KclError> {
|
) -> Result<f64, KclError> {
|
||||||
let line = args.get_tag_engine_info(tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
||||||
@ -320,9 +321,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 async fn angle_to_match_length_y(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angle_to_match_length_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (tag, to, sketch_group) = args.get_tag_to_number_sketch_group()?;
|
let (tag, to, sketch_group) = args.get_tag_to_number_sketch_group()?;
|
||||||
let result = inner_angle_to_match_length_y(&tag, to, sketch_group, args.clone())?;
|
let result = inner_angle_to_match_length_y(&tag, to, sketch_group, exec_state, args.clone())?;
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,9 +349,10 @@ fn inner_angle_to_match_length_y(
|
|||||||
tag: &TagIdentifier,
|
tag: &TagIdentifier,
|
||||||
to: f64,
|
to: f64,
|
||||||
sketch_group: SketchGroup,
|
sketch_group: SketchGroup,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<f64, KclError> {
|
) -> Result<f64, KclError> {
|
||||||
let line = args.get_tag_engine_info(tag)?;
|
let line = args.get_tag_engine_info(exec_state, tag)?;
|
||||||
let path = line.path.clone().ok_or_else(|| {
|
let path = line.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
message: format!("Expected a line segment with a path, found `{:?}`", line),
|
||||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::types::TagDeclarator,
|
ast::types::TagDeclarator,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
executor::KclValue,
|
executor::{ExecState, KclValue},
|
||||||
std::{Args, SketchGroup, SketchSurface},
|
std::{Args, SketchGroup, SketchSurface},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,11 +22,11 @@ pub enum SketchSurfaceOrGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sketch a circle.
|
/// Sketch a circle.
|
||||||
pub async fn circle(args: Args) -> Result<KclValue, KclError> {
|
pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (center, radius, sketch_surface_or_group, tag): ([f64; 2], f64, SketchSurfaceOrGroup, Option<TagDeclarator>) =
|
let (center, radius, sketch_surface_or_group, tag): ([f64; 2], f64, SketchSurfaceOrGroup, Option<TagDeclarator>) =
|
||||||
args.get_circle_args()?;
|
args.get_circle_args()?;
|
||||||
|
|
||||||
let sketch_group = inner_circle(center, radius, sketch_surface_or_group, tag, args).await?;
|
let sketch_group = inner_circle(center, radius, sketch_surface_or_group, tag, exec_state, args).await?;
|
||||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,15 +59,21 @@ async fn inner_circle(
|
|||||||
radius: f64,
|
radius: f64,
|
||||||
sketch_surface_or_group: SketchSurfaceOrGroup,
|
sketch_surface_or_group: SketchSurfaceOrGroup,
|
||||||
tag: Option<TagDeclarator>,
|
tag: Option<TagDeclarator>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
let sketch_surface = match sketch_surface_or_group {
|
let sketch_surface = match sketch_surface_or_group {
|
||||||
SketchSurfaceOrGroup::SketchSurface(surface) => surface,
|
SketchSurfaceOrGroup::SketchSurface(surface) => surface,
|
||||||
SketchSurfaceOrGroup::SketchGroup(group) => group.on,
|
SketchSurfaceOrGroup::SketchGroup(group) => group.on,
|
||||||
};
|
};
|
||||||
let mut sketch_group =
|
let mut sketch_group = crate::std::sketch::inner_start_profile_at(
|
||||||
crate::std::sketch::inner_start_profile_at([center[0] + radius, center[1]], sketch_surface, None, args.clone())
|
[center[0] + radius, center[1]],
|
||||||
.await?;
|
sketch_surface,
|
||||||
|
None,
|
||||||
|
exec_state,
|
||||||
|
args.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Call arc.
|
// Call arc.
|
||||||
sketch_group = crate::std::sketch::inner_arc(
|
sketch_group = crate::std::sketch::inner_arc(
|
||||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ExtrudeGroup, KclValue},
|
executor::{ExecState, ExtrudeGroup, KclValue},
|
||||||
std::{sketch::FaceTag, Args},
|
std::{sketch::FaceTag, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,10 +24,10 @@ pub struct ShellData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a shell.
|
/// Create a shell.
|
||||||
pub async fn shell(args: Args) -> Result<KclValue, KclError> {
|
pub async fn shell(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group): (ShellData, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
let (data, extrude_group): (ShellData, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
||||||
|
|
||||||
let extrude_group = inner_shell(data, extrude_group, args).await?;
|
let extrude_group = inner_shell(data, extrude_group, exec_state, args).await?;
|
||||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +154,7 @@ pub async fn shell(args: Args) -> Result<KclValue, KclError> {
|
|||||||
async fn inner_shell(
|
async fn inner_shell(
|
||||||
data: ShellData,
|
data: ShellData,
|
||||||
extrude_group: Box<ExtrudeGroup>,
|
extrude_group: Box<ExtrudeGroup>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
if data.faces.is_empty() {
|
if data.faces.is_empty() {
|
||||||
@ -165,7 +166,7 @@ async fn inner_shell(
|
|||||||
|
|
||||||
let mut face_ids = Vec::new();
|
let mut face_ids = Vec::new();
|
||||||
for tag in data.faces {
|
for tag in data.faces {
|
||||||
let extrude_plane_id = tag.get_face_id(&extrude_group, &args, false).await?;
|
let extrude_plane_id = tag.get_face_id(&extrude_group, exec_state, &args, false).await?;
|
||||||
|
|
||||||
face_ids.push(extrude_plane_id);
|
face_ids.push(extrude_plane_id);
|
||||||
}
|
}
|
||||||
@ -179,7 +180,7 @@ async fn inner_shell(
|
|||||||
|
|
||||||
// Flush the batch for our fillets/chamfers if there are any.
|
// Flush the batch for our fillets/chamfers if there are any.
|
||||||
// If we do not do these for sketch on face, things will fail with face does not exist.
|
// If we do not do these for sketch on face, things will fail with face does not exist.
|
||||||
args.flush_batch_for_extrude_group_set(extrude_group.clone().into())
|
args.flush_batch_for_extrude_group_set(exec_state, extrude_group.clone().into())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
@ -197,10 +198,10 @@ async fn inner_shell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Make the inside of a 3D object hollow.
|
/// Make the inside of a 3D object hollow.
|
||||||
pub async fn hollow(args: Args) -> Result<KclValue, KclError> {
|
pub async fn hollow(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (thickness, extrude_group): (f64, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
let (thickness, extrude_group): (f64, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
||||||
|
|
||||||
let extrude_group = inner_hollow(thickness, extrude_group, args).await?;
|
let extrude_group = inner_hollow(thickness, extrude_group, exec_state, args).await?;
|
||||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,11 +237,12 @@ pub async fn hollow(args: Args) -> Result<KclValue, KclError> {
|
|||||||
async fn inner_hollow(
|
async fn inner_hollow(
|
||||||
thickness: f64,
|
thickness: f64,
|
||||||
extrude_group: Box<ExtrudeGroup>,
|
extrude_group: Box<ExtrudeGroup>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
// Flush the batch for our fillets/chamfers if there are any.
|
// Flush the batch for our fillets/chamfers if there are any.
|
||||||
// If we do not do these for sketch on face, things will fail with face does not exist.
|
// If we do not do these for sketch on face, things will fail with face does not exist.
|
||||||
args.flush_batch_for_extrude_group_set(extrude_group.clone().into())
|
args.flush_batch_for_extrude_group_set(exec_state, extrude_group.clone().into())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
|
@ -13,8 +13,8 @@ use crate::{
|
|||||||
ast::types::TagDeclarator,
|
ast::types::TagDeclarator,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
BasePath, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup,
|
BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d,
|
||||||
SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
|
SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
utils::{
|
utils::{
|
||||||
@ -50,11 +50,12 @@ impl FaceTag {
|
|||||||
pub async fn get_face_id(
|
pub async fn get_face_id(
|
||||||
&self,
|
&self,
|
||||||
extrude_group: &ExtrudeGroup,
|
extrude_group: &ExtrudeGroup,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: &Args,
|
args: &Args,
|
||||||
must_be_planar: bool,
|
must_be_planar: bool,
|
||||||
) -> Result<uuid::Uuid, KclError> {
|
) -> Result<uuid::Uuid, KclError> {
|
||||||
match self {
|
match self {
|
||||||
FaceTag::Tag(ref t) => args.get_adjacent_face_to_tag(t, must_be_planar).await,
|
FaceTag::Tag(ref t) => args.get_adjacent_face_to_tag(exec_state, t, must_be_planar).await,
|
||||||
FaceTag::StartOrEnd(StartOrEnd::Start) => extrude_group.start_cap_id.ok_or_else(|| {
|
FaceTag::StartOrEnd(StartOrEnd::Start) => extrude_group.start_cap_id.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: "Expected a start face".to_string(),
|
message: "Expected a start face".to_string(),
|
||||||
@ -89,7 +90,7 @@ pub enum StartOrEnd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line to a point.
|
/// Draw a line to a point.
|
||||||
pub async fn line_to(args: Args) -> Result<KclValue, KclError> {
|
pub async fn line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -160,7 +161,7 @@ async fn inner_line_to(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line to a point on the x-axis.
|
/// Draw a line to a point on the x-axis.
|
||||||
pub async fn x_line_to(args: Args) -> Result<KclValue, KclError> {
|
pub async fn x_line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (to, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
let (to, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -208,7 +209,7 @@ async fn inner_x_line_to(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line to a point on the y-axis.
|
/// Draw a line to a point on the y-axis.
|
||||||
pub async fn y_line_to(args: Args) -> Result<KclValue, KclError> {
|
pub async fn y_line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (to, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
let (to, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -248,7 +249,7 @@ async fn inner_y_line_to(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line.
|
/// Draw a line.
|
||||||
pub async fn line(args: Args) -> Result<KclValue, KclError> {
|
pub async fn line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -333,7 +334,7 @@ async fn inner_line(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line on the x-axis.
|
/// Draw a line on the x-axis.
|
||||||
pub async fn x_line(args: Args) -> Result<KclValue, KclError> {
|
pub async fn x_line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (length, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
let (length, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -376,7 +377,7 @@ async fn inner_x_line(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line on the y-axis.
|
/// Draw a line on the y-axis.
|
||||||
pub async fn y_line(args: Args) -> Result<KclValue, KclError> {
|
pub async fn y_line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (length, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
let (length, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -430,7 +431,7 @@ pub enum AngledLineData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an angled line.
|
/// Draw an angled line.
|
||||||
pub async fn angled_line(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angled_line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -519,7 +520,7 @@ async fn inner_angled_line(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an angled line of a given x length.
|
/// Draw an angled line of a given x length.
|
||||||
pub async fn angled_line_of_x_length(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angled_line_of_x_length(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -587,7 +588,7 @@ pub struct AngledLineToData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an angled line to a given x coordinate.
|
/// Draw an angled line to a given x coordinate.
|
||||||
pub async fn angled_line_to_x(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angled_line_to_x(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (AngledLineToData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (AngledLineToData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -644,7 +645,7 @@ async fn inner_angled_line_to_x(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an angled line of a given y length.
|
/// Draw an angled line of a given y length.
|
||||||
pub async fn angled_line_of_y_length(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angled_line_of_y_length(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -704,7 +705,7 @@ async fn inner_angled_line_of_y_length(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an angled line to a given y coordinate.
|
/// Draw an angled line to a given y coordinate.
|
||||||
pub async fn angled_line_to_y(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angled_line_to_y(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (AngledLineToData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (AngledLineToData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -775,10 +776,10 @@ pub struct AngledLineThatIntersectsData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an angled line that intersects with a given line.
|
/// Draw an angled line that intersects with a given line.
|
||||||
pub async fn angled_line_that_intersects(args: Args) -> Result<KclValue, KclError> {
|
pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (AngledLineThatIntersectsData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (AngledLineThatIntersectsData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, tag, args).await?;
|
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, tag, exec_state, args).await?;
|
||||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,9 +809,10 @@ async fn inner_angled_line_that_intersects(
|
|||||||
data: AngledLineThatIntersectsData,
|
data: AngledLineThatIntersectsData,
|
||||||
sketch_group: SketchGroup,
|
sketch_group: SketchGroup,
|
||||||
tag: Option<TagDeclarator>,
|
tag: Option<TagDeclarator>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
let intersect_path = args.get_tag_engine_info(&data.intersect_tag)?;
|
let intersect_path = args.get_tag_engine_info(exec_state, &data.intersect_tag)?;
|
||||||
let path = intersect_path.path.clone().ok_or_else(|| {
|
let path = intersect_path.path.clone().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Expected an intersect path with a path, found `{:?}`", intersect_path),
|
message: format!("Expected an intersect path with a path, found `{:?}`", intersect_path),
|
||||||
@ -831,10 +833,10 @@ async fn inner_angled_line_that_intersects(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start a sketch at a given point.
|
/// Start a sketch at a given point.
|
||||||
pub async fn start_sketch_at(args: Args) -> Result<KclValue, KclError> {
|
pub async fn start_sketch_at(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let data: [f64; 2] = args.get_data()?;
|
let data: [f64; 2] = args.get_data()?;
|
||||||
|
|
||||||
let sketch_group = inner_start_sketch_at(data, args).await?;
|
let sketch_group = inner_start_sketch_at(data, exec_state, args).await?;
|
||||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -872,11 +874,15 @@ pub async fn start_sketch_at(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "startSketchAt",
|
name = "startSketchAt",
|
||||||
}]
|
}]
|
||||||
async fn inner_start_sketch_at(data: [f64; 2], args: Args) -> Result<SketchGroup, KclError> {
|
async fn inner_start_sketch_at(
|
||||||
|
data: [f64; 2],
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<SketchGroup, KclError> {
|
||||||
// Let's assume it's the XY plane for now, this is just for backwards compatibility.
|
// Let's assume it's the XY plane for now, this is just for backwards compatibility.
|
||||||
let xy_plane = PlaneData::XY;
|
let xy_plane = PlaneData::XY;
|
||||||
let sketch_surface = inner_start_sketch_on(SketchData::Plane(xy_plane), None, args.clone()).await?;
|
let sketch_surface = inner_start_sketch_on(SketchData::Plane(xy_plane), None, exec_state, &args).await?;
|
||||||
let sketch_group = inner_start_profile_at(data, sketch_surface, None, args).await?;
|
let sketch_group = inner_start_profile_at(data, sketch_surface, None, exec_state, args).await?;
|
||||||
Ok(sketch_group)
|
Ok(sketch_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,10 +1012,10 @@ impl From<PlaneData> for Plane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start a sketch on a specific plane or face.
|
/// Start a sketch on a specific plane or face.
|
||||||
pub async fn start_sketch_on(args: Args) -> Result<KclValue, KclError> {
|
pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, tag): (SketchData, Option<FaceTag>) = args.get_data_and_optional_tag()?;
|
let (data, tag): (SketchData, Option<FaceTag>) = args.get_data_and_optional_tag()?;
|
||||||
|
|
||||||
match inner_start_sketch_on(data, tag, args).await? {
|
match inner_start_sketch_on(data, tag, exec_state, &args).await? {
|
||||||
SketchSurface::Plane(plane) => Ok(KclValue::Plane(plane)),
|
SketchSurface::Plane(plane) => Ok(KclValue::Plane(plane)),
|
||||||
SketchSurface::Face(face) => Ok(KclValue::Face(face)),
|
SketchSurface::Face(face) => Ok(KclValue::Face(face)),
|
||||||
}
|
}
|
||||||
@ -1119,7 +1125,12 @@ pub async fn start_sketch_on(args: Args) -> Result<KclValue, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "startSketchOn",
|
name = "startSketchOn",
|
||||||
}]
|
}]
|
||||||
async fn inner_start_sketch_on(data: SketchData, tag: Option<FaceTag>, args: Args) -> Result<SketchSurface, KclError> {
|
async fn inner_start_sketch_on(
|
||||||
|
data: SketchData,
|
||||||
|
tag: Option<FaceTag>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: &Args,
|
||||||
|
) -> Result<SketchSurface, KclError> {
|
||||||
match data {
|
match data {
|
||||||
SketchData::Plane(plane_data) => {
|
SketchData::Plane(plane_data) => {
|
||||||
let plane = start_sketch_on_plane(plane_data, args).await?;
|
let plane = start_sketch_on_plane(plane_data, args).await?;
|
||||||
@ -1132,7 +1143,7 @@ async fn inner_start_sketch_on(data: SketchData, tag: Option<FaceTag>, args: Arg
|
|||||||
source_ranges: vec![args.source_range],
|
source_ranges: vec![args.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
let face = start_sketch_on_face(extrude_group, tag, args).await?;
|
let face = start_sketch_on_face(extrude_group, tag, exec_state, args).await?;
|
||||||
Ok(SketchSurface::Face(face))
|
Ok(SketchSurface::Face(face))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1141,9 +1152,10 @@ async fn inner_start_sketch_on(data: SketchData, tag: Option<FaceTag>, args: Arg
|
|||||||
async fn start_sketch_on_face(
|
async fn start_sketch_on_face(
|
||||||
extrude_group: Box<ExtrudeGroup>,
|
extrude_group: Box<ExtrudeGroup>,
|
||||||
tag: FaceTag,
|
tag: FaceTag,
|
||||||
args: Args,
|
exec_state: &mut ExecState,
|
||||||
|
args: &Args,
|
||||||
) -> Result<Box<Face>, KclError> {
|
) -> Result<Box<Face>, KclError> {
|
||||||
let extrude_plane_id = tag.get_face_id(&extrude_group, &args, true).await?;
|
let extrude_plane_id = tag.get_face_id(&extrude_group, exec_state, args, true).await?;
|
||||||
|
|
||||||
Ok(Box::new(Face {
|
Ok(Box::new(Face {
|
||||||
id: extrude_plane_id,
|
id: extrude_plane_id,
|
||||||
@ -1157,7 +1169,7 @@ async fn start_sketch_on_face(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_sketch_on_plane(data: PlaneData, args: Args) -> Result<Box<Plane>, KclError> {
|
async fn start_sketch_on_plane(data: PlaneData, args: &Args) -> Result<Box<Plane>, KclError> {
|
||||||
let mut plane: Plane = data.clone().into();
|
let mut plane: Plane = data.clone().into();
|
||||||
|
|
||||||
// Get the default planes.
|
// Get the default planes.
|
||||||
@ -1199,11 +1211,11 @@ async fn start_sketch_on_plane(data: PlaneData, args: Args) -> Result<Box<Plane>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start a new profile at a given point.
|
/// Start a new profile at a given point.
|
||||||
pub async fn start_profile_at(args: Args) -> Result<KclValue, KclError> {
|
pub async fn start_profile_at(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (start, sketch_surface, tag): ([f64; 2], SketchSurface, Option<TagDeclarator>) =
|
let (start, sketch_surface, tag): ([f64; 2], SketchSurface, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_surface()?;
|
args.get_data_and_sketch_surface()?;
|
||||||
|
|
||||||
let sketch_group = inner_start_profile_at(start, sketch_surface, tag, args).await?;
|
let sketch_group = inner_start_profile_at(start, sketch_surface, tag, exec_state, args).await?;
|
||||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1248,12 +1260,13 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
to: [f64; 2],
|
to: [f64; 2],
|
||||||
sketch_surface: SketchSurface,
|
sketch_surface: SketchSurface,
|
||||||
tag: Option<TagDeclarator>,
|
tag: Option<TagDeclarator>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
if let SketchSurface::Face(face) = &sketch_surface {
|
if let SketchSurface::Face(face) = &sketch_surface {
|
||||||
// Flush the batch for our fillets/chamfers if there are any.
|
// Flush the batch for our fillets/chamfers if there are any.
|
||||||
// If we do not do these for sketch on face, things will fail with face does not exist.
|
// If we do not do these for sketch on face, things will fail with face does not exist.
|
||||||
args.flush_batch_for_extrude_group_set(face.extrude_group.clone().into())
|
args.flush_batch_for_extrude_group_set(exec_state, face.extrude_group.clone().into())
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1328,7 +1341,7 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the X component of the sketch profile start point.
|
/// Returns the X component of the sketch profile start point.
|
||||||
pub async fn profile_start_x(args: Args) -> Result<KclValue, KclError> {
|
pub async fn profile_start_x(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
||||||
let x = inner_profile_start_x(sketch_group)?;
|
let x = inner_profile_start_x(sketch_group)?;
|
||||||
args.make_user_val_from_f64(x)
|
args.make_user_val_from_f64(x)
|
||||||
@ -1352,7 +1365,7 @@ pub(crate) fn inner_profile_start_x(sketch_group: SketchGroup) -> Result<f64, Kc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Y component of the sketch profile start point.
|
/// Returns the Y component of the sketch profile start point.
|
||||||
pub async fn profile_start_y(args: Args) -> Result<KclValue, KclError> {
|
pub async fn profile_start_y(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
||||||
let x = inner_profile_start_y(sketch_group)?;
|
let x = inner_profile_start_y(sketch_group)?;
|
||||||
args.make_user_val_from_f64(x)
|
args.make_user_val_from_f64(x)
|
||||||
@ -1375,7 +1388,7 @@ pub(crate) fn inner_profile_start_y(sketch_group: SketchGroup) -> Result<f64, Kc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sketch profile start point.
|
/// Returns the sketch profile start point.
|
||||||
pub async fn profile_start(args: Args) -> Result<KclValue, KclError> {
|
pub async fn profile_start(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
||||||
let point = inner_profile_start(sketch_group)?;
|
let point = inner_profile_start(sketch_group)?;
|
||||||
Ok(KclValue::UserVal(UserVal {
|
Ok(KclValue::UserVal(UserVal {
|
||||||
@ -1409,7 +1422,7 @@ pub(crate) fn inner_profile_start(sketch_group: SketchGroup) -> Result<[f64; 2],
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Close the current sketch.
|
/// Close the current sketch.
|
||||||
pub async fn close(args: Args) -> Result<KclValue, KclError> {
|
pub async fn close(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (sketch_group, tag): (SketchGroup, Option<TagDeclarator>) = args.get_sketch_group_and_optional_tag()?;
|
let (sketch_group, tag): (SketchGroup, Option<TagDeclarator>) = args.get_sketch_group_and_optional_tag()?;
|
||||||
|
|
||||||
let new_sketch_group = inner_close(sketch_group, tag, args).await?;
|
let new_sketch_group = inner_close(sketch_group, tag, args).await?;
|
||||||
@ -1516,7 +1529,7 @@ pub enum ArcData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw an arc.
|
/// Draw an arc.
|
||||||
pub async fn arc(args: Args) -> Result<KclValue, KclError> {
|
pub async fn arc(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (ArcData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (ArcData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -1637,7 +1650,7 @@ pub enum TangentialArcData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a tangential arc.
|
/// Draw a tangential arc.
|
||||||
pub async fn tangential_arc(args: Args) -> Result<KclValue, KclError> {
|
pub async fn tangential_arc(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (TangentialArcData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (TangentialArcData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -1767,7 +1780,7 @@ fn tan_arc_to(sketch_group: &SketchGroup, to: &[f64; 2]) -> ModelingCmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a tangential arc to a specific point.
|
/// Draw a tangential arc to a specific point.
|
||||||
pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
pub async fn tangential_arc_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
super::args::FromArgs::from_args(&args, 0)?;
|
super::args::FromArgs::from_args(&args, 0)?;
|
||||||
|
|
||||||
@ -1776,7 +1789,7 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a tangential arc to point some distance away..
|
/// Draw a tangential arc to point some distance away..
|
||||||
pub async fn tangential_arc_to_relative(args: Args) -> Result<KclValue, KclError> {
|
pub async fn tangential_arc_to_relative(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
super::args::FromArgs::from_args(&args, 0)?;
|
super::args::FromArgs::from_args(&args, 0)?;
|
||||||
|
|
||||||
@ -1951,7 +1964,7 @@ pub struct BezierData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a bezier curve.
|
/// Draw a bezier curve.
|
||||||
pub async fn bezier_curve(args: Args) -> Result<KclValue, KclError> {
|
pub async fn bezier_curve(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, sketch_group, tag): (BezierData, SketchGroup, Option<TagDeclarator>) =
|
let (data, sketch_group, tag): (BezierData, SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
@ -2043,7 +2056,7 @@ async fn inner_bezier_curve(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Use a sketch to cut a hole in another sketch.
|
/// Use a sketch to cut a hole in another sketch.
|
||||||
pub async fn hole(args: Args) -> Result<KclValue, KclError> {
|
pub async fn hole(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (hole_sketch_group, sketch_group): (SketchGroupSet, SketchGroup) = args.get_sketch_groups()?;
|
let (hole_sketch_group, sketch_group): (SketchGroupSet, SketchGroup) = args.get_sketch_groups()?;
|
||||||
|
|
||||||
let new_sketch_group = inner_hole(hole_sketch_group, sketch_group, args).await?;
|
let new_sketch_group = inner_hole(hole_sketch_group, sketch_group, args).await?;
|
||||||
|
@ -4,10 +4,15 @@ use anyhow::Result;
|
|||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
use crate::{errors::KclError, executor::KclValue, settings::types::UnitLength, std::Args};
|
use crate::{
|
||||||
|
errors::KclError,
|
||||||
|
executor::{ExecState, KclValue},
|
||||||
|
settings::types::UnitLength,
|
||||||
|
std::Args,
|
||||||
|
};
|
||||||
|
|
||||||
/// Millimeters conversion factor for current projects units.
|
/// Millimeters conversion factor for current projects units.
|
||||||
pub async fn mm(args: Args) -> Result<KclValue, KclError> {
|
pub async fn mm(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_mm(&args)?;
|
let result = inner_mm(&args)?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -48,7 +53,7 @@ fn inner_mm(args: &Args) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Inches conversion factor for current projects units.
|
/// Inches conversion factor for current projects units.
|
||||||
pub async fn inch(args: Args) -> Result<KclValue, KclError> {
|
pub async fn inch(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_inch(&args)?;
|
let result = inner_inch(&args)?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -89,7 +94,7 @@ fn inner_inch(args: &Args) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Feet conversion factor for current projects units.
|
/// Feet conversion factor for current projects units.
|
||||||
pub async fn ft(args: Args) -> Result<KclValue, KclError> {
|
pub async fn ft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_ft(&args)?;
|
let result = inner_ft(&args)?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -131,7 +136,7 @@ fn inner_ft(args: &Args) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Meters conversion factor for current projects units.
|
/// Meters conversion factor for current projects units.
|
||||||
pub async fn m(args: Args) -> Result<KclValue, KclError> {
|
pub async fn m(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_m(&args)?;
|
let result = inner_m(&args)?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -173,7 +178,7 @@ fn inner_m(args: &Args) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Centimeters conversion factor for current projects units.
|
/// Centimeters conversion factor for current projects units.
|
||||||
pub async fn cm(args: Args) -> Result<KclValue, KclError> {
|
pub async fn cm(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_cm(&args)?;
|
let result = inner_cm(&args)?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
@ -215,7 +220,7 @@ fn inner_cm(args: &Args) -> Result<f64, KclError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Yards conversion factor for current projects units.
|
/// Yards conversion factor for current projects units.
|
||||||
pub async fn yd(args: Args) -> Result<KclValue, KclError> {
|
pub async fn yd(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let result = inner_yd(&args)?;
|
let result = inner_yd(&args)?;
|
||||||
|
|
||||||
args.make_user_val_from_f64(result)
|
args.make_user_val_from_f64(result)
|
||||||
|
@ -53,13 +53,13 @@ pub async fn execute_wasm(
|
|||||||
is_mock,
|
is_mock,
|
||||||
};
|
};
|
||||||
|
|
||||||
let memory = ctx.run(&program, Some(memory)).await.map_err(String::from)?;
|
let exec_state = ctx.run(&program, Some(memory)).await.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.
|
||||||
// DO NOT USE serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
|
// DO NOT USE serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
|
||||||
// it will break the frontend.
|
// it will break the frontend.
|
||||||
JsValue::from_serde(&memory).map_err(|e| e.to_string())
|
JsValue::from_serde(&exec_state.memory).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
// wasm_bindgen wrapper for execute
|
// wasm_bindgen wrapper for execute
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
// Make sure pipe value doesn't leak into the function call.
|
||||||
|
fn f = (ignored) => {
|
||||||
|
return %
|
||||||
|
}
|
||||||
|
|
||||||
|
const answer = %
|
||||||
|
|> f(%)
|
@ -85,5 +85,9 @@ gen_test_fail!(
|
|||||||
object_prop_not_found,
|
object_prop_not_found,
|
||||||
"undefined value: Property 'age' not found in object"
|
"undefined value: Property 'age' not found in object"
|
||||||
);
|
);
|
||||||
|
gen_test_fail!(
|
||||||
|
pipe_substitution_inside_function_called_from_pipeline,
|
||||||
|
"semantic: cannot use % outside a pipe expression"
|
||||||
|
);
|
||||||
gen_test!(sketch_group_in_object);
|
gen_test!(sketch_group_in_object);
|
||||||
gen_test!(add_lots);
|
gen_test!(add_lots);
|
||||||
|
@ -35,12 +35,12 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
|
|||||||
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 ctx = kcl_lib::executor::ExecutorContext::new(&client, Default::default()).await?;
|
let ctx = kcl_lib::executor::ExecutorContext::new(&client, Default::default()).await?;
|
||||||
let memory = ctx.run(&program, None).await?;
|
let exec_state = ctx.run(&program, None).await?;
|
||||||
|
|
||||||
// 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.
|
||||||
let KclValue::UserVal(user_val) = memory.get(name, SourceRange::default()).unwrap() else {
|
let KclValue::UserVal(user_val) = exec_state.memory.get(name, SourceRange::default()).unwrap() else {
|
||||||
anyhow::bail!("part001 not found in memory: {:?}", memory);
|
anyhow::bail!("part001 not found in memory: {:?}", exec_state.memory);
|
||||||
};
|
};
|
||||||
let Some((sketch_group, _meta)) = user_val.get::<SketchGroup>() else {
|
let Some((sketch_group, _meta)) = user_val.get::<SketchGroup>() else {
|
||||||
anyhow::bail!("part001 was not a SketchGroup");
|
anyhow::bail!("part001 was not a SketchGroup");
|
||||||
|
Reference in New Issue
Block a user