diff --git a/docs/kcl/import.md b/docs/kcl/import.md index 3dfde0358f..1ac55a3a9c 100644 --- a/docs/kcl/import.md +++ b/docs/kcl/import.md @@ -4,8 +4,12 @@ excerpt: "Import a CAD file." layout: manual --- +**WARNING:** This function is deprecated. + Import a CAD file. +**DEPRECATED** Prefer to use import statements. + For formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory. Note: The import command currently only works when using the native Modeling App. diff --git a/docs/kcl/index.md b/docs/kcl/index.md index 7c3bfafda3..8356c1a271 100644 --- a/docs/kcl/index.md +++ b/docs/kcl/index.md @@ -51,7 +51,6 @@ layout: manual * [`helixRevolutions`](kcl/helixRevolutions) * [`hole`](kcl/hole) * [`hollow`](kcl/hollow) -* [`import`](kcl/import) * [`inch`](kcl/inch) * [`lastSegX`](kcl/lastSegX) * [`lastSegY`](kcl/lastSegY) diff --git a/docs/kcl/std.json b/docs/kcl/std.json index 8a11ad99ac..fb2d644c49 100644 --- a/docs/kcl/std.json +++ b/docs/kcl/std.json @@ -92765,7 +92765,7 @@ { "name": "import", "summary": "Import a CAD file.", - "description": "For formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory.\n\nNote: The import command currently only works when using the native Modeling App.\n\nFor importing KCL functions using the `import` statement, see the docs on [KCL modules](/docs/kcl/modules).", + "description": "**DEPRECATED** Prefer to use import statements.\n\nFor formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory.\n\nNote: The import command currently only works when using the native Modeling App.\n\nFor importing KCL functions using the `import` statement, see the docs on [KCL modules](/docs/kcl/modules).", "tags": [], "keywordArguments": false, "args": [ @@ -93168,7 +93168,7 @@ "labelRequired": true }, "unpublished": false, - "deprecated": false, + "deprecated": true, "examples": [ "model = import(\"tests/inputs/cube.obj\")", "model = import(\"tests/inputs/cube.obj\", { format = \"obj\", units = \"m\" })", diff --git a/src/wasm-lib/kcl/src/execution/import.rs b/src/wasm-lib/kcl/src/execution/import.rs new file mode 100644 index 0000000000..62d69397d8 --- /dev/null +++ b/src/wasm-lib/kcl/src/execution/import.rs @@ -0,0 +1,294 @@ +use std::{ffi::OsStr, path::Path, str::FromStr}; + +use anyhow::Result; +use kcmc::{ + coord::{Axis, AxisDirectionPair, Direction, System}, + each_cmd as mcmd, + format::InputFormat, + ok_response::OkModelingCmdResponse, + shared::FileImportFormat, + units::UnitLength, + websocket::OkWebSocketResponseData, + ImportFile, ModelingCmd, +}; +use kittycad_modeling_cmds as kcmc; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use crate::{ + errors::{KclError, KclErrorDetails}, + execution::{ExecState, ImportedGeometry}, + fs::FileSystem, + source_range::SourceRange, +}; + +use super::ExecutorContext; + +// Zoo co-ordinate system. +// +// * Forward: -Y +// * Up: +Z +// * Handedness: Right +pub const ZOO_COORD_SYSTEM: System = System { + forward: AxisDirectionPair { + axis: Axis::Y, + direction: Direction::Negative, + }, + up: AxisDirectionPair { + axis: Axis::Z, + direction: Direction::Positive, + }, +}; + +pub async fn import_foreign( + file_path: &Path, + format: Option, + exec_state: &mut ExecState, + ctxt: &ExecutorContext, + source_range: SourceRange, +) -> Result { + // Make sure the file exists. + if !ctxt.fs.exists(file_path, source_range).await? { + return Err(KclError::Semantic(KclErrorDetails { + message: format!("File `{}` does not exist.", file_path.display()), + source_ranges: vec![source_range], + })); + } + + let ext_format = get_import_format_from_extension(file_path.extension().ok_or_else(|| { + KclError::Semantic(KclErrorDetails { + message: format!("No file extension found for `{}`", file_path.display()), + source_ranges: vec![source_range], + }) + })?) + .map_err(|e| { + KclError::Semantic(KclErrorDetails { + message: e.to_string(), + source_ranges: vec![source_range], + }) + })?; + + // Get the format type from the extension of the file. + let format = if let Some(format) = format { + // Validate the given format with the extension format. + validate_extension_format(ext_format, format.clone()).map_err(|e| { + KclError::Semantic(KclErrorDetails { + message: e.to_string(), + source_ranges: vec![source_range], + }) + })?; + format + } else { + ext_format + }; + + // Get the file contents for each file path. + let file_contents = ctxt.fs.read(file_path, source_range).await.map_err(|e| { + KclError::Semantic(KclErrorDetails { + message: e.to_string(), + source_ranges: vec![source_range], + }) + })?; + + // We want the file_path to be without the parent. + let file_name = std::path::Path::new(&file_path) + .file_name() + .map(|p| p.to_string_lossy().to_string()) + .ok_or_else(|| { + KclError::Semantic(KclErrorDetails { + message: format!("Could not get the file name from the path `{}`", file_path.display()), + source_ranges: vec![source_range], + }) + })?; + let mut import_files = vec![kcmc::ImportFile { + path: file_name.to_string(), + data: file_contents.clone(), + }]; + + // In the case of a gltf importing a bin file we need to handle that! and figure out where the + // file is relative to our current file. + if let InputFormat::Gltf(..) = format { + // Check if the file is a binary gltf file, in that case we don't need to import the bin + // file. + if !file_contents.starts_with(b"glTF") { + let json = gltf_json::Root::from_slice(&file_contents).map_err(|e| { + KclError::Semantic(KclErrorDetails { + message: e.to_string(), + source_ranges: vec![source_range], + }) + })?; + + // Read the gltf file and check if there is a bin file. + for buffer in json.buffers.iter() { + if let Some(uri) = &buffer.uri { + if !uri.starts_with("data:") { + // We want this path relative to the file_path given. + let bin_path = std::path::Path::new(&file_path) + .parent() + .map(|p| p.join(uri)) + .map(|p| p.to_string_lossy().to_string()) + .ok_or_else(|| { + KclError::Semantic(KclErrorDetails { + message: format!( + "Could not get the parent path of the file `{}`", + file_path.display() + ), + source_ranges: vec![source_range], + }) + })?; + + let bin_contents = ctxt.fs.read(&bin_path, source_range).await.map_err(|e| { + KclError::Semantic(KclErrorDetails { + message: e.to_string(), + source_ranges: vec![source_range], + }) + })?; + + import_files.push(ImportFile { + path: uri.to_string(), + data: bin_contents, + }); + } + } + } + } + } + Ok(PreImportedGeometry { + id: exec_state.next_uuid(), + source_range, + command: mcmd::ImportFiles { + files: import_files.clone(), + format, + }, + }) +} + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct PreImportedGeometry { + id: Uuid, + command: mcmd::ImportFiles, + source_range: SourceRange, +} + +pub async fn send_to_engine(pre: PreImportedGeometry, ctxt: &ExecutorContext) -> Result { + if ctxt.is_mock() { + return Ok(ImportedGeometry { + id: pre.id, + value: pre.command.files.iter().map(|f| f.path.to_string()).collect(), + meta: vec![pre.source_range.into()], + }); + } + + let resp = ctxt + .engine + .send_modeling_cmd(pre.id, pre.source_range, &ModelingCmd::from(pre.command.clone())) + .await?; + + let OkWebSocketResponseData::Modeling { + modeling_response: OkModelingCmdResponse::ImportFiles(imported_files), + } = &resp + else { + return Err(KclError::Engine(KclErrorDetails { + message: format!("ImportFiles response was not as expected: {:?}", resp), + source_ranges: vec![pre.source_range], + })); + }; + + Ok(ImportedGeometry { + id: imported_files.object_id, + value: pre.command.files.iter().map(|f| f.path.to_string()).collect(), + meta: vec![pre.source_range.into()], + }) +} + +/// Get the source format from the extension. +fn get_import_format_from_extension(ext: &OsStr) -> Result { + let ext = ext + .to_str() + .ok_or_else(|| anyhow::anyhow!("Invalid file extension: `{ext:?}`"))?; + let format = match FileImportFormat::from_str(ext) { + Ok(format) => format, + Err(_) => { + if ext == "stp" { + FileImportFormat::Step + } else if ext == "glb" { + FileImportFormat::Gltf + } else { + anyhow::bail!("unknown source format for file extension: {ext}. Try setting the `--src-format` flag explicitly or use a valid format.") + } + } + }; + + // Make the default units millimeters. + let ul = UnitLength::Millimeters; + + // Zoo co-ordinate system. + // + // * Forward: -Y + // * Up: +Z + // * Handedness: Right + match format { + FileImportFormat::Step => Ok(InputFormat::Step(kcmc::format::step::import::Options { + split_closed_faces: false, + })), + FileImportFormat::Stl => Ok(InputFormat::Stl(kcmc::format::stl::import::Options { + coords: ZOO_COORD_SYSTEM, + units: ul, + })), + FileImportFormat::Obj => Ok(InputFormat::Obj(kcmc::format::obj::import::Options { + coords: ZOO_COORD_SYSTEM, + units: ul, + })), + FileImportFormat::Gltf => Ok(InputFormat::Gltf(kcmc::format::gltf::import::Options {})), + FileImportFormat::Ply => Ok(InputFormat::Ply(kcmc::format::ply::import::Options { + coords: ZOO_COORD_SYSTEM, + units: ul, + })), + FileImportFormat::Fbx => Ok(InputFormat::Fbx(kcmc::format::fbx::import::Options {})), + FileImportFormat::Sldprt => Ok(InputFormat::Sldprt(kcmc::format::sldprt::import::Options { + split_closed_faces: false, + })), + } +} + +fn validate_extension_format(ext: InputFormat, given: InputFormat) -> Result<()> { + if let InputFormat::Stl(_) = ext { + if let InputFormat::Stl(_) = given { + return Ok(()); + } + } + + if let InputFormat::Obj(_) = ext { + if let InputFormat::Obj(_) = given { + return Ok(()); + } + } + + if let InputFormat::Ply(_) = ext { + if let InputFormat::Ply(_) = given { + return Ok(()); + } + } + + if ext == given { + return Ok(()); + } + + anyhow::bail!( + "The given format does not match the file extension. Expected: `{}`, Given: `{}`", + get_name_of_format(ext), + get_name_of_format(given) + ) +} + +fn get_name_of_format(type_: InputFormat) -> &'static str { + match type_ { + InputFormat::Fbx(_) => "fbx", + InputFormat::Gltf(_) => "gltf", + InputFormat::Obj(_) => "obj", + InputFormat::Ply(_) => "ply", + InputFormat::Sldprt(_) => "sldprt", + InputFormat::Step(_) => "step", + InputFormat::Stl(_) => "stl", + } +} diff --git a/src/wasm-lib/kcl/src/execution/mod.rs b/src/wasm-lib/kcl/src/execution/mod.rs index 985d3889b0..223d9de660 100644 --- a/src/wasm-lib/kcl/src/execution/mod.rs +++ b/src/wasm-lib/kcl/src/execution/mod.rs @@ -23,6 +23,7 @@ type Point2D = kcmc::shared::Point2d; type Point3D = kcmc::shared::Point3d; pub use function_param::FunctionParam; +pub(crate) use import::{import_foreign, send_to_engine as send_import_to_engine, ZOO_COORD_SYSTEM}; pub use kcl_value::{KclObjectFields, KclValue, UnitAngle, UnitLen}; use uuid::Uuid; @@ -32,6 +33,7 @@ pub(crate) mod cache; mod cad_op; mod exec_ast; mod function_param; +mod import; mod kcl_value; use crate::{ @@ -40,7 +42,7 @@ use crate::{ execution::cache::{CacheInformation, CacheResult}, fs::{FileManager, FileSystem}, parsing::ast::types::{ - BodyItem, Expr, FunctionExpression, ImportSelector, ItemVisibility, Node, NodeRef, NonCodeValue, + BodyItem, Expr, FunctionExpression, ImportPath, ImportSelector, ItemVisibility, Node, NodeRef, NonCodeValue, Program as AstProgram, TagDeclarator, TagNode, }, settings::types::UnitLength, @@ -181,34 +183,15 @@ impl ExecState { self.global.artifacts.insert(id, artifact); } - async fn add_module( - &mut self, - path: std::path::PathBuf, - ctxt: &ExecutorContext, - source_range: SourceRange, - ) -> Result { - // Need to avoid borrowing self in the closure. - let new_module_id = ModuleId::from_usize(self.global.path_to_source_id.len()); - let mut is_new = false; - let id = *self.global.path_to_source_id.entry(path.clone()).or_insert_with(|| { - is_new = true; - new_module_id - }); + fn add_module(&mut self, id: ModuleId, path: std::path::PathBuf, repr: ModuleRepr) -> ModuleId { + debug_assert!(!self.global.path_to_source_id.contains_key(&path)); - if is_new { - let source = ctxt.fs.read_to_string(&path, source_range).await?; - // TODO handle parsing errors properly - let parsed = crate::parsing::parse_str(&source, id).parse_errs_as_err()?; + self.global.path_to_source_id.insert(path.clone(), id); - let module_info = ModuleInfo { - id, - path, - parsed: Some(parsed), - }; - self.global.module_infos.insert(id, module_info); - } + let module_info = ModuleInfo { id, repr, path }; + self.global.module_infos.insert(id, module_info); - Ok(id) + id } pub fn length_unit(&self) -> UnitLen { @@ -240,7 +223,7 @@ impl GlobalState { ModuleInfo { id: root_id, path: root_path.clone(), - parsed: None, + repr: ModuleRepr::Root, }, ); global.path_to_source_id.insert(root_path, root_id); @@ -1253,7 +1236,15 @@ pub struct ModuleInfo { id: ModuleId, /// Absolute path of the module's source file. path: std::path::PathBuf, - parsed: Option>, + repr: ModuleRepr, +} + +#[allow(clippy::large_enum_variant)] +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub enum ModuleRepr { + Root, + Kcl(Node), + Foreign(import::PreImportedGeometry), } #[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy, ts_rs::TS, JsonSchema)] @@ -2511,33 +2502,68 @@ impl ExecutorContext { async fn open_module( &self, - path: &str, + path: &ImportPath, exec_state: &mut ExecState, source_range: SourceRange, ) -> Result { - let resolved_path = if let Some(project_dir) = &self.settings.project_directory { - project_dir.join(path) - } else { - std::path::PathBuf::from(&path) - }; + match path { + ImportPath::Kcl { filename } => { + let resolved_path = if let Some(project_dir) = &self.settings.project_directory { + project_dir.join(filename) + } else { + std::path::PathBuf::from(filename) + }; - if exec_state.mod_local.import_stack.contains(&resolved_path) { - return Err(KclError::ImportCycle(KclErrorDetails { - message: format!( - "circular import of modules is not allowed: {} -> {}", - exec_state - .mod_local - .import_stack - .iter() - .map(|p| p.as_path().to_string_lossy()) - .collect::>() - .join(" -> "), - resolved_path.to_string_lossy() - ), + if exec_state.mod_local.import_stack.contains(&resolved_path) { + return Err(KclError::ImportCycle(KclErrorDetails { + message: format!( + "circular import of modules is not allowed: {} -> {}", + exec_state + .mod_local + .import_stack + .iter() + .map(|p| p.as_path().to_string_lossy()) + .collect::>() + .join(" -> "), + resolved_path.to_string_lossy() + ), + source_ranges: vec![source_range], + })); + } + + if let Some(id) = exec_state.global.path_to_source_id.get(&resolved_path) { + return Ok(*id); + } + + let source = self.fs.read_to_string(&resolved_path, source_range).await?; + let id = ModuleId::from_usize(exec_state.global.path_to_source_id.len()); + // TODO handle parsing errors properly + let parsed = crate::parsing::parse_str(&source, id).parse_errs_as_err()?; + let repr = ModuleRepr::Kcl(parsed); + + Ok(exec_state.add_module(id, resolved_path, repr)) + } + ImportPath::Foreign { path } => { + let resolved_path = if let Some(project_dir) = &self.settings.project_directory { + project_dir.join(path) + } else { + std::path::PathBuf::from(path) + }; + + if let Some(id) = exec_state.global.path_to_source_id.get(&resolved_path) { + return Ok(*id); + } + + let geom = import::import_foreign(&resolved_path, None, exec_state, self, source_range).await?; + let repr = ModuleRepr::Foreign(geom); + let id = ModuleId::from_usize(exec_state.global.path_to_source_id.len()); + Ok(exec_state.add_module(id, resolved_path, repr)) + } + i => Err(KclError::Semantic(KclErrorDetails { + message: format!("Unsupported import: `{i}`"), source_ranges: vec![source_range], - })); + })), } - exec_state.add_module(resolved_path.clone(), self, source_range).await } async fn exec_module( @@ -2551,43 +2577,51 @@ impl ExecutorContext { // TODO It sucks that we have to clone the whole module AST here let info = exec_state.global.module_infos[&module_id].clone(); - let mut local_state = ModuleState { - import_stack: exec_state.mod_local.import_stack.clone(), - ..ModuleState::new(&self.settings) - }; - local_state.import_stack.push(info.path.clone()); - std::mem::swap(&mut exec_state.mod_local, &mut local_state); - let original_execution = self.engine.replace_execution_kind(exec_kind); + match &info.repr { + ModuleRepr::Root => unreachable!(), + ModuleRepr::Kcl(program) => { + let mut local_state = ModuleState { + import_stack: exec_state.mod_local.import_stack.clone(), + ..ModuleState::new(&self.settings) + }; + local_state.import_stack.push(info.path.clone()); + std::mem::swap(&mut exec_state.mod_local, &mut local_state); + let original_execution = self.engine.replace_execution_kind(exec_kind); - // The unwrap here is safe since we only elide the AST for the top module. - let result = self - .inner_execute(&info.parsed.unwrap(), exec_state, crate::execution::BodyType::Root) - .await; + let result = self + .inner_execute(program, exec_state, crate::execution::BodyType::Root) + .await; - let new_units = exec_state.length_unit(); - std::mem::swap(&mut exec_state.mod_local, &mut local_state); - if new_units != old_units { - self.engine.set_units(old_units.into(), Default::default()).await?; - } - self.engine.replace_execution_kind(original_execution); + let new_units = exec_state.length_unit(); + std::mem::swap(&mut exec_state.mod_local, &mut local_state); + if new_units != old_units { + self.engine.set_units(old_units.into(), Default::default()).await?; + } + self.engine.replace_execution_kind(original_execution); - let result = result.map_err(|err| { - if let KclError::ImportCycle(_) = err { - // It was an import cycle. Keep the original message. - err.override_source_ranges(vec![source_range]) - } else { - KclError::Semantic(KclErrorDetails { - message: format!( - "Error loading imported file. Open it to view more details. {}: {}", - info.path.display(), - err.message() - ), - source_ranges: vec![source_range], - }) - } - })?; + let result = result.map_err(|err| { + if let KclError::ImportCycle(_) = err { + // It was an import cycle. Keep the original message. + err.override_source_ranges(vec![source_range]) + } else { + KclError::Semantic(KclErrorDetails { + message: format!( + "Error loading imported file. Open it to view more details. {}: {}", + info.path.display(), + err.message() + ), + source_ranges: vec![source_range], + }) + } + })?; - Ok((result, local_state.memory, local_state.module_exports)) + Ok((result, local_state.memory, local_state.module_exports)) + } + ModuleRepr::Foreign(geom) => { + let geom = send_import_to_engine(geom.clone(), self).await?; + Ok((Some(KclValue::ImportedGeometry(geom)), ProgramMemory::new(), Vec::new())) + } + } } #[async_recursion] diff --git a/src/wasm-lib/kcl/src/parsing/ast/digest.rs b/src/wasm-lib/kcl/src/parsing/ast/digest.rs index bf9097dd98..4131924b68 100644 --- a/src/wasm-lib/kcl/src/parsing/ast/digest.rs +++ b/src/wasm-lib/kcl/src/parsing/ast/digest.rs @@ -66,7 +66,8 @@ impl ImportStatement { } } hasher.update(slf.visibility.digestable_id()); - let path = slf.path.as_bytes(); + let path = slf.path.to_string(); + let path = path.as_bytes(); hasher.update(path.len().to_ne_bytes()); hasher.update(path); }); diff --git a/src/wasm-lib/kcl/src/parsing/ast/types/mod.rs b/src/wasm-lib/kcl/src/parsing/ast/types/mod.rs index 40e304a7b4..e5bd13b805 100644 --- a/src/wasm-lib/kcl/src/parsing/ast/types/mod.rs +++ b/src/wasm-lib/kcl/src/parsing/ast/types/mod.rs @@ -1256,6 +1256,32 @@ impl ImportSelector { ImportSelector::None { alias: Some(alias) } => alias.rename(old_name, new_name), } } + + pub fn exposes_imported_name(&self) -> bool { + matches!(self, ImportSelector::None { alias: None }) + } + + pub fn imports_items(&self) -> bool { + !matches!(self, ImportSelector::None { .. }) + } +} + +#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, ts_rs::TS, JsonSchema)] +#[ts(export)] +#[serde(tag = "type")] +pub enum ImportPath { + Kcl { filename: String }, + Foreign { path: String }, + Std, +} + +impl fmt::Display for ImportPath { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ImportPath::Kcl { filename: s } | ImportPath::Foreign { path: s } => write!(f, "{s}"), + ImportPath::Std => write!(f, "std"), + } + } } #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] @@ -1263,7 +1289,7 @@ impl ImportSelector { #[serde(tag = "type")] pub struct ImportStatement { pub selector: ImportSelector, - pub path: String, + pub path: ImportPath, #[serde(default, skip_serializing_if = "ItemVisibility::is_default")] pub visibility: ItemVisibility, @@ -1312,12 +1338,15 @@ impl ImportStatement { return Some(alias.name.clone()); } - let mut parts = self.path.split('.'); + let mut parts = match &self.path { + ImportPath::Kcl { filename: s } | ImportPath::Foreign { path: s } => s.split('.'), + _ => return None, + }; let name = parts.next()?; - let ext = parts.next()?; + let _ext = parts.next()?; let rest = parts.next(); - if rest.is_some() || ext != "kcl" { + if rest.is_some() { return None; } diff --git a/src/wasm-lib/kcl/src/parsing/parser.rs b/src/wasm-lib/kcl/src/parsing/parser.rs index bcf07b3ba5..d60c6a3fc4 100644 --- a/src/wasm-lib/kcl/src/parsing/parser.rs +++ b/src/wasm-lib/kcl/src/parsing/parser.rs @@ -12,7 +12,10 @@ use winnow::{ token::{any, one_of, take_till}, }; -use super::{ast::types::LabelledExpression, token::NumericSuffix}; +use super::{ + ast::types::{ImportPath, LabelledExpression}, + token::NumericSuffix, +}; use crate::{ docs::StdLibFn, errors::{CompilationError, Severity, Tag}, @@ -1545,33 +1548,11 @@ fn import_stmt(i: &mut TokenSlice) -> PResult> { }; let mut end: usize = path.end; - let path_string = match path.inner.value { - LiteralValue::String(s) => s, - _ => unreachable!(), - }; - if path_string.is_empty() { - return Err(ErrMode::Cut( - CompilationError::fatal( - SourceRange::new(path.start, path.end, path.module_id), - "import path cannot be empty", - ) - .into(), - )); - } - if path_string - .chars() - .any(|c| !c.is_ascii_alphanumeric() && c != '_' && c != '-' && c != '.') - { - return Err(ErrMode::Cut( - CompilationError::fatal( - SourceRange::new(path.start, path.end, path.module_id), - "import path may only contain alphanumeric characters, underscore, hyphen, and period. Files in other directories are not yet supported.", - ) - .into(), - )); - } - if let ImportSelector::None { alias: ref mut a } = selector { + if let ImportSelector::None { + alias: ref mut selector_alias, + } = selector + { if let Some(alias) = opt(preceded( (whitespace, import_as_keyword, whitespace), identifier.context(expected("an identifier to alias the import")), @@ -1579,35 +1560,40 @@ fn import_stmt(i: &mut TokenSlice) -> PResult> { .parse_next(i)? { end = alias.end; - *a = Some(alias); + *selector_alias = Some(alias); } ParseContext::warn(CompilationError::err( SourceRange::new(start, path.end, path.module_id), "Importing a whole module is experimental, likely to be buggy, and likely to change", )); + } - if a.is_none() - && (!path_string.ends_with(".kcl") - || path_string.starts_with("_") - || path_string.contains('-') - || path_string[0..path_string.len() - 4].contains('.')) - { - return Err(ErrMode::Cut( - CompilationError::fatal( - SourceRange::new(path.start, path.end, path.module_id), - "import path is not a valid identifier and must be aliased.".to_owned(), - ) - .into(), - )); - } + let path_string = match path.inner.value { + LiteralValue::String(s) => s, + _ => unreachable!(), + }; + let path = validate_path_string( + path_string, + selector.exposes_imported_name(), + SourceRange::new(path.start, path.end, path.module_id), + )?; + + if matches!(path, ImportPath::Foreign { .. }) && selector.imports_items() { + return Err(ErrMode::Cut( + CompilationError::fatal( + SourceRange::new(start, end, module_id), + "individual items can only be imported from KCL files", + ) + .into(), + )); } Ok(Node::boxed( ImportStatement { selector, visibility, - path: path_string, + path, digest: None, }, start, @@ -1616,6 +1602,72 @@ fn import_stmt(i: &mut TokenSlice) -> PResult> { )) } +const FOREIGN_IMPORT_EXTENSIONS: [&str; 8] = ["fbx", "gltf", "glb", "obj", "ply", "sldprt", "step", "stl"]; + +/// Validates the path string in an `import` statement. +/// +/// `var_name` is `true` if the path will be used as a variable name. +fn validate_path_string(path_string: String, var_name: bool, path_range: SourceRange) -> PResult { + if path_string.is_empty() { + return Err(ErrMode::Cut( + CompilationError::fatal(path_range, "import path cannot be empty").into(), + )); + } + + if var_name + && (path_string.starts_with("_") + || path_string.contains('-') + || path_string.chars().filter(|c| *c == '.').count() > 1) + { + return Err(ErrMode::Cut( + CompilationError::fatal(path_range, "import path is not a valid identifier and must be aliased.").into(), + )); + } + + let path = if path_string.ends_with(".kcl") { + if path_string + .chars() + .any(|c| !c.is_ascii_alphanumeric() && c != '_' && c != '-' && c != '.') + { + return Err(ErrMode::Cut( + CompilationError::fatal( + path_range, + "import path may only contain alphanumeric characters, underscore, hyphen, and period. KCL files in other directories are not yet supported.", + ) + .into(), + )); + } + + ImportPath::Kcl { filename: path_string } + } else if path_string.starts_with("std") { + ParseContext::warn(CompilationError::err( + path_range, + "explicit imports from the standard library are experimental, likely to be buggy, and likely to change.", + )); + + ImportPath::Std + } else if path_string.contains('.') { + let extn = &path_string[path_string.rfind('.').unwrap() + 1..]; + if !FOREIGN_IMPORT_EXTENSIONS.contains(&extn) { + ParseContext::warn(CompilationError::err( + path_range, + format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", FOREIGN_IMPORT_EXTENSIONS.join(", ")), + )) + } + ImportPath::Foreign { path: path_string } + } else { + return Err(ErrMode::Cut( + CompilationError::fatal( + path_range, + format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", FOREIGN_IMPORT_EXTENSIONS.join(", ")), + ) + .into(), + )); + }; + + Ok(path) +} + fn import_item(i: &mut TokenSlice) -> PResult> { let name = nameable_identifier .context(expected("an identifier to import")) @@ -3611,7 +3663,11 @@ mySk1 = startSketchAt([0, 0])"#; fn assert_err(p: &str, msg: &str, src_expected: [usize; 2]) { let result = crate::parsing::top_level_parse(p); let err = result.unwrap_errs().next().unwrap(); - assert_eq!(err.message, msg); + assert!( + err.message.starts_with(msg), + "Found `{}`, expected `{msg}`", + err.message + ); let src_actual = [err.source_range.start(), err.source_range.end()]; assert_eq!( src_expected, @@ -3977,7 +4033,7 @@ e fn bad_imports() { assert_err( r#"import cube from "../cube.kcl""#, - "import path may only contain alphanumeric characters, underscore, hyphen, and period. Files in other directories are not yet supported.", + "import path may only contain alphanumeric characters, underscore, hyphen, and period. KCL files in other directories are not yet supported.", [17, 30], ); assert_err( @@ -3985,17 +4041,21 @@ e "as is not the 'from' keyword", [9, 11], ); - assert_err(r#"import a from "dsfs" as b"#, "Unexpected token: as", [21, 23]); - assert_err(r#"import * from "dsfs" as b"#, "Unexpected token: as", [21, 23]); + assert_err( + r#"import a from "dsfs" as b"#, + "unsupported import path format", + [14, 20], + ); + assert_err( + r#"import * from "dsfs" as b"#, + "unsupported import path format", + [14, 20], + ); assert_err(r#"import a from b"#, "invalid string literal", [14, 15]); assert_err(r#"import * "dsfs""#, "\"dsfs\" is not the 'from' keyword", [9, 15]); assert_err(r#"import from "dsfs""#, "\"dsfs\" is not the 'from' keyword", [12, 18]); assert_err(r#"import "dsfs.kcl" as *"#, "Unexpected token: as", [18, 20]); - assert_err( - r#"import "dsfs""#, - "import path is not a valid identifier and must be aliased.", - [7, 13], - ); + assert_err(r#"import "dsfs""#, "unsupported import path format", [7, 13]); assert_err( r#"import "foo.bar.kcl""#, "import path is not a valid identifier and must be aliased.", @@ -4017,7 +4077,19 @@ e fn warn_import() { let some_program_string = r#"import "foo.kcl""#; let (_, errs) = assert_no_err(some_program_string); - assert_eq!(errs.len(), 1); + assert_eq!(errs.len(), 1, "{errs:#?}"); + + let some_program_string = r#"import "foo.obj""#; + let (_, errs) = assert_no_err(some_program_string); + assert_eq!(errs.len(), 1, "{errs:#?}"); + + let some_program_string = r#"import "foo.sldprt""#; + let (_, errs) = assert_no_err(some_program_string); + assert_eq!(errs.len(), 1, "{errs:#?}"); + + let some_program_string = r#"import "foo.bad""#; + let (_, errs) = assert_no_err(some_program_string); + assert_eq!(errs.len(), 2, "{errs:#?}"); } #[test] diff --git a/src/wasm-lib/kcl/src/simulation_tests.rs b/src/wasm-lib/kcl/src/simulation_tests.rs index f4577655f0..6908c35c3c 100644 --- a/src/wasm-lib/kcl/src/simulation_tests.rs +++ b/src/wasm-lib/kcl/src/simulation_tests.rs @@ -872,6 +872,27 @@ mod import_side_effect { super::execute(TEST_NAME, false).await } } +mod import_foreign { + const TEST_NAME: &str = "import_foreign"; + + /// 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, false).await + } +} mod array_elem_push_fail { const TEST_NAME: &str = "array_elem_push_fail"; diff --git a/src/wasm-lib/kcl/src/std/import.rs b/src/wasm-lib/kcl/src/std/import.rs index 89ad712a20..7f6d5b0f84 100644 --- a/src/wasm-lib/kcl/src/std/import.rs +++ b/src/wasm-lib/kcl/src/std/import.rs @@ -1,44 +1,16 @@ //! Standard library functions involved in importing files. -use std::str::FromStr; - use anyhow::Result; use derive_docs::stdlib; -use kcmc::{ - coord::{Axis, AxisDirectionPair, Direction, System}, - each_cmd as mcmd, - format::InputFormat, - ok_response::OkModelingCmdResponse, - shared::FileImportFormat, - units::UnitLength, - websocket::OkWebSocketResponseData, - ImportFile, ModelingCmd, -}; +use kcmc::{coord::System, format::InputFormat, units::UnitLength}; use kittycad_modeling_cmds as kcmc; use crate::{ errors::{KclError, KclErrorDetails}, - execution::{ExecState, ImportedGeometry, KclValue}, - fs::FileSystem, + execution::{import_foreign, send_import_to_engine, ExecState, ImportedGeometry, KclValue, ZOO_COORD_SYSTEM}, std::Args, }; -// Zoo co-ordinate system. -// -// * Forward: -Y -// * Up: +Z -// * Handedness: Right -const ZOO_COORD_SYSTEM: System = System { - forward: AxisDirectionPair { - axis: Axis::Y, - direction: Direction::Negative, - }, - up: AxisDirectionPair { - axis: Axis::Z, - direction: Direction::Positive, - }, -}; - /// Import format specifier #[derive(serde :: Serialize, serde :: Deserialize, PartialEq, Debug, Clone, schemars :: JsonSchema)] #[cfg_attr(feature = "tabled", derive(tabled::Tabled))] @@ -135,6 +107,8 @@ pub async fn import(exec_state: &mut ExecState, args: Args) -> Result Result Result { - let format = match FileImportFormat::from_str(ext) { - Ok(format) => format, - Err(_) => { - if ext == "stp" { - FileImportFormat::Step - } else if ext == "glb" { - FileImportFormat::Gltf - } else { - anyhow::bail!("unknown source format for file extension: {}. Try setting the `--src-format` flag explicitly or use a valid format.", ext) - } - } - }; - - // Make the default units millimeters. - let ul = UnitLength::Millimeters; - - // Zoo co-ordinate system. - // - // * Forward: -Y - // * Up: +Z - // * Handedness: Right - match format { - FileImportFormat::Step => Ok(InputFormat::Step(kcmc::format::step::import::Options { - split_closed_faces: false, - })), - FileImportFormat::Stl => Ok(InputFormat::Stl(kcmc::format::stl::import::Options { - coords: ZOO_COORD_SYSTEM, - units: ul, - })), - FileImportFormat::Obj => Ok(InputFormat::Obj(kcmc::format::obj::import::Options { - coords: ZOO_COORD_SYSTEM, - units: ul, - })), - FileImportFormat::Gltf => Ok(InputFormat::Gltf(kcmc::format::gltf::import::Options {})), - FileImportFormat::Ply => Ok(InputFormat::Ply(kcmc::format::ply::import::Options { - coords: ZOO_COORD_SYSTEM, - units: ul, - })), - FileImportFormat::Fbx => Ok(InputFormat::Fbx(kcmc::format::fbx::import::Options {})), - FileImportFormat::Sldprt => Ok(InputFormat::Sldprt(kcmc::format::sldprt::import::Options { - split_closed_faces: false, - })), - } -} - -fn validate_extension_format(ext: InputFormat, given: InputFormat) -> Result<()> { - if let InputFormat::Stl(_) = ext { - if let InputFormat::Stl(_) = given { - return Ok(()); - } - } - - if let InputFormat::Obj(_) = ext { - if let InputFormat::Obj(_) = given { - return Ok(()); - } - } - - if let InputFormat::Ply(_) = ext { - if let InputFormat::Ply(_) = given { - return Ok(()); - } - } - - if ext == given { - return Ok(()); - } - - anyhow::bail!( - "The given format does not match the file extension. Expected: `{}`, Given: `{}`", - get_name_of_format(ext), - get_name_of_format(given) + .await?, + &args.ctx, ) -} - -fn get_name_of_format(type_: InputFormat) -> &'static str { - match type_ { - InputFormat::Fbx(_) => "fbx", - InputFormat::Gltf(_) => "gltf", - InputFormat::Obj(_) => "obj", - InputFormat::Ply(_) => "ply", - InputFormat::Sldprt(_) => "sldprt", - InputFormat::Step(_) => "step", - InputFormat::Stl(_) => "stl", - } + .await } diff --git a/src/wasm-lib/kcl/tests/import_constant/ast.snap b/src/wasm-lib/kcl/tests/import_constant/ast.snap index bbdef2d578..d639731f4b 100644 --- a/src/wasm-lib/kcl/tests/import_constant/ast.snap +++ b/src/wasm-lib/kcl/tests/import_constant/ast.snap @@ -7,7 +7,10 @@ description: Result of parsing import_constant.kcl "body": [ { "end": 39, - "path": "export_constant.kcl", + "path": { + "type": "Kcl", + "filename": "export_constant.kcl" + }, "selector": { "type": "List", "items": [ diff --git a/src/wasm-lib/kcl/tests/import_cycle1/ast.snap b/src/wasm-lib/kcl/tests/import_cycle1/ast.snap index 130f36251f..f98e259f32 100644 --- a/src/wasm-lib/kcl/tests/import_cycle1/ast.snap +++ b/src/wasm-lib/kcl/tests/import_cycle1/ast.snap @@ -7,7 +7,10 @@ description: Result of parsing import_cycle1.kcl "body": [ { "end": 35, - "path": "import_cycle2.kcl", + "path": { + "type": "Kcl", + "filename": "import_cycle2.kcl" + }, "selector": { "type": "List", "items": [ diff --git a/src/wasm-lib/kcl/tests/import_export/ast.snap b/src/wasm-lib/kcl/tests/import_export/ast.snap index c25c6808d5..bbcc8f0818 100644 --- a/src/wasm-lib/kcl/tests/import_export/ast.snap +++ b/src/wasm-lib/kcl/tests/import_export/ast.snap @@ -7,7 +7,10 @@ description: Result of parsing import_export.kcl "body": [ { "end": 32, - "path": "export_1.kcl", + "path": { + "type": "Kcl", + "filename": "export_1.kcl" + }, "selector": { "type": "List", "items": [ diff --git a/src/wasm-lib/kcl/tests/import_foreign/artifact_commands.snap b/src/wasm-lib/kcl/tests/import_foreign/artifact_commands.snap new file mode 100644 index 0000000000..1c8216df15 --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/artifact_commands.snap @@ -0,0 +1,3281 @@ +--- +source: kcl/src/simulation_tests.rs +description: Artifact commands import_foreign.kcl +--- +[ + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "make_plane", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "x_axis": { + "x": 1.0, + "y": 0.0, + "z": 0.0 + }, + "y_axis": { + "x": 0.0, + "y": 1.0, + "z": 0.0 + }, + "size": 100.0, + "clobber": false, + "hide": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "plane_set_color", + "plane_id": "[uuid]", + "color": { + "r": 0.7, + "g": 0.28, + "b": 0.28, + "a": 0.4 + } + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "make_plane", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "x_axis": { + "x": 0.0, + "y": 1.0, + "z": 0.0 + }, + "y_axis": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "size": 100.0, + "clobber": false, + "hide": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "plane_set_color", + "plane_id": "[uuid]", + "color": { + "r": 0.28, + "g": 0.7, + "b": 0.28, + "a": 0.4 + } + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "make_plane", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "x_axis": { + "x": 1.0, + "y": 0.0, + "z": 0.0 + }, + "y_axis": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "size": 100.0, + "clobber": false, + "hide": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "plane_set_color", + "plane_id": "[uuid]", + "color": { + "r": 0.28, + "g": 0.28, + "b": 0.7, + "a": 0.4 + } + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "make_plane", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "x_axis": { + "x": -1.0, + "y": 0.0, + "z": 0.0 + }, + "y_axis": { + "x": 0.0, + "y": 1.0, + "z": 0.0 + }, + "size": 100.0, + "clobber": false, + "hide": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "make_plane", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "x_axis": { + "x": 0.0, + "y": -1.0, + "z": 0.0 + }, + "y_axis": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "size": 100.0, + "clobber": false, + "hide": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "make_plane", + "origin": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "x_axis": { + "x": -1.0, + "y": 0.0, + "z": 0.0 + }, + "y_axis": { + "x": 0.0, + "y": 0.0, + "z": 1.0 + }, + "size": 100.0, + "clobber": false, + "hide": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "edge_lines_visible", + "hidden": false + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "set_scene_units", + "unit": "mm" + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "object_visible", + "object_id": "[uuid]", + "hidden": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 0, + 0 + ], + "command": { + "type": "object_visible", + "object_id": "[uuid]", + "hidden": true + } + }, + { + "cmdId": "[uuid]", + "range": [ + 0, + 36, + 0 + ], + "command": { + "type": "import_files", + "files": [ + { + "path": "cube.gltf", + "data": [ + 123, + 10, + 32, + 32, + 34, + 97, + 115, + 115, + 101, + 116, + 34, + 58, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 34, + 103, + 101, + 110, + 101, + 114, + 97, + 116, + 111, + 114, + 34, + 58, + 32, + 34, + 75, + 104, + 114, + 111, + 110, + 111, + 115, + 32, + 103, + 108, + 84, + 70, + 32, + 66, + 108, + 101, + 110, + 100, + 101, + 114, + 32, + 73, + 47, + 79, + 32, + 118, + 51, + 46, + 52, + 46, + 53, + 48, + 34, + 44, + 10, + 32, + 32, + 32, + 32, + 34, + 118, + 101, + 114, + 115, + 105, + 111, + 110, + 34, + 58, + 32, + 34, + 50, + 46, + 48, + 34, + 10, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 34, + 115, + 99, + 101, + 110, + 101, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 34, + 115, + 99, + 101, + 110, + 101, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 83, + 99, + 101, + 110, + 101, + 34, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 111, + 100, + 101, + 115, + 34, + 58, + 32, + 91, + 48, + 93, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 34, + 110, + 111, + 100, + 101, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 109, + 101, + 115, + 104, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 67, + 117, + 98, + 101, + 34, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 34, + 109, + 97, + 116, + 101, + 114, + 105, + 97, + 108, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 100, + 111, + 117, + 98, + 108, + 101, + 83, + 105, + 100, + 101, + 100, + 34, + 58, + 32, + 116, + 114, + 117, + 101, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 77, + 97, + 116, + 101, + 114, + 105, + 97, + 108, + 34, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 112, + 98, + 114, + 77, + 101, + 116, + 97, + 108, + 108, + 105, + 99, + 82, + 111, + 117, + 103, + 104, + 110, + 101, + 115, + 115, + 34, + 58, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 97, + 115, + 101, + 67, + 111, + 108, + 111, + 114, + 70, + 97, + 99, + 116, + 111, + 114, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 48, + 46, + 56, + 48, + 48, + 48, + 48, + 48, + 48, + 49, + 49, + 57, + 50, + 48, + 57, + 50, + 57, + 44, + 32, + 48, + 46, + 56, + 48, + 48, + 48, + 48, + 48, + 48, + 49, + 49, + 57, + 50, + 48, + 57, + 50, + 57, + 44, + 32, + 48, + 46, + 56, + 48, + 48, + 48, + 48, + 48, + 48, + 49, + 49, + 57, + 50, + 48, + 57, + 50, + 57, + 44, + 32, + 49, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 109, + 101, + 116, + 97, + 108, + 108, + 105, + 99, + 70, + 97, + 99, + 116, + 111, + 114, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 114, + 111, + 117, + 103, + 104, + 110, + 101, + 115, + 115, + 70, + 97, + 99, + 116, + 111, + 114, + 34, + 58, + 32, + 48, + 46, + 53, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 34, + 109, + 101, + 115, + 104, + 101, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 67, + 117, + 98, + 101, + 34, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 112, + 114, + 105, + 109, + 105, + 116, + 105, + 118, + 101, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 97, + 116, + 116, + 114, + 105, + 98, + 117, + 116, + 101, + 115, + 34, + 58, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 80, + 79, + 83, + 73, + 84, + 73, + 79, + 78, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 84, + 69, + 88, + 67, + 79, + 79, + 82, + 68, + 95, + 48, + 34, + 58, + 32, + 49, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 78, + 79, + 82, + 77, + 65, + 76, + 34, + 58, + 32, + 50, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 105, + 110, + 100, + 105, + 99, + 101, + 115, + 34, + 58, + 32, + 51, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 109, + 97, + 116, + 101, + 114, + 105, + 97, + 108, + 34, + 58, + 32, + 48, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 93, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 34, + 97, + 99, + 99, + 101, + 115, + 115, + 111, + 114, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 86, + 105, + 101, + 119, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 109, + 112, + 111, + 110, + 101, + 110, + 116, + 84, + 121, + 112, + 101, + 34, + 58, + 32, + 53, + 49, + 50, + 54, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 117, + 110, + 116, + 34, + 58, + 32, + 50, + 52, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 109, + 97, + 120, + 34, + 58, + 32, + 91, + 49, + 44, + 32, + 49, + 44, + 32, + 49, + 93, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 109, + 105, + 110, + 34, + 58, + 32, + 91, + 45, + 49, + 44, + 32, + 45, + 49, + 44, + 32, + 45, + 49, + 93, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 32, + 34, + 86, + 69, + 67, + 51, + 34, + 10, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 86, + 105, + 101, + 119, + 34, + 58, + 32, + 49, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 109, + 112, + 111, + 110, + 101, + 110, + 116, + 84, + 121, + 112, + 101, + 34, + 58, + 32, + 53, + 49, + 50, + 54, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 117, + 110, + 116, + 34, + 58, + 32, + 50, + 52, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 32, + 34, + 86, + 69, + 67, + 50, + 34, + 10, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 86, + 105, + 101, + 119, + 34, + 58, + 32, + 50, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 109, + 112, + 111, + 110, + 101, + 110, + 116, + 84, + 121, + 112, + 101, + 34, + 58, + 32, + 53, + 49, + 50, + 54, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 117, + 110, + 116, + 34, + 58, + 32, + 50, + 52, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 32, + 34, + 86, + 69, + 67, + 51, + 34, + 10, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 86, + 105, + 101, + 119, + 34, + 58, + 32, + 51, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 109, + 112, + 111, + 110, + 101, + 110, + 116, + 84, + 121, + 112, + 101, + 34, + 58, + 32, + 53, + 49, + 50, + 51, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 99, + 111, + 117, + 110, + 116, + 34, + 58, + 32, + 51, + 54, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 32, + 34, + 83, + 67, + 65, + 76, + 65, + 82, + 34, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 86, + 105, + 101, + 119, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + 34, + 58, + 32, + 50, + 56, + 56, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 79, + 102, + 102, + 115, + 101, + 116, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 97, + 114, + 103, + 101, + 116, + 34, + 58, + 32, + 51, + 52, + 57, + 54, + 50, + 10, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + 34, + 58, + 32, + 49, + 57, + 50, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 79, + 102, + 102, + 115, + 101, + 116, + 34, + 58, + 32, + 50, + 56, + 56, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 97, + 114, + 103, + 101, + 116, + 34, + 58, + 32, + 51, + 52, + 57, + 54, + 50, + 10, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + 34, + 58, + 32, + 50, + 56, + 56, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 79, + 102, + 102, + 115, + 101, + 116, + 34, + 58, + 32, + 52, + 56, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 97, + 114, + 103, + 101, + 116, + 34, + 58, + 32, + 51, + 52, + 57, + 54, + 50, + 10, + 32, + 32, + 32, + 32, + 125, + 44, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 34, + 58, + 32, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + 34, + 58, + 32, + 55, + 50, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 79, + 102, + 102, + 115, + 101, + 116, + 34, + 58, + 32, + 55, + 54, + 56, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 116, + 97, + 114, + 103, + 101, + 116, + 34, + 58, + 32, + 51, + 52, + 57, + 54, + 51, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 44, + 10, + 32, + 32, + 34, + 98, + 117, + 102, + 102, + 101, + 114, + 115, + 34, + 58, + 32, + 91, + 10, + 32, + 32, + 32, + 32, + 123, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + 34, + 58, + 32, + 56, + 52, + 48, + 44, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 117, + 114, + 105, + 34, + 58, + 32, + 34, + 100, + 97, + 116, + 97, + 58, + 97, + 112, + 112, + 108, + 105, + 99, + 97, + 116, + 105, + 111, + 110, + 47, + 111, + 99, + 116, + 101, + 116, + 45, + 115, + 116, + 114, + 101, + 97, + 109, + 59, + 98, + 97, + 115, + 101, + 54, + 52, + 44, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 65, + 103, + 80, + 119, + 65, + 65, + 65, + 68, + 56, + 65, + 65, + 67, + 65, + 47, + 65, + 65, + 65, + 65, + 80, + 119, + 65, + 65, + 73, + 68, + 56, + 65, + 65, + 65, + 65, + 47, + 65, + 65, + 68, + 65, + 80, + 103, + 65, + 65, + 65, + 68, + 56, + 65, + 65, + 77, + 65, + 43, + 65, + 65, + 65, + 65, + 80, + 119, + 65, + 65, + 119, + 68, + 52, + 65, + 65, + 65, + 65, + 47, + 65, + 65, + 65, + 103, + 80, + 119, + 65, + 65, + 103, + 68, + 52, + 65, + 65, + 67, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 103, + 65, + 65, + 73, + 68, + 56, + 65, + 65, + 73, + 65, + 43, + 65, + 65, + 68, + 65, + 80, + 103, + 65, + 65, + 103, + 68, + 52, + 65, + 65, + 77, + 65, + 43, + 65, + 65, + 67, + 65, + 80, + 103, + 65, + 65, + 119, + 68, + 52, + 65, + 65, + 73, + 65, + 43, + 65, + 65, + 65, + 103, + 80, + 119, + 65, + 65, + 81, + 68, + 56, + 65, + 65, + 67, + 65, + 47, + 65, + 65, + 66, + 65, + 80, + 119, + 65, + 65, + 89, + 68, + 56, + 65, + 65, + 65, + 65, + 47, + 65, + 65, + 65, + 65, + 80, + 103, + 65, + 65, + 65, + 68, + 56, + 65, + 65, + 77, + 65, + 43, + 65, + 65, + 66, + 65, + 80, + 119, + 65, + 65, + 119, + 68, + 52, + 65, + 65, + 69, + 65, + 47, + 65, + 65, + 65, + 103, + 80, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 89, + 68, + 56, + 65, + 65, + 73, + 65, + 43, + 65, + 65, + 65, + 65, + 80, + 103, + 65, + 65, + 103, + 68, + 52, + 65, + 65, + 77, + 65, + 43, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 119, + 68, + 52, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 80, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 67, + 47, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 68, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 103, + 76, + 56, + 65, + 65, + 65, + 67, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 73, + 65, + 47, + 65, + 65, + 67, + 65, + 118, + 119, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 65, + 67, + 65, + 65, + 81, + 65, + 79, + 65, + 66, + 81, + 65, + 65, + 81, + 65, + 85, + 65, + 65, + 99, + 65, + 67, + 103, + 65, + 71, + 65, + 66, + 73, + 65, + 67, + 103, + 65, + 83, + 65, + 66, + 89, + 65, + 70, + 119, + 65, + 84, + 65, + 65, + 119, + 65, + 70, + 119, + 65, + 77, + 65, + 66, + 65, + 65, + 68, + 119, + 65, + 68, + 65, + 65, + 107, + 65, + 68, + 119, + 65, + 74, + 65, + 66, + 85, + 65, + 66, + 81, + 65, + 67, + 65, + 65, + 103, + 65, + 66, + 81, + 65, + 73, + 65, + 65, + 115, + 65, + 69, + 81, + 65, + 78, + 65, + 65, + 65, + 65, + 69, + 81, + 65, + 65, + 65, + 65, + 81, + 65, + 34, + 10, + 32, + 32, + 32, + 32, + 125, + 10, + 32, + 32, + 93, + 10, + 125, + 10 + ] + } + ], + "format": { + "type": "gltf" + } + } + } +] diff --git a/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_flowchart.snap b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_flowchart.snap new file mode 100644 index 0000000000..ed9ba47bcb --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_flowchart.snap @@ -0,0 +1,6 @@ +--- +source: kcl/src/simulation_tests.rs +description: Artifact graph flowchart import_glob.kcl +extension: md +snapshot_kind: binary +--- diff --git a/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_flowchart.snap.md b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_flowchart.snap.md new file mode 100644 index 0000000000..13e5335097 --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_flowchart.snap.md @@ -0,0 +1,3 @@ +```mermaid +flowchart LR +``` diff --git a/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_mind_map.snap b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_mind_map.snap new file mode 100644 index 0000000000..b51658e9be --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_mind_map.snap @@ -0,0 +1,6 @@ +--- +source: kcl/src/simulation_tests.rs +description: Artifact graph mind map import_glob.kcl +extension: md +snapshot_kind: binary +--- diff --git a/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_mind_map.snap.md b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_mind_map.snap.md new file mode 100644 index 0000000000..32dc0f6d42 --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/artifact_graph_mind_map.snap.md @@ -0,0 +1,4 @@ +```mermaid +mindmap + root +``` diff --git a/src/wasm-lib/kcl/tests/import_foreign/ast.snap b/src/wasm-lib/kcl/tests/import_foreign/ast.snap new file mode 100644 index 0000000000..a432f94148 --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/ast.snap @@ -0,0 +1,71 @@ +--- +source: kcl/src/simulation_tests.rs +description: Result of parsing import_foreign.kcl +--- +{ + "Ok": { + "body": [ + { + "end": 36, + "path": { + "type": "Foreign", + "path": "../inputs/cube.gltf" + }, + "selector": { + "type": "None", + "alias": { + "end": 36, + "name": "cube", + "start": 32, + "type": "Identifier" + } + }, + "start": 0, + "type": "ImportStatement", + "type": "ImportStatement" + }, + { + "declaration": { + "end": 50, + "id": { + "end": 43, + "name": "model", + "start": 38, + "type": "Identifier" + }, + "init": { + "end": 50, + "name": "cube", + "start": 46, + "type": "Identifier", + "type": "Identifier" + }, + "start": 38, + "type": "VariableDeclarator" + }, + "end": 50, + "kind": "const", + "start": 38, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + } + ], + "end": 51, + "nonCodeMeta": { + "nonCodeNodes": { + "0": [ + { + "end": 38, + "start": 36, + "type": "NonCodeNode", + "value": { + "type": "newLine" + } + } + ] + }, + "startNodes": [] + }, + "start": 0 + } +} diff --git a/src/wasm-lib/kcl/tests/import_foreign/input.kcl b/src/wasm-lib/kcl/tests/import_foreign/input.kcl new file mode 100644 index 0000000000..23f5e20b65 --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/input.kcl @@ -0,0 +1,3 @@ +import "../inputs/cube.gltf" as cube + +model = cube diff --git a/src/wasm-lib/kcl/tests/import_foreign/ops.snap b/src/wasm-lib/kcl/tests/import_foreign/ops.snap new file mode 100644 index 0000000000..0db7d2bc2d --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/ops.snap @@ -0,0 +1,6 @@ +--- +source: kcl/src/simulation_tests.rs +description: Operations executed import_glob.kcl +snapshot_kind: text +--- +[] diff --git a/src/wasm-lib/kcl/tests/import_foreign/program_memory.snap b/src/wasm-lib/kcl/tests/import_foreign/program_memory.snap new file mode 100644 index 0000000000..58ad5e2b6b --- /dev/null +++ b/src/wasm-lib/kcl/tests/import_foreign/program_memory.snap @@ -0,0 +1,64 @@ +--- +source: kcl/src/simulation_tests.rs +description: Program memory after executing import_foreign.kcl +--- +{ + "environments": [ + { + "bindings": { + "HALF_TURN": { + "type": "Number", + "value": 180.0, + "__meta": [] + }, + "QUARTER_TURN": { + "type": "Number", + "value": 90.0, + "__meta": [] + }, + "THREE_QUARTER_TURN": { + "type": "Number", + "value": 270.0, + "__meta": [] + }, + "ZERO": { + "type": "Number", + "value": 0.0, + "__meta": [] + }, + "cube": { + "type": "Module", + "value": 1, + "__meta": [ + { + "sourceRange": [ + 0, + 36, + 0 + ] + } + ] + }, + "model": { + "type": "ImportedGeometry", + "id": "[uuid]", + "value": [ + "cube.gltf" + ], + "__meta": [ + { + "sourceRange": [ + 0, + 36, + 0 + ] + } + ] + } + }, + "parent": null + } + ], + "currentEnv": 0, + "return": null +} diff --git a/src/wasm-lib/kcl/tests/import_glob/ast.snap b/src/wasm-lib/kcl/tests/import_glob/ast.snap index adb68e2c47..e161ec22b7 100644 --- a/src/wasm-lib/kcl/tests/import_glob/ast.snap +++ b/src/wasm-lib/kcl/tests/import_glob/ast.snap @@ -7,7 +7,10 @@ description: Result of parsing import_glob.kcl "body": [ { "end": 35, - "path": "export_constant.kcl", + "path": { + "type": "Kcl", + "filename": "export_constant.kcl" + }, "selector": { "end": 8, "start": 7, diff --git a/src/wasm-lib/kcl/tests/import_side_effect/ast.snap b/src/wasm-lib/kcl/tests/import_side_effect/ast.snap index 451ec8bd4d..a77e1111ed 100644 --- a/src/wasm-lib/kcl/tests/import_side_effect/ast.snap +++ b/src/wasm-lib/kcl/tests/import_side_effect/ast.snap @@ -7,7 +7,10 @@ description: Result of parsing import_side_effect.kcl "body": [ { "end": 40, - "path": "export_side_effect.kcl", + "path": { + "type": "Kcl", + "filename": "export_side_effect.kcl" + }, "selector": { "type": "List", "items": [ diff --git a/src/wasm-lib/kcl/tests/import_whole/ast.snap b/src/wasm-lib/kcl/tests/import_whole/ast.snap index ac31106536..64ff0a399f 100644 --- a/src/wasm-lib/kcl/tests/import_whole/ast.snap +++ b/src/wasm-lib/kcl/tests/import_whole/ast.snap @@ -7,7 +7,10 @@ description: Result of parsing import_whole.kcl "body": [ { "end": 66, - "path": "exported_mod.kcl", + "path": { + "type": "Kcl", + "filename": "exported_mod.kcl" + }, "selector": { "type": "None", "alias": {