Initial kcl to core codegen (C++) util (#2999)
* wip on this * wip on kcl-to-core tool * Update conn_mock_core.rs * stopping point * wip * use enum for is_mock for added versatility * get at least circular patterns working to finish POC * fmt * fmt part 2 * Update Cargo.lock * quick fix for tests * quick fix * more fixes * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * get more cases of this working * Update src/wasm-lib/kcl-to-core/src/conn_mock_core.rs Co-authored-by: Jonathan Tran <jonnytran@gmail.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * kcl core gen plane code by default * fmt * fix build? * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) * Fix clippy errors * Remove unneeded clippy allow * post merge build fix attempt * Add missing indexmap dependency * Fix to use IndexMap instead of HashMap * Migrate to kittycad-modeling-cmds * fix build * fmt * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) * Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)" This reverts commit991cdde15e. * Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)" This reverts commita4ae03c740. * Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)" This reverts commit9a082e7c9f. * Regenerate derive_docs * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) * Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)" This reverts commita8bdb35627. * Fix e2e test failing by masking state indicator * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) * Confirm snapshot change * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) * Confirm snapshot change * Fix build from last merge with main --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Jonathan Tran <jonnytran@gmail.com> Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch> Co-authored-by: Frank Noirot <frank@zoo.dev>
This commit is contained in:
		
							
								
								
									
										81
									
								
								src/wasm-lib/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										81
									
								
								src/wasm-lib/Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -70,12 +70,55 @@ version = "0.1.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "anstream"
 | 
			
		||||
version = "0.6.15"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "anstyle",
 | 
			
		||||
 "anstyle-parse",
 | 
			
		||||
 "anstyle-query",
 | 
			
		||||
 "anstyle-wincon",
 | 
			
		||||
 "colorchoice",
 | 
			
		||||
 "is_terminal_polyfill",
 | 
			
		||||
 "utf8parse",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "anstyle"
 | 
			
		||||
version = "1.0.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "anstyle-parse"
 | 
			
		||||
version = "0.2.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "utf8parse",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "anstyle-query"
 | 
			
		||||
version = "1.1.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-sys 0.52.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "anstyle-wincon"
 | 
			
		||||
version = "3.0.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "anstyle",
 | 
			
		||||
 "windows-sys 0.52.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "anyhow"
 | 
			
		||||
version = "1.0.89"
 | 
			
		||||
@ -405,8 +448,12 @@ version = "4.5.18"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "anstream",
 | 
			
		||||
 "anstyle",
 | 
			
		||||
 "clap_lex",
 | 
			
		||||
 "strsim",
 | 
			
		||||
 "unicase",
 | 
			
		||||
 "unicode-width",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -427,6 +474,12 @@ version = "0.7.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "colorchoice"
 | 
			
		||||
version = "1.0.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "colored"
 | 
			
		||||
version = "2.1.0"
 | 
			
		||||
