Merge branch 'main' into achalmers/kw-fn-sketches

This commit is contained in:
Adam Chalmers
2025-01-30 11:40:22 -06:00
49 changed files with 2644 additions and 319 deletions

2
.gitignore vendored
View File

@ -45,7 +45,7 @@ e2e/playwright/temp3.png
e2e/playwright/export-snapshots/*
!e2e/playwright/export-snapshots/*.png
/kcl-samples
/test-results/
/playwright-report/
/blob-report/

View File

@ -14,8 +14,6 @@ For formats lacking unit data (such as STL, OBJ, or PLY files), the default unit
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
```

View File

@ -94300,7 +94300,7 @@
{
"name": "import",
"summary": "Import a CAD file.",
"description": "**DEPRECATED** Prefer to use import statements.\n\nFor formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory.\n\nNote: The import command currently only works when using the native Modeling App.\n\nFor importing KCL functions using the `import` statement, see the docs on [KCL modules](/docs/kcl/modules).",
"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": [

View File

@ -323,6 +323,7 @@ export class KclManager {
await this.ensureWasmInit()
const { logs, errors, execState, isInterrupted } = await executeAst({
ast,
path: codeManager.currentFilePath || undefined,
engineCommandManager: this.engineCommandManager,
})

View File

@ -80,6 +80,10 @@ export default class CodeManager {
}))
}
get currentFilePath(): string | null {
return this._currentFilePath
}
updateCurrentFilePath(path: string) {
this._currentFilePath = path
}

View File

@ -59,27 +59,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
)

View File

@ -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()

View File

@ -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))
}

View File

@ -570,9 +570,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))
@ -594,6 +604,7 @@ export const executor = async (
}
const execOutcome: RustExecOutcome = await execute(
JSON.stringify(node),
path,
JSON.stringify(programMemoryOverride?.toRaw() || null),
JSON.stringify({ settings: jsAppSettings }),
engineCommandManager,

View File

@ -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
}

View File

@ -1710,7 +1710,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.31"
version = "0.2.32"
dependencies = [
"anyhow",
"approx 0.5.1",

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.2.31"
version = "0.2.32"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -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(),

View File

@ -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(())

View File

@ -131,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),
}
}
@ -142,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 {
@ -204,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(),
@ -215,9 +215,8 @@ 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 {
@ -1752,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 {
@ -1763,6 +1765,7 @@ impl Default for ExecutorSettings {
show_grid: false,
replay: None,
project_directory: None,
current_file: None,
}
}
}
@ -1776,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,
}
}
}
@ -1789,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,
}
}
}
@ -1802,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());
}
}
}
@ -2019,6 +2043,7 @@ impl ExecutorContext {
show_grid: false,
replay: None,
project_directory: None,
current_file: None,
},
None,
engine_addr,
@ -2578,7 +2603,20 @@ impl ExecutorContext {
let info = exec_state.global.module_infos[&module_id].clone();
match &info.repr {
ModuleRepr::Root => unreachable!(),
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(),
@ -3460,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

View File

@ -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")),
}
}

View File

@ -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 {
@ -779,6 +779,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";

View File

@ -118,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")
/// ```

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -1,12 +1,13 @@
---
source: kcl/src/simulation_tests.rs
description: Result of parsing import_cycle1.kcl
snapshot_kind: text
---
{
"Ok": {
"body": [
{
"end": 35,
"end": 69,
"path": {
"type": "Kcl",
"filename": "import_cycle2.kcl"
@ -16,29 +17,29 @@ description: Result of parsing import_cycle1.kcl
"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": {
@ -46,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": {
@ -72,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"
@ -116,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
}

View File

@ -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
╰────

View File

@ -1,3 +1,4 @@
@settings(defaultLengthUnit = mm)
import three from "import_cycle3.kcl"
export fn two = () => { return three() - 1 }

View File

@ -1,3 +1,4 @@
@settings(defaultLengthUnit = in)
import one from "input.kcl"
export fn three = () => { return one() + one() + one() }

View File

@ -1,3 +1,4 @@
@settings(defaultLengthUnit = in)
import two from "import_cycle2.kcl"
export fn one() {

View File

@ -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"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl/src/simulation_tests.rs
description: Artifact graph flowchart import_function_not_sketch.kcl
extension: md
snapshot_kind: binary
---

View File

@ -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
```

View File

@ -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
---

View File

@ -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
```

View 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
}
}

View File

@ -0,0 +1,6 @@
@settings(defaultLengthUnit = in)
import two from "my_functions.kcl"
export fn one() {
return two() - 1
}

View File

@ -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 }

View File

@ -0,0 +1,6 @@
---
source: kcl/src/simulation_tests.rs
description: Operations executed import_function_not_sketch.kcl
snapshot_kind: text
---
[]

View File

@ -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

View File

@ -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]"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl/src/simulation_tests.rs
description: Artifact graph flowchart import_side_effect.kcl
extension: md
snapshot_kind: binary
---

View File

@ -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
```

View File

@ -0,0 +1,6 @@
---
source: kcl/src/simulation_tests.rs
description: Artifact graph mind map import_side_effect.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,8 @@
```mermaid
mindmap
root
Plane
Path
Segment
Solid2d
```

View File

@ -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"
· ────────────────────────────────────────
╰────

View File

@ -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 }, %)

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);