diff --git a/src/wasm-lib/.config/insta.yaml b/src/wasm-lib/.config/insta.yaml new file mode 100644 index 000000000..24d8c60c6 --- /dev/null +++ b/src/wasm-lib/.config/insta.yaml @@ -0,0 +1,2 @@ +test: + runner: nextest diff --git a/src/wasm-lib/Cargo.lock b/src/wasm-lib/Cargo.lock index cf7d925f6..3bce8606b 100644 --- a/src/wasm-lib/Cargo.lock +++ b/src/wasm-lib/Cargo.lock @@ -1453,13 +1453,14 @@ checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" [[package]] name = "insta" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" +checksum = "a1f72d3e19488cf7d8ea52d2fc0f8754fc933398b337cd3cbdb28aaeb35159ef" dependencies = [ "console", "lazy_static", "linked-hash-map", + "regex", "serde", "similar", ] diff --git a/src/wasm-lib/Cargo.toml b/src/wasm-lib/Cargo.toml index dff8ef70e..d0579c67b 100644 --- a/src/wasm-lib/Cargo.toml +++ b/src/wasm-lib/Cargo.toml @@ -57,6 +57,10 @@ debug = true [profile.dev] debug = 0 +[profile.dev.package] +insta.opt-level = 3 +similar.opt-level = 3 + [profile.test] debug = "line-tables-only" diff --git a/src/wasm-lib/justfile b/src/wasm-lib/justfile index 953527c77..752959131 100644 --- a/src/wasm-lib/justfile +++ b/src/wasm-lib/justfile @@ -1,10 +1,29 @@ +cnr := "cargo nextest run" +cita := "cargo insta test --accept" + # Create a new KCL snapshot test from `tests/inputs/my-test.kcl`. new-test name: echo "kcl_test!(\"{{name}}\", {{name}});" >> tests/executor/visuals.rs - TWENTY_TWENTY=overwrite cargo nextest run --test executor -E 'test(=visuals::{{name}})' + TWENTY_TWENTY=overwrite {{cnr}} --test executor -E 'test(=visuals::{{name}})' lint: cargo clippy --workspace --all-targets -- -D warnings redo-kcl-stdlib-docs: - EXPECTORATE=overwrite cargo nextest run -p kcl-lib docs::gen_std_tests::test_generate_stdlib + EXPECTORATE=overwrite {{cnr}} -p kcl-lib docs::gen_std_tests::test_generate_stdlib + +# Create a new KCL deterministic simulation test case. +new-sim-test test_name kcl_program: + # Each test file gets its own directory. This will contain the KCL program, and its + # snapshotted artifacts (e.g. serialized tokens, serialized ASTs, program memory, + # PNG snapshots, etc). + mkdir kcl/tests/{{test_name}} + echo "{{kcl_program}}" > kcl/tests/{{test_name}}/input.kcl + # Add the various tests for this new test case. + cat kcl/tests/simtest.tmpl | sed "s/TEST_NAME_HERE/{{test_name}}/" >> kcl/src/tests.rs + # Run all the tests for the first time, in the right order. + {{cita}} -p kcl-lib -- tests::{{test_name}}::tokenize + {{cita}} -p kcl-lib -- tests::{{test_name}}::parse + {{cita}} -p kcl-lib -- tests::{{test_name}}::unparse + TWENTY_TWENTY=overwrite {{cita}} -p kcl-lib -- tests::{{test_name}}::kcl_test_execute + diff --git a/src/wasm-lib/kcl/Cargo.toml b/src/wasm-lib/kcl/Cargo.toml index 6b9be258f..afaa62f52 100644 --- a/src/wasm-lib/kcl/Cargo.toml +++ b/src/wasm-lib/kcl/Cargo.toml @@ -77,16 +77,8 @@ engine = [] pyo3 = ["dep:pyo3"] # Helper functions also used in benchmarks. lsp-test-util = [] - tabled = ["dep:tabled"] -[profile.release] -panic = "abort" -debug = true - -[profile.bench] -debug = true # Flamegraphs of benchmarks require accurate debug symbols - [dev-dependencies] base64 = "0.22.1" criterion = { version = "0.5.1", features = ["async_tokio"] } @@ -94,7 +86,7 @@ expectorate = "1.1.0" handlebars = "6.2.0" iai = "0.1" image = { version = "0.25.3", default-features = false, features = ["png"] } -insta = { version = "1.40.0", features = ["json"] } +insta = { version = "1.41.0", features = ["json", "filters"] } itertools = "0.13.0" pretty_assertions = "1.4.1" tokio = { version = "1.40.0", features = ["rt-multi-thread", "macros", "time"] } diff --git a/src/wasm-lib/kcl/src/executor.rs b/src/wasm-lib/kcl/src/executor.rs index bb7fb7bc0..36f8563f4 100644 --- a/src/wasm-lib/kcl/src/executor.rs +++ b/src/wasm-lib/kcl/src/executor.rs @@ -2454,7 +2454,19 @@ impl ExecutorContext { id_generator: IdGenerator, project_directory: Option, ) -> Result { - let _ = self.run(program, None, id_generator, project_directory).await?; + self.execute_and_prepare(program, id_generator, project_directory) + .await + .map(|(_state, snap)| snap) + } + + /// Execute the program, return the interpreter and outputs. + pub async fn execute_and_prepare( + &self, + program: &Program, + id_generator: IdGenerator, + project_directory: Option, + ) -> Result<(ExecState, TakeSnapshot)> { + let state = self.run(program, None, id_generator, project_directory).await?; // Zoom to fit. self.engine @@ -2487,7 +2499,7 @@ impl ExecutorContext { else { anyhow::bail!("Unexpected response from engine: {:?}", resp); }; - Ok(contents) + Ok((state, contents)) } } diff --git a/src/wasm-lib/kcl/src/lib.rs b/src/wasm-lib/kcl/src/lib.rs index f0ef19f43..b239d7387 100644 --- a/src/wasm-lib/kcl/src/lib.rs +++ b/src/wasm-lib/kcl/src/lib.rs @@ -25,6 +25,8 @@ pub mod lint; pub mod lsp; pub mod parser; pub mod settings; +#[cfg(test)] +mod simulation_tests; pub mod std; #[cfg(not(target_arch = "wasm32"))] pub mod test_server; diff --git a/src/wasm-lib/kcl/src/parser/parser_impl.rs b/src/wasm-lib/kcl/src/parser/parser_impl.rs index f7f15dc7b..6b86e7f07 100644 --- a/src/wasm-lib/kcl/src/parser/parser_impl.rs +++ b/src/wasm-lib/kcl/src/parser/parser_impl.rs @@ -3043,7 +3043,6 @@ e let parser = crate::parser::Parser::new(tokens); let result = parser.ast(); assert!(result.is_err()); - dbg!(&result); assert!(result .err() .unwrap() diff --git a/src/wasm-lib/kcl/src/simulation_tests.rs b/src/wasm-lib/kcl/src/simulation_tests.rs new file mode 100644 index 000000000..bcbcdf7cf --- /dev/null +++ b/src/wasm-lib/kcl/src/simulation_tests.rs @@ -0,0 +1,130 @@ +use crate::{ast::types::Program, errors::KclError, parser::Parser, token::Token}; + +/// Deserialize the data from a snapshot. +fn get(snapshot: &str) -> T { + let mut parts = snapshot.split("---"); + let _empty = parts.next().unwrap(); + let _header = parts.next().unwrap(); + let snapshot_data = parts.next().unwrap(); + serde_json::from_str(snapshot_data) + .and_then(serde_json::from_value) + .unwrap() +} + +fn assert_snapshot(test_name: &str, operation: &str, f: F) +where + F: FnOnce() -> R, +{ + let mut settings = insta::Settings::clone_current(); + // These make the snapshots more readable and match our dir structure. + settings.set_omit_expression(true); + settings.set_snapshot_path(format!("../tests/{test_name}")); + settings.set_prepend_module_to_snapshot(false); + settings.set_description(format!("{operation} {test_name}.kcl")); + // Sorting maps makes them easier to diff. + settings.set_sort_maps(true); + // Replace UUIDs with the string "[uuid]", because otherwise the tests would constantly + // be changing the UUID. This is a stopgap measure until we make the engine more deterministic. + settings.add_filter( + r"\b[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}\b", + "[uuid]", + ); + // Run `f` (the closure that was passed in) with these settings. + settings.bind(f); +} + +fn read(filename: &'static str, test_name: &str) -> String { + std::fs::read_to_string(format!("tests/{test_name}/{filename}")).unwrap() +} + +fn tokenize(test_name: &str) { + let input = read("input.kcl", test_name); + let token_res = crate::token::lexer(&input); + + assert_snapshot(test_name, "Result of tokenizing", || { + insta::assert_json_snapshot!("tokens", token_res); + }); +} + +fn parse(test_name: &str) { + let input = read("tokens.snap", test_name); + let tokens: Result, KclError> = get(&input); + let Ok(tokens) = tokens else { + return; + }; + + // Parse the tokens into an AST. + let parse_res = Parser::new(tokens).ast(); + assert_snapshot(test_name, "Result of parsing", || { + insta::assert_json_snapshot!("ast", parse_res); + }); +} + +fn unparse(test_name: &str) { + let input = read("ast.snap", test_name); + let ast_res: Result = get(&input); + let Ok(ast) = ast_res else { + return; + }; + // Check recasting the AST produces the original string. + let actual = ast.recast(&Default::default(), 0); + let expected = read("input.kcl", test_name); + pretty_assertions::assert_eq!( + actual, + expected, + "Parse then unparse didn't recreate the original KCL file" + ); +} + +async fn execute(test_name: &str) { + // Read the AST from disk. + let input = read("ast.snap", test_name); + let ast_res: Result = get(&input); + let Ok(ast) = ast_res else { + return; + }; + + // Run the program. + let exec_res = crate::test_server::execute_and_snapshot_ast(ast, crate::settings::types::UnitLength::Mm).await; + match exec_res { + Ok((program_memory, png)) => { + twenty_twenty::assert_image(format!("tests/{test_name}/rendered_model.png"), &png, 0.99); + assert_snapshot(test_name, "Program memory after executing", || { + insta::assert_json_snapshot!("program_memory", program_memory); + }); + } + Err(e) => { + assert_snapshot(test_name, "Error from executing", || { + insta::assert_snapshot!("execution_error", e); + }); + } + } +} + +mod cube { + const TEST_NAME: &str = "cube"; + + /// Test tokenizing KCL. + #[test] + fn tokenize() { + super::tokenize(TEST_NAME) + } + + /// Test parsing KCL. + #[test] + fn parse() { + super::parse(TEST_NAME) + } + + /// Test that parsing and unparsing KCL produces the original KCL input. + #[test] + fn unparse() { + super::unparse(TEST_NAME) + } + + /// Test that KCL is executed correctly. + #[tokio::test(flavor = "multi_thread")] + async fn kcl_test_execute() { + super::execute(TEST_NAME).await + } +} diff --git a/src/wasm-lib/kcl/src/snapshots/kcl_lib__tests__tokenize_cube.snap b/src/wasm-lib/kcl/src/snapshots/kcl_lib__tests__tokenize_cube.snap new file mode 100644 index 000000000..73a6d1acc --- /dev/null +++ b/src/wasm-lib/kcl/src/snapshots/kcl_lib__tests__tokenize_cube.snap @@ -0,0 +1,969 @@ +--- +source: kcl/src/tests.rs +expression: tokens +--- +Ok: + - type: keyword + start: 0 + end: 2 + value: fn + - type: whitespace + start: 2 + end: 3 + value: " " + - type: word + start: 3 + end: 9 + value: square + - type: whitespace + start: 9 + end: 10 + value: " " + - type: operator + start: 10 + end: 11 + value: "=" + - type: whitespace + start: 11 + end: 12 + value: " " + - type: brace + start: 12 + end: 13 + value: ( + - type: word + start: 13 + end: 19 + value: length + - type: comma + start: 19 + end: 20 + value: "," + - type: whitespace + start: 20 + end: 21 + value: " " + - type: word + start: 21 + end: 27 + value: center + - type: brace + start: 27 + end: 28 + value: ) + - type: whitespace + start: 28 + end: 29 + value: " " + - type: operator + start: 29 + end: 31 + value: "=>" + - type: whitespace + start: 31 + end: 32 + value: " " + - type: brace + start: 32 + end: 33 + value: "{" + - type: whitespace + start: 33 + end: 36 + value: "\n " + - type: word + start: 36 + end: 37 + value: l + - type: whitespace + start: 37 + end: 38 + value: " " + - type: operator + start: 38 + end: 39 + value: "=" + - type: whitespace + start: 39 + end: 40 + value: " " + - type: word + start: 40 + end: 46 + value: length + - type: whitespace + start: 46 + end: 47 + value: " " + - type: operator + start: 47 + end: 48 + value: / + - type: whitespace + start: 48 + end: 49 + value: " " + - type: number + start: 49 + end: 50 + value: "2" + - type: whitespace + start: 50 + end: 53 + value: "\n " + - type: word + start: 53 + end: 54 + value: x + - type: whitespace + start: 54 + end: 55 + value: " " + - type: operator + start: 55 + end: 56 + value: "=" + - type: whitespace + start: 56 + end: 57 + value: " " + - type: word + start: 57 + end: 63 + value: center + - type: brace + start: 63 + end: 64 + value: "[" + - type: number + start: 64 + end: 65 + value: "0" + - type: brace + start: 65 + end: 66 + value: "]" + - type: whitespace + start: 66 + end: 69 + value: "\n " + - type: word + start: 69 + end: 70 + value: y + - type: whitespace + start: 70 + end: 71 + value: " " + - type: operator + start: 71 + end: 72 + value: "=" + - type: whitespace + start: 72 + end: 73 + value: " " + - type: word + start: 73 + end: 79 + value: center + - type: brace + start: 79 + end: 80 + value: "[" + - type: number + start: 80 + end: 81 + value: "1" + - type: brace + start: 81 + end: 82 + value: "]" + - type: whitespace + start: 82 + end: 85 + value: "\n " + - type: word + start: 85 + end: 87 + value: p0 + - type: whitespace + start: 87 + end: 88 + value: " " + - type: operator + start: 88 + end: 89 + value: "=" + - type: whitespace + start: 89 + end: 90 + value: " " + - type: brace + start: 90 + end: 91 + value: "[" + - type: operator + start: 91 + end: 92 + value: "-" + - type: word + start: 92 + end: 93 + value: l + - type: whitespace + start: 93 + end: 94 + value: " " + - type: operator + start: 94 + end: 95 + value: + + - type: whitespace + start: 95 + end: 96 + value: " " + - type: word + start: 96 + end: 97 + value: x + - type: comma + start: 97 + end: 98 + value: "," + - type: whitespace + start: 98 + end: 99 + value: " " + - type: operator + start: 99 + end: 100 + value: "-" + - type: word + start: 100 + end: 101 + value: l + - type: whitespace + start: 101 + end: 102 + value: " " + - type: operator + start: 102 + end: 103 + value: + + - type: whitespace + start: 103 + end: 104 + value: " " + - type: word + start: 104 + end: 105 + value: y + - type: brace + start: 105 + end: 106 + value: "]" + - type: whitespace + start: 106 + end: 109 + value: "\n " + - type: word + start: 109 + end: 111 + value: p1 + - type: whitespace + start: 111 + end: 112 + value: " " + - type: operator + start: 112 + end: 113 + value: "=" + - type: whitespace + start: 113 + end: 114 + value: " " + - type: brace + start: 114 + end: 115 + value: "[" + - type: operator + start: 115 + end: 116 + value: "-" + - type: word + start: 116 + end: 117 + value: l + - type: whitespace + start: 117 + end: 118 + value: " " + - type: operator + start: 118 + end: 119 + value: + + - type: whitespace + start: 119 + end: 120 + value: " " + - type: word + start: 120 + end: 121 + value: x + - type: comma + start: 121 + end: 122 + value: "," + - type: whitespace + start: 122 + end: 124 + value: " " + - type: word + start: 124 + end: 125 + value: l + - type: whitespace + start: 125 + end: 126 + value: " " + - type: operator + start: 126 + end: 127 + value: + + - type: whitespace + start: 127 + end: 128 + value: " " + - type: word + start: 128 + end: 129 + value: y + - type: brace + start: 129 + end: 130 + value: "]" + - type: whitespace + start: 130 + end: 133 + value: "\n " + - type: word + start: 133 + end: 135 + value: p2 + - type: whitespace + start: 135 + end: 136 + value: " " + - type: operator + start: 136 + end: 137 + value: "=" + - type: whitespace + start: 137 + end: 138 + value: " " + - type: brace + start: 138 + end: 139 + value: "[" + - type: whitespace + start: 139 + end: 140 + value: " " + - type: word + start: 140 + end: 141 + value: l + - type: whitespace + start: 141 + end: 142 + value: " " + - type: operator + start: 142 + end: 143 + value: + + - type: whitespace + start: 143 + end: 144 + value: " " + - type: word + start: 144 + end: 145 + value: x + - type: comma + start: 145 + end: 146 + value: "," + - type: whitespace + start: 146 + end: 148 + value: " " + - type: word + start: 148 + end: 149 + value: l + - type: whitespace + start: 149 + end: 150 + value: " " + - type: operator + start: 150 + end: 151 + value: + + - type: whitespace + start: 151 + end: 152 + value: " " + - type: word + start: 152 + end: 153 + value: y + - type: brace + start: 153 + end: 154 + value: "]" + - type: whitespace + start: 154 + end: 157 + value: "\n " + - type: word + start: 157 + end: 159 + value: p3 + - type: whitespace + start: 159 + end: 160 + value: " " + - type: operator + start: 160 + end: 161 + value: "=" + - type: whitespace + start: 161 + end: 162 + value: " " + - type: brace + start: 162 + end: 163 + value: "[" + - type: whitespace + start: 163 + end: 164 + value: " " + - type: word + start: 164 + end: 165 + value: l + - type: whitespace + start: 165 + end: 166 + value: " " + - type: operator + start: 166 + end: 167 + value: + + - type: whitespace + start: 167 + end: 168 + value: " " + - type: word + start: 168 + end: 169 + value: x + - type: comma + start: 169 + end: 170 + value: "," + - type: whitespace + start: 170 + end: 171 + value: " " + - type: operator + start: 171 + end: 172 + value: "-" + - type: word + start: 172 + end: 173 + value: l + - type: whitespace + start: 173 + end: 174 + value: " " + - type: operator + start: 174 + end: 175 + value: + + - type: whitespace + start: 175 + end: 176 + value: " " + - type: word + start: 176 + end: 177 + value: y + - type: brace + start: 177 + end: 178 + value: "]" + - type: whitespace + start: 178 + end: 181 + value: "\n " + - type: keyword + start: 181 + end: 187 + value: return + - type: whitespace + start: 187 + end: 188 + value: " " + - type: word + start: 188 + end: 201 + value: startSketchAt + - type: brace + start: 201 + end: 202 + value: ( + - type: word + start: 202 + end: 204 + value: p0 + - type: brace + start: 204 + end: 205 + value: ) + - type: whitespace + start: 205 + end: 210 + value: "\n " + - type: operator + start: 210 + end: 212 + value: "|>" + - type: whitespace + start: 212 + end: 213 + value: " " + - type: word + start: 213 + end: 219 + value: lineTo + - type: brace + start: 219 + end: 220 + value: ( + - type: word + start: 220 + end: 222 + value: p1 + - type: comma + start: 222 + end: 223 + value: "," + - type: whitespace + start: 223 + end: 224 + value: " " + - type: operator + start: 224 + end: 225 + value: "%" + - type: brace + start: 225 + end: 226 + value: ) + - type: whitespace + start: 226 + end: 231 + value: "\n " + - type: operator + start: 231 + end: 233 + value: "|>" + - type: whitespace + start: 233 + end: 234 + value: " " + - type: word + start: 234 + end: 240 + value: lineTo + - type: brace + start: 240 + end: 241 + value: ( + - type: word + start: 241 + end: 243 + value: p2 + - type: comma + start: 243 + end: 244 + value: "," + - type: whitespace + start: 244 + end: 245 + value: " " + - type: operator + start: 245 + end: 246 + value: "%" + - type: brace + start: 246 + end: 247 + value: ) + - type: whitespace + start: 247 + end: 252 + value: "\n " + - type: operator + start: 252 + end: 254 + value: "|>" + - type: whitespace + start: 254 + end: 255 + value: " " + - type: word + start: 255 + end: 261 + value: lineTo + - type: brace + start: 261 + end: 262 + value: ( + - type: word + start: 262 + end: 264 + value: p3 + - type: comma + start: 264 + end: 265 + value: "," + - type: whitespace + start: 265 + end: 266 + value: " " + - type: operator + start: 266 + end: 267 + value: "%" + - type: brace + start: 267 + end: 268 + value: ) + - type: whitespace + start: 268 + end: 273 + value: "\n " + - type: operator + start: 273 + end: 275 + value: "|>" + - type: whitespace + start: 275 + end: 276 + value: " " + - type: word + start: 276 + end: 282 + value: lineTo + - type: brace + start: 282 + end: 283 + value: ( + - type: word + start: 283 + end: 285 + value: p0 + - type: comma + start: 285 + end: 286 + value: "," + - type: whitespace + start: 286 + end: 287 + value: " " + - type: operator + start: 287 + end: 288 + value: "%" + - type: brace + start: 288 + end: 289 + value: ) + - type: whitespace + start: 289 + end: 294 + value: "\n " + - type: operator + start: 294 + end: 296 + value: "|>" + - type: whitespace + start: 296 + end: 297 + value: " " + - type: word + start: 297 + end: 302 + value: close + - type: brace + start: 302 + end: 303 + value: ( + - type: operator + start: 303 + end: 304 + value: "%" + - type: brace + start: 304 + end: 305 + value: ) + - type: whitespace + start: 305 + end: 306 + value: "\n" + - type: brace + start: 306 + end: 307 + value: "}" + - type: whitespace + start: 307 + end: 309 + value: "\n\n" + - type: keyword + start: 309 + end: 311 + value: fn + - type: whitespace + start: 311 + end: 312 + value: " " + - type: word + start: 312 + end: 316 + value: cube + - type: whitespace + start: 316 + end: 317 + value: " " + - type: operator + start: 317 + end: 318 + value: "=" + - type: whitespace + start: 318 + end: 319 + value: " " + - type: brace + start: 319 + end: 320 + value: ( + - type: word + start: 320 + end: 326 + value: length + - type: comma + start: 326 + end: 327 + value: "," + - type: whitespace + start: 327 + end: 328 + value: " " + - type: word + start: 328 + end: 334 + value: center + - type: brace + start: 334 + end: 335 + value: ) + - type: whitespace + start: 335 + end: 336 + value: " " + - type: operator + start: 336 + end: 338 + value: "=>" + - type: whitespace + start: 338 + end: 339 + value: " " + - type: brace + start: 339 + end: 340 + value: "{" + - type: whitespace + start: 340 + end: 343 + value: "\n " + - type: keyword + start: 343 + end: 349 + value: return + - type: whitespace + start: 349 + end: 350 + value: " " + - type: word + start: 350 + end: 356 + value: square + - type: brace + start: 356 + end: 357 + value: ( + - type: word + start: 357 + end: 363 + value: length + - type: comma + start: 363 + end: 364 + value: "," + - type: whitespace + start: 364 + end: 365 + value: " " + - type: word + start: 365 + end: 371 + value: center + - type: brace + start: 371 + end: 372 + value: ) + - type: whitespace + start: 372 + end: 377 + value: "\n " + - type: operator + start: 377 + end: 379 + value: "|>" + - type: whitespace + start: 379 + end: 380 + value: " " + - type: word + start: 380 + end: 387 + value: extrude + - type: brace + start: 387 + end: 388 + value: ( + - type: word + start: 388 + end: 394 + value: length + - type: comma + start: 394 + end: 395 + value: "," + - type: whitespace + start: 395 + end: 396 + value: " " + - type: operator + start: 396 + end: 397 + value: "%" + - type: brace + start: 397 + end: 398 + value: ) + - type: whitespace + start: 398 + end: 399 + value: "\n" + - type: brace + start: 399 + end: 400 + value: "}" + - type: whitespace + start: 400 + end: 402 + value: "\n\n" + - type: word + start: 402 + end: 407 + value: width + - type: whitespace + start: 407 + end: 408 + value: " " + - type: operator + start: 408 + end: 409 + value: "=" + - type: whitespace + start: 409 + end: 410 + value: " " + - type: number + start: 410 + end: 412 + value: "20" + - type: whitespace + start: 412 + end: 413 + value: "\n" + - type: word + start: 413 + end: 417 + value: cube + - type: brace + start: 417 + end: 418 + value: ( + - type: word + start: 418 + end: 423 + value: width + - type: comma + start: 423 + end: 424 + value: "," + - type: whitespace + start: 424 + end: 425 + value: " " + - type: brace + start: 425 + end: 426 + value: "[" + - type: number + start: 426 + end: 428 + value: "20" + - type: comma + start: 428 + end: 429 + value: "," + - type: whitespace + start: 429 + end: 430 + value: " " + - type: number + start: 430 + end: 431 + value: "0" + - type: brace + start: 431 + end: 432 + value: "]" + - type: brace + start: 432 + end: 433 + value: ) + - type: whitespace + start: 433 + end: 434 + value: "\n" diff --git a/src/wasm-lib/kcl/src/test_server.rs b/src/wasm-lib/kcl/src/test_server.rs index 2b59954a2..42415d42c 100644 --- a/src/wasm-lib/kcl/src/test_server.rs +++ b/src/wasm-lib/kcl/src/test_server.rs @@ -1,7 +1,8 @@ //! Types used to send data to the test server. use crate::{ - executor::{new_zoo_client, ExecutorContext, ExecutorSettings, IdGenerator}, + ast::types::Program, + executor::{new_zoo_client, ExecutorContext, ExecutorSettings, IdGenerator, ProgramMemory}, settings::types::UnitLength, }; @@ -16,22 +17,37 @@ pub struct RequestBody { /// This returns the bytes of the snapshot. pub async fn execute_and_snapshot(code: &str, units: UnitLength) -> anyhow::Result { let ctx = new_context(units, true).await?; - do_execute_and_snapshot(&ctx, code).await + let tokens = crate::token::lexer(code)?; + let parser = crate::parser::Parser::new(tokens); + let program = parser.ast()?; + do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap) +} + +/// Executes a kcl program and takes a snapshot of the result. +/// This returns the bytes of the snapshot. +pub async fn execute_and_snapshot_ast( + ast: Program, + units: UnitLength, +) -> anyhow::Result<(ProgramMemory, image::DynamicImage)> { + let ctx = new_context(units, true).await?; + do_execute_and_snapshot(&ctx, ast) + .await + .map(|(state, snap)| (state.memory, snap)) } pub async fn execute_and_snapshot_no_auth(code: &str, units: UnitLength) -> anyhow::Result { let ctx = new_context(units, false).await?; - do_execute_and_snapshot(&ctx, code).await -} - -async fn do_execute_and_snapshot(ctx: &ExecutorContext, code: &str) -> anyhow::Result { let tokens = crate::token::lexer(code)?; let parser = crate::parser::Parser::new(tokens); let program = parser.ast()?; + do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap) +} - let snapshot = ctx - .execute_and_prepare_snapshot(&program, IdGenerator::default(), None) - .await?; +async fn do_execute_and_snapshot( + ctx: &ExecutorContext, + program: Program, +) -> anyhow::Result<(crate::executor::ExecState, image::DynamicImage)> { + let (exec_state, snapshot) = ctx.execute_and_prepare(&program, IdGenerator::default(), None).await?; // Create a temporary file to write the output to. let output_file = std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4())); @@ -39,7 +55,7 @@ async fn do_execute_and_snapshot(ctx: &ExecutorContext, code: &str) -> anyhow::R std::fs::write(&output_file, snapshot.contents.0)?; // Decode the snapshot, return it. let img = image::ImageReader::open(output_file).unwrap().decode()?; - Ok(img) + Ok((exec_state, img)) } async fn new_context(units: UnitLength, with_auth: bool) -> anyhow::Result { diff --git a/src/wasm-lib/kcl/tests/cube/ast.snap b/src/wasm-lib/kcl/tests/cube/ast.snap new file mode 100644 index 000000000..e07632995 --- /dev/null +++ b/src/wasm-lib/kcl/tests/cube/ast.snap @@ -0,0 +1,795 @@ +--- +source: kcl/src/tests.rs +description: Result of parsing cube.kcl +snapshot_kind: text +--- +{ + "Ok": { + "start": 0, + "end": 344, + "body": [ + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 0, + "end": 316, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 3, + "end": 316, + "id": { + "type": "Identifier", + "start": 3, + "end": 7, + "name": "cube" + }, + "init": { + "type": "FunctionExpression", + "type": "FunctionExpression", + "start": 10, + "end": 316, + "params": [ + { + "type": "Parameter", + "identifier": { + "type": "Identifier", + "start": 11, + "end": 17, + "name": "length" + }, + "optional": false + }, + { + "type": "Parameter", + "identifier": { + "type": "Identifier", + "start": 19, + "end": 25, + "name": "center" + }, + "optional": false + } + ], + "body": { + "start": 30, + "end": 316, + "body": [ + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 34, + "end": 48, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 34, + "end": 48, + "id": { + "type": "Identifier", + "start": 34, + "end": 35, + "name": "l" + }, + "init": { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 38, + "end": 48, + "operator": "/", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 38, + "end": 44, + "name": "length" + }, + "right": { + "type": "Literal", + "type": "Literal", + "start": 47, + "end": 48, + "value": 2, + "raw": "2" + } + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 51, + "end": 64, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 51, + "end": 64, + "id": { + "type": "Identifier", + "start": 51, + "end": 52, + "name": "x" + }, + "init": { + "type": "MemberExpression", + "type": "MemberExpression", + "start": 55, + "end": 64, + "object": { + "type": "Identifier", + "type": "Identifier", + "start": 55, + "end": 61, + "name": "center" + }, + "property": { + "type": "Literal", + "type": "Literal", + "start": 62, + "end": 63, + "value": 0, + "raw": "0" + }, + "computed": false + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 67, + "end": 80, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 67, + "end": 80, + "id": { + "type": "Identifier", + "start": 67, + "end": 68, + "name": "y" + }, + "init": { + "type": "MemberExpression", + "type": "MemberExpression", + "start": 71, + "end": 80, + "object": { + "type": "Identifier", + "type": "Identifier", + "start": 71, + "end": 77, + "name": "center" + }, + "property": { + "type": "Literal", + "type": "Literal", + "start": 78, + "end": 79, + "value": 1, + "raw": "1" + }, + "computed": false + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 83, + "end": 104, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 83, + "end": 104, + "id": { + "type": "Identifier", + "start": 83, + "end": 85, + "name": "p0" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 88, + "end": 104, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 89, + "end": 95, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 89, + "end": 91, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 90, + "end": 91, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 94, + "end": 95, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 97, + "end": 103, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 97, + "end": 99, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 98, + "end": 99, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 102, + "end": 103, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 107, + "end": 127, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 107, + "end": 127, + "id": { + "type": "Identifier", + "start": 107, + "end": 109, + "name": "p1" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 112, + "end": 127, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 113, + "end": 119, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 113, + "end": 115, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 114, + "end": 115, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 118, + "end": 119, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 121, + "end": 126, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 121, + "end": 122, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 125, + "end": 126, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 130, + "end": 149, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 130, + "end": 149, + "id": { + "type": "Identifier", + "start": 130, + "end": 132, + "name": "p2" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 135, + "end": 149, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 136, + "end": 141, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 136, + "end": 137, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 140, + "end": 141, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 143, + "end": 148, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 143, + "end": 144, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 147, + "end": 148, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 152, + "end": 172, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 152, + "end": 172, + "id": { + "type": "Identifier", + "start": 152, + "end": 154, + "name": "p3" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 157, + "end": 172, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 158, + "end": 163, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 158, + "end": 159, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 162, + "end": 163, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 165, + "end": 171, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 165, + "end": 167, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 166, + "end": 167, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 170, + "end": 171, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "ReturnStatement", + "type": "ReturnStatement", + "start": 176, + "end": 314, + "argument": { + "type": "PipeExpression", + "type": "PipeExpression", + "start": 183, + "end": 314, + "body": [ + { + "type": "CallExpression", + "type": "CallExpression", + "start": 183, + "end": 200, + "callee": { + "type": "Identifier", + "start": 183, + "end": 196, + "name": "startSketchAt" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 197, + "end": 199, + "name": "p0" + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 206, + "end": 219, + "callee": { + "type": "Identifier", + "start": 206, + "end": 212, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 213, + "end": 215, + "name": "p1" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 217, + "end": 218 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 225, + "end": 238, + "callee": { + "type": "Identifier", + "start": 225, + "end": 231, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 232, + "end": 234, + "name": "p2" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 236, + "end": 237 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 244, + "end": 257, + "callee": { + "type": "Identifier", + "start": 244, + "end": 250, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 251, + "end": 253, + "name": "p3" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 255, + "end": 256 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 263, + "end": 276, + "callee": { + "type": "Identifier", + "start": 263, + "end": 269, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 270, + "end": 272, + "name": "p0" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 274, + "end": 275 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 282, + "end": 290, + "callee": { + "type": "Identifier", + "start": 282, + "end": 287, + "name": "close" + }, + "arguments": [ + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 288, + "end": 289 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 296, + "end": 314, + "callee": { + "type": "Identifier", + "start": 296, + "end": 303, + "name": "extrude" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 304, + "end": 310, + "name": "length" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 312, + "end": 313 + } + ], + "optional": false + } + ] + } + } + ], + "nonCodeMeta": { + "nonCodeNodes": { + "6": [ + { + "type": "NonCodeNode", + "start": 172, + "end": 176, + "value": { + "type": "newLine" + } + } + ] + }, + "start": [] + } + } + } + } + ], + "kind": "fn" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 318, + "end": 343, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 318, + "end": 343, + "id": { + "type": "Identifier", + "start": 318, + "end": 324, + "name": "myCube" + }, + "init": { + "type": "CallExpression", + "type": "CallExpression", + "start": 327, + "end": 343, + "callee": { + "type": "Identifier", + "start": 327, + "end": 331, + "name": "cube" + }, + "arguments": [ + { + "type": "Literal", + "type": "Literal", + "start": 332, + "end": 334, + "value": 40, + "raw": "40" + }, + { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 336, + "end": 342, + "elements": [ + { + "type": "Literal", + "type": "Literal", + "start": 337, + "end": 338, + "value": 0, + "raw": "0" + }, + { + "type": "Literal", + "type": "Literal", + "start": 340, + "end": 341, + "value": 0, + "raw": "0" + } + ] + } + ], + "optional": false + } + } + ], + "kind": "const" + } + ], + "nonCodeMeta": { + "nonCodeNodes": { + "0": [ + { + "type": "NonCodeNode", + "start": 316, + "end": 318, + "value": { + "type": "newLine" + } + } + ] + }, + "start": [] + } + } +} diff --git a/src/wasm-lib/kcl/tests/cube/execution_error.snap.new b/src/wasm-lib/kcl/tests/cube/execution_error.snap.new new file mode 100644 index 000000000..3765efbd1 --- /dev/null +++ b/src/wasm-lib/kcl/tests/cube/execution_error.snap.new @@ -0,0 +1,7 @@ +--- +source: kcl/src/simulation_tests.rs +assertion_line: 98 +description: Error from executing cube.kcl +snapshot_kind: text +--- +No API token found in environment variables. Use KITTYCAD_API_TOKEN or ZOO_API_TOKEN diff --git a/src/wasm-lib/kcl/tests/cube/input.kcl b/src/wasm-lib/kcl/tests/cube/input.kcl new file mode 100644 index 000000000..3bc04fd10 --- /dev/null +++ b/src/wasm-lib/kcl/tests/cube/input.kcl @@ -0,0 +1,19 @@ +fn cube = (length, center) => { + l = length / 2 + x = center[0] + y = center[1] + p0 = [-l + x, -l + y] + p1 = [-l + x, l + y] + p2 = [l + x, l + y] + p3 = [l + x, -l + y] + + return startSketchAt(p0) + |> lineTo(p1, %) + |> lineTo(p2, %) + |> lineTo(p3, %) + |> lineTo(p0, %) + |> close(%) + |> extrude(length, %) +} + +myCube = cube(40, [0, 0]) diff --git a/src/wasm-lib/kcl/tests/cube/program_memory.snap b/src/wasm-lib/kcl/tests/cube/program_memory.snap new file mode 100644 index 000000000..625b6b9a6 --- /dev/null +++ b/src/wasm-lib/kcl/tests/cube/program_memory.snap @@ -0,0 +1,976 @@ +--- +source: kcl/src/tests.rs +description: Program memory after executing cube.kcl +snapshot_kind: text +--- +{ + "environments": [ + { + "bindings": { + "HALF_TURN": { + "type": "UserVal", + "type": "UserVal", + "value": 180, + "__meta": [] + }, + "QUARTER_TURN": { + "type": "UserVal", + "type": "UserVal", + "value": 90, + "__meta": [] + }, + "THREE_QUARTER_TURN": { + "type": "UserVal", + "type": "UserVal", + "value": 270, + "__meta": [] + }, + "ZERO": { + "type": "UserVal", + "type": "UserVal", + "value": 0, + "__meta": [] + }, + "cube": { + "type": "Function", + "expression": { + "type": "FunctionExpression", + "start": 10, + "end": 316, + "params": [ + { + "type": "Parameter", + "identifier": { + "type": "Identifier", + "start": 11, + "end": 17, + "name": "length" + }, + "optional": false + }, + { + "type": "Parameter", + "identifier": { + "type": "Identifier", + "start": 19, + "end": 25, + "name": "center" + }, + "optional": false + } + ], + "body": { + "start": 30, + "end": 316, + "body": [ + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 34, + "end": 48, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 34, + "end": 48, + "id": { + "type": "Identifier", + "start": 34, + "end": 35, + "name": "l" + }, + "init": { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 38, + "end": 48, + "operator": "/", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 38, + "end": 44, + "name": "length" + }, + "right": { + "type": "Literal", + "type": "Literal", + "start": 47, + "end": 48, + "value": 2, + "raw": "2" + } + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 51, + "end": 64, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 51, + "end": 64, + "id": { + "type": "Identifier", + "start": 51, + "end": 52, + "name": "x" + }, + "init": { + "type": "MemberExpression", + "type": "MemberExpression", + "start": 55, + "end": 64, + "object": { + "type": "Identifier", + "type": "Identifier", + "start": 55, + "end": 61, + "name": "center" + }, + "property": { + "type": "Literal", + "type": "Literal", + "start": 62, + "end": 63, + "value": 0, + "raw": "0" + }, + "computed": false + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 67, + "end": 80, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 67, + "end": 80, + "id": { + "type": "Identifier", + "start": 67, + "end": 68, + "name": "y" + }, + "init": { + "type": "MemberExpression", + "type": "MemberExpression", + "start": 71, + "end": 80, + "object": { + "type": "Identifier", + "type": "Identifier", + "start": 71, + "end": 77, + "name": "center" + }, + "property": { + "type": "Literal", + "type": "Literal", + "start": 78, + "end": 79, + "value": 1, + "raw": "1" + }, + "computed": false + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 83, + "end": 104, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 83, + "end": 104, + "id": { + "type": "Identifier", + "start": 83, + "end": 85, + "name": "p0" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 88, + "end": 104, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 89, + "end": 95, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 89, + "end": 91, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 90, + "end": 91, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 94, + "end": 95, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 97, + "end": 103, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 97, + "end": 99, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 98, + "end": 99, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 102, + "end": 103, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 107, + "end": 127, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 107, + "end": 127, + "id": { + "type": "Identifier", + "start": 107, + "end": 109, + "name": "p1" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 112, + "end": 127, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 113, + "end": 119, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 113, + "end": 115, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 114, + "end": 115, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 118, + "end": 119, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 121, + "end": 126, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 121, + "end": 122, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 125, + "end": 126, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 130, + "end": 149, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 130, + "end": 149, + "id": { + "type": "Identifier", + "start": 130, + "end": 132, + "name": "p2" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 135, + "end": 149, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 136, + "end": 141, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 136, + "end": 137, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 140, + "end": 141, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 143, + "end": 148, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 143, + "end": 144, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 147, + "end": 148, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "type": "VariableDeclaration", + "start": 152, + "end": 172, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 152, + "end": 172, + "id": { + "type": "Identifier", + "start": 152, + "end": 154, + "name": "p3" + }, + "init": { + "type": "ArrayExpression", + "type": "ArrayExpression", + "start": 157, + "end": 172, + "elements": [ + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 158, + "end": 163, + "operator": "+", + "left": { + "type": "Identifier", + "type": "Identifier", + "start": 158, + "end": 159, + "name": "l" + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 162, + "end": 163, + "name": "x" + } + }, + { + "type": "BinaryExpression", + "type": "BinaryExpression", + "start": 165, + "end": 171, + "operator": "+", + "left": { + "type": "UnaryExpression", + "type": "UnaryExpression", + "start": 165, + "end": 167, + "operator": "-", + "argument": { + "type": "Identifier", + "type": "Identifier", + "start": 166, + "end": 167, + "name": "l" + } + }, + "right": { + "type": "Identifier", + "type": "Identifier", + "start": 170, + "end": 171, + "name": "y" + } + } + ] + } + } + ], + "kind": "const" + }, + { + "type": "ReturnStatement", + "type": "ReturnStatement", + "start": 176, + "end": 314, + "argument": { + "type": "PipeExpression", + "type": "PipeExpression", + "start": 183, + "end": 314, + "body": [ + { + "type": "CallExpression", + "type": "CallExpression", + "start": 183, + "end": 200, + "callee": { + "type": "Identifier", + "start": 183, + "end": 196, + "name": "startSketchAt" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 197, + "end": 199, + "name": "p0" + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 206, + "end": 219, + "callee": { + "type": "Identifier", + "start": 206, + "end": 212, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 213, + "end": 215, + "name": "p1" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 217, + "end": 218 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 225, + "end": 238, + "callee": { + "type": "Identifier", + "start": 225, + "end": 231, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 232, + "end": 234, + "name": "p2" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 236, + "end": 237 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 244, + "end": 257, + "callee": { + "type": "Identifier", + "start": 244, + "end": 250, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 251, + "end": 253, + "name": "p3" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 255, + "end": 256 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 263, + "end": 276, + "callee": { + "type": "Identifier", + "start": 263, + "end": 269, + "name": "lineTo" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 270, + "end": 272, + "name": "p0" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 274, + "end": 275 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 282, + "end": 290, + "callee": { + "type": "Identifier", + "start": 282, + "end": 287, + "name": "close" + }, + "arguments": [ + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 288, + "end": 289 + } + ], + "optional": false + }, + { + "type": "CallExpression", + "type": "CallExpression", + "start": 296, + "end": 314, + "callee": { + "type": "Identifier", + "start": 296, + "end": 303, + "name": "extrude" + }, + "arguments": [ + { + "type": "Identifier", + "type": "Identifier", + "start": 304, + "end": 310, + "name": "length" + }, + { + "type": "PipeSubstitution", + "type": "PipeSubstitution", + "start": 312, + "end": 313 + } + ], + "optional": false + } + ] + } + } + ], + "nonCodeMeta": { + "nonCodeNodes": { + "6": [ + { + "type": "NonCodeNode", + "start": 172, + "end": 176, + "value": { + "type": "newLine" + } + } + ] + }, + "start": [] + } + } + }, + "memory": { + "environments": [ + { + "bindings": { + "HALF_TURN": { + "type": "UserVal", + "type": "UserVal", + "value": 180, + "__meta": [] + }, + "QUARTER_TURN": { + "type": "UserVal", + "type": "UserVal", + "value": 90, + "__meta": [] + }, + "THREE_QUARTER_TURN": { + "type": "UserVal", + "type": "UserVal", + "value": 270, + "__meta": [] + }, + "ZERO": { + "type": "UserVal", + "type": "UserVal", + "value": 0, + "__meta": [] + } + }, + "parent": null + } + ], + "currentEnv": 0, + "return": null + }, + "__meta": [ + { + "sourceRange": [ + 10, + 316 + ] + } + ] + }, + "myCube": { + "type": "Solid", + "type": "Solid", + "id": "[uuid]", + "value": [ + { + "faceId": "[uuid]", + "id": "[uuid]", + "sourceRange": [ + 206, + 219 + ], + "tag": null, + "type": "extrudePlane" + }, + { + "faceId": "[uuid]", + "id": "[uuid]", + "sourceRange": [ + 225, + 238 + ], + "tag": null, + "type": "extrudePlane" + }, + { + "faceId": "[uuid]", + "id": "[uuid]", + "sourceRange": [ + 244, + 257 + ], + "tag": null, + "type": "extrudePlane" + }, + { + "faceId": "[uuid]", + "id": "[uuid]", + "sourceRange": [ + 263, + 276 + ], + "tag": null, + "type": "extrudePlane" + } + ], + "sketch": { + "type": "Sketch", + "id": "[uuid]", + "paths": [ + { + "__geoMeta": { + "id": "[uuid]", + "sourceRange": [ + 206, + 219 + ] + }, + "from": [ + -20.0, + -20.0 + ], + "tag": null, + "to": [ + -20.0, + 20.0 + ], + "type": "ToPoint" + }, + { + "__geoMeta": { + "id": "[uuid]", + "sourceRange": [ + 225, + 238 + ] + }, + "from": [ + -20.0, + 20.0 + ], + "tag": null, + "to": [ + 20.0, + 20.0 + ], + "type": "ToPoint" + }, + { + "__geoMeta": { + "id": "[uuid]", + "sourceRange": [ + 244, + 257 + ] + }, + "from": [ + 20.0, + 20.0 + ], + "tag": null, + "to": [ + 20.0, + -20.0 + ], + "type": "ToPoint" + }, + { + "__geoMeta": { + "id": "[uuid]", + "sourceRange": [ + 263, + 276 + ] + }, + "from": [ + 20.0, + -20.0 + ], + "tag": null, + "to": [ + -20.0, + -20.0 + ], + "type": "ToPoint" + }, + { + "__geoMeta": { + "id": "[uuid]", + "sourceRange": [ + 282, + 290 + ] + }, + "from": [ + -20.0, + -20.0 + ], + "tag": null, + "to": [ + -20.0, + -20.0 + ], + "type": "ToPoint" + } + ], + "on": { + "type": "plane", + "id": "[uuid]", + "value": "XY", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "xAxis": { + "x": 1.0, + "y": 0.0, + "z": 0.0 + }, + "yAxis": { + "x": 0.0, + "y": 1.0, + "z": 0.0 + }, + "zAxis": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "__meta": [] + }, + "start": { + "from": [ + -20.0, + -20.0 + ], + "to": [ + -20.0, + -20.0 + ], + "tag": null, + "__geoMeta": { + "id": "[uuid]", + "sourceRange": [ + 183, + 200 + ] + } + }, + "__meta": [ + { + "sourceRange": [ + 183, + 200 + ] + } + ] + }, + "height": 40.0, + "startCapId": "[uuid]", + "endCapId": "[uuid]", + "__meta": [ + { + "sourceRange": [ + 183, + 200 + ] + } + ] + } + }, + "parent": null + } + ], + "currentEnv": 0, + "return": null +} diff --git a/src/wasm-lib/kcl/tests/cube/rendered_model.png b/src/wasm-lib/kcl/tests/cube/rendered_model.png new file mode 100644 index 000000000..1a74f37b4 Binary files /dev/null and b/src/wasm-lib/kcl/tests/cube/rendered_model.png differ diff --git a/src/wasm-lib/kcl/tests/cube/tokens.snap b/src/wasm-lib/kcl/tests/cube/tokens.snap new file mode 100644 index 000000000..6136c0486 --- /dev/null +++ b/src/wasm-lib/kcl/tests/cube/tokens.snap @@ -0,0 +1,1257 @@ +--- +source: kcl/src/tests.rs +description: Result of tokenizing cube.kcl +snapshot_kind: text +--- +{ + "Ok": [ + { + "type": "keyword", + "start": 0, + "end": 2, + "value": "fn" + }, + { + "type": "whitespace", + "start": 2, + "end": 3, + "value": " " + }, + { + "type": "word", + "start": 3, + "end": 7, + "value": "cube" + }, + { + "type": "whitespace", + "start": 7, + "end": 8, + "value": " " + }, + { + "type": "operator", + "start": 8, + "end": 9, + "value": "=" + }, + { + "type": "whitespace", + "start": 9, + "end": 10, + "value": " " + }, + { + "type": "brace", + "start": 10, + "end": 11, + "value": "(" + }, + { + "type": "word", + "start": 11, + "end": 17, + "value": "length" + }, + { + "type": "comma", + "start": 17, + "end": 18, + "value": "," + }, + { + "type": "whitespace", + "start": 18, + "end": 19, + "value": " " + }, + { + "type": "word", + "start": 19, + "end": 25, + "value": "center" + }, + { + "type": "brace", + "start": 25, + "end": 26, + "value": ")" + }, + { + "type": "whitespace", + "start": 26, + "end": 27, + "value": " " + }, + { + "type": "operator", + "start": 27, + "end": 29, + "value": "=>" + }, + { + "type": "whitespace", + "start": 29, + "end": 30, + "value": " " + }, + { + "type": "brace", + "start": 30, + "end": 31, + "value": "{" + }, + { + "type": "whitespace", + "start": 31, + "end": 34, + "value": "\n " + }, + { + "type": "word", + "start": 34, + "end": 35, + "value": "l" + }, + { + "type": "whitespace", + "start": 35, + "end": 36, + "value": " " + }, + { + "type": "operator", + "start": 36, + "end": 37, + "value": "=" + }, + { + "type": "whitespace", + "start": 37, + "end": 38, + "value": " " + }, + { + "type": "word", + "start": 38, + "end": 44, + "value": "length" + }, + { + "type": "whitespace", + "start": 44, + "end": 45, + "value": " " + }, + { + "type": "operator", + "start": 45, + "end": 46, + "value": "/" + }, + { + "type": "whitespace", + "start": 46, + "end": 47, + "value": " " + }, + { + "type": "number", + "start": 47, + "end": 48, + "value": "2" + }, + { + "type": "whitespace", + "start": 48, + "end": 51, + "value": "\n " + }, + { + "type": "word", + "start": 51, + "end": 52, + "value": "x" + }, + { + "type": "whitespace", + "start": 52, + "end": 53, + "value": " " + }, + { + "type": "operator", + "start": 53, + "end": 54, + "value": "=" + }, + { + "type": "whitespace", + "start": 54, + "end": 55, + "value": " " + }, + { + "type": "word", + "start": 55, + "end": 61, + "value": "center" + }, + { + "type": "brace", + "start": 61, + "end": 62, + "value": "[" + }, + { + "type": "number", + "start": 62, + "end": 63, + "value": "0" + }, + { + "type": "brace", + "start": 63, + "end": 64, + "value": "]" + }, + { + "type": "whitespace", + "start": 64, + "end": 67, + "value": "\n " + }, + { + "type": "word", + "start": 67, + "end": 68, + "value": "y" + }, + { + "type": "whitespace", + "start": 68, + "end": 69, + "value": " " + }, + { + "type": "operator", + "start": 69, + "end": 70, + "value": "=" + }, + { + "type": "whitespace", + "start": 70, + "end": 71, + "value": " " + }, + { + "type": "word", + "start": 71, + "end": 77, + "value": "center" + }, + { + "type": "brace", + "start": 77, + "end": 78, + "value": "[" + }, + { + "type": "number", + "start": 78, + "end": 79, + "value": "1" + }, + { + "type": "brace", + "start": 79, + "end": 80, + "value": "]" + }, + { + "type": "whitespace", + "start": 80, + "end": 83, + "value": "\n " + }, + { + "type": "word", + "start": 83, + "end": 85, + "value": "p0" + }, + { + "type": "whitespace", + "start": 85, + "end": 86, + "value": " " + }, + { + "type": "operator", + "start": 86, + "end": 87, + "value": "=" + }, + { + "type": "whitespace", + "start": 87, + "end": 88, + "value": " " + }, + { + "type": "brace", + "start": 88, + "end": 89, + "value": "[" + }, + { + "type": "operator", + "start": 89, + "end": 90, + "value": "-" + }, + { + "type": "word", + "start": 90, + "end": 91, + "value": "l" + }, + { + "type": "whitespace", + "start": 91, + "end": 92, + "value": " " + }, + { + "type": "operator", + "start": 92, + "end": 93, + "value": "+" + }, + { + "type": "whitespace", + "start": 93, + "end": 94, + "value": " " + }, + { + "type": "word", + "start": 94, + "end": 95, + "value": "x" + }, + { + "type": "comma", + "start": 95, + "end": 96, + "value": "," + }, + { + "type": "whitespace", + "start": 96, + "end": 97, + "value": " " + }, + { + "type": "operator", + "start": 97, + "end": 98, + "value": "-" + }, + { + "type": "word", + "start": 98, + "end": 99, + "value": "l" + }, + { + "type": "whitespace", + "start": 99, + "end": 100, + "value": " " + }, + { + "type": "operator", + "start": 100, + "end": 101, + "value": "+" + }, + { + "type": "whitespace", + "start": 101, + "end": 102, + "value": " " + }, + { + "type": "word", + "start": 102, + "end": 103, + "value": "y" + }, + { + "type": "brace", + "start": 103, + "end": 104, + "value": "]" + }, + { + "type": "whitespace", + "start": 104, + "end": 107, + "value": "\n " + }, + { + "type": "word", + "start": 107, + "end": 109, + "value": "p1" + }, + { + "type": "whitespace", + "start": 109, + "end": 110, + "value": " " + }, + { + "type": "operator", + "start": 110, + "end": 111, + "value": "=" + }, + { + "type": "whitespace", + "start": 111, + "end": 112, + "value": " " + }, + { + "type": "brace", + "start": 112, + "end": 113, + "value": "[" + }, + { + "type": "operator", + "start": 113, + "end": 114, + "value": "-" + }, + { + "type": "word", + "start": 114, + "end": 115, + "value": "l" + }, + { + "type": "whitespace", + "start": 115, + "end": 116, + "value": " " + }, + { + "type": "operator", + "start": 116, + "end": 117, + "value": "+" + }, + { + "type": "whitespace", + "start": 117, + "end": 118, + "value": " " + }, + { + "type": "word", + "start": 118, + "end": 119, + "value": "x" + }, + { + "type": "comma", + "start": 119, + "end": 120, + "value": "," + }, + { + "type": "whitespace", + "start": 120, + "end": 121, + "value": " " + }, + { + "type": "word", + "start": 121, + "end": 122, + "value": "l" + }, + { + "type": "whitespace", + "start": 122, + "end": 123, + "value": " " + }, + { + "type": "operator", + "start": 123, + "end": 124, + "value": "+" + }, + { + "type": "whitespace", + "start": 124, + "end": 125, + "value": " " + }, + { + "type": "word", + "start": 125, + "end": 126, + "value": "y" + }, + { + "type": "brace", + "start": 126, + "end": 127, + "value": "]" + }, + { + "type": "whitespace", + "start": 127, + "end": 130, + "value": "\n " + }, + { + "type": "word", + "start": 130, + "end": 132, + "value": "p2" + }, + { + "type": "whitespace", + "start": 132, + "end": 133, + "value": " " + }, + { + "type": "operator", + "start": 133, + "end": 134, + "value": "=" + }, + { + "type": "whitespace", + "start": 134, + "end": 135, + "value": " " + }, + { + "type": "brace", + "start": 135, + "end": 136, + "value": "[" + }, + { + "type": "word", + "start": 136, + "end": 137, + "value": "l" + }, + { + "type": "whitespace", + "start": 137, + "end": 138, + "value": " " + }, + { + "type": "operator", + "start": 138, + "end": 139, + "value": "+" + }, + { + "type": "whitespace", + "start": 139, + "end": 140, + "value": " " + }, + { + "type": "word", + "start": 140, + "end": 141, + "value": "x" + }, + { + "type": "comma", + "start": 141, + "end": 142, + "value": "," + }, + { + "type": "whitespace", + "start": 142, + "end": 143, + "value": " " + }, + { + "type": "word", + "start": 143, + "end": 144, + "value": "l" + }, + { + "type": "whitespace", + "start": 144, + "end": 145, + "value": " " + }, + { + "type": "operator", + "start": 145, + "end": 146, + "value": "+" + }, + { + "type": "whitespace", + "start": 146, + "end": 147, + "value": " " + }, + { + "type": "word", + "start": 147, + "end": 148, + "value": "y" + }, + { + "type": "brace", + "start": 148, + "end": 149, + "value": "]" + }, + { + "type": "whitespace", + "start": 149, + "end": 152, + "value": "\n " + }, + { + "type": "word", + "start": 152, + "end": 154, + "value": "p3" + }, + { + "type": "whitespace", + "start": 154, + "end": 155, + "value": " " + }, + { + "type": "operator", + "start": 155, + "end": 156, + "value": "=" + }, + { + "type": "whitespace", + "start": 156, + "end": 157, + "value": " " + }, + { + "type": "brace", + "start": 157, + "end": 158, + "value": "[" + }, + { + "type": "word", + "start": 158, + "end": 159, + "value": "l" + }, + { + "type": "whitespace", + "start": 159, + "end": 160, + "value": " " + }, + { + "type": "operator", + "start": 160, + "end": 161, + "value": "+" + }, + { + "type": "whitespace", + "start": 161, + "end": 162, + "value": " " + }, + { + "type": "word", + "start": 162, + "end": 163, + "value": "x" + }, + { + "type": "comma", + "start": 163, + "end": 164, + "value": "," + }, + { + "type": "whitespace", + "start": 164, + "end": 165, + "value": " " + }, + { + "type": "operator", + "start": 165, + "end": 166, + "value": "-" + }, + { + "type": "word", + "start": 166, + "end": 167, + "value": "l" + }, + { + "type": "whitespace", + "start": 167, + "end": 168, + "value": " " + }, + { + "type": "operator", + "start": 168, + "end": 169, + "value": "+" + }, + { + "type": "whitespace", + "start": 169, + "end": 170, + "value": " " + }, + { + "type": "word", + "start": 170, + "end": 171, + "value": "y" + }, + { + "type": "brace", + "start": 171, + "end": 172, + "value": "]" + }, + { + "type": "whitespace", + "start": 172, + "end": 176, + "value": "\n\n " + }, + { + "type": "keyword", + "start": 176, + "end": 182, + "value": "return" + }, + { + "type": "whitespace", + "start": 182, + "end": 183, + "value": " " + }, + { + "type": "word", + "start": 183, + "end": 196, + "value": "startSketchAt" + }, + { + "type": "brace", + "start": 196, + "end": 197, + "value": "(" + }, + { + "type": "word", + "start": 197, + "end": 199, + "value": "p0" + }, + { + "type": "brace", + "start": 199, + "end": 200, + "value": ")" + }, + { + "type": "whitespace", + "start": 200, + "end": 203, + "value": "\n " + }, + { + "type": "operator", + "start": 203, + "end": 205, + "value": "|>" + }, + { + "type": "whitespace", + "start": 205, + "end": 206, + "value": " " + }, + { + "type": "word", + "start": 206, + "end": 212, + "value": "lineTo" + }, + { + "type": "brace", + "start": 212, + "end": 213, + "value": "(" + }, + { + "type": "word", + "start": 213, + "end": 215, + "value": "p1" + }, + { + "type": "comma", + "start": 215, + "end": 216, + "value": "," + }, + { + "type": "whitespace", + "start": 216, + "end": 217, + "value": " " + }, + { + "type": "operator", + "start": 217, + "end": 218, + "value": "%" + }, + { + "type": "brace", + "start": 218, + "end": 219, + "value": ")" + }, + { + "type": "whitespace", + "start": 219, + "end": 222, + "value": "\n " + }, + { + "type": "operator", + "start": 222, + "end": 224, + "value": "|>" + }, + { + "type": "whitespace", + "start": 224, + "end": 225, + "value": " " + }, + { + "type": "word", + "start": 225, + "end": 231, + "value": "lineTo" + }, + { + "type": "brace", + "start": 231, + "end": 232, + "value": "(" + }, + { + "type": "word", + "start": 232, + "end": 234, + "value": "p2" + }, + { + "type": "comma", + "start": 234, + "end": 235, + "value": "," + }, + { + "type": "whitespace", + "start": 235, + "end": 236, + "value": " " + }, + { + "type": "operator", + "start": 236, + "end": 237, + "value": "%" + }, + { + "type": "brace", + "start": 237, + "end": 238, + "value": ")" + }, + { + "type": "whitespace", + "start": 238, + "end": 241, + "value": "\n " + }, + { + "type": "operator", + "start": 241, + "end": 243, + "value": "|>" + }, + { + "type": "whitespace", + "start": 243, + "end": 244, + "value": " " + }, + { + "type": "word", + "start": 244, + "end": 250, + "value": "lineTo" + }, + { + "type": "brace", + "start": 250, + "end": 251, + "value": "(" + }, + { + "type": "word", + "start": 251, + "end": 253, + "value": "p3" + }, + { + "type": "comma", + "start": 253, + "end": 254, + "value": "," + }, + { + "type": "whitespace", + "start": 254, + "end": 255, + "value": " " + }, + { + "type": "operator", + "start": 255, + "end": 256, + "value": "%" + }, + { + "type": "brace", + "start": 256, + "end": 257, + "value": ")" + }, + { + "type": "whitespace", + "start": 257, + "end": 260, + "value": "\n " + }, + { + "type": "operator", + "start": 260, + "end": 262, + "value": "|>" + }, + { + "type": "whitespace", + "start": 262, + "end": 263, + "value": " " + }, + { + "type": "word", + "start": 263, + "end": 269, + "value": "lineTo" + }, + { + "type": "brace", + "start": 269, + "end": 270, + "value": "(" + }, + { + "type": "word", + "start": 270, + "end": 272, + "value": "p0" + }, + { + "type": "comma", + "start": 272, + "end": 273, + "value": "," + }, + { + "type": "whitespace", + "start": 273, + "end": 274, + "value": " " + }, + { + "type": "operator", + "start": 274, + "end": 275, + "value": "%" + }, + { + "type": "brace", + "start": 275, + "end": 276, + "value": ")" + }, + { + "type": "whitespace", + "start": 276, + "end": 279, + "value": "\n " + }, + { + "type": "operator", + "start": 279, + "end": 281, + "value": "|>" + }, + { + "type": "whitespace", + "start": 281, + "end": 282, + "value": " " + }, + { + "type": "word", + "start": 282, + "end": 287, + "value": "close" + }, + { + "type": "brace", + "start": 287, + "end": 288, + "value": "(" + }, + { + "type": "operator", + "start": 288, + "end": 289, + "value": "%" + }, + { + "type": "brace", + "start": 289, + "end": 290, + "value": ")" + }, + { + "type": "whitespace", + "start": 290, + "end": 293, + "value": "\n " + }, + { + "type": "operator", + "start": 293, + "end": 295, + "value": "|>" + }, + { + "type": "whitespace", + "start": 295, + "end": 296, + "value": " " + }, + { + "type": "word", + "start": 296, + "end": 303, + "value": "extrude" + }, + { + "type": "brace", + "start": 303, + "end": 304, + "value": "(" + }, + { + "type": "word", + "start": 304, + "end": 310, + "value": "length" + }, + { + "type": "comma", + "start": 310, + "end": 311, + "value": "," + }, + { + "type": "whitespace", + "start": 311, + "end": 312, + "value": " " + }, + { + "type": "operator", + "start": 312, + "end": 313, + "value": "%" + }, + { + "type": "brace", + "start": 313, + "end": 314, + "value": ")" + }, + { + "type": "whitespace", + "start": 314, + "end": 315, + "value": "\n" + }, + { + "type": "brace", + "start": 315, + "end": 316, + "value": "}" + }, + { + "type": "whitespace", + "start": 316, + "end": 318, + "value": "\n\n" + }, + { + "type": "word", + "start": 318, + "end": 324, + "value": "myCube" + }, + { + "type": "whitespace", + "start": 324, + "end": 325, + "value": " " + }, + { + "type": "operator", + "start": 325, + "end": 326, + "value": "=" + }, + { + "type": "whitespace", + "start": 326, + "end": 327, + "value": " " + }, + { + "type": "word", + "start": 327, + "end": 331, + "value": "cube" + }, + { + "type": "brace", + "start": 331, + "end": 332, + "value": "(" + }, + { + "type": "number", + "start": 332, + "end": 334, + "value": "40" + }, + { + "type": "comma", + "start": 334, + "end": 335, + "value": "," + }, + { + "type": "whitespace", + "start": 335, + "end": 336, + "value": " " + }, + { + "type": "brace", + "start": 336, + "end": 337, + "value": "[" + }, + { + "type": "number", + "start": 337, + "end": 338, + "value": "0" + }, + { + "type": "comma", + "start": 338, + "end": 339, + "value": "," + }, + { + "type": "whitespace", + "start": 339, + "end": 340, + "value": " " + }, + { + "type": "number", + "start": 340, + "end": 341, + "value": "0" + }, + { + "type": "brace", + "start": 341, + "end": 342, + "value": "]" + }, + { + "type": "brace", + "start": 342, + "end": 343, + "value": ")" + }, + { + "type": "whitespace", + "start": 343, + "end": 344, + "value": "\n" + } + ] +} diff --git a/src/wasm-lib/kcl/tests/simtest.tmpl b/src/wasm-lib/kcl/tests/simtest.tmpl new file mode 100644 index 000000000..785cba1d7 --- /dev/null +++ b/src/wasm-lib/kcl/tests/simtest.tmpl @@ -0,0 +1,27 @@ +mod TEST_NAME_HERE { + const TEST_NAME: &str = "TEST_NAME_HERE"; + + /// Test tokenizing KCL. + #[test] + fn tokenize() { + super::tokenize(TEST_NAME) + } + + /// Test parsing KCL. + #[test] + fn parse() { + super::parse(TEST_NAME) + } + + /// Test that parsing and unparsing KCL produces the original KCL input. + #[test] + fn unparse() { + super::unparse(TEST_NAME) + } + + /// Test that KCL is executed correctly. + #[tokio::test(flavor = "multi_thread")] + async fn kcl_test_execute() { + super::execute(TEST_NAME).await + } +}