@ -1433,6 +1486,12 @@ dependencies = [
 | 
			
		||||
 "windows-sys 0.52.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "is_terminal_polyfill"
 | 
			
		||||
version = "1.70.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "itertools"
 | 
			
		||||
version = "0.10.5"
 | 
			
		||||
@ -1563,6 +1622,20 @@ dependencies = [
 | 
			
		||||
 "tokio",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "kcl-to-core"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "anyhow",
 | 
			
		||||
 "async-trait",
 | 
			
		||||
 "indexmap 2.5.0",
 | 
			
		||||
 "kcl-lib",
 | 
			
		||||
 "kittycad",
 | 
			
		||||
 "kittycad-modeling-cmds",
 | 
			
		||||
 "tokio",
 | 
			
		||||
 "uuid",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "kittycad"
 | 
			
		||||
version = "0.3.23"
 | 
			
		||||
@ -1575,6 +1648,7 @@ dependencies = [
 | 
			
		||||
 "bigdecimal",
 | 
			
		||||
 "bytes",
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "clap",
 | 
			
		||||
 "data-encoding",
 | 
			
		||||
 "format_serde_error",
 | 
			
		||||
 "futures",
 | 
			
		||||
@ -3348,6 +3422,7 @@ dependencies = [
 | 
			
		||||
 "signal-hook-registry",
 | 
			
		||||
 "socket2",
 | 
			
		||||
 "tokio-macros",
 | 
			
		||||
 "tracing",
 | 
			
		||||
 "windows-sys 0.52.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -3737,6 +3812,12 @@ version = "0.7.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "utf8parse"
 | 
			
		||||
version = "0.2.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "uuid"
 | 
			
		||||
version = "1.10.0"
 | 
			
		||||
 | 
			
		||||
@ -66,6 +66,7 @@ members = [
 | 
			
		||||
	"kcl",
 | 
			
		||||
	"kcl-macros",
 | 
			
		||||
	"kcl-test-server",
 | 
			
		||||
	"kcl-to-core",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[workspace.dependencies]
 | 
			
		||||
 | 
			
		||||
@ -758,7 +758,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
 | 
			
		||||
                fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
                stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
                settings: Default::default(),
 | 
			
		||||
                is_mock: true,
 | 
			
		||||
                context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            ctx.run(&program, None).await.unwrap();
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_someFn {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_someFn {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_show {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
@ -47,7 +47,7 @@ mod test_examples_show {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_show {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ mod test_examples_my_func {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
@ -48,7 +48,7 @@ mod test_examples_my_func {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ mod test_examples_line_to {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
@ -48,7 +48,7 @@ mod test_examples_line_to {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_min {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
@ -47,7 +47,7 @@ mod test_examples_min {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_show {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_import {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_import {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_import {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_show {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ mod test_examples_some_function {
 | 
			
		||||
            fs: std::sync::Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        ctx.run(&program, None).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								src/wasm-lib/kcl-to-core/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/wasm-lib/kcl-to-core/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "kcl-to-core"
 | 
			
		||||
description = "Utility methods to convert kcl to engine core executable tests"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
license = "MIT"
 | 
			
		||||
repository = "https://github.com/KittyCAD/modeling-app"
 | 
			
		||||
 | 
			
		||||
[lib]
 | 
			
		||||
 | 
			
		||||
[[bin]]
 | 
			
		||||
name = "kcl-to-core"
 | 
			
		||||
path = "src/tool.rs"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
anyhow = "1"
 | 
			
		||||
async-trait = "0.1.81"
 | 
			
		||||
indexmap = "2.5.0"
 | 
			
		||||
kcl-lib = { path = "../kcl" }
 | 
			
		||||
kittycad = { workspace = true, features = ["clap"] }
 | 
			
		||||
kittycad-modeling-cmds = { workspace = true }
 | 
			
		||||
tokio = { version = "1.38", features = ["full", "time", "rt", "tracing"] }
 | 
			
		||||
uuid = { version = "1.9.1", features = ["v4", "js", "serde"] }
 | 
			
		||||
							
								
								
									
										469
									
								
								src/wasm-lib/kcl-to-core/src/conn_mock_core.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										469
									
								
								src/wasm-lib/kcl-to-core/src/conn_mock_core.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,469 @@
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use indexmap::IndexMap;
 | 
			
		||||
use kcl_lib::{errors::KclError, executor::DefaultPlanes};
 | 
			
		||||
use kittycad_modeling_cmds::{
 | 
			
		||||
    self as kcmc,
 | 
			
		||||
    id::ModelingCmdId,
 | 
			
		||||
    ok_response::OkModelingCmdResponse,
 | 
			
		||||
    shared::PathSegment::{self, *},
 | 
			
		||||
    websocket::{ModelingBatch, ModelingCmdReq, OkWebSocketResponseData, WebSocketRequest, WebSocketResponse},
 | 
			
		||||
};
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    sync::{Arc, Mutex},
 | 
			
		||||
};
 | 
			
		||||
use tokio::sync::RwLock;
 | 
			
		||||
 | 
			
		||||
const CPP_PREFIX: &str = "const double scaleFactor = 100;\n";
 | 
			
		||||
const NEED_PLANES: bool = true;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct EngineConnection {
 | 
			
		||||
    batch: Arc<Mutex<Vec<(WebSocketRequest, kcl_lib::executor::SourceRange)>>>,
 | 
			
		||||
    batch_end: Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::executor::SourceRange)>>>,
 | 
			
		||||
    core_test: Arc<Mutex<String>>,
 | 
			
		||||
    default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EngineConnection {
 | 
			
		||||
    pub async fn new(result: Arc<Mutex<String>>) -> Result<EngineConnection> {
 | 
			
		||||
        if let Ok(mut code) = result.lock() {
 | 
			
		||||
            code.push_str(CPP_PREFIX);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(EngineConnection {
 | 
			
		||||
            batch: Arc::new(Mutex::new(Vec::new())),
 | 
			
		||||
            batch_end: Arc::new(Mutex::new(IndexMap::new())),
 | 
			
		||||
            core_test: result,
 | 
			
		||||
            default_planes: Default::default(),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn handle_command(&self, cmd_id: &ModelingCmdId, cmd: &kcmc::ModelingCmd) -> (String, OkModelingCmdResponse) {
 | 
			
		||||
        let cpp_id = id_to_cpp(cmd_id);
 | 
			
		||||
        let cmd_id = format!("{}", cmd_id);
 | 
			
		||||
        let mut this_response = OkModelingCmdResponse::Empty {};
 | 
			
		||||
 | 
			
		||||
        let new_code = match cmd {
 | 
			
		||||
            kcmc::ModelingCmd::ObjectVisible(kcmc::ObjectVisible { hidden, object_id }) => {
 | 
			
		||||
                format!(r#"scene->getSceneObject(Utils::UUID("{object_id}"))->setHidden({hidden});"#)
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::EnableSketchMode(kcmc::EnableSketchMode {
 | 
			
		||||
                entity_id,
 | 
			
		||||
                animated: _,
 | 
			
		||||
                ortho: _,
 | 
			
		||||
                adjust_camera: _,
 | 
			
		||||
                planar_normal,
 | 
			
		||||
            }) => {
 | 
			
		||||
                if let Some(normal) = planar_normal {
 | 
			
		||||
                    format!(
 | 
			
		||||
                        r#"
 | 
			
		||||
                        if(!scene->enableSketchMode(Utils::UUID("{entity_id}"), glm::dvec3 {{ {}, {}, {}, }}, nullopt))
 | 
			
		||||
                        {{
 | 
			
		||||
                            Utils::Plane plane_{cpp_id}(glm::dvec3 {{ 0, 0, 0 }}, glm::dvec3 {{ 1, 0, 0 }}, glm::dvec3 {{ 0, 1, 0 }});
 | 
			
		||||
                            scene->enableSketchMode(plane_{cpp_id}, nullopt, nullopt, false);
 | 
			
		||||
                        }}
 | 
			
		||||
                    "#,
 | 
			
		||||
                        normal.x, normal.y, normal.z
 | 
			
		||||
                    )
 | 
			
		||||
                } else {
 | 
			
		||||
                    "".into()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::SketchModeDisable(kcmc::SketchModeDisable {}) => "scene->disableSketchMode();".into(),
 | 
			
		||||
            kcmc::ModelingCmd::MakePlane(kcmc::MakePlane {
 | 
			
		||||
                origin,
 | 
			
		||||
                x_axis,
 | 
			
		||||
                y_axis,
 | 
			
		||||
                size,
 | 
			
		||||
                ..
 | 
			
		||||
            }) => {
 | 
			
		||||
                let plane_id = format!("plane_{}", cpp_id);
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    auto {plane_id} = make_shared<Object>("plane", glm::dvec3 {{ 0, 0, 0 }});
 | 
			
		||||
                    {plane_id}->setUUID(Utils::UUID("{cmd_id}"));
 | 
			
		||||
                    {plane_id}->makePlane(glm::dvec3 {{ {}, {}, {} }} * scaleFactor, glm::dvec3 {{ {}, {}, {} }}, glm::dvec3 {{ {}, {}, {} }}, {}, false);
 | 
			
		||||
                    {plane_id}->setHidden();
 | 
			
		||||
                    scene->addSceneObject({plane_id});
 | 
			
		||||
                "#,
 | 
			
		||||
                    origin.x.0,
 | 
			
		||||
                    origin.y.0,
 | 
			
		||||
                    origin.z.0,
 | 
			
		||||
                    x_axis.x,
 | 
			
		||||
                    x_axis.y,
 | 
			
		||||
                    x_axis.z,
 | 
			
		||||
                    y_axis.x,
 | 
			
		||||
                    y_axis.y,
 | 
			
		||||
                    y_axis.z,
 | 
			
		||||
                    size.0
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::StartPath(kcmc::StartPath {}) => {
 | 
			
		||||
                let sketch_id = format!("sketch_{}", cpp_id);
 | 
			
		||||
                let path_id = format!("path_{}", cpp_id);
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    auto {sketch_id} = make_shared<Object>("sketch", glm::dvec3 {{ 0, 0, 0 }});
 | 
			
		||||
                    {sketch_id}->setUUID(Utils::UUID("{cmd_id}"));
 | 
			
		||||
                    {sketch_id}->makePath(true);
 | 
			
		||||
                    auto {path_id} = {sketch_id}->get<Model::Brep::Path>();
 | 
			
		||||
                    scene->addSceneObject({sketch_id});
 | 
			
		||||
                "#
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::MovePathPen(kcmc::MovePathPen { path, to }) => {
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    path_{}->moveTo(glm::dvec3 {{ {}, {}, 0.0 }} * scaleFactor);
 | 
			
		||||
                "#,
 | 
			
		||||
                    id_to_cpp(path),
 | 
			
		||||
                    to.x.0,
 | 
			
		||||
                    to.y.0
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::ExtendPath(kcmc::ExtendPath { path, segment }) => match segment {
 | 
			
		||||
                Line { end, relative } => {
 | 
			
		||||
                    format!(
 | 
			
		||||
                        r#"
 | 
			
		||||
                            path_{}->lineTo(glm::dvec3 {{ {}, {}, 0.0 }} * scaleFactor, {{ {} }});
 | 
			
		||||
                        "#,
 | 
			
		||||
                        id_to_cpp(path),
 | 
			
		||||
                        end.x.0,
 | 
			
		||||
                        end.y.0,
 | 
			
		||||
                        relative
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                PathSegment::Arc {
 | 
			
		||||
                    center,
 | 
			
		||||
                    radius,
 | 
			
		||||
                    start,
 | 
			
		||||
                    end,
 | 
			
		||||
                    relative,
 | 
			
		||||
                } => {
 | 
			
		||||
                    let start = start.value;
 | 
			
		||||
                    let end = end.value;
 | 
			
		||||
                    let radius = radius.0;
 | 
			
		||||
 | 
			
		||||
                    format!(
 | 
			
		||||
                        r#"
 | 
			
		||||
                            path_{}->addArc(glm::dvec2 {{ {}, {} }} * scaleFactor, {radius} * scaleFactor, {start}, {end}, {{ {} }});
 | 
			
		||||
                        "#,
 | 
			
		||||
                        id_to_cpp(path),
 | 
			
		||||
                        center.x.0,
 | 
			
		||||
                        center.y.0,
 | 
			
		||||
                        relative
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                PathSegment::TangentialArcTo {
 | 
			
		||||
                    angle_snap_increment: _,
 | 
			
		||||
                    to,
 | 
			
		||||
                } => {
 | 
			
		||||
                    format!(
 | 
			
		||||
                        r#"
 | 
			
		||||
                            path_{}->tangentialArcTo(glm::dvec3 {{ {}, {}, {} }} * scaleFactor, nullopt, {{ true }});
 | 
			
		||||
                        "#,
 | 
			
		||||
                        id_to_cpp(path),
 | 
			
		||||
                        to.x.0,
 | 
			
		||||
                        to.y.0,
 | 
			
		||||
                        to.z.0,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                _ => {
 | 
			
		||||
                    format!("//{:?}", cmd)
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            kcmc::ModelingCmd::ClosePath(kcmc::ClosePath { path_id }) => {
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    path_{}->close();
 | 
			
		||||
                    sketch_{}->toSolid2D();
 | 
			
		||||
                "#,
 | 
			
		||||
                    uuid_to_cpp(path_id),
 | 
			
		||||
                    uuid_to_cpp(path_id)
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::Extrude(kcmc::Extrude { distance, target }) => {
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    scene->getSceneObject(Utils::UUID("{target}"))->extrudeToSolid3D({} * scaleFactor, true);
 | 
			
		||||
                "#,
 | 
			
		||||
                    distance.0
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::Revolve(kcmc::Revolve {
 | 
			
		||||
                angle,
 | 
			
		||||
                axis,
 | 
			
		||||
                axis_is_2d,
 | 
			
		||||
                origin,
 | 
			
		||||
                target,
 | 
			
		||||
                tolerance,
 | 
			
		||||
            }) => {
 | 
			
		||||
                let ox = origin.x.0;
 | 
			
		||||
                let oy = origin.y.0;
 | 
			
		||||
                let oz = origin.z.0;
 | 
			
		||||
                let ax = axis.x;
 | 
			
		||||
                let ay = axis.y;
 | 
			
		||||
                let az = axis.z;
 | 
			
		||||
                let angle = angle.value;
 | 
			
		||||
                let tolerance = tolerance.0;
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    scene->getSceneObject(Utils::UUID("{target}"))->revolveToSolid3D(nullopt, glm::dvec3 {{ {ox}, {oy}, {oz} }} * scaleFactor, glm::dvec3 {{ {ax}, {ay}, {az} }}, {axis_is_2d}, {angle}, {tolerance});
 | 
			
		||||
                "#
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::Solid2dAddHole(kcmc::Solid2dAddHole { hole_id, object_id }) => {
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"scene->getSceneObject(Utils::UUID("{object_id}"))->get<Model::Brep::Solid2D>()->addHole(
 | 
			
		||||
                    make_shared<Model::Brep::Path>(*scene->getSceneObject(Utils::UUID("{hole_id}"))->get<Model::Brep::Solid2D>()->getPath())
 | 
			
		||||
                );"#
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::Solid3dGetExtrusionFaceInfo(kcmc::Solid3dGetExtrusionFaceInfo {
 | 
			
		||||
                object_id,
 | 
			
		||||
                edge_id,
 | 
			
		||||
            }) => {
 | 
			
		||||
                format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    //face info get {} {}
 | 
			
		||||
                "#,
 | 
			
		||||
                    object_id, edge_id
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::EntityCircularPattern(kcmc::EntityCircularPattern {
 | 
			
		||||
                entity_id,
 | 
			
		||||
                axis,
 | 
			
		||||
                center,
 | 
			
		||||
                num_repetitions,
 | 
			
		||||
                arc_degrees,
 | 
			
		||||
                rotate_duplicates,
 | 
			
		||||
            }) => {
 | 
			
		||||
                let entity_ids = generate_repl_uuids(*num_repetitions as usize);
 | 
			
		||||
 | 
			
		||||
                this_response = OkModelingCmdResponse::EntityCircularPattern(kcmc::output::EntityCircularPattern {
 | 
			
		||||
                    entity_ids: entity_ids.clone(),
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                let mut base_code: String = format!(
 | 
			
		||||
                    r#"
 | 
			
		||||
                    auto reps_{cpp_id} = scene->entityCircularPattern(Utils::UUID("{}"), {num_repetitions}, glm::dvec3 {{ {}, {}, {} }}  * scaleFactor, glm::dvec3 {{ {}, {}, {} }}  * scaleFactor, {arc_degrees}, {rotate_duplicates});
 | 
			
		||||
                "#,
 | 
			
		||||
                    entity_id, axis.x, axis.y, axis.z, center.x.0, center.y.0, center.z.0
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                let repl_uuid_fix_code = codegen_cpp_repl_uuid_setters(&cpp_id, &entity_ids);
 | 
			
		||||
                base_code.push_str(&repl_uuid_fix_code);
 | 
			
		||||
 | 
			
		||||
                base_code
 | 
			
		||||
            }
 | 
			
		||||
            kcmc::ModelingCmd::EntityLinearPattern(kcmc::EntityLinearPattern {
 | 
			
		||||
                entity_id: _,
 | 
			
		||||
                axis: _,
 | 
			
		||||
                num_repetitions: _,
 | 
			
		||||
                spacing: _,
 | 
			
		||||
            }) => {
 | 
			
		||||
                // let num_transforms = transforms.len();
 | 
			
		||||
                // let num_repetitions = transform.iter().map(|t| if t.replicate { 1 } else { 0 } ).sum();
 | 
			
		||||
 | 
			
		||||
                // let mut base_code: String = format!(
 | 
			
		||||
                //     r#"
 | 
			
		||||
                //     std::vector<std::optional<Scene::Scene::LinearPatternTransform>> transforms_{cpp_id}({num_transforms});
 | 
			
		||||
                // "#);
 | 
			
		||||
 | 
			
		||||
                // for t in transform {
 | 
			
		||||
                //     translations_xyz.push(t.translate.x.to_millimeters(state.units));
 | 
			
		||||
                //     translations_xyz.push(t.translate.y.to_millimeters(state.units));
 | 
			
		||||
                //     translations_xyz.push(t.translate.z.to_millimeters(state.units));
 | 
			
		||||
                //     scale_xyz.push(t.scale.x);
 | 
			
		||||
                //     scale_xyz.push(t.scale.y);
 | 
			
		||||
                //     scale_xyz.push(t.scale.z);
 | 
			
		||||
                // }
 | 
			
		||||
 | 
			
		||||
                // let entity_ids = generate_repl_uuids(*num_repetitions as usize);
 | 
			
		||||
 | 
			
		||||
                // this_response = OkModelingCmdResponse::EntityLinearPattern {
 | 
			
		||||
                //     data: kittycad::types::EntityLinearPattern {
 | 
			
		||||
                //         entity_ids: entity_ids.clone(),
 | 
			
		||||
                //     },
 | 
			
		||||
                // };
 | 
			
		||||
 | 
			
		||||
                // let mut base_code: String = format!(
 | 
			
		||||
                //     r#"
 | 
			
		||||
                //     auto reps_{cpp_id} = scene->entityCircularPattern(Utils::UUID("{}"), {num_repetitions}, glm::dvec3 {{ {}, {}, {} }}  * scaleFactor, glm::dvec3 {{ {}, {}, {} }}  * scaleFactor, {arc_degrees}, {rotate_duplicates});
 | 
			
		||||
                // "#,
 | 
			
		||||
                //     entity_id, axis.x, axis.y, axis.z, center.x, center.y, center.z
 | 
			
		||||
                // );
 | 
			
		||||
 | 
			
		||||
                // let repl_uuid_fix_code = codegen_cpp_repl_uuid_setters(&cpp_id, &entity_ids);
 | 
			
		||||
                // base_code.push_str(&repl_uuid_fix_code);
 | 
			
		||||
 | 
			
		||||
                // base_code
 | 
			
		||||
                format!("//{:?}", cmd)
 | 
			
		||||
            }
 | 
			
		||||
            _ => {
 | 
			
		||||
                //helps us follow along with the currently unhandled engine commands
 | 
			
		||||
                format!("//{:?}", cmd)
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        (new_code, this_response)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn id_to_cpp(id: &ModelingCmdId) -> String {
 | 
			
		||||
    uuid_to_cpp(&id.0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn uuid_to_cpp(id: &uuid::Uuid) -> String {
 | 
			
		||||
    let str = format!("{}", id);
 | 
			
		||||
    str::replace(&str, "-", "_")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn generate_repl_uuids(count: usize) -> Vec<uuid::Uuid> {
 | 
			
		||||
    let mut repl_ids: Vec<uuid::Uuid> = Vec::new();
 | 
			
		||||
 | 
			
		||||
    repl_ids.resize_with(count, uuid::Uuid::new_v4);
 | 
			
		||||
    repl_ids
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn codegen_cpp_repl_uuid_setters(reps_id: &str, entity_ids: &[uuid::Uuid]) -> String {
 | 
			
		||||
    let mut codegen = String::new();
 | 
			
		||||
 | 
			
		||||
    for (i, id) in entity_ids.iter().enumerate() {
 | 
			
		||||
        let cpp_id = uuid_to_cpp(id);
 | 
			
		||||
        let iter = format!(
 | 
			
		||||
            r#"
 | 
			
		||||
            //change object id -> {id}
 | 
			
		||||
            auto repl_{cpp_id} = scene->getSceneObject(reps_{reps_id}[{i}]);
 | 
			
		||||
            scene->removeSceneObject(repl_{cpp_id}->getUUID(), false);
 | 
			
		||||
            repl_{cpp_id}->setUUID(Utils::UUID("{id}"));
 | 
			
		||||
            scene->addSceneObject(repl_{cpp_id});
 | 
			
		||||
        "#
 | 
			
		||||
        );
 | 
			
		||||
        codegen.push_str(&iter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    codegen
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[async_trait::async_trait]
 | 
			
		||||
impl kcl_lib::engine::EngineManager for EngineConnection {
 | 
			
		||||
    fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, kcl_lib::executor::SourceRange)>>> {
 | 
			
		||||
        self.batch.clone()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::executor::SourceRange)>>> {
 | 
			
		||||
        self.batch_end.clone()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn default_planes(&self, source_range: kcl_lib::executor::SourceRange) -> Result<DefaultPlanes, KclError> {
 | 
			
		||||
        if NEED_PLANES {
 | 
			
		||||
            {
 | 
			
		||||
                let opt = self.default_planes.read().await.as_ref().cloned();
 | 
			
		||||
                if let Some(planes) = opt {
 | 
			
		||||
                    return Ok(planes);
 | 
			
		||||
                }
 | 
			
		||||
            } // drop the read lock
 | 
			
		||||
 | 
			
		||||
            let new_planes = self.new_default_planes(source_range).await?;
 | 
			
		||||
            *self.default_planes.write().await = Some(new_planes.clone());
 | 
			
		||||
 | 
			
		||||
            Ok(new_planes)
 | 
			
		||||
        } else {
 | 
			
		||||
            Ok(DefaultPlanes::default())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn clear_scene_post_hook(&self, _source_range: kcl_lib::executor::SourceRange) -> Result<(), KclError> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn inner_send_modeling_cmd(
 | 
			
		||||
        &self,
 | 
			
		||||
        id: uuid::Uuid,
 | 
			
		||||
        _source_range: kcl_lib::executor::SourceRange,
 | 
			
		||||
        cmd: WebSocketRequest,
 | 
			
		||||
        _id_to_source_range: std::collections::HashMap<uuid::Uuid, kcl_lib::executor::SourceRange>,
 | 
			
		||||
    ) -> Result<WebSocketResponse, KclError> {
 | 
			
		||||
        match cmd {
 | 
			
		||||
            WebSocketRequest::ModelingCmdBatchReq(ModelingBatch {
 | 
			
		||||
                ref requests,
 | 
			
		||||
                batch_id: _,
 | 
			
		||||
                responses: _,
 | 
			
		||||
            }) => {
 | 
			
		||||
                let mut responses = HashMap::new();
 | 
			
		||||
                for request in requests {
 | 
			
		||||
                    let (new_code, this_response);
 | 
			
		||||
 | 
			
		||||
                    if let Ok(mut test_code) = self.core_test.lock() {
 | 
			
		||||
                        (new_code, this_response) = self.handle_command(&request.cmd_id, &request.cmd);
 | 
			
		||||
 | 
			
		||||
                        if !new_code.is_empty() {
 | 
			
		||||
                            let new_code = new_code
 | 
			
		||||
                                .trim()
 | 
			
		||||
                                .split(' ')
 | 
			
		||||
                                .filter(|s| !s.is_empty())
 | 
			
		||||
                                .collect::<Vec<_>>()
 | 
			
		||||
                                .join(" ")
 | 
			
		||||
                                + "\n";
 | 
			
		||||
                            //println!("{new_code}");
 | 
			
		||||
                            test_code.push_str(&new_code);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        this_response = OkModelingCmdResponse::Empty {};
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    responses.insert(
 | 
			
		||||
                        request.cmd_id,
 | 
			
		||||
                        kcmc::websocket::BatchResponse::Success {
 | 
			
		||||
                            response: this_response,
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                Ok(WebSocketResponse::Success(kcmc::websocket::SuccessWebSocketResponse {
 | 
			
		||||
                    success: true,
 | 
			
		||||
                    request_id: Some(id),
 | 
			
		||||
                    resp: OkWebSocketResponseData::ModelingBatch { responses },
 | 
			
		||||
                }))
 | 
			
		||||
            }
 | 
			
		||||
            WebSocketRequest::ModelingCmdReq(ModelingCmdReq { cmd, cmd_id }) => {
 | 
			
		||||
                //also handle unbatched requests inline
 | 
			
		||||
                let (new_code, this_response);
 | 
			
		||||
 | 
			
		||||
                if let Ok(mut test_code) = self.core_test.lock() {
 | 
			
		||||
                    (new_code, this_response) = self.handle_command(&cmd_id, &cmd);
 | 
			
		||||
 | 
			
		||||
                    if !new_code.is_empty() {
 | 
			
		||||
                        let new_code = new_code
 | 
			
		||||
                            .trim()
 | 
			
		||||
                            .split(' ')
 | 
			
		||||
                            .filter(|s| !s.is_empty())
 | 
			
		||||
                            .collect::<Vec<_>>()
 | 
			
		||||
                            .join(" ")
 | 
			
		||||
                            + "\n";
 | 
			
		||||
                        //println!("{new_code}");
 | 
			
		||||
                        test_code.push_str(&new_code);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    this_response = OkModelingCmdResponse::Empty {};
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Ok(WebSocketResponse::Success(kcmc::websocket::SuccessWebSocketResponse {
 | 
			
		||||
                    success: true,
 | 
			
		||||
                    request_id: Some(id),
 | 
			
		||||
                    resp: OkWebSocketResponseData::Modeling {
 | 
			
		||||
                        modeling_response: this_response,
 | 
			
		||||
                    },
 | 
			
		||||
                }))
 | 
			
		||||
            }
 | 
			
		||||
            _ => Ok(WebSocketResponse::Success(kcmc::websocket::SuccessWebSocketResponse {
 | 
			
		||||
                success: true,
 | 
			
		||||
                request_id: Some(id),
 | 
			
		||||
                resp: OkWebSocketResponseData::Modeling {
 | 
			
		||||
                    modeling_response: OkModelingCmdResponse::Empty {},
 | 
			
		||||
                },
 | 
			
		||||
            })),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								src/wasm-lib/kcl-to-core/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/wasm-lib/kcl-to-core/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use kcl_lib::executor::ExecutorContext;
 | 
			
		||||
use std::sync::{Arc, Mutex};
 | 
			
		||||
 | 
			
		||||
#[cfg(not(target_arch = "wasm32"))]
 | 
			
		||||
mod conn_mock_core;
 | 
			
		||||
 | 
			
		||||
///Converts the given kcl code to an engine test
 | 
			
		||||
pub async fn kcl_to_engine_core(code: &str) -> Result<String> {
 | 
			
		||||
    let tokens = kcl_lib::token::lexer(code)?;
 | 
			
		||||
    let parser = kcl_lib::parser::Parser::new(tokens);
 | 
			
		||||
    let program = parser.ast()?;
 | 
			
		||||
 | 
			
		||||
    let result = Arc::new(Mutex::new("".into()));
 | 
			
		||||
    let ref_result = Arc::clone(&result);
 | 
			
		||||
 | 
			
		||||
    let ctx = ExecutorContext {
 | 
			
		||||
        engine: Arc::new(Box::new(
 | 
			
		||||
            crate::conn_mock_core::EngineConnection::new(ref_result).await?,
 | 
			
		||||
        )),
 | 
			
		||||
        fs: Arc::new(kcl_lib::fs::FileManager::new()),
 | 
			
		||||
        stdlib: Arc::new(kcl_lib::std::StdLib::new()),
 | 
			
		||||
        settings: Default::default(),
 | 
			
		||||
        context_type: kcl_lib::executor::ContextType::MockCustomForwarded,
 | 
			
		||||
    };
 | 
			
		||||
    let _memory = ctx.run(&program, None).await?;
 | 
			
		||||
 | 
			
		||||
    let result = result.lock().expect("mutex lock").clone();
 | 
			
		||||
    Ok(result)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								src/wasm-lib/kcl-to-core/src/tool.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/wasm-lib/kcl-to-core/src/tool.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
use kcl_to_core::*;
 | 
			
		||||
use std::{env, fs};
 | 
			
		||||
 | 
			
		||||
#[tokio::main]
 | 
			
		||||
async fn main() {
 | 
			
		||||
    let args: Vec<String> = env::args().collect();
 | 
			
		||||
 | 
			
		||||
    if args.len() < 2 {
 | 
			
		||||
        println!("Usage: kcl-to-core path/to/file.kcl");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let file_path = &args[1];
 | 
			
		||||
    let kcl = fs::read_to_string(file_path).expect("read file");
 | 
			
		||||
 | 
			
		||||
    let result = kcl_to_engine_core(&kcl).await.expect("kcl conversion");
 | 
			
		||||
 | 
			
		||||
    println!("{}", result);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								src/wasm-lib/kcl-to-core/tests/kcl_to_core_test.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/wasm-lib/kcl-to-core/tests/kcl_to_core_test.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
use kcl_to_core::*;
 | 
			
		||||
 | 
			
		||||
#[tokio::test]
 | 
			
		||||
async fn kcl_to_core_test() {
 | 
			
		||||
    let result = kcl_to_engine_core(
 | 
			
		||||
        r#"
 | 
			
		||||
        const part001 = startSketchOn('XY')
 | 
			
		||||
            |> startProfileAt([11.19, 28.35], %)
 | 
			
		||||
            |> line([28.67, -13.25], %, $here)
 | 
			
		||||
            |> line([-4.12, -22.81], %)
 | 
			
		||||
            |> line([-33.24, 14.55], %)
 | 
			
		||||
            |> close(%)
 | 
			
		||||
            |> extrude(5, %)
 | 
			
		||||
    "#,
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
 | 
			
		||||
    assert!(result.is_ok());
 | 
			
		||||
}
 | 
			
		||||
@ -1649,6 +1649,22 @@ impl ExtrudeSurface {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The type of ExecutorContext being used
 | 
			
		||||
#[derive(PartialEq, Debug, Default, Clone)]
 | 
			
		||||
pub enum ContextType {
 | 
			
		||||
    /// Live engine connection
 | 
			
		||||
    #[default]
 | 
			
		||||
    Live,
 | 
			
		||||
 | 
			
		||||
    /// Completely mocked connection
 | 
			
		||||
    /// Mock mode is only for the modeling app when they just want to mock engine calls and not
 | 
			
		||||
    /// actually make them.
 | 
			
		||||
    Mock,
 | 
			
		||||
 | 
			
		||||
    /// Handled by some other interpreter/conversion system
 | 
			
		||||
    MockCustomForwarded,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The executor context.
 | 
			
		||||
/// Cloning will return another handle to the same engine connection/session,
 | 
			
		||||
/// as this uses `Arc` under the hood.
 | 
			
		||||
@ -1658,9 +1674,7 @@ pub struct ExecutorContext {
 | 
			
		||||
    pub fs: Arc<FileManager>,
 | 
			
		||||
    pub stdlib: Arc<StdLib>,
 | 
			
		||||
    pub settings: ExecutorSettings,
 | 
			
		||||
    /// Mock mode is only for the modeling app when they just want to mock engine calls and not
 | 
			
		||||
    /// actually make them.
 | 
			
		||||
    pub is_mock: bool,
 | 
			
		||||
    pub context_type: ContextType,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The executor settings.
 | 
			
		||||
@ -1770,10 +1784,14 @@ impl ExecutorContext {
 | 
			
		||||
            fs: Arc::new(FileManager::new()),
 | 
			
		||||
            stdlib: Arc::new(StdLib::new()),
 | 
			
		||||
            settings,
 | 
			
		||||
            is_mock: false,
 | 
			
		||||
            context_type: ContextType::Live,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn is_mock(&self) -> bool {
 | 
			
		||||
        self.context_type == ContextType::Mock || self.context_type == ContextType::MockCustomForwarded
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// For executing unit tests.
 | 
			
		||||
    #[cfg(not(target_arch = "wasm32"))]
 | 
			
		||||
    pub async fn new_for_unit_test(units: UnitLength, engine_addr: Option<String>) -> Result<Self> {
 | 
			
		||||
@ -2155,7 +2173,7 @@ mod tests {
 | 
			
		||||
            fs: Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
            stdlib: Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
            settings: Default::default(),
 | 
			
		||||
            is_mock: true,
 | 
			
		||||
            context_type: ContextType::Mock,
 | 
			
		||||
        };
 | 
			
		||||
        let exec_state = ctx.run(&program, None).await?;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ impl Args {
 | 
			
		||||
                fs: Arc::new(crate::fs::FileManager::new()),
 | 
			
		||||
                stdlib: Arc::new(crate::std::StdLib::new()),
 | 
			
		||||
                settings: Default::default(),
 | 
			
		||||
                is_mock: true,
 | 
			
		||||
                context_type: crate::executor::ContextType::Mock,
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -247,7 +247,7 @@ pub(crate) async fn do_post_extrude(sketch: Sketch, length: f64, args: Args) ->
 | 
			
		||||
                        Some(extrude_surface)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else if args.ctx.is_mock {
 | 
			
		||||
            } else if args.ctx.is_mock() {
 | 
			
		||||
                // Only pre-populate the extrude surface if we are in mock mode.
 | 
			
		||||
 | 
			
		||||
                let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::executor::ExtrudePlane {
 | 
			
		||||
@ -296,7 +296,7 @@ fn analyze_faces(args: &Args, face_infos: Vec<ExtrusionFaceInfo>) -> Faces {
 | 
			
		||||
        sides: HashMap::with_capacity(face_infos.len()),
 | 
			
		||||
        ..Default::default()
 | 
			
		||||
    };
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.is_mock() {
 | 
			
		||||
        // Create fake IDs for start and end caps, to make extrudes mock-execute safe
 | 
			
		||||
        faces.start_cap_id = Some(Uuid::new_v4());
 | 
			
		||||
        faces.end_cap_id = Some(Uuid::new_v4());
 | 
			
		||||
 | 
			
		||||
@ -228,7 +228,7 @@ pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result
 | 
			
		||||
    name = "getOppositeEdge",
 | 
			
		||||
}]
 | 
			
		||||
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());
 | 
			
		||||
    }
 | 
			
		||||
    let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
 | 
			
		||||
@ -309,7 +309,7 @@ async fn inner_get_next_adjacent_edge(
 | 
			
		||||
    exec_state: &mut ExecState,
 | 
			
		||||
    args: Args,
 | 
			
		||||
) -> Result<Uuid, KclError> {
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.is_mock() {
 | 
			
		||||
        return Ok(Uuid::new_v4());
 | 
			
		||||
    }
 | 
			
		||||
    let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
 | 
			
		||||
@ -398,7 +398,7 @@ async fn inner_get_previous_adjacent_edge(
 | 
			
		||||
    exec_state: &mut ExecState,
 | 
			
		||||
    args: Args,
 | 
			
		||||
) -> Result<Uuid, KclError> {
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.is_mock() {
 | 
			
		||||
        return Ok(Uuid::new_v4());
 | 
			
		||||
    }
 | 
			
		||||
    let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
 | 
			
		||||
 | 
			
		||||
@ -284,7 +284,7 @@ async fn inner_import(
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.is_mock() {
 | 
			
		||||
        return Ok(ImportedGeometry {
 | 
			
		||||
            id: uuid::Uuid::new_v4(),
 | 
			
		||||
            value: import_files.iter().map(|f| f.path.to_string()).collect(),
 | 
			
		||||
 | 
			
		||||
@ -112,7 +112,7 @@ async fn inner_mirror_2d(
 | 
			
		||||
        SketchSet::Sketches(sketches) => sketches,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.is_mock() {
 | 
			
		||||
        return Ok(starting_sketches);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -290,7 +290,7 @@ async fn inner_pattern_transform<'a>(
 | 
			
		||||
 | 
			
		||||
    let starting_solids: Vec<Box<Solid>> = solid_set.into();
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.context_type == crate::executor::ContextType::Mock {
 | 
			
		||||
        return Ok(starting_solids);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -513,7 +513,7 @@ async fn inner_pattern_linear_2d(
 | 
			
		||||
) -> Result<Vec<Box<Sketch>>, KclError> {
 | 
			
		||||
    let starting_sketches: Vec<Box<Sketch>> = sketch_set.into();
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.context_type == crate::executor::ContextType::Mock {
 | 
			
		||||
        return Ok(starting_sketches);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -591,7 +591,7 @@ async fn inner_pattern_linear_3d(
 | 
			
		||||
 | 
			
		||||
    let starting_solids: Vec<Box<Solid>> = solid_set.into();
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.context_type == crate::executor::ContextType::Mock {
 | 
			
		||||
        return Ok(starting_solids);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -783,7 +783,7 @@ async fn inner_pattern_circular_2d(
 | 
			
		||||
) -> Result<Vec<Box<Sketch>>, KclError> {
 | 
			
		||||
    let starting_sketches: Vec<Box<Sketch>> = sketch_set.into();
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.context_type == crate::executor::ContextType::Mock {
 | 
			
		||||
        return Ok(starting_sketches);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -852,7 +852,7 @@ async fn inner_pattern_circular_3d(
 | 
			
		||||
 | 
			
		||||
    let starting_solids: Vec<Box<Solid>> = solid_set.into();
 | 
			
		||||
 | 
			
		||||
    if args.ctx.is_mock {
 | 
			
		||||
    if args.ctx.context_type == crate::executor::ContextType::Mock {
 | 
			
		||||
        return Ok(starting_solids);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,11 @@ pub async fn execute_wasm(
 | 
			
		||||
        ))
 | 
			
		||||
    };
 | 
			
		||||
    let fs = Arc::new(kcl_lib::fs::FileManager::new(fs_manager));
 | 
			
		||||
    let context_type = if is_mock {
 | 
			
		||||
        kcl_lib::executor::ContextType::Mock
 | 
			
		||||
    } else {
 | 
			
		||||
        kcl_lib::executor::ContextType::Live
 | 
			
		||||
    };
 | 
			
		||||
    let ctx = kcl_lib::executor::ExecutorContext {
 | 
			
		||||
        engine,
 | 
			
		||||
        fs,
 | 
			
		||||
@ -50,7 +55,7 @@ pub async fn execute_wasm(
 | 
			
		||||
            units,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        },
 | 
			
		||||
        is_mock,
 | 
			
		||||
        context_type,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let exec_state = ctx.run(&program, Some(memory)).await.map_err(String::from)?;
 | 
			
		||||
@ -274,7 +279,7 @@ pub async fn kcl_lsp_run(
 | 
			
		||||
                units,
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            is_mock: false,
 | 
			
		||||
            context_type: kcl_lib::executor::ContextType::Live,
 | 
			
		||||
        })
 | 
			
		||||
    } else {
 | 
			
		||||
        None
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ async fn setup(program: &str) -> (ExecutorContext, Program) {
 | 
			
		||||
        fs: std::sync::Arc::new(kcl_lib::fs::FileManager::new()),
 | 
			
		||||
        stdlib: std::sync::Arc::new(kcl_lib::std::StdLib::new()),
 | 
			
		||||
        settings: Default::default(),
 | 
			
		||||
        is_mock: true,
 | 
			
		||||
        context_type: kcl_lib::executor::ContextType::Mock,
 | 
			
		||||
    };
 | 
			
		||||
    (ctx, program)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user