Merge branch 'main' into nadro/gh-5157/center-rectangle-kcl-fix
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -44,7 +44,7 @@ e2e/playwright/temp3.png
|
||||
e2e/playwright/export-snapshots/*
|
||||
!e2e/playwright/export-snapshots/*.png
|
||||
|
||||
|
||||
/kcl-samples
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
|
@ -4,14 +4,16 @@ 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.
|
||||
|
||||
For importing KCL functions using the `import` statement, see the docs on [KCL modules](/docs/kcl/modules).
|
||||
|
||||
```js
|
||||
import(file_path: String, options?: ImportFormat) -> ImportedGeometry
|
||||
```
|
||||
|
@ -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)
|
||||
|
@ -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.",
|
||||
"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\" })",
|
||||
|
@ -322,6 +322,7 @@ export class KclManager {
|
||||
await this.ensureWasmInit()
|
||||
const { logs, errors, execState, isInterrupted } = await executeAst({
|
||||
ast,
|
||||
path: codeManager.currentFilePath || undefined,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
})
|
||||
|
||||
|
@ -80,6 +80,10 @@ export default class CodeManager {
|
||||
}))
|
||||
}
|
||||
|
||||
get currentFilePath(): string | null {
|
||||
return this._currentFilePath
|
||||
}
|
||||
|
||||
updateCurrentFilePath(path: string) {
|
||||
this._currentFilePath = path
|
||||
}
|
||||
|
@ -52,27 +52,22 @@ afterAll(async () => {
|
||||
} catch (e) {}
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
process.chdir('..')
|
||||
})
|
||||
|
||||
// The tests have to be sequential because we need to change directories
|
||||
// to support `import` working properly.
|
||||
// @ts-expect-error
|
||||
describe.sequential('Test KCL Samples from public Github repository', () => {
|
||||
// @ts-expect-error
|
||||
describe.sequential('when performing enginelessExecutor', () => {
|
||||
describe('Test KCL Samples from public Github repository', () => {
|
||||
describe('when performing enginelessExecutor', () => {
|
||||
manifest.forEach((file: KclSampleFile) => {
|
||||
// @ts-expect-error
|
||||
it.sequential(
|
||||
it(
|
||||
`should execute ${file.title} (${file.file}) successfully`,
|
||||
async () => {
|
||||
const [dirProject, fileKcl] =
|
||||
file.pathFromProjectDirectoryToFirstFile.split('/')
|
||||
process.chdir(dirProject)
|
||||
const code = await fs.readFile(fileKcl, 'utf-8')
|
||||
const code = await fs.readFile(
|
||||
file.pathFromProjectDirectoryToFirstFile,
|
||||
'utf-8'
|
||||
)
|
||||
const ast = assertParse(code)
|
||||
await enginelessExecutor(ast, programMemoryInit())
|
||||
await enginelessExecutor(
|
||||
ast,
|
||||
programMemoryInit(),
|
||||
file.pathFromProjectDirectoryToFirstFile
|
||||
)
|
||||
},
|
||||
files.length * 1000
|
||||
)
|
||||
|
@ -46,12 +46,14 @@ export const toolTips: Array<ToolTip> = [
|
||||
|
||||
export async function executeAst({
|
||||
ast,
|
||||
path,
|
||||
engineCommandManager,
|
||||
// If you set programMemoryOverride we assume you mean mock mode. Since that
|
||||
// is the only way to go about it.
|
||||
programMemoryOverride,
|
||||
}: {
|
||||
ast: Node<Program>
|
||||
path?: string
|
||||
engineCommandManager: EngineCommandManager
|
||||
programMemoryOverride?: ProgramMemory
|
||||
isInterrupted?: boolean
|
||||
@ -63,8 +65,8 @@ export async function executeAst({
|
||||
}> {
|
||||
try {
|
||||
const execState = await (programMemoryOverride
|
||||
? enginelessExecutor(ast, programMemoryOverride)
|
||||
: executor(ast, engineCommandManager))
|
||||
? enginelessExecutor(ast, programMemoryOverride, path)
|
||||
: executor(ast, engineCommandManager, path))
|
||||
|
||||
await engineCommandManager.waitForAllCommands()
|
||||
|
||||
|
@ -31,6 +31,9 @@ class FileSystemManager {
|
||||
}
|
||||
|
||||
async join(dir: string, path: string): Promise<string> {
|
||||
if (path.startsWith(dir)) {
|
||||
path = path.slice(dir.length)
|
||||
}
|
||||
return Promise.resolve(window.electron.path.join(dir, path))
|
||||
}
|
||||
|
||||
|
@ -567,9 +567,19 @@ export function sketchFromKclValue(
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a KCL program.
|
||||
* @param node The AST of the program to execute.
|
||||
* @param path The full path of the file being executed. Use `null` for
|
||||
* expressions that don't have a file, like expressions in the command bar.
|
||||
* @param programMemoryOverride If this is not `null`, this will be used as the
|
||||
* initial program memory, and the execution will be engineless (AKA mock
|
||||
* execution).
|
||||
*/
|
||||
export const executor = async (
|
||||
node: Node<Program>,
|
||||
engineCommandManager: EngineCommandManager,
|
||||
path?: string,
|
||||
programMemoryOverride: ProgramMemory | Error | null = null
|
||||
): Promise<ExecState> => {
|
||||
if (programMemoryOverride !== null && err(programMemoryOverride))
|
||||
@ -591,6 +601,7 @@ export const executor = async (
|
||||
}
|
||||
const execOutcome: RustExecOutcome = await execute(
|
||||
JSON.stringify(node),
|
||||
path,
|
||||
JSON.stringify(programMemoryOverride?.toRaw() || null),
|
||||
JSON.stringify({ settings: jsAppSettings }),
|
||||
engineCommandManager,
|
||||
|
@ -80,7 +80,8 @@ class MockEngineCommandManager {
|
||||
|
||||
export async function enginelessExecutor(
|
||||
ast: Node<Program>,
|
||||
pmo: ProgramMemory | Error = ProgramMemory.empty()
|
||||
pmo: ProgramMemory | Error = ProgramMemory.empty(),
|
||||
path?: string
|
||||
): Promise<ExecState> {
|
||||
if (pmo !== null && err(pmo)) return Promise.reject(pmo)
|
||||
|
||||
@ -90,7 +91,7 @@ export async function enginelessExecutor(
|
||||
}) as any as EngineCommandManager
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
mockEngineCommandManager.startNewSession()
|
||||
const execState = await executor(ast, mockEngineCommandManager, pmo)
|
||||
const execState = await executor(ast, mockEngineCommandManager, path, pmo)
|
||||
await mockEngineCommandManager.waitForAllCommands()
|
||||
return execState
|
||||
}
|
||||
|
6
src/wasm-lib/Cargo.lock
generated
6
src/wasm-lib/Cargo.lock
generated
@ -1710,7 +1710,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.30"
|
||||
version = "0.2.32"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1844,9 +1844,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad-modeling-cmds"
|
||||
version = "0.2.92"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5fc91d0cdacd1c2ba906f564e58ce07c70a5c471f19b0f4c0b67e754077bfdc"
|
||||
checksum = "67a993046541732e3c3ddd8a0364b55b7b138a9258beff353b6e7a043a41dce3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
@ -76,7 +76,7 @@ members = [
|
||||
[workspace.dependencies]
|
||||
http = "1"
|
||||
kittycad = { version = "0.3.28", default-features = false, features = ["js", "requests"] }
|
||||
kittycad-modeling-cmds = { version = "0.2.92", features = [
|
||||
kittycad-modeling-cmds = { version = "0.2.93", features = [
|
||||
"ts-rs",
|
||||
"websocket",
|
||||
] }
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.30"
|
||||
version = "0.2.32"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -197,10 +197,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
source_range: SourceRange,
|
||||
cmd: &ModelingCmd,
|
||||
) -> Result<(), crate::errors::KclError> {
|
||||
let execution_kind = self.execution_kind();
|
||||
if execution_kind.is_isolated() {
|
||||
return Err(KclError::Semantic(KclErrorDetails { message: "Cannot send modeling commands while importing. Wrap your code in a function if you want to import the file.".to_owned(), source_ranges: vec![source_range] }));
|
||||
}
|
||||
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
||||
cmd: cmd.clone(),
|
||||
cmd_id: id.into(),
|
||||
|
@ -462,12 +462,14 @@ impl ArtifactGraph {
|
||||
output.push_str("mindmap\n");
|
||||
output.push_str(" root\n");
|
||||
|
||||
let mut ids_seen: fnv::FnvHashSet<ArtifactId> = Default::default();
|
||||
|
||||
for (_, artifact) in &self.map {
|
||||
// Only the planes are roots.
|
||||
let Artifact::Plane(_) = artifact else {
|
||||
continue;
|
||||
};
|
||||
self.mind_map_artifact(&mut output, artifact, " ")?;
|
||||
self.mind_map_artifact(&mut output, &mut ids_seen, artifact, " ")?;
|
||||
}
|
||||
|
||||
output.push_str("```\n");
|
||||
@ -475,9 +477,16 @@ impl ArtifactGraph {
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn mind_map_artifact<W: Write>(&self, output: &mut W, artifact: &Artifact, prefix: &str) -> std::fmt::Result {
|
||||
fn mind_map_artifact<W: Write>(
|
||||
&self,
|
||||
output: &mut W,
|
||||
ids_seen: &mut fnv::FnvHashSet<ArtifactId>,
|
||||
artifact: &Artifact,
|
||||
prefix: &str,
|
||||
) -> std::fmt::Result {
|
||||
match artifact {
|
||||
Artifact::Plane(_plane) => {
|
||||
ids_seen.clear();
|
||||
writeln!(output, "{prefix}Plane")?;
|
||||
}
|
||||
Artifact::Path(_path) => {
|
||||
@ -515,11 +524,17 @@ impl ArtifactGraph {
|
||||
}
|
||||
}
|
||||
|
||||
if ids_seen.contains(&artifact.id()) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
ids_seen.insert(artifact.id());
|
||||
|
||||
for child_id in artifact.child_ids() {
|
||||
let Some(child_artifact) = self.map.get(&child_id) else {
|
||||
continue;
|
||||
};
|
||||
self.mind_map_artifact(output, child_artifact, &format!("{} ", prefix))?;
|
||||
self.mind_map_artifact(output, ids_seen, child_artifact, &format!("{} ", prefix))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
294
src/wasm-lib/kcl/src/execution/import.rs
Normal file
294
src/wasm-lib/kcl/src/execution/import.rs
Normal file
@ -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<InputFormat>,
|
||||
exec_state: &mut ExecState,
|
||||
ctxt: &ExecutorContext,
|
||||
source_range: SourceRange,
|
||||
) -> Result<PreImportedGeometry, KclError> {
|
||||
// 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<ImportedGeometry, KclError> {
|
||||
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<InputFormat> {
|
||||
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",
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ type Point2D = kcmc::shared::Point2d<f64>;
|
||||
type Point3D = kcmc::shared::Point3d<f64>;
|
||||
|
||||
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,
|
||||
@ -129,7 +131,7 @@ pub struct ExecOutcome {
|
||||
impl ExecState {
|
||||
pub fn new(exec_settings: &ExecutorSettings) -> Self {
|
||||
ExecState {
|
||||
global: GlobalState::new(),
|
||||
global: GlobalState::new(exec_settings),
|
||||
mod_local: ModuleState::new(exec_settings),
|
||||
}
|
||||
}
|
||||
@ -140,7 +142,7 @@ impl ExecState {
|
||||
// This is for the front end to keep track of the ids.
|
||||
id_generator.next_id = 0;
|
||||
|
||||
let mut global = GlobalState::new();
|
||||
let mut global = GlobalState::new(exec_settings);
|
||||
global.id_generator = id_generator;
|
||||
|
||||
*self = ExecState {
|
||||
@ -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<ModuleId, KclError> {
|
||||
// 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 {
|
||||
@ -221,7 +204,7 @@ impl ExecState {
|
||||
}
|
||||
|
||||
impl GlobalState {
|
||||
fn new() -> Self {
|
||||
fn new(settings: &ExecutorSettings) -> Self {
|
||||
let mut global = GlobalState {
|
||||
id_generator: Default::default(),
|
||||
path_to_source_id: Default::default(),
|
||||
@ -232,15 +215,14 @@ impl GlobalState {
|
||||
artifact_graph: Default::default(),
|
||||
};
|
||||
|
||||
// TODO(#4434): Use the top-level file's path.
|
||||
let root_path = PathBuf::new();
|
||||
let root_id = ModuleId::default();
|
||||
let root_path = settings.current_file.clone().unwrap_or_default();
|
||||
global.module_infos.insert(
|
||||
root_id,
|
||||
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 +1235,15 @@ pub struct ModuleInfo {
|
||||
id: ModuleId,
|
||||
/// Absolute path of the module's source file.
|
||||
path: std::path::PathBuf,
|
||||
parsed: Option<Node<AstProgram>>,
|
||||
repr: ModuleRepr,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub enum ModuleRepr {
|
||||
Root,
|
||||
Kcl(Node<AstProgram>),
|
||||
Foreign(import::PreImportedGeometry),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy, ts_rs::TS, JsonSchema)]
|
||||
@ -1761,6 +1751,9 @@ pub struct ExecutorSettings {
|
||||
/// The directory of the current project. This is used for resolving import
|
||||
/// paths. If None is given, the current working directory is used.
|
||||
pub project_directory: Option<PathBuf>,
|
||||
/// This is the path to the current file being executed.
|
||||
/// We use this for preventing cyclic imports.
|
||||
pub current_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for ExecutorSettings {
|
||||
@ -1772,6 +1765,7 @@ impl Default for ExecutorSettings {
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
project_directory: None,
|
||||
current_file: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1785,6 +1779,7 @@ impl From<crate::settings::types::Configuration> for ExecutorSettings {
|
||||
show_grid: config.settings.modeling.show_scale_grid,
|
||||
replay: None,
|
||||
project_directory: None,
|
||||
current_file: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1798,6 +1793,7 @@ impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSet
|
||||
show_grid: config.settings.modeling.show_scale_grid,
|
||||
replay: None,
|
||||
project_directory: None,
|
||||
current_file: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1811,6 +1807,25 @@ impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
|
||||
show_grid: modeling.show_scale_grid,
|
||||
replay: None,
|
||||
project_directory: None,
|
||||
current_file: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExecutorSettings {
|
||||
/// Add the current file path to the executor settings.
|
||||
pub fn with_current_file(&mut self, current_file: PathBuf) {
|
||||
// We want the parent directory of the file.
|
||||
if current_file.extension() == Some(std::ffi::OsStr::new("kcl")) {
|
||||
self.current_file = Some(current_file.clone());
|
||||
// Get the parent directory.
|
||||
if let Some(parent) = current_file.parent() {
|
||||
self.project_directory = Some(parent.to_path_buf());
|
||||
} else {
|
||||
self.project_directory = Some(std::path::PathBuf::from(""));
|
||||
}
|
||||
} else {
|
||||
self.project_directory = Some(current_file.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2028,6 +2043,7 @@ impl ExecutorContext {
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
project_directory: None,
|
||||
current_file: None,
|
||||
},
|
||||
None,
|
||||
engine_addr,
|
||||
@ -2511,33 +2527,68 @@ impl ExecutorContext {
|
||||
|
||||
async fn open_module(
|
||||
&self,
|
||||
path: &str,
|
||||
path: &ImportPath,
|
||||
exec_state: &mut ExecState,
|
||||
source_range: SourceRange,
|
||||
) -> Result<ModuleId, KclError> {
|
||||
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::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.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 +2602,64 @@ 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 => 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::<Vec<_>>()
|
||||
.join(" -> "),
|
||||
info.path.display()
|
||||
),
|
||||
source_ranges: vec![source_range],
|
||||
})),
|
||||
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]
|
||||
@ -2608,15 +2680,20 @@ impl ExecutorContext {
|
||||
let (result, _, _) = self
|
||||
.exec_module(module_id, exec_state, ExecutionKind::Normal, metadata.source_range)
|
||||
.await?;
|
||||
result.ok_or_else(|| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"Evaluating module `{}` as part of an assembly did not produce a result",
|
||||
identifier.name
|
||||
),
|
||||
source_ranges: vec![metadata.source_range, meta[0].source_range],
|
||||
})
|
||||
})?
|
||||
result.unwrap_or_else(|| {
|
||||
// The module didn't have a return value. Currently,
|
||||
// the only way to have a return value is with the final
|
||||
// statement being an expression statement.
|
||||
//
|
||||
// TODO: Make a warning when we support them in the
|
||||
// execution phase.
|
||||
let mut new_meta = vec![metadata.to_owned()];
|
||||
new_meta.extend(meta);
|
||||
KclValue::KclNone {
|
||||
value: Default::default(),
|
||||
meta: new_meta,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
value
|
||||
}
|
||||
@ -3421,6 +3498,16 @@ const inInches = 1.0 * inch()"#;
|
||||
assert_eq!(1.0, mem_get_json(exec_state.memory(), "inInches").as_f64().unwrap());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_unit_overriden_in() {
|
||||
let ast = r#"@settings(defaultLengthUnit = in)
|
||||
const inMm = 25.4 * mm()
|
||||
const inInches = 2.0 * inch()"#;
|
||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||
assert_eq!(1.0, mem_get_json(exec_state.memory(), "inMm").as_f64().unwrap().round());
|
||||
assert_eq!(2.0, mem_get_json(exec_state.memory(), "inInches").as_f64().unwrap());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_zero_param_fn() {
|
||||
let ast = r#"const sigmaAllow = 35000 // psi
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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<BoxNode<ImportStatement>> {
|
||||
};
|
||||
|
||||
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<BoxNode<ImportStatement>> {
|
||||
.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<BoxNode<ImportStatement>> {
|
||||
))
|
||||
}
|
||||
|
||||
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<ImportPath> {
|
||||
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<Node<ImportItem>> {
|
||||
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]
|
||||
|
@ -62,14 +62,14 @@ impl FromStr for NumericSuffix {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"_" => Ok(NumericSuffix::Count),
|
||||
"mm" => Ok(NumericSuffix::Mm),
|
||||
"cm" => Ok(NumericSuffix::Cm),
|
||||
"m" => Ok(NumericSuffix::M),
|
||||
"mm" | "millimeters" => Ok(NumericSuffix::Mm),
|
||||
"cm" | "centimeters" => Ok(NumericSuffix::Cm),
|
||||
"m" | "meters" => Ok(NumericSuffix::M),
|
||||
"inch" | "in" => Ok(NumericSuffix::Inch),
|
||||
"ft" => Ok(NumericSuffix::Ft),
|
||||
"yd" => Ok(NumericSuffix::Yd),
|
||||
"deg" => Ok(NumericSuffix::Deg),
|
||||
"rad" => Ok(NumericSuffix::Rad),
|
||||
"ft" | "feet" => Ok(NumericSuffix::Ft),
|
||||
"yd" | "yards" => Ok(NumericSuffix::Yd),
|
||||
"deg" | "degrees" => Ok(NumericSuffix::Deg),
|
||||
"rad" | "radians" => Ok(NumericSuffix::Rad),
|
||||
_ => Err(CompilationError::err(SourceRange::default(), "invalid unit of measure")),
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ async fn execute(test_name: &str, render_to_png: bool) {
|
||||
let exec_res = crate::test_server::execute_and_snapshot_ast(
|
||||
ast.into(),
|
||||
crate::settings::types::UnitLength::Mm,
|
||||
Some(Path::new("tests").join(test_name)),
|
||||
Some(Path::new("tests").join(test_name).join("input.kcl").to_owned()),
|
||||
)
|
||||
.await;
|
||||
match exec_res {
|
||||
@ -767,6 +767,27 @@ mod import_cycle1 {
|
||||
super::execute(TEST_NAME, false).await
|
||||
}
|
||||
}
|
||||
mod import_function_not_sketch {
|
||||
const TEST_NAME: &str = "import_function_not_sketch";
|
||||
|
||||
/// 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, true).await
|
||||
}
|
||||
}
|
||||
mod import_constant {
|
||||
const TEST_NAME: &str = "import_constant";
|
||||
|
||||
@ -872,6 +893,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";
|
||||
|
||||
|
@ -143,10 +143,8 @@ async fn inner_chamfer(
|
||||
radius: LengthUnit(data.length),
|
||||
tolerance: LengthUnit(DEFAULT_TOLERANCE), // We can let the user set this in the future.
|
||||
cut_type: CutType::Chamfer,
|
||||
// We pass in the command id as the face id.
|
||||
// So the resulting face of the fillet will be the same.
|
||||
// This is because that's how most other endpoints work.
|
||||
face_id: Some(id),
|
||||
// We make this a none so that we can remove it in the future.
|
||||
face_id: None,
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
@ -152,10 +152,8 @@ async fn inner_fillet(
|
||||
radius: LengthUnit(data.radius),
|
||||
tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||
cut_type: CutType::Fillet,
|
||||
// We pass in the command id as the face id.
|
||||
// So the resulting face of the fillet will be the same.
|
||||
// This is because that's how most other endpoints work.
|
||||
face_id: Some(id),
|
||||
// We make this a none so that we can remove it in the future.
|
||||
face_id: None,
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
@ -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<KclValue,
|
||||
|
||||
/// 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
|
||||
@ -144,9 +118,6 @@ pub async fn import(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
/// Note: The import command currently only works when using the native
|
||||
/// Modeling App.
|
||||
///
|
||||
/// For importing KCL functions using the `import` statement, see the docs on
|
||||
/// [KCL modules](/docs/kcl/modules).
|
||||
///
|
||||
/// ```no_run
|
||||
/// model = import("tests/inputs/cube.obj")
|
||||
/// ```
|
||||
@ -178,6 +149,7 @@ pub async fn import(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
#[stdlib {
|
||||
name = "import",
|
||||
feature_tree_operation = true,
|
||||
deprecated = true,
|
||||
tags = [],
|
||||
}]
|
||||
async fn inner_import(
|
||||
@ -193,232 +165,17 @@ async fn inner_import(
|
||||
}));
|
||||
}
|
||||
|
||||
// Make sure the file exists.
|
||||
if !args.ctx.fs.exists(&file_path, args.source_range).await? {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("File `{}` does not exist.", file_path),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
}
|
||||
|
||||
let ext_format = get_import_format_from_extension(file_path.split('.').last().ok_or_else(|| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: format!("No file extension found for `{}`", file_path),
|
||||
source_ranges: vec![args.source_range],
|
||||
})
|
||||
})?)
|
||||
.map_err(|e| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: e.to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
// Get the format type from the extension of the file.
|
||||
let format = if let Some(options) = options {
|
||||
// Validate the given format with the extension format.
|
||||
let format: InputFormat = options.into();
|
||||
validate_extension_format(ext_format, format.clone()).map_err(|e| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: e.to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
})
|
||||
})?;
|
||||
format
|
||||
} else {
|
||||
ext_format
|
||||
};
|
||||
|
||||
// Get the file contents for each file path.
|
||||
let file_contents = args.ctx.fs.read(&file_path, args.source_range).await.map_err(|e| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: e.to_string(),
|
||||
source_ranges: vec![args.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),
|
||||
source_ranges: vec![args.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![args.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),
|
||||
source_ranges: vec![args.source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
let bin_contents = args.ctx.fs.read(&bin_path, args.source_range).await.map_err(|e| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: e.to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
import_files.push(ImportFile {
|
||||
path: uri.to_string(),
|
||||
data: bin_contents,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if args.ctx.is_mock() {
|
||||
return Ok(ImportedGeometry {
|
||||
id: exec_state.next_uuid(),
|
||||
value: import_files.iter().map(|f| f.path.to_string()).collect(),
|
||||
meta: vec![args.source_range.into()],
|
||||
});
|
||||
}
|
||||
|
||||
let id = exec_state.next_uuid();
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::ImportFiles {
|
||||
files: import_files.clone(),
|
||||
format,
|
||||
}),
|
||||
let format = options.map(InputFormat::from);
|
||||
send_import_to_engine(
|
||||
import_foreign(
|
||||
std::path::Path::new(&file_path),
|
||||
format,
|
||||
exec_state,
|
||||
&args.ctx,
|
||||
args.source_range,
|
||||
)
|
||||
.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![args.source_range],
|
||||
}));
|
||||
};
|
||||
|
||||
Ok(ImportedGeometry {
|
||||
id: imported_files.object_id,
|
||||
value: import_files.iter().map(|f| f.path.to_string()).collect(),
|
||||
meta: vec![args.source_range.into()],
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the source format from the extension.
|
||||
fn get_import_format_from_extension(ext: &str) -> Result<InputFormat> {
|
||||
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
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ pub struct RequestBody {
|
||||
pub async fn execute_and_snapshot(
|
||||
code: &str,
|
||||
units: UnitLength,
|
||||
project_directory: Option<PathBuf>,
|
||||
current_file: Option<PathBuf>,
|
||||
) -> Result<image::DynamicImage, ExecError> {
|
||||
let ctx = new_context(units, true, project_directory).await?;
|
||||
let ctx = new_context(units, true, current_file).await?;
|
||||
let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
|
||||
let res = do_execute_and_snapshot(&ctx, program)
|
||||
.await
|
||||
@ -38,9 +38,9 @@ pub async fn execute_and_snapshot(
|
||||
pub async fn execute_and_snapshot_ast(
|
||||
ast: Program,
|
||||
units: UnitLength,
|
||||
project_directory: Option<PathBuf>,
|
||||
current_file: Option<PathBuf>,
|
||||
) -> Result<(ExecState, image::DynamicImage), ExecErrorWithState> {
|
||||
let ctx = new_context(units, true, project_directory).await?;
|
||||
let ctx = new_context(units, true, current_file).await?;
|
||||
let res = do_execute_and_snapshot(&ctx, ast).await;
|
||||
ctx.close().await;
|
||||
res
|
||||
@ -49,9 +49,9 @@ pub async fn execute_and_snapshot_ast(
|
||||
pub async fn execute_and_snapshot_no_auth(
|
||||
code: &str,
|
||||
units: UnitLength,
|
||||
project_directory: Option<PathBuf>,
|
||||
current_file: Option<PathBuf>,
|
||||
) -> Result<image::DynamicImage, ExecError> {
|
||||
let ctx = new_context(units, false, project_directory).await?;
|
||||
let ctx = new_context(units, false, current_file).await?;
|
||||
let program = Program::parse_no_errs(code).map_err(KclErrorWithOutputs::no_outputs)?;
|
||||
let res = do_execute_and_snapshot(&ctx, program)
|
||||
.await
|
||||
@ -88,7 +88,7 @@ async fn do_execute_and_snapshot(
|
||||
pub async fn new_context(
|
||||
units: UnitLength,
|
||||
with_auth: bool,
|
||||
project_directory: Option<PathBuf>,
|
||||
current_file: Option<PathBuf>,
|
||||
) -> Result<ExecutorContext, ConnectionError> {
|
||||
let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None)
|
||||
.map_err(ConnectionError::CouldNotMakeClient)?;
|
||||
@ -99,18 +99,20 @@ pub async fn new_context(
|
||||
client.set_base_url("https://api.zoo.dev".to_string());
|
||||
}
|
||||
|
||||
let ctx = ExecutorContext::new(
|
||||
&client,
|
||||
ExecutorSettings {
|
||||
units,
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
project_directory,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(ConnectionError::Establishing)?;
|
||||
let mut settings = ExecutorSettings {
|
||||
units,
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
project_directory: None,
|
||||
current_file: None,
|
||||
};
|
||||
if let Some(current_file) = current_file {
|
||||
settings.with_current_file(current_file);
|
||||
}
|
||||
let ctx = ExecutorContext::new(&client, settings)
|
||||
.await
|
||||
.map_err(ConnectionError::Establishing)?;
|
||||
Ok(ctx)
|
||||
}
|
||||
|
@ -661,8 +661,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 5.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -50,32 +50,6 @@ mindmap
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Wall
|
||||
Wall
|
||||
Cap Start
|
||||
|
@ -72,32 +72,6 @@ mindmap
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
@ -186,32 +160,6 @@ mindmap
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
@ -282,32 +230,6 @@ mindmap
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
|
@ -654,8 +654,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -671,8 +670,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -654,8 +654,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -671,8 +670,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -654,8 +654,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -654,8 +654,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -640,8 +640,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -657,8 +656,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 2.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -2487,8 +2487,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 1.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2504,8 +2503,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 1.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2521,8 +2519,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 1.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2538,8 +2535,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 1.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Error from executing fillet-and-shell.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
KCL Engine error
|
||||
|
||||
× engine: Modeling command failed: websocket closed early
|
||||
╭─[1:1]
|
||||
1 │ rpizWidth = 30
|
||||
· ▲
|
||||
2 │ rpizLength = 65
|
||||
╰────
|
@ -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": [
|
||||
|
@ -1,41 +1,45 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Result of parsing import_cycle1.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"Ok": {
|
||||
"body": [
|
||||
{
|
||||
"end": 35,
|
||||
"path": "import_cycle2.kcl",
|
||||
"end": 69,
|
||||
"path": {
|
||||
"type": "Kcl",
|
||||
"filename": "import_cycle2.kcl"
|
||||
},
|
||||
"selector": {
|
||||
"type": "List",
|
||||
"items": [
|
||||
{
|
||||
"alias": null,
|
||||
"end": 10,
|
||||
"end": 44,
|
||||
"name": {
|
||||
"end": 10,
|
||||
"end": 44,
|
||||
"name": "two",
|
||||
"start": 7,
|
||||
"start": 41,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"start": 7,
|
||||
"start": 41,
|
||||
"type": "ImportItem"
|
||||
}
|
||||
]
|
||||
},
|
||||
"start": 0,
|
||||
"start": 34,
|
||||
"type": "ImportStatement",
|
||||
"type": "ImportStatement"
|
||||
},
|
||||
{
|
||||
"declaration": {
|
||||
"end": 75,
|
||||
"end": 109,
|
||||
"id": {
|
||||
"end": 50,
|
||||
"end": 84,
|
||||
"name": "one",
|
||||
"start": 47,
|
||||
"start": 81,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
@ -43,25 +47,25 @@ description: Result of parsing import_cycle1.kcl
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"end": 73,
|
||||
"end": 107,
|
||||
"left": {
|
||||
"arguments": [],
|
||||
"callee": {
|
||||
"end": 67,
|
||||
"end": 101,
|
||||
"name": "two",
|
||||
"start": 64,
|
||||
"start": 98,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"end": 69,
|
||||
"start": 64,
|
||||
"end": 103,
|
||||
"start": 98,
|
||||
"type": "CallExpression",
|
||||
"type": "CallExpression"
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"end": 73,
|
||||
"end": 107,
|
||||
"raw": "1",
|
||||
"start": 72,
|
||||
"start": 106,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
@ -69,43 +73,43 @@ description: Result of parsing import_cycle1.kcl
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 64,
|
||||
"start": 98,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
},
|
||||
"end": 73,
|
||||
"start": 57,
|
||||
"end": 107,
|
||||
"start": 91,
|
||||
"type": "ReturnStatement",
|
||||
"type": "ReturnStatement"
|
||||
}
|
||||
],
|
||||
"end": 75,
|
||||
"start": 53
|
||||
"end": 109,
|
||||
"start": 87
|
||||
},
|
||||
"end": 75,
|
||||
"end": 109,
|
||||
"params": [],
|
||||
"start": 50,
|
||||
"start": 84,
|
||||
"type": "FunctionExpression",
|
||||
"type": "FunctionExpression"
|
||||
},
|
||||
"start": 47,
|
||||
"start": 81,
|
||||
"type": "VariableDeclarator"
|
||||
},
|
||||
"end": 75,
|
||||
"end": 109,
|
||||
"kind": "fn",
|
||||
"start": 37,
|
||||
"start": 71,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration",
|
||||
"visibility": "export"
|
||||
}
|
||||
],
|
||||
"end": 76,
|
||||
"end": 110,
|
||||
"nonCodeMeta": {
|
||||
"nonCodeNodes": {
|
||||
"0": [
|
||||
{
|
||||
"end": 37,
|
||||
"start": 35,
|
||||
"end": 71,
|
||||
"start": 69,
|
||||
"type": "NonCodeNode",
|
||||
"value": {
|
||||
"type": "newLine"
|
||||
@ -113,7 +117,42 @@ description: Result of parsing import_cycle1.kcl
|
||||
}
|
||||
]
|
||||
},
|
||||
"startNodes": []
|
||||
"startNodes": [
|
||||
{
|
||||
"end": 33,
|
||||
"start": 0,
|
||||
"type": "NonCodeNode",
|
||||
"value": {
|
||||
"type": "annotation",
|
||||
"name": {
|
||||
"end": 9,
|
||||
"name": "settings",
|
||||
"start": 1,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"end": 32,
|
||||
"key": {
|
||||
"end": 27,
|
||||
"name": "defaultLengthUnit",
|
||||
"start": 10,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"start": 10,
|
||||
"type": "ObjectProperty",
|
||||
"value": {
|
||||
"end": 32,
|
||||
"name": "in",
|
||||
"start": 30,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"start": 0
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Error from executing import_cycle1.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
KCL ImportCycle error
|
||||
|
||||
× import cycle: circular import of modules is not allowed: tests/
|
||||
│ import_cycle1/import_cycle2.kcl -> tests/import_cycle1/import_cycle3.kcl
|
||||
│ -> tests/import_cycle1/input.kcl -> tests/import_cycle1/import_cycle2.kcl
|
||||
╭─[1:1]
|
||||
1 │ import two from "import_cycle2.kcl"
|
||||
│ -> tests/import_cycle1/input.kcl
|
||||
╭─[2:1]
|
||||
1 │ @settings(defaultLengthUnit = in)
|
||||
2 │ import two from "import_cycle2.kcl"
|
||||
· ───────────────────────────────────
|
||||
2 │
|
||||
3 │
|
||||
╰────
|
||||
|
@ -1,3 +1,4 @@
|
||||
@settings(defaultLengthUnit = mm)
|
||||
import three from "import_cycle3.kcl"
|
||||
|
||||
export fn two = () => { return three() - 1 }
|
||||
|
@ -1,3 +1,4 @@
|
||||
@settings(defaultLengthUnit = in)
|
||||
import one from "input.kcl"
|
||||
|
||||
export fn three = () => { return one() + one() + one() }
|
||||
|
@ -1,3 +1,4 @@
|
||||
@settings(defaultLengthUnit = in)
|
||||
import two from "import_cycle2.kcl"
|
||||
|
||||
export fn one() {
|
||||
|
@ -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": [
|
||||
|
3281
src/wasm-lib/kcl/tests/import_foreign/artifact_commands.snap
Normal file
3281
src/wasm-lib/kcl/tests/import_foreign/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart import_glob.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,3 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
```
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph mind map import_glob.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,4 @@
|
||||
```mermaid
|
||||
mindmap
|
||||
root
|
||||
```
|
71
src/wasm-lib/kcl/tests/import_foreign/ast.snap
Normal file
71
src/wasm-lib/kcl/tests/import_foreign/ast.snap
Normal file
@ -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
|
||||
}
|
||||
}
|
3
src/wasm-lib/kcl/tests/import_foreign/input.kcl
Normal file
3
src/wasm-lib/kcl/tests/import_foreign/input.kcl
Normal file
@ -0,0 +1,3 @@
|
||||
import "../inputs/cube.gltf" as cube
|
||||
|
||||
model = cube
|
6
src/wasm-lib/kcl/tests/import_foreign/ops.snap
Normal file
6
src/wasm-lib/kcl/tests/import_foreign/ops.snap
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Operations executed import_glob.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
[]
|
64
src/wasm-lib/kcl/tests/import_foreign/program_memory.snap
Normal file
64
src/wasm-lib/kcl/tests/import_foreign/program_memory.snap
Normal file
@ -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
|
||||
}
|
@ -0,0 +1,833 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact commands import_function_not_sketch.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
[
|
||||
{
|
||||
"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,
|
||||
33,
|
||||
0
|
||||
],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "in"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
52,
|
||||
71,
|
||||
1
|
||||
],
|
||||
"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": 60.0,
|
||||
"clobber": false,
|
||||
"hide": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "enable_sketch_mode",
|
||||
"entity_id": "[uuid]",
|
||||
"ortho": false,
|
||||
"animated": false,
|
||||
"adjust_camera": false,
|
||||
"planar_normal": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "start_path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "move_path_pen",
|
||||
"path": "[uuid]",
|
||||
"to": {
|
||||
"x": 4.0,
|
||||
"y": 12.0,
|
||||
"z": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
109,
|
||||
124,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 2.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
130,
|
||||
146,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 0.0,
|
||||
"y": -6.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
152,
|
||||
168,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 4.0,
|
||||
"y": -6.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
174,
|
||||
190,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 0.0,
|
||||
"y": -6.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
196,
|
||||
218,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": -3.75,
|
||||
"y": -4.5,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
224,
|
||||
242,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 0.0,
|
||||
"y": -5.5,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
248,
|
||||
264,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": -2.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
270,
|
||||
278,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "close_path",
|
||||
"path_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
270,
|
||||
278,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "sketch_mode_disable"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "revolve",
|
||||
"target": "[uuid]",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"axis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"axis_is_2d": true,
|
||||
"angle": {
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "object_bring_to_front",
|
||||
"object_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_extrusion_face_info",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
284,
|
||||
310,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "in"
|
||||
}
|
||||
}
|
||||
]
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart import_function_not_sketch.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,82 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[77, 103, 1]"]
|
||||
3["Segment<br>[109, 124, 1]"]
|
||||
4["Segment<br>[130, 146, 1]"]
|
||||
5["Segment<br>[152, 168, 1]"]
|
||||
6["Segment<br>[174, 190, 1]"]
|
||||
7["Segment<br>[196, 218, 1]"]
|
||||
8["Segment<br>[224, 242, 1]"]
|
||||
9["Segment<br>[248, 264, 1]"]
|
||||
10["Segment<br>[270, 278, 1]"]
|
||||
11[Solid2d]
|
||||
end
|
||||
1["Plane<br>[52, 71, 1]"]
|
||||
12["Sweep Revolve<br>[284, 310, 1]"]
|
||||
13[Wall]
|
||||
14[Wall]
|
||||
15[Wall]
|
||||
16[Wall]
|
||||
17[Wall]
|
||||
18[Wall]
|
||||
19[Wall]
|
||||
20[Wall]
|
||||
21["SweepEdge Adjacent"]
|
||||
22["SweepEdge Adjacent"]
|
||||
23["SweepEdge Adjacent"]
|
||||
24["SweepEdge Adjacent"]
|
||||
25["SweepEdge Adjacent"]
|
||||
26["SweepEdge Adjacent"]
|
||||
27["SweepEdge Adjacent"]
|
||||
1 --- 2
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
2 --- 5
|
||||
2 --- 6
|
||||
2 --- 7
|
||||
2 --- 8
|
||||
2 --- 9
|
||||
2 --- 10
|
||||
2 ---- 12
|
||||
2 --- 11
|
||||
3 --- 13
|
||||
3 x--> 21
|
||||
4 --- 14
|
||||
4 --- 21
|
||||
5 --- 15
|
||||
5 --- 22
|
||||
6 --- 16
|
||||
6 --- 23
|
||||
7 --- 17
|
||||
7 --- 24
|
||||
8 --- 18
|
||||
8 --- 25
|
||||
9 --- 19
|
||||
9 --- 26
|
||||
10 --- 20
|
||||
10 --- 27
|
||||
12 --- 13
|
||||
12 --- 14
|
||||
12 --- 15
|
||||
12 --- 16
|
||||
12 --- 17
|
||||
12 --- 18
|
||||
12 --- 19
|
||||
12 --- 20
|
||||
12 <--x 3
|
||||
12 --- 21
|
||||
12 <--x 4
|
||||
12 <--x 5
|
||||
12 --- 22
|
||||
12 <--x 6
|
||||
12 --- 23
|
||||
12 <--x 7
|
||||
12 --- 24
|
||||
12 <--x 8
|
||||
12 --- 25
|
||||
12 <--x 9
|
||||
12 --- 26
|
||||
12 <--x 10
|
||||
12 --- 27
|
||||
```
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph mind map import_function_not_sketch.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,63 @@
|
||||
```mermaid
|
||||
mindmap
|
||||
root
|
||||
Plane
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Sweep Revolve
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
```
|
159
src/wasm-lib/kcl/tests/import_function_not_sketch/ast.snap
Normal file
159
src/wasm-lib/kcl/tests/import_function_not_sketch/ast.snap
Normal file
@ -0,0 +1,159 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Result of parsing import_function_not_sketch.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"Ok": {
|
||||
"body": [
|
||||
{
|
||||
"end": 68,
|
||||
"path": {
|
||||
"type": "Kcl",
|
||||
"filename": "my_functions.kcl"
|
||||
},
|
||||
"selector": {
|
||||
"type": "List",
|
||||
"items": [
|
||||
{
|
||||
"alias": null,
|
||||
"end": 44,
|
||||
"name": {
|
||||
"end": 44,
|
||||
"name": "two",
|
||||
"start": 41,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"start": 41,
|
||||
"type": "ImportItem"
|
||||
}
|
||||
]
|
||||
},
|
||||
"start": 34,
|
||||
"type": "ImportStatement",
|
||||
"type": "ImportStatement"
|
||||
},
|
||||
{
|
||||
"declaration": {
|
||||
"end": 108,
|
||||
"id": {
|
||||
"end": 83,
|
||||
"name": "one",
|
||||
"start": 80,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
"body": {
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"end": 106,
|
||||
"left": {
|
||||
"arguments": [],
|
||||
"callee": {
|
||||
"end": 100,
|
||||
"name": "two",
|
||||
"start": 97,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"end": 102,
|
||||
"start": 97,
|
||||
"type": "CallExpression",
|
||||
"type": "CallExpression"
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"end": 106,
|
||||
"raw": "1",
|
||||
"start": 105,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 97,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
},
|
||||
"end": 106,
|
||||
"start": 90,
|
||||
"type": "ReturnStatement",
|
||||
"type": "ReturnStatement"
|
||||
}
|
||||
],
|
||||
"end": 108,
|
||||
"start": 86
|
||||
},
|
||||
"end": 108,
|
||||
"params": [],
|
||||
"start": 83,
|
||||
"type": "FunctionExpression",
|
||||
"type": "FunctionExpression"
|
||||
},
|
||||
"start": 80,
|
||||
"type": "VariableDeclarator"
|
||||
},
|
||||
"end": 108,
|
||||
"kind": "fn",
|
||||
"start": 70,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration",
|
||||
"visibility": "export"
|
||||
}
|
||||
],
|
||||
"end": 109,
|
||||
"nonCodeMeta": {
|
||||
"nonCodeNodes": {
|
||||
"0": [
|
||||
{
|
||||
"end": 70,
|
||||
"start": 68,
|
||||
"type": "NonCodeNode",
|
||||
"value": {
|
||||
"type": "newLine"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"startNodes": [
|
||||
{
|
||||
"end": 33,
|
||||
"start": 0,
|
||||
"type": "NonCodeNode",
|
||||
"value": {
|
||||
"type": "annotation",
|
||||
"name": {
|
||||
"end": 9,
|
||||
"name": "settings",
|
||||
"start": 1,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"end": 32,
|
||||
"key": {
|
||||
"end": 27,
|
||||
"name": "defaultLengthUnit",
|
||||
"start": 10,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"start": 10,
|
||||
"type": "ObjectProperty",
|
||||
"value": {
|
||||
"end": 32,
|
||||
"name": "in",
|
||||
"start": 30,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"start": 0
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
@settings(defaultLengthUnit = in)
|
||||
import two from "my_functions.kcl"
|
||||
|
||||
export fn one() {
|
||||
return two() - 1
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
export part001 = startSketchOn('XY')
|
||||
|> startProfileAt([4, 12], %)
|
||||
|> line([2, 0], %)
|
||||
|> line([0, -6], %)
|
||||
|> line([4, -6], %)
|
||||
|> line([0, -6], %)
|
||||
|> line([-3.75, -4.5], %)
|
||||
|> line([0, -5.5], %)
|
||||
|> line([-2, 0], %)
|
||||
|> close(%)
|
||||
|> revolve({ axis = 'y' }, %) // default angle is 360
|
||||
|
||||
export fn two = () => { return 5 }
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Operations executed import_function_not_sketch.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
[]
|
@ -0,0 +1,956 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Program memory after executing import_function_not_sketch.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"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": []
|
||||
},
|
||||
"one": {
|
||||
"type": "Function",
|
||||
"expression": {
|
||||
"body": {
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"end": 106,
|
||||
"left": {
|
||||
"arguments": [],
|
||||
"callee": {
|
||||
"end": 100,
|
||||
"name": "two",
|
||||
"start": 97,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"end": 102,
|
||||
"start": 97,
|
||||
"type": "CallExpression",
|
||||
"type": "CallExpression"
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"end": 106,
|
||||
"raw": "1",
|
||||
"start": 105,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 97,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
},
|
||||
"end": 106,
|
||||
"start": 90,
|
||||
"type": "ReturnStatement",
|
||||
"type": "ReturnStatement"
|
||||
}
|
||||
],
|
||||
"end": 108,
|
||||
"start": 86
|
||||
},
|
||||
"end": 108,
|
||||
"params": [],
|
||||
"start": 83,
|
||||
"type": "FunctionExpression"
|
||||
},
|
||||
"memory": {
|
||||
"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": []
|
||||
},
|
||||
"two": {
|
||||
"type": "Function",
|
||||
"expression": {
|
||||
"body": {
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"end": 368,
|
||||
"moduleId": 1,
|
||||
"raw": "5",
|
||||
"start": 367,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 368,
|
||||
"moduleId": 1,
|
||||
"start": 360,
|
||||
"type": "ReturnStatement",
|
||||
"type": "ReturnStatement"
|
||||
}
|
||||
],
|
||||
"end": 370,
|
||||
"moduleId": 1,
|
||||
"start": 358
|
||||
},
|
||||
"end": 370,
|
||||
"moduleId": 1,
|
||||
"params": [],
|
||||
"start": 352,
|
||||
"type": "FunctionExpression"
|
||||
},
|
||||
"memory": {
|
||||
"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": []
|
||||
},
|
||||
"part001": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
109,
|
||||
124,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
130,
|
||||
146,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
152,
|
||||
168,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
174,
|
||||
190,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
196,
|
||||
218,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
224,
|
||||
242,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
248,
|
||||
264,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
270,
|
||||
278,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
109,
|
||||
124,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
4.0,
|
||||
12.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.0,
|
||||
12.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
130,
|
||||
146,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.0,
|
||||
12.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.0,
|
||||
6.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
152,
|
||||
168,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.0,
|
||||
6.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
174,
|
||||
190,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
-6.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
196,
|
||||
218,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
-6.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.25,
|
||||
-10.5
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
224,
|
||||
242,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.25,
|
||||
-10.5
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.25,
|
||||
-16.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
248,
|
||||
264,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.25,
|
||||
-16.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
4.25,
|
||||
-16.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
270,
|
||||
278,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
4.25,
|
||||
-16.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
4.0,
|
||||
12.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
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"__meta": []
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
4.0,
|
||||
12.0
|
||||
],
|
||||
"to": [
|
||||
4.0,
|
||||
12.0
|
||||
],
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"height": 0.0,
|
||||
"startCapId": null,
|
||||
"endCapId": null,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"parent": null
|
||||
}
|
||||
],
|
||||
"currentEnv": 0,
|
||||
"return": null
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
352,
|
||||
370,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parent": null
|
||||
}
|
||||
],
|
||||
"currentEnv": 0,
|
||||
"return": null
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
83,
|
||||
108,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"two": {
|
||||
"type": "Function",
|
||||
"expression": {
|
||||
"body": {
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"end": 368,
|
||||
"moduleId": 1,
|
||||
"raw": "5",
|
||||
"start": 367,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 368,
|
||||
"moduleId": 1,
|
||||
"start": 360,
|
||||
"type": "ReturnStatement",
|
||||
"type": "ReturnStatement"
|
||||
}
|
||||
],
|
||||
"end": 370,
|
||||
"moduleId": 1,
|
||||
"start": 358
|
||||
},
|
||||
"end": 370,
|
||||
"moduleId": 1,
|
||||
"params": [],
|
||||
"start": 352,
|
||||
"type": "FunctionExpression"
|
||||
},
|
||||
"memory": {
|
||||
"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": []
|
||||
},
|
||||
"part001": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
109,
|
||||
124,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
130,
|
||||
146,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
152,
|
||||
168,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
174,
|
||||
190,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
196,
|
||||
218,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
224,
|
||||
242,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
248,
|
||||
264,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
270,
|
||||
278,
|
||||
1
|
||||
],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
109,
|
||||
124,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
4.0,
|
||||
12.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.0,
|
||||
12.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
130,
|
||||
146,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.0,
|
||||
12.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.0,
|
||||
6.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
152,
|
||||
168,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.0,
|
||||
6.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
174,
|
||||
190,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
-6.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
196,
|
||||
218,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
-6.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.25,
|
||||
-10.5
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
224,
|
||||
242,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.25,
|
||||
-10.5
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
6.25,
|
||||
-16.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
248,
|
||||
264,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
6.25,
|
||||
-16.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
4.25,
|
||||
-16.0
|
||||
],
|
||||
"type": "ToPoint"
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
270,
|
||||
278,
|
||||
1
|
||||
]
|
||||
},
|
||||
"from": [
|
||||
4.25,
|
||||
-16.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
4.0,
|
||||
12.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
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"__meta": []
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
4.0,
|
||||
12.0
|
||||
],
|
||||
"to": [
|
||||
4.0,
|
||||
12.0
|
||||
],
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"height": 0.0,
|
||||
"startCapId": null,
|
||||
"endCapId": null,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
77,
|
||||
103,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"parent": null
|
||||
}
|
||||
],
|
||||
"currentEnv": 0,
|
||||
"return": null
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
352,
|
||||
370,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parent": null
|
||||
}
|
||||
],
|
||||
"currentEnv": 0,
|
||||
"return": null
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 95 KiB |
@ -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,
|
||||
|
@ -281,5 +281,123 @@ snapshot_kind: text
|
||||
"object_id": "[uuid]",
|
||||
"hidden": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
81,
|
||||
100,
|
||||
1
|
||||
],
|
||||
"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": 60.0,
|
||||
"clobber": false,
|
||||
"hide": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
106,
|
||||
149,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "enable_sketch_mode",
|
||||
"entity_id": "[uuid]",
|
||||
"ortho": false,
|
||||
"animated": false,
|
||||
"adjust_camera": false,
|
||||
"planar_normal": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
106,
|
||||
149,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "start_path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
106,
|
||||
149,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "move_path_pen",
|
||||
"path": "[uuid]",
|
||||
"to": {
|
||||
"x": 10.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
106,
|
||||
149,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "arc",
|
||||
"center": {
|
||||
"x": 0.0,
|
||||
"y": 0.0
|
||||
},
|
||||
"radius": 10.0,
|
||||
"start": {
|
||||
"unit": "degrees",
|
||||
"value": 0.0
|
||||
},
|
||||
"end": {
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"relative": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [
|
||||
106,
|
||||
149,
|
||||
1
|
||||
],
|
||||
"command": {
|
||||
"type": "close_path",
|
||||
"path_id": "[uuid]"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart import_side_effect.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,12 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[106, 149, 1]"]
|
||||
3["Segment<br>[106, 149, 1]"]
|
||||
4[Solid2d]
|
||||
end
|
||||
1["Plane<br>[81, 100, 1]"]
|
||||
1 --- 2
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
```
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Artifact graph mind map import_side_effect.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -0,0 +1,8 @@
|
||||
```mermaid
|
||||
mindmap
|
||||
root
|
||||
Plane
|
||||
Path
|
||||
Segment
|
||||
Solid2d
|
||||
```
|
@ -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": [
|
||||
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Error from executing import_side_effect.kcl
|
||||
---
|
||||
KCL Semantic error
|
||||
|
||||
× semantic: Error loading imported file. Open it to view more details.
|
||||
│ tests/import_side_effect/export_side_effect.kcl: Cannot send modeling
|
||||
│ commands while importing. Wrap your code in a function if you want to
|
||||
│ import the file.
|
||||
╭────
|
||||
1 │ import foo from "export_side_effect.kcl"
|
||||
· ────────────────────────────────────────
|
||||
╰────
|
@ -2,4 +2,4 @@ export fn foo = () => { return 0 }
|
||||
|
||||
// This interacts with the engine.
|
||||
part001 = startSketchOn('XY')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> circle({ center = [0, 0], radius = 10 }, %)
|
||||
|
112
src/wasm-lib/kcl/tests/import_side_effect/program_memory.snap
Normal file
112
src/wasm-lib/kcl/tests/import_side_effect/program_memory.snap
Normal file
@ -0,0 +1,112 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Program memory after executing import_side_effect.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"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": []
|
||||
},
|
||||
"foo": {
|
||||
"type": "Function",
|
||||
"expression": {
|
||||
"body": {
|
||||
"body": [
|
||||
{
|
||||
"argument": {
|
||||
"end": 32,
|
||||
"moduleId": 1,
|
||||
"raw": "0",
|
||||
"start": 31,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 32,
|
||||
"moduleId": 1,
|
||||
"start": 24,
|
||||
"type": "ReturnStatement",
|
||||
"type": "ReturnStatement"
|
||||
}
|
||||
],
|
||||
"end": 34,
|
||||
"moduleId": 1,
|
||||
"start": 22
|
||||
},
|
||||
"end": 34,
|
||||
"moduleId": 1,
|
||||
"params": [],
|
||||
"start": 16,
|
||||
"type": "FunctionExpression"
|
||||
},
|
||||
"memory": {
|
||||
"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": []
|
||||
}
|
||||
},
|
||||
"parent": null
|
||||
}
|
||||
],
|
||||
"currentEnv": 0,
|
||||
"return": null
|
||||
},
|
||||
"__meta": [
|
||||
{
|
||||
"sourceRange": [
|
||||
16,
|
||||
34,
|
||||
1
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parent": null
|
||||
}
|
||||
],
|
||||
"currentEnv": 0,
|
||||
"return": null
|
||||
}
|
@ -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": {
|
||||
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Error from executing import_whole.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
KCL Engine error
|
||||
|
||||
× engine: Modeling command failed: websocket closed early
|
||||
╭─[1:1]
|
||||
1 │ import "exported_mod.kcl" as foo
|
||||
· ▲
|
||||
2 │
|
||||
╰────
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Error from executing kittycad_svg.kcl
|
||||
snapshot_kind: text
|
||||
---
|
||||
KCL Engine error
|
||||
|
||||
× engine: Modeling command failed: websocket closed early
|
||||
╭─[1:1]
|
||||
1 │ svg = startSketchOn('XY')
|
||||
· ▲
|
||||
2 │ |> startProfileAt([0, 0], %)
|
||||
╰────
|
@ -782,8 +782,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 5.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -799,8 +798,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 5.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1009,8 +1007,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 5.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1026,8 +1023,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 5.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -43,34 +43,8 @@ mindmap
|
||||
SweepEdge Adjacent
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
EdgeCut Fillet
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
EdgeCut Fillet
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Cap Start
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
|
@ -675,8 +675,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 20.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -692,8 +691,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 50.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "chamfer",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "chamfer"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -709,8 +707,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 50.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "chamfer",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "chamfer"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -675,8 +675,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 20.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -692,8 +691,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 50.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "chamfer",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "chamfer"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -709,8 +707,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 50.0,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "chamfer",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "chamfer"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -57,39 +57,6 @@ mindmap
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Cap Start
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Cap Start
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
|
@ -766,8 +766,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 0.25,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -783,8 +782,7 @@ snapshot_kind: text
|
||||
"edge_id": "[uuid]",
|
||||
"radius": 0.5707134902949093,
|
||||
"tolerance": 0.0000001,
|
||||
"cut_type": "fillet",
|
||||
"face_id": "[uuid]"
|
||||
"cut_type": "fillet"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -63,39 +63,6 @@ mindmap
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Path
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Wall
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Segment
|
||||
Sweep Extrusion
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
Cap End
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
SweepEdge Opposite
|
||||
SweepEdge Adjacent
|
||||
Solid2d
|
||||
Wall
|
||||
Wall
|
||||
Wall
|
||||
|
@ -58,6 +58,7 @@ pub async fn clear_scene_and_bust_cache(
|
||||
#[wasm_bindgen]
|
||||
pub async fn execute(
|
||||
program_ast_json: &str,
|
||||
path: Option<String>,
|
||||
program_memory_override_str: &str,
|
||||
settings: &str,
|
||||
engine_manager: kcl_lib::wasm_engine::EngineCommandManager,
|
||||
@ -73,11 +74,16 @@ pub async fn execute(
|
||||
// You cannot override the memory in non-mock mode.
|
||||
let is_mock = program_memory_override.is_some();
|
||||
|
||||
let settings: kcl_lib::Configuration = serde_json::from_str(settings).map_err(|e| e.to_string())?;
|
||||
let config: kcl_lib::Configuration = serde_json::from_str(settings).map_err(|e| e.to_string())?;
|
||||
let mut settings: kcl_lib::ExecutorSettings = config.into();
|
||||
if let Some(path) = path {
|
||||
settings.with_current_file(std::path::PathBuf::from(path));
|
||||
}
|
||||
|
||||
let ctx = if is_mock {
|
||||
kcl_lib::ExecutorContext::new_mock(fs_manager, settings.into()).await?
|
||||
kcl_lib::ExecutorContext::new_mock(fs_manager, settings).await?
|
||||
} else {
|
||||
kcl_lib::ExecutorContext::new(engine_manager, fs_manager, settings.into()).await?
|
||||
kcl_lib::ExecutorContext::new(engine_manager, fs_manager, settings).await?
|
||||
};
|
||||
|
||||
let mut exec_state = ExecState::new(&ctx.settings);
|
||||
|
Reference in New Issue
Block a user