Compare commits

...

92 Commits

Author SHA1 Message Date
8210663923 replicate bad error 2023-11-10 05:55:57 +11:00
7272cc9fbd Describe Rust version for devs (#1044)
Fixes #1042
2023-11-09 17:01:52 +00:00
b925ed9b65 KCL stdlib and circle function (#1029)
Allows stdlib functions to be written as KCL, not as Rust. 

Rust stdlib functions will hereafter be referred to as "core" not "std".

Right now the only stdlib function I implemented is a circle function (it's a wrapper around the core arc function which sets the arc's start/end to 0 and 360 respectively). I know I want to change this function as soon as KCL has enums, which is my next task. So, I don't want users to start using this right away. To that end, I've named this function "unstable_stdlib_circle" not "circle". Once the function is ready to be stabilized, I can rename it to just "circle".

Note that this PR modifies the existing "sketch and extrude a cylinder" KCL test so that instead of using a user-defined circle function, it uses the unstable_stdlib_circle function now. And the twenty-twenty tests pass, so we know my stdlib is working.

https://github.com/KittyCAD/modeling-app/issues/922
2023-11-09 09:58:20 -06:00
0db5db2181 Bump js-sys from 0.3.64 to 0.3.65 in /src/wasm-lib (#980)
Bumps [js-sys](https://github.com/rustwasm/wasm-bindgen) from 0.3.64 to 0.3.65.
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/commits)

---
updated-dependencies:
- dependency-name: js-sys
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 23:41:53 -06:00
898e3db9d1 AST function nodes no longer have stdlib function members (#1031)
* AST function nodes no longer have stdlib function members

IMO the AST should not need an actual pointer to a stdlib function -- that is a completely separate concern from the AST.

Instead, the AST nodes can just store function names, and the executor will have a stdlib which it can look up those names in.

* Fix tests

* Update snapshot tests
2023-11-08 20:23:59 -06:00
d337ac2546 Test with a circle function (#1030) 2023-11-08 15:06:41 -06:00
371d8e08f7 Refactor the call_fn fn to be more readable (#1028) 2023-11-08 13:44:31 -06:00
338c43a29d Fix auto-version in nightly builds (#1026)
* WIP Fix auto-version in nightly builds
Fixes #1015

* WIP

* Revert "WIP"

This reverts commit 7838bf1298.

* Need to update src-tauri/tauri.release.conf.json after CI changes

* Fixes just to test

* Clean up after tests
2023-11-08 13:58:37 +00:00
52bb5a2657 Bump @sentry/react from 7.65.0 to 7.77.0 (#977)
Bumps [@sentry/react](https://github.com/getsentry/sentry-javascript) from 7.65.0 to 7.77.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.65.0...7.77.0)

---
updated-dependencies:
- dependency-name: "@sentry/react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 10:39:40 +00:00
1b6a06d266 Bump vscode-languageserver-protocol from 3.17.3 to 3.17.5 (#978)
Bumps [vscode-languageserver-protocol](https://github.com/Microsoft/vscode-languageserver-node/tree/HEAD/protocol) from 3.17.3 to 3.17.5.
- [Commits](https://github.com/Microsoft/vscode-languageserver-node/commits/release/types/3.17.5/protocol)

---
updated-dependencies:
- dependency-name: vscode-languageserver-protocol
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 05:28:24 -05:00
c68d4778a5 Bump @tauri-apps/api from 1.5.0 to 1.5.1 (#979)
Bumps [@tauri-apps/api](https://github.com/tauri-apps/tauri) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/@tauri-apps/api-v1.5...@tauri-apps/api-v1.5.1)

---
updated-dependencies:
- dependency-name: "@tauri-apps/api"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 05:28:01 -05:00
a8abea4fb5 Bump eslint from 8.46.0 to 8.53.0 (#1001)
Bumps [eslint](https://github.com/eslint/eslint) from 8.46.0 to 8.53.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.46.0...v8.53.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 05:27:13 -05:00
a0678d22a8 fix epsilon bug (#1025) 2023-11-08 09:27:53 +00:00
acbfae2e65 Bump wasm-bindgen from 0.2.87 to 0.2.88 in /src/wasm-lib (#981)
Bumps [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) from 0.2.87 to 0.2.88.
- [Release notes](https://github.com/rustwasm/wasm-bindgen/releases)
- [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustwasm/wasm-bindgen/compare/0.2.87...0.2.88)

---
updated-dependencies:
- dependency-name: wasm-bindgen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 23:56:23 -06:00
1e1bec6a8a Bump winnow (#1024) 2023-11-07 23:55:45 -06:00
06462b5a65 Bump syn from 2.0.38 to 2.0.39 in /src/wasm-lib (#1000)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.38 to 2.0.39.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.38...2.0.39)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 22:45:58 -06:00
2f292fb1be Bump tauri-plugin-fs-extra from 11048fd to 6865299 in /src-tauri (#1023)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `11048fd` to `6865299`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](11048fd997...6865299149)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 22:45:20 -06:00
8184e7b376 Bump serde from 1.0.190 to 1.0.192 in /src-tauri (#1009)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.190 to 1.0.192.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.190...v1.0.192)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 22:45:03 -06:00
b1084cbf80 Bump serde from 1.0.190 to 1.0.192 in /src/wasm-lib (#1012)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.190 to 1.0.192.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.190...v1.0.192)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 22:44:55 -06:00
548b45905e Cut release v0.11.3 (#1020)
cut release v0.11.3
2023-11-08 12:57:00 +11:00
141fd2f3f1 fix variables panel and others (#1021) 2023-11-08 01:27:43 +00:00
604d931962 selections fix follow up (#1019) 2023-11-07 23:10:30 +00:00
b1668410f8 Neaten up stdlib code (#1017) 2023-11-07 12:12:18 -06:00
13176cec38 Cut release v0.11.2 (#1005)
* Cut release v0.11.2

* Replace 'release' with '*' for artifact upload

* New logic to prevent top-level artifact.zip changes

* Fix upload

---------

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
2023-11-07 05:20:26 -05:00
3a59ae13b6 fix selections (#1013) 2023-11-07 07:21:32 +00:00
57c2481943 unused imports (#1011) 2023-11-07 03:29:50 +00:00
a1c555c51e clear errors on good parse (#1008) 2023-11-07 02:02:44 +00:00
4d520541be Build release & sign only on merge / release / release PR (#991)
* Add env variable for release || schedule || Cut out v PR

* Skip Windows, Apple, and Tauri Updater signing

* Add tauri args to bypass updater on debug

* Trying to address includeRelease and includeDebug issues

* WIP

* Clean up, fix bool eval

* -c to --config

* Remove src-tauri

* inline config

* Cleanup

* Remove concurrency block

* Test release

* Escape backslash

* Clean up

* Add back concurrency and BUILD_RELEASE eval

* Back to build:wasm (no speed impr noticed)

* Adam's suggestions

Co-authored-by: Adam Chalmers <adam.chalmers@kittycad.io>

* New logic to prevent top-level artifact.zip changes

---------

Co-authored-by: Adam Chalmers <adam.chalmers@kittycad.io>
2023-11-06 19:51:32 -05:00
82586f002b Test Jess's KCL error (#1004) 2023-11-06 14:01:51 -06:00
4bd08f7444 safe parse (#996)
* safe parse

* use safe parse on mouse up, stream
2023-11-06 06:47:45 +00:00
6b2603b1c4 don't overwrite current file on onboarding-replay (#1003)
don't over write file on onboarding
2023-11-06 04:03:21 +00:00
af49bebde3 compare formated asts before execute (#1002) 2023-11-06 03:43:01 +00:00
ca056996fd stop double execute on project open (#997) 2023-11-06 14:33:19 +11:00
34163da361 start of fixing changing files and cleaning up after execute (#897)
* start of fixing changing files and cleaning up after execute

* stop constraints from leaving artifacts

* don't write file on initial load
2023-11-06 11:49:13 +11:00
7c22bac638 Remove unwraps from binary expression algorithm (#992) 2023-11-03 13:30:19 -05:00
37a65b166b Fix silly mistakes in previous CI.yml PRs (#988)
* Fix silly mistakes in previous CI.yml PRs

This is what happens when I code before my morning matcha

Part of #987
2023-11-02 12:34:38 -05:00
1189f272ba Use debug builds for wasm-pack on PRs (#986) 2023-11-02 09:55:58 -05:00
ca5bc880dc Build tauri app in debug mode on PRs, release mode on releases (#985)
Build tauri app in debug mode on PRs, release mode on merges.

Release builds are very slow and should only be used for actual releases. Fast debug builds should be used for CI on PRs.
2023-11-02 09:55:36 -05:00
828daba304 Tweak Codespell CI (#975)
Ensure codespell CI job actually catches typos
2023-11-01 23:35:41 +00:00
0b9ba55bb4 Nicer error messages for unknown tokens (#974) 2023-11-01 23:08:22 +00:00
2d2a85ae7d remove view change from debug panel (#866)
remove view change from debug
2023-11-01 23:03:58 +00:00
cc57a302cc Update twenty-twenty (#973)
Due to engine PR #1566
2023-11-01 22:35:17 +00:00
fdbfd0c4b6 Fix typos (#972)
* Update twenty-twenty

Due to engine PR #1566

* Fix typos
2023-11-01 22:34:54 +00:00
2e419907e6 Tokenizing fallibility (#883)
Tokenization tracks invalid tokens and produces a nice error about them

---------

Co-authored-by: Adam Chalmers <adam.chalmers@kittycad.io>
2023-11-01 17:20:49 -05:00
3d0c5c10b0 KCL literals are typed, not JSON values (#971)
We now control the KCL type system instead of reusing JSON's type system.
2023-11-01 13:52:50 -05:00
4d47c067b7 Snapshot testing for parser (#969)
See https://docs.rs/insta for more.
2023-11-01 12:40:40 -05:00
3b3b5371eb Bump wasm-streams from 0.3.0 to 0.4.0 in /src/wasm-lib (#961)
Bumps [wasm-streams](https://github.com/MattiasBuelens/wasm-streams) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/MattiasBuelens/wasm-streams/releases)
- [Changelog](https://github.com/MattiasBuelens/wasm-streams/blob/main/CHANGELOG.md)
- [Commits](https://github.com/MattiasBuelens/wasm-streams/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: wasm-streams
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 08:43:18 -05:00
3ea77f8e1e Bump zustand from 4.4.0 to 4.4.5 (#963)
Bumps [zustand](https://github.com/pmndrs/zustand) from 4.4.0 to 4.4.5.
- [Release notes](https://github.com/pmndrs/zustand/releases)
- [Commits](https://github.com/pmndrs/zustand/compare/v4.4.0...v4.4.5)

---
updated-dependencies:
- dependency-name: zustand
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2023-11-01 09:14:57 -04:00
4fa7c07e54 Bump @uiw/react-codemirror from 4.21.13 to 4.21.20 (#967)
Bumps [@uiw/react-codemirror](https://github.com/uiwjs/react-codemirror) from 4.21.13 to 4.21.20.
- [Release notes](https://github.com/uiwjs/react-codemirror/releases)
- [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.21.13...v4.21.20)

---
updated-dependencies:
- dependency-name: "@uiw/react-codemirror"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2023-11-01 09:14:04 -04:00
c66a96a333 Bump @testing-library/react from 13.4.0 to 14.0.0 (#965)
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 13.4.0 to 14.0.0.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v13.4.0...v14.0.0)

---
updated-dependencies:
- dependency-name: "@testing-library/react"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 07:42:24 -04:00
4196ff91ac Bump vite from 4.4.9 to 4.5.0 (#966)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.4.9 to 4.5.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.5.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 07:41:58 -04:00
cf66b93963 Fix most Github Actions 'annotations' in PRs (#417)
* Fix Github Actions 'annotations' in PRs
Fixes #383

* Fix the React Hooks complains, and _app for rust

* Revert "Fix the React Hooks complains, and _app for rust"

This reverts commit 4a2ff925e5.

* Add back prettier fix and rust _app

* Fmt

* More annotation fixes

* More non-hooks fixes

* Rollback with eslint rule

* Add APPLE_TEAM_ID secret

* Revert "Add APPLE_TEAM_ID secret"

This reverts commit 346aaff5f4.

* More fixes
2023-11-01 07:39:31 -04:00
0b0219b810 Add repository field to Cargo.toml (#960) 2023-10-31 18:24:19 -05:00
36c7fcf6d7 Add a basic tauri e2e test on Linux (#923)
* WIP e2e test

* Working test on Linux

* Clean up

* Add to CI

* Fix

* Install tauri-driver

* Migrate to ubuntu-latest

* Add button check and click

* Update name

* Separate job for e2e test

* Fix path

* Fix perms

* Fix perms

* Single build-test-apps job

* Lint wdio file
2023-10-31 18:30:24 -04:00
023c3cbb90 New math parser (#956)
* New math parser

* Remove old parser

* Comments

* Move tests into parser_impl, remove dead code

* Backport some math tests
2023-10-31 14:16:18 -05:00
387f7e0912 New benchmark for parsing binary expressions (#957) 2023-10-31 18:04:24 +00:00
9b55b1fd12 Bump serde_json from 1.0.107 to 1.0.108 in /src-tauri (#954)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.107 to 1.0.108.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.107...v1.0.108)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2023-10-31 09:58:27 -05:00
4b6662169c Bump tauri-plugin-fs-extra from 68d77f9 to 11048fd in /src-tauri (#955)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `68d77f9` to `11048fd`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](68d77f999c...11048fd997)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:50:50 -04:00
d36abfcb3d Bump serde_json from 1.0.107 to 1.0.108 in /src/wasm-lib (#953)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.107 to 1.0.108.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.107...v1.0.108)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:50:07 -04:00
9002ae9efb Bump winnow from 0.5.17 to 0.5.18 in /src/wasm-lib (#952)
Bumps [winnow](https://github.com/winnow-rs/winnow) from 0.5.17 to 0.5.18.
- [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md)
- [Commits](https://github.com/winnow-rs/winnow/compare/v0.5.17...v0.5.18)

---
updated-dependencies:
- dependency-name: winnow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:49:51 -04:00
4deea25394 Bump @codemirror/autocomplete from 6.9.0 to 6.10.2 (#951)
Bumps [@codemirror/autocomplete](https://github.com/codemirror/autocomplete) from 6.9.0 to 6.10.2.
- [Changelog](https://github.com/codemirror/autocomplete/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/autocomplete/compare/6.9.0...6.10.2)

---
updated-dependencies:
- dependency-name: "@codemirror/autocomplete"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:49:15 -04:00
b5940d2cb7 Bump @tauri-apps/cli from 1.5.2 to 1.5.6 (#950)
Bumps [@tauri-apps/cli](https://github.com/tauri-apps/tauri) from 1.5.2 to 1.5.6.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/@tauri-apps/cli-v1.5.2...@tauri-apps/cli-v1.5.6)

---
updated-dependencies:
- dependency-name: "@tauri-apps/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:48:51 -04:00
932b467c1e Bump @testing-library/user-event from 13.5.0 to 14.5.1 (#949)
Bumps [@testing-library/user-event](https://github.com/testing-library/user-event) from 13.5.0 to 14.5.1.
- [Release notes](https://github.com/testing-library/user-event/releases)
- [Changelog](https://github.com/testing-library/user-event/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/user-event/compare/v13.5.0...v14.5.1)

---
updated-dependencies:
- dependency-name: "@testing-library/user-event"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:48:34 -04:00
7c7f5c81c4 Bump web-vitals from 2.1.4 to 3.5.0 (#948)
Bumps [web-vitals](https://github.com/GoogleChrome/web-vitals) from 2.1.4 to 3.5.0.
- [Changelog](https://github.com/GoogleChrome/web-vitals/blob/main/CHANGELOG.md)
- [Commits](https://github.com/GoogleChrome/web-vitals/compare/v2.1.4...v3.5.0)

---
updated-dependencies:
- dependency-name: web-vitals
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:48:05 -04:00
066b4f3e06 Bump typescript from 4.9.5 to 5.2.2 (#778)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.9.5 to 5.2.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.9.5...v5.2.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 06:47:34 -04:00
c6067bfc7a Bump kittycad from 0.2.38 to 0.2.41 in /src-tauri (#935)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.38 to 0.2.41.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.38...v0.2.41)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 22:22:05 -05:00
2018f0d517 Bump actions/setup-node from 3 to 4 (#924)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 22:21:57 -05:00
74aae3d15f Bump openapitor from 57b4d8b to 1b2562f in /src/wasm-lib (#938)
Bumps [openapitor](https://github.com/KittyCAD/kittycad.rs) from `57b4d8b` to `1b2562f`.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](57b4d8b168...1b2562f4b3)

---
updated-dependencies:
- dependency-name: openapitor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 22:21:35 -05:00
812f419e75 Bump serde from 1.0.189 to 1.0.190 in /src/wasm-lib (#941)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.189 to 1.0.190.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.189...v1.0.190)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 22:21:23 -05:00
5ec8cc69db Bump tauri-plugin-fs-extra from 9b20f28 to 68d77f9 in /src-tauri (#942)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `9b20f28` to `68d77f9`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](9b20f28d74...68d77f999c)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 22:21:14 -05:00
a5302b6e0e Nitpick my Winnow code (#946) 2023-10-30 22:20:37 -05:00
2114cc0d94 Bump @babel/traverse from 7.22.8 to 7.23.2 (#879)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.8 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:45:36 -04:00
2471ce1aba Bump swr from 2.2.0 to 2.2.2 (#332)
Bumps [swr](https://github.com/vercel/swr) from 2.2.0 to 2.2.2.
- [Release notes](https://github.com/vercel/swr/releases)
- [Commits](https://github.com/vercel/swr/compare/v2.2.0...v2.2.2)

---
updated-dependencies:
- dependency-name: swr
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2023-10-30 20:45:18 -04:00
35772475b9 Bump uuid and @types/uuid (#617)
Bumps [uuid](https://github.com/uuidjs/uuid) and [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/uuid). These dependencies needed to be updated together.

Updates `uuid` from 9.0.0 to 9.0.1
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v9.0.0...v9.0.1)

Updates `@types/uuid` from 9.0.2 to 9.0.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/uuid)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: "@types/uuid"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:44:51 -04:00
86c592c0f6 Bump vite-tsconfig-paths from 4.2.0 to 4.2.1 (#750)
Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v4.2.0...v4.2.1)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:44:33 -04:00
0e98973cfa Bump @types/debounce-promise from 3.1.6 to 3.1.8 (#899)
Bumps [@types/debounce-promise](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/debounce-promise) from 3.1.6 to 3.1.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/debounce-promise)

---
updated-dependencies:
- dependency-name: "@types/debounce-promise"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:43:46 -04:00
7dd16fe6de Bump clap from 4.4.6 to 4.4.7 in /src/wasm-lib (#939)
Bumps [clap](https://github.com/clap-rs/clap) from 4.4.6 to 4.4.7.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.4.6...v4.4.7)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:42:58 -04:00
478b636049 Bump crypto-js from 4.1.1 to 4.2.0 (#940)
Bumps [crypto-js](https://github.com/brix/crypto-js) from 4.1.1 to 4.2.0.
- [Commits](https://github.com/brix/crypto-js/compare/4.1.1...4.2.0)

---
updated-dependencies:
- dependency-name: crypto-js
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:42:43 -04:00
c779311a56 Bump serde from 1.0.189 to 1.0.190 in /src-tauri (#943)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.189 to 1.0.190.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.189...v1.0.190)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:42:01 -04:00
ca02ec1151 Bump futures from 0.3.28 to 0.3.29 in /src/wasm-lib (#944)
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.28 to 0.3.29.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.28...0.3.29)

---
updated-dependencies:
- dependency-name: futures
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 20:41:37 -04:00
b271d5060e Fix typos and unnecessary import paths (#945) 2023-10-27 18:42:35 +00:00
19f11fe55a Cut release v0.11.1 (#936) 2023-10-26 07:27:29 -04:00
f6f1574982 Use kittycad::Angle instead of our own (#934) 2023-10-24 16:32:41 -07:00
6dc4fbc808 Use KittyCAD rust library from workspace (#932)
* Use KittyCAD rust library from workspace

* Clippy
2023-10-24 20:49:06 +00:00
8843d02380 Cargo update (#929) 2023-10-24 11:24:59 -07:00
3578ec07e6 Bump uuid from 1.4.1 to 1.5.0 in /src/wasm-lib (#926)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.4.1...1.5.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 10:42:07 -07:00
db35f73e41 Bump thiserror from 1.0.49 to 1.0.50 in /src/wasm-lib (#927)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.49 to 1.0.50.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.49...1.0.50)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 10:41:47 -07:00
5cfc2b7941 DRY the code (#921) 2023-10-24 17:30:14 +00:00
318e4a0cc7 Update kittycad.rs (#919) 2023-10-23 14:03:38 -07:00
1e23be8f08 Update rustix (#920) 2023-10-23 14:03:28 -07:00
ef547e7db8 bump kc lib 45 (#913) 2023-10-20 05:05:42 +00:00
71b48bbd89 Fix nightly last_update link (#901) 2023-10-18 21:01:44 -04:00
157 changed files with 10505 additions and 6080 deletions

3
.codespellrc Normal file
View File

@ -0,0 +1,3 @@
[codespell]
ignore-words-list: crate,everytime
skip: **/target,node_modules,build

View File

@ -12,27 +12,32 @@ on:
# Daily at 04:00 AM UTC # Daily at 04:00 AM UTC
# Will checkout the last commit from the default branch (main as of 2023-10-04) # Will checkout the last commit from the default branch (main as of 2023-10-04)
env:
BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && contains(github.event.pull_request.title, 'Cut release v') }}
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
check-format: check-format:
runs-on: 'ubuntu-20.04' runs-on: 'ubuntu-latest'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
- run: yarn install - run: yarn install
- run: yarn fmt-check - run: yarn fmt-check
check-types: check-types:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
@ -44,12 +49,27 @@ jobs:
- run: yarn build:wasm - run: yarn build:wasm
- run: yarn tsc - run: yarn tsc
check-typos:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
- name: Install codespell
run: |
python -m pip install codespell
- name: Run codespell
run: codespell --config .codespellrc # Edit this file to tweak the typo list and other configuration.
build-test-web: build-test-web:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
@ -68,14 +88,15 @@ jobs:
- run: yarn test:cov - run: yarn test:cov
prepare-json-files: prepare-json-files:
runs-on: ubuntu-20.04 # seperate job on Ubuntu for easy string manipulations (compared to Windows) runs-on: ubuntu-latest # seperate job on Ubuntu for easy string manipulations (compared to Windows)
outputs: outputs:
version: ${{ steps.export_version.outputs.version }} version: ${{ steps.export_version.outputs.version }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
@ -84,8 +105,8 @@ jobs:
if: github.event_name == 'schedule' if: github.event_name == 'schedule'
run: | run: |
VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons
echo "$(jq --arg url 'https://dl.kittycad.io/releases/modeling-app/test/nightly/last_update.json' \ echo "$(jq --arg url 'https://dl.kittycad.io/releases/modeling-app/nightly/last_update.json' \
'.tauri.updater.endpoints[]=$url' src-tauri/tauri.conf.json --indent 2)" > src-tauri/tauri.conf.json '.tauri.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: github.event_name == 'schedule' if: github.event_name == 'schedule'
@ -93,16 +114,18 @@ jobs:
path: | path: |
package.json package.json
src-tauri/tauri.conf.json src-tauri/tauri.conf.json
src-tauri/tauri.release.conf.json
- id: export_version - id: export_version
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT" run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
build-apps:
needs: [check-format, build-test-web, prepare-json-files, check-types] build-test-apps:
needs: [prepare-json-files]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-latest, ubuntu-20.04, windows-latest] os: [macos-latest, ubuntu-latest, windows-latest]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -114,25 +137,32 @@ jobs:
ls -l artifact ls -l artifact
cp artifact/package.json package.json cp artifact/package.json package.json
cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json
cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json
- name: install ubuntu system dependencies - name: Install ubuntu system dependencies
if: matrix.os == 'ubuntu-20.04' if: matrix.os == 'ubuntu-latest'
run: | run: >
sudo apt-get update sudo apt-get update &&
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev sudo apt-get install -y
libgtk-3-dev
libgtksourceview-3.0-dev
webkit2gtk-4.0
libappindicator3-dev
webkit2gtk-driver
xvfb
- name: Sync node version and setup cache - name: Sync node version and setup cache
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm. cache: 'yarn' # Set this to npm, yarn or pnpm.
- run: yarn install - run: yarn install
- name: Rust setup - name: Setup Rust
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
- name: Rust cache - name: Setup Rust cache
uses: swatinem/rust-cache@v2 uses: swatinem/rust-cache@v2
with: with:
workspaces: './src-tauri -> target' workspaces: './src-tauri -> target'
@ -141,24 +171,27 @@ jobs:
with: with:
workspaces: './src/wasm-lib' workspaces: './src/wasm-lib'
- name: wasm prep - name: Run build:wasm manually
shell: bash shell: bash
env:
MODE: ${{ env.BUILD_RELEASE == 'true' && '--release' || '--debug' }}
run: | run: |
mkdir src/wasm-lib/pkg; cd src/wasm-lib mkdir src/wasm-lib/pkg; cd src/wasm-lib
npx wasm-pack build --target web --out-dir pkg echo "building with ${{ env.MODE }}"
npx wasm-pack build --target web --out-dir pkg ${{ env.MODE }}
cd ../../ cd ../../
cp src/wasm-lib/pkg/wasm_lib_bg.wasm public cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
- name: Fix format - name: Fix format
run: yarn fmt run: yarn fmt
- name: install apple silicon target mac - name: Install Universal target (MacOS only)
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
run: | run: |
rustup target add aarch64-apple-darwin rustup target add aarch64-apple-darwin
- name: Prepare Windows certificate and variables - name: Prepare certificate and variables (Windows only)
if: matrix.os == 'windows-latest' if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }}
run: | run: |
echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12 echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12
cat /d/Certificate_pkcs12.p12 cat /d/Certificate_pkcs12.p12
@ -172,8 +205,8 @@ jobs:
echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH
shell: bash shell: bash
- name: Setup Windows certicate with SSM KSP - name: Setup certicate with SSM KSP (Windows only)
if: matrix.os == 'windows-latest' if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }}
run: | run: |
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
msiexec /i smtools-windows-x64.msi /quiet /qn msiexec /i smtools-windows-x64.msi /quiet /qn
@ -183,8 +216,17 @@ jobs:
smksp_cert_sync.exe smksp_cert_sync.exe
shell: cmd shell: cmd
- name: Build and sign the app for the current platform - name: Build the app (debug)
uses: tauri-apps/tauri-action@v0 uses: tauri-apps/tauri-action@v0
if: ${{ env.BUILD_RELEASE == 'false' }}
with:
includeRelease: false
includeDebug: true
args: ${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }}
- name: Build the app (release) and sign
uses: tauri-apps/tauri-action@v0
if: ${{ env.BUILD_RELEASE == 'true' }}
env: env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
@ -194,17 +236,35 @@ jobs:
APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
with: with:
args: ${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }} args: "${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }} ${{ env.TAURI_CONF_ARGS }}"
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
env:
PREFIX: ${{ matrix.os == 'macos-latest' && 'src-tauri/target/universal-apple-darwin' || 'src-tauri/target' }}
MODE: ${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}
with: with:
path: ${{ matrix.os == 'macos-latest' && 'src-tauri/target/universal-apple-darwin/release/bundle/*/*' || 'src-tauri/target/release/bundle/*/*' }} path: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*"
- name: Install tauri-driver for e2e tests (linux only)
if: matrix.os == 'ubuntu-latest'
uses: actions-rs/cargo@v1
with:
command: install
args: tauri-driver
- name: Run e2e tests (linux only)
if: matrix.os == 'ubuntu-latest'
run: xvfb-run yarn test:e2e
env:
MODE: ${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}
publish-apps-release: publish-apps-release:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }} if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
needs: [build-test-web, prepare-json-files, build-apps] needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
env: env:
VERSION_NO_V: ${{ needs.prepare-json-files.outputs.version }} VERSION_NO_V: ${{ needs.prepare-json-files.outputs.version }}
VERSION: ${{ github.event_name == 'release' && format('v{0}', needs.prepare-json-files.outputs.version) || needs.prepare-json-files.outputs.version }} VERSION: ${{ github.event_name == 'release' && format('v{0}', needs.prepare-json-files.outputs.version) || needs.prepare-json-files.outputs.version }}

View File

@ -48,7 +48,7 @@ We recommend downloading the latest application binary from [our Releases page](
## Running a development build ## Running a development build
First, [install Rust via `rustup`](https://www.rust-lang.org/tools/install). This project uses a lot of Rust compiled to [WASM](https://webassembly.org/) within it. Then, run: First, [install Rust via `rustup`](https://www.rust-lang.org/tools/install). This project uses a lot of Rust compiled to [WASM](https://webassembly.org/) within it. We always use the latest stable version of Rust, so you may need to run `rustup update stable`. Then, run:
``` ```
yarn install yarn install
@ -104,7 +104,7 @@ To spin up up tauri dev, `yarn install` and `yarn build:wasm-dev` need to have b
yarn tauri dev yarn tauri dev
``` ```
Will spin up the web app before opening up the tauri dev desktop app. Note that it's probably a good idea to close the browser tab that gets opened since at the time of writting they can conflict. Will spin up the web app before opening up the tauri dev desktop app. Note that it's probably a good idea to close the browser tab that gets opened since at the time of writing they can conflict.
The dev instance automatically opens up the browser devtools which can be disabled by [commenting it out](https://github.com/KittyCAD/modeling-app/blob/main/src-tauri/src/main.rs#L92.) The dev instance automatically opens up the browser devtools which can be disabled by [commenting it out](https://github.com/KittyCAD/modeling-app/blob/main/src-tauri/src/main.rs#L92.)

View File

@ -3812,7 +3812,7 @@
"args": [ "args": [
{ {
"name": "data", "name": "data",
"type": "AngeledLineThatIntersectsData", "type": "AngledLineThatIntersectsData",
"schema": { "schema": {
"description": "Data for drawing an angled line that intersects with a given line.", "description": "Data for drawing an angled line that intersects with a given line.",
"type": "object", "type": "object",

View File

@ -763,12 +763,12 @@ Draw an angled line that intersects with a given line.
``` ```
angledLineThatIntersects(data: AngeledLineThatIntersectsData, sketch_group: SketchGroup) -> SketchGroup angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch_group: SketchGroup) -> SketchGroup
``` ```
#### Arguments #### Arguments
* `data`: `AngeledLineThatIntersectsData` - Data for drawing an angled line that intersects with a given line. * `data`: `AngledLineThatIntersectsData` - Data for drawing an angled line that intersects with a given line.
``` ```
{ {
// The angle of the line. // The angle of the line.

View File

@ -0,0 +1,11 @@
describe('Modeling App', () => {
it('open the sign in page', async () => {
const button = await $('#signin')
expect(button).toHaveText('Sign in')
// Workaround for .click(), see https://github.com/tauri-apps/tauri/issues/6541
await button.waitForClickable()
await browser.execute('arguments[0].click();', button)
// TODO: handle auth
})
})

View File

@ -1,33 +1,33 @@
{ {
"name": "untitled-app", "name": "untitled-app",
"version": "0.11.0", "version": "0.11.3",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.9.0", "@codemirror/autocomplete": "^6.10.2",
"@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.13", "@headlessui/react": "^1.7.13",
"@headlessui/tailwindcss": "^0.2.0", "@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "^0.0.43", "@kittycad/lib": "^0.0.45",
"@lezer/javascript": "^1.4.7", "@lezer/javascript": "^1.4.7",
"@open-rpc/client-js": "^1.8.1", "@open-rpc/client-js": "^1.8.1",
"@react-hook/resize-observer": "^1.2.6", "@react-hook/resize-observer": "^1.2.6",
"@replit/codemirror-interact": "^6.3.0", "@replit/codemirror-interact": "^6.3.0",
"@sentry/react": "^7.65.0", "@sentry/react": "^7.77.0",
"@tauri-apps/api": "^1.5.0", "@tauri-apps/api": "^1.5.1",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0", "@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^13.2.1", "@testing-library/user-event": "^14.5.1",
"@ts-stack/markdown": "^1.5.0", "@ts-stack/markdown": "^1.5.0",
"@types/node": "^16.7.13", "@types/node": "^16.7.13",
"@types/react": "^18.0.0", "@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0", "@types/react-dom": "^18.0.0",
"@uiw/react-codemirror": "^4.21.13", "@uiw/react-codemirror": "^4.21.20",
"@xstate/inspect": "^0.8.0", "@xstate/inspect": "^0.8.0",
"@xstate/react": "^3.2.2", "@xstate/react": "^3.2.2",
"crypto-js": "^4.1.1", "crypto-js": "^4.2.0",
"debounce-promise": "^3.1.2", "debounce-promise": "^3.1.2",
"formik": "^2.4.3", "formik": "^2.4.3",
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
@ -43,20 +43,20 @@
"react-modal-promise": "^1.0.2", "react-modal-promise": "^1.0.2",
"react-router-dom": "^6.14.2", "react-router-dom": "^6.14.2",
"sketch-helpers": "^0.0.4", "sketch-helpers": "^0.0.4",
"swr": "^2.0.4", "swr": "^2.2.2",
"tauri-plugin-fs-extra-api": "https://github.com/tauri-apps/tauri-plugin-fs-extra#v1", "tauri-plugin-fs-extra-api": "https://github.com/tauri-apps/tauri-plugin-fs-extra#v1",
"toml": "^3.0.0", "toml": "^3.0.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^4.4.2", "typescript": "^5.2.2",
"uuid": "^9.0.0", "uuid": "^9.0.1",
"vitest": "^0.34.6", "vitest": "^0.34.6",
"vscode-jsonrpc": "^8.1.0", "vscode-jsonrpc": "^8.1.0",
"vscode-languageserver-protocol": "^3.17.3", "vscode-languageserver-protocol": "^3.17.5",
"wasm-pack": "^0.12.1", "wasm-pack": "^0.12.1",
"web-vitals": "^2.1.0", "web-vitals": "^3.5.0",
"ws": "^8.13.0", "ws": "^8.13.0",
"xstate": "^4.38.2", "xstate": "^4.38.2",
"zustand": "^4.1.4" "zustand": "^4.4.5"
}, },
"scripts": { "scripts": {
"start": "vite", "start": "vite",
@ -69,6 +69,7 @@
"test:nowatch": "vitest run --mode development", "test:nowatch": "vitest run --mode development",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)", "test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
"test:cov": "vitest run --coverage --mode development", "test:cov": "vitest run --coverage --mode development",
"test:e2e": "wdio run wdio.conf.js",
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &", "simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000", "simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
"fmt": "prettier --write ./src", "fmt": "prettier --write ./src",
@ -102,18 +103,18 @@
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/preset-env": "^7.22.9", "@babel/preset-env": "^7.22.9",
"@tauri-apps/cli": "^1.5.0", "@tauri-apps/cli": "^1.5.6",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/debounce-promise": "^3.1.6", "@types/debounce-promise": "^3.1.8",
"@types/isomorphic-fetch": "^0.0.36", "@types/isomorphic-fetch": "^0.0.36",
"@types/react-modal": "^3.16.0", "@types/react-modal": "^3.16.0",
"@types/uuid": "^9.0.1", "@types/uuid": "^9.0.4",
"@types/wicg-file-system-access": "^2020.9.6", "@types/wicg-file-system-access": "^2020.9.6",
"@types/ws": "^8.5.5", "@types/ws": "^8.5.5",
"@vitejs/plugin-react": "^4.0.3", "@vitejs/plugin-react": "^4.0.3",
"@vitest/coverage-istanbul": "^0.34.1", "@vitest/coverage-istanbul": "^0.34.1",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"eslint": "^8.44.0", "eslint": "^8.53.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-plugin-css-modules": "^2.11.0", "eslint-plugin-css-modules": "^2.11.0",
"happy-dom": "^10.8.0", "happy-dom": "^10.8.0",
@ -122,9 +123,13 @@
"prettier": "^2.8.0", "prettier": "^2.8.0",
"setimmediate": "^1.0.5", "setimmediate": "^1.0.5",
"tailwindcss": "^3.2.4", "tailwindcss": "^3.2.4",
"vite": "^4.4.3", "vite": "^4.5.0",
"vite-plugin-eslint": "^1.8.1", "vite-plugin-eslint": "^1.8.1",
"vite-tsconfig-paths": "^4.2.0", "vite-tsconfig-paths": "^4.2.1",
"yarn": "^1.22.19" "yarn": "^1.22.19",
"@wdio/cli": "^7.7.3",
"@wdio/local-runner": "^7.7.3",
"@wdio/mocha-framework": "^7.7.3",
"@wdio/spec-reporter": "^7.7.3"
} }
} }

69
src-tauri/Cargo.lock generated
View File

@ -122,6 +122,12 @@ dependencies = [
"system-deps 6.1.0", "system-deps 6.1.0",
] ]
[[package]]
name = "atomic"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -1567,7 +1573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [ dependencies = [
"hermit-abi 0.3.1", "hermit-abi 0.3.1",
"rustix 0.38.13", "rustix 0.38.21",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -1658,9 +1664,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.2.33" version = "0.2.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d341a81a4dfef43460d395c87d86c17e24affb96db0e7f4a35e8688f0e092344" checksum = "874914cd40bfd43674406683bb3f0924d41780698a4ade96f2e180a73678bdd1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1759,9 +1765,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.7" version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -2833,9 +2839,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.20" version = "0.11.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.2",
"bytes", "bytes",
@ -2862,6 +2868,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"system-configuration",
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
"tokio-rustls", "tokio-rustls",
@ -3011,9 +3018,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.19" version = "0.37.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"errno", "errno",
@ -3025,14 +3032,14 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.13" version = "0.38.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
dependencies = [ dependencies = [
"bitflags 2.4.0", "bitflags 2.4.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.7", "linux-raw-sys 0.4.10",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -3208,9 +3215,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.189" version = "1.0.192"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -3226,9 +3233,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.189" version = "1.0.192"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3248,9 +3255,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.107" version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [ dependencies = [
"itoa 1.0.6", "itoa 1.0.6",
"ryu", "ryu",
@ -3600,6 +3607,27 @@ dependencies = [
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "system-deps" name = "system-deps"
version = "5.0.0" version = "5.0.0"
@ -3828,7 +3856,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-plugin-fs-extra" name = "tauri-plugin-fs-extra"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#9b20f28d747f6ec3ba5a80bfcd5edc1d573b4c90" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#6865299149ffd183365e3ff291acf3edac78ca61"
dependencies = [ dependencies = [
"log", "log",
"serde", "serde",
@ -3927,7 +3955,7 @@ dependencies = [
"cfg-if", "cfg-if",
"fastrand", "fastrand",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"rustix 0.37.19", "rustix 0.37.27",
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
@ -4292,6 +4320,7 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
dependencies = [ dependencies = [
"atomic",
"getrandom 0.2.9", "getrandom 0.2.9",
"serde", "serde",
] ]

View File

@ -4,7 +4,7 @@ version = "0.1.0"
description = "A Tauri App" description = "A Tauri App"
authors = ["you"] authors = ["you"]
license = "" license = ""
repository = "" repository = "https://github.com/KittyCAD/modeling-app"
default-run = "app" default-run = "app"
edition = "2021" edition = "2021"
rust-version = "1.60" rust-version = "1.60"
@ -16,7 +16,7 @@ tauri-build = { version = "1.5.0", features = [] }
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
kittycad = "0.2.33" kittycad = "0.2.41"
oauth2 = "4.4.2" oauth2 = "4.4.2"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

View File

@ -68,7 +68,7 @@ async fn login(app: tauri::AppHandle, host: &str) -> Result<String, InvokeError>
}; };
// Open the system browser with the auth_uri. // Open the system browser with the auth_uri.
// We do this in the browser and not a seperate window because we want 1password and // We do this in the browser and not a separate window because we want 1password and
// other crap to work well. // other crap to work well.
tauri::api::shell::open(&app.shell_scope(), auth_uri.secret(), None) tauri::api::shell::open(&app.shell_scope(), auth_uri.secret(), None)
.map_err(|e| InvokeError::from_anyhow(e.into()))?; .map_err(|e| InvokeError::from_anyhow(e.into()))?;
@ -129,10 +129,10 @@ async fn get_user(
fn main() { fn main() {
tauri::Builder::default() tauri::Builder::default()
.setup(|app| { .setup(|_app| {
#[cfg(debug_assertions)] // only include this code on debug builds #[cfg(debug_assertions)] // only include this code on debug builds
{ {
let window = app.get_window("main").unwrap(); let window = _app.get_window("main").unwrap();
// comment out the below if you don't devtools to open everytime. // comment out the below if you don't devtools to open everytime.
// it's useful because otherwise devtools shuts everytime rust code changes. // it's useful because otherwise devtools shuts everytime rust code changes.
window.open_devtools(); window.open_devtools();

View File

@ -8,7 +8,7 @@
}, },
"package": { "package": {
"productName": "kittycad-modeling", "productName": "kittycad-modeling",
"version": "0.11.0" "version": "0.11.3"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {
@ -72,23 +72,13 @@
}, },
"resources": [], "resources": [],
"shortDescription": "", "shortDescription": "",
"targets": "all", "targets": "all"
"windows": {
"certificateThumbprint": "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D",
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.digicert.com"
}
}, },
"security": { "security": {
"csp": null "csp": null
}, },
"updater": { "updater": {
"active": true, "active": false
"endpoints": [
"https://dl.kittycad.io/releases/modeling-app/last_update.json"
],
"dialog": true,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
}, },
"windows": [ "windows": [
{ {

View File

@ -1,4 +1,3 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": { "package": {

View File

@ -0,0 +1,21 @@
{
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"tauri": {
"updater": {
"active": true,
"endpoints": [
"https://dl.kittycad.io/releases/modeling-app/last_update.json"
],
"dialog": true,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
},
"bundle": {
"identifier": "io.kittycad.modeling-app",
"windows": {
"certificateThumbprint": "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D",
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.digicert.com"
}
}
}
}

View File

@ -1,4 +1,3 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": { "package": {

View File

@ -1,4 +1,4 @@
import { useEffect, useCallback, MouseEventHandler } from 'react' import { useCallback, MouseEventHandler } from 'react'
import { DebugPanel } from './components/DebugPanel' import { DebugPanel } from './components/DebugPanel'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { PaneType, useStore } from './useStore' import { PaneType, useStore } from './useStore'
@ -19,7 +19,6 @@ import {
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { getNormalisedCoordinates } from './lib/utils' import { getNormalisedCoordinates } from './lib/utils'
import { isTauri } from './lib/isTauri'
import { useLoaderData } from 'react-router-dom' import { useLoaderData } from 'react-router-dom'
import { IndexLoaderData } from './Router' import { IndexLoaderData } from './Router'
import { useGlobalStateContext } from 'hooks/useGlobalStateContext' import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
@ -31,11 +30,10 @@ import { TextEditor } from 'components/TextEditor'
import { Themes, getSystemTheme } from 'lib/theme' import { Themes, getSystemTheme } from 'lib/theme'
import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions' import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions'
import { engineCommandManager } from './lang/std/engineConnection' import { engineCommandManager } from './lang/std/engineConnection'
import { kclManager } from 'lang/KclSinglton'
import { useModelingContext } from 'hooks/useModelingContext' import { useModelingContext } from 'hooks/useModelingContext'
export function App() { export function App() {
const { code: loadedCode, project, file } = useLoaderData() as IndexLoaderData const { project, file } = useLoaderData() as IndexLoaderData
useHotKeyListener() useHotKeyListener()
const { const {
@ -82,26 +80,6 @@ export function App() {
? 'opacity-40' ? 'opacity-40'
: '' : ''
// Use file code loaded from disk
// on mount, and overwrite any locally-stored code
useEffect(() => {
if (isTauri() && loadedCode !== null) {
if (kclManager.engineCommandManager.engineConnection?.isReady()) {
// If the engine is ready, promptly execute the loaded code
kclManager.setCodeAndExecute(loadedCode)
} else {
// Otherwise, just set the code and wait for the connection to complete
kclManager.setCode(loadedCode)
}
}
return () => {
// Clear code on unmount if in desktop app
if (isTauri()) {
kclManager.setCode('')
}
}
}, [loadedCode])
useEngineConnectionSubscriptions() useEngineConnectionSubscriptions()
const debounceSocketSend = throttle<EngineCommand>((message) => { const debounceSocketSend = throttle<EngineCommand>((message) => {
@ -248,7 +226,7 @@ export function App() {
<Stream className="absolute inset-0 z-0" /> <Stream className="absolute inset-0 z-0" />
{showDebugPanel && ( {showDebugPanel && (
<DebugPanel <DebugPanel
title="Debug" title="Debug (AST Explorer)"
className={ className={
'transition-opacity transition-duration-75 ' + 'transition-opacity transition-duration-75 ' +
paneOpacity + paneOpacity +

View File

@ -42,7 +42,7 @@ import CommandBarProvider from 'components/CommandBar'
import { TEST, VITE_KC_SENTRY_DSN } from './env' import { TEST, VITE_KC_SENTRY_DSN } from './env'
import * as Sentry from '@sentry/react' import * as Sentry from '@sentry/react'
import ModelingMachineProvider from 'components/ModelingMachineProvider' import ModelingMachineProvider from 'components/ModelingMachineProvider'
import { KclContextProvider } from 'lang/KclSinglton' import { KclContextProvider, kclManager } from 'lang/KclSinglton'
import FileMachineProvider from 'components/FileMachineProvider' import FileMachineProvider from 'components/FileMachineProvider'
import { sep } from '@tauri-apps/api/path' import { sep } from '@tauri-apps/api/path'
@ -207,6 +207,7 @@ const router = createBrowserRouter(
projectPath + sep + PROJECT_ENTRYPOINT projectPath + sep + PROJECT_ENTRYPOINT
) )
const children = await readDir(projectPath, { recursive: true }) const children = await readDir(projectPath, { recursive: true })
kclManager.setCodeAndExecute(code, false)
return { return {
code, code,

View File

@ -1,4 +1,3 @@
import { ToolTip } from './useStore'
import { Fragment, WheelEvent, useRef, useMemo } from 'react' import { Fragment, WheelEvent, useRef, useMemo } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons' import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
@ -15,23 +14,6 @@ export const sketchButtonClassnames = {
icon: 'text-fern-20 h-auto group-hover:text-fern-10 hover:text-fern-10 dark:text-chalkboard-100 dark:group-hover:text-chalkboard-100 dark:hover:text-chalkboard-100 group-disabled:bg-chalkboard-60 hover:group-disabled:text-inherit', icon: 'text-fern-20 h-auto group-hover:text-fern-10 hover:text-fern-10 dark:text-chalkboard-100 dark:group-hover:text-chalkboard-100 dark:hover:text-chalkboard-100 group-disabled:bg-chalkboard-60 hover:group-disabled:text-inherit',
} }
const sketchFnLabels: Record<ToolTip | 'sketch_line' | 'move', string> = {
sketch_line: 'Line',
line: 'Line',
move: 'Move',
angledLine: 'Angled Line',
angledLineThatIntersects: 'Angled Line That Intersects',
angledLineOfXLength: 'Angled Line Of X Length',
angledLineOfYLength: 'Angled Line Of Y Length',
angledLineToX: 'Angled Line To X',
angledLineToY: 'Angled Line To Y',
lineTo: 'Line to Point',
xLine: 'Horizontal Line',
yLine: 'Vertical Line',
xLineTo: 'Horizontal Line to Point',
yLineTo: 'Vertical Line to Point',
}
export const Toolbar = () => { export const Toolbar = () => {
const { state, send, context } = useModelingContext() const { state, send, context } = useModelingContext()
const toolbarButtonsRef = useRef<HTMLSpanElement>(null) const toolbarButtonsRef = useRef<HTMLSpanElement>(null)

View File

@ -184,6 +184,7 @@ function DisplayObj({
</li> </li>
) )
} }
return null
})} })}
</ul> </ul>
</span> </span>

View File

@ -1,5 +1,5 @@
import { useEffect, useState, useRef } from 'react' import { useEffect, useState, useRef } from 'react'
import { parse, BinaryPart, Value, executor } from '../lang/wasm' import { parse, BinaryPart, Value } from '../lang/wasm'
import { import {
createIdentifier, createIdentifier,
createLiteral, createLiteral,
@ -10,6 +10,7 @@ import { findAllPreviousVariables, PrevVariable } from '../lang/queryAst'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
import { kclManager, useKclContext } from 'lang/KclSinglton' import { kclManager, useKclContext } from 'lang/KclSinglton'
import { useModelingContext } from 'hooks/useModelingContext' import { useModelingContext } from 'hooks/useModelingContext'
import { executeAst } from 'useStore'
export const AvailableVars = ({ export const AvailableVars = ({
onVarClick, onVarClick,
@ -130,27 +131,29 @@ export function useCalc({
if (!programMemory || !selectionRange) return if (!programMemory || !selectionRange) return
const varInfo = findAllPreviousVariables( const varInfo = findAllPreviousVariables(
kclManager.ast, kclManager.ast,
programMemory, kclManager.programMemory,
selectionRange selectionRange
) )
setAvailableVarInfo(varInfo) setAvailableVarInfo(varInfo)
}, [kclManager.ast, programMemory, selectionRange]) }, [kclManager.ast, kclManager.programMemory, selectionRange])
useEffect(() => { useEffect(() => {
try { try {
const code = `const __result__ = ${value}\nshow(__result__)` const code = `const __result__ = ${value}`
const ast = parse(code) const ast = parse(code)
const _programMem: any = { root: {}, return: null } const _programMem: any = { root: {}, return: null }
availableVarInfo.variables.forEach(({ key, value }) => { availableVarInfo.variables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] } _programMem.root[key] = { type: 'userVal', value, __meta: [] }
}) })
executeAst({
executor(
ast, ast,
_programMem,
engineCommandManager, engineCommandManager,
kclManager.defaultPlanes defaultPlanes: kclManager.defaultPlanes,
).then((programMemory) => { useFakeExecutor: true,
programMemoryOverride: JSON.parse(
JSON.stringify(kclManager.programMemory)
),
}).then(({ programMemory }) => {
const resultDeclaration = ast.body.find( const resultDeclaration = ast.body.find(
(a) => (a) =>
a.type === 'VariableDeclaration' && a.type === 'VariableDeclaration' &&
@ -167,7 +170,7 @@ export function useCalc({
setCalcResult('NAN') setCalcResult('NAN')
setValueNode(null) setValueNode(null)
} }
}, [value]) }, [value, availableVarInfo])
return { return {
valueNode, valueNode,
@ -212,7 +215,10 @@ export const CreateNewVariable = ({
}) => { }) => {
return ( return (
<> <>
<label htmlFor="create-new-variable" className="block mt-3 font-mono"> <label
htmlFor="create-new-variable"
className="block mt-3 font-mono text-gray-900"
>
Create new variable Create new variable
</label> </label>
<div className="mt-1 flex gap-2 items-center"> <div className="mt-1 flex gap-2 items-center">
@ -223,6 +229,7 @@ export const CreateNewVariable = ({
onChange={(e) => { onChange={(e) => {
setShouldCreateVariable(e.target.checked) setShouldCreateVariable(e.target.checked)
}} }}
className="bg-white text-gray-900"
/> />
)} )}
<input <input

View File

@ -1,29 +1,7 @@
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel' import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
import { v4 as uuidv4 } from 'uuid'
import { EngineCommand } from '../lang/std/engineConnection'
import { useState } from 'react'
import { ActionButton } from '../components/ActionButton'
import { faCheck } from '@fortawesome/free-solid-svg-icons'
import { isReducedMotion } from 'lang/util'
import { AstExplorer } from './AstExplorer' import { AstExplorer } from './AstExplorer'
import { engineCommandManager } from '../lang/std/engineConnection'
type SketchModeCmd = Extract<
Extract<EngineCommand, { type: 'modeling_cmd_req' }>['cmd'],
{ type: 'default_camera_enable_sketch_mode' }
>
export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => { export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
const [sketchModeCmd, setSketchModeCmd] = useState<SketchModeCmd>({
type: 'default_camera_enable_sketch_mode',
origin: { x: 0, y: 0, z: 0 },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
distance_to_plane: 100,
ortho: true,
animated: !isReducedMotion(),
})
if (!sketchModeCmd) return null
return ( return (
<CollapsiblePanel <CollapsiblePanel
{...props} {...props}
@ -34,67 +12,6 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
style={{ maxHeight: 'calc(100% - 3rem - 1.25rem - 1.25rem)' }} style={{ maxHeight: 'calc(100% - 3rem - 1.25rem - 1.25rem)' }}
> >
<section className="p-4 flex flex-col gap-4"> <section className="p-4 flex flex-col gap-4">
<Xyz
onChange={setSketchModeCmd}
pointKey="origin"
data={sketchModeCmd}
/>
<Xyz
onChange={setSketchModeCmd}
pointKey="x_axis"
data={sketchModeCmd}
/>
<Xyz
onChange={setSketchModeCmd}
pointKey="y_axis"
data={sketchModeCmd}
/>
<div className="flex">
<div className="pr-4">distance_to_plane</div>
<input
className="w-16 dark:bg-chalkboard-90"
type="number"
value={sketchModeCmd.distance_to_plane}
onChange={({ target }) => {
setSketchModeCmd({
...sketchModeCmd,
distance_to_plane: Number(target.value),
})
}}
/>
<div className="pr-4">ortho</div>
<input
className="w-16"
type="checkbox"
checked={sketchModeCmd.ortho}
onChange={(a) =>
setSketchModeCmd({
...sketchModeCmd,
ortho: a.target.checked,
})
}
/>
</div>
<ActionButton
Element="button"
onClick={() => {
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: sketchModeCmd,
cmd_id: uuidv4(),
})
}}
className="hover:border-succeed-50"
icon={{
icon: faCheck,
bgClassName:
'bg-succeed-80 group-hover:bg-succeed-70 hover:bg-succeed-70',
iconClassName:
'text-succeed-20 group-hover:text-succeed-10 hover:text-succeed-10',
}}
>
Send sketch mode command
</ActionButton>
<div style={{ height: '400px' }} className="overflow-y-auto"> <div style={{ height: '400px' }} className="overflow-y-auto">
<AstExplorer /> <AstExplorer />
</div> </div>
@ -102,41 +19,3 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
</CollapsiblePanel> </CollapsiblePanel>
) )
} }
const Xyz = ({
pointKey,
data,
onChange,
}: {
pointKey: 'origin' | 'y_axis' | 'x_axis'
data: SketchModeCmd
onChange: (a: SketchModeCmd) => void
}) => {
if (!data) return null
return (
<div className="flex">
<div className="pr-4">{pointKey}</div>
{Object.entries(data[pointKey]).map(([axis, val]) => {
return (
<div key={axis} className="flex">
<div className="w-4">{axis}</div>
<input
className="w-16 dark:bg-chalkboard-90"
type="number"
value={val}
onChange={({ target }) => {
onChange({
...data,
[pointKey]: {
...data[pointKey],
[axis]: Number(target.value),
},
})
}}
/>
</div>
)
})}
</div>
)
}

View File

@ -2,7 +2,7 @@ import { IndexLoaderData, paths } from 'Router'
import { ActionButton } from './ActionButton' import { ActionButton } from './ActionButton'
import Tooltip from './Tooltip' import Tooltip from './Tooltip'
import { FileEntry } from '@tauri-apps/api/fs' import { FileEntry } from '@tauri-apps/api/fs'
import { Dispatch, useEffect, useRef, useState } from 'react' import { Dispatch, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { Dialog, Disclosure } from '@headlessui/react' import { Dialog, Disclosure } from '@headlessui/react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
@ -163,7 +163,6 @@ const FileTreeItem = ({
function openFile() { function openFile() {
if (fileOrDir.children !== undefined) return // Don't open directories if (fileOrDir.children !== undefined) return // Don't open directories
kclManager.setCode('')
navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`) navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`)
closePanel() closePanel()
} }

View File

@ -20,7 +20,6 @@ import {
recast, recast,
parse, parse,
Program, Program,
VariableDeclarator,
PipeExpression, PipeExpression,
CallExpression, CallExpression,
} from 'lang/wasm' } from 'lang/wasm'
@ -148,7 +147,7 @@ export const ModelingMachineProvider = ({
engineCommandManager.artifactMap[sketchEnginePathId] = { engineCommandManager.artifactMap[sketchEnginePathId] = {
type: 'result', type: 'result',
range: [startProfileAtCallExp.start, startProfileAtCallExp.end], range: [startProfileAtCallExp.start, startProfileAtCallExp.end],
commandType: 'extend_path', commandType: 'start_path',
data: null, data: null,
raw: {} as any, raw: {} as any,
} }

View File

@ -108,7 +108,7 @@ export const SetAngleLengthModal = ({
</label> </label>
<div className="mt-1 flex"> <div className="mt-1 flex">
<button <button
className="border border-gray-300 px-2" className="border border-gray-300 px-2 text-gray-900"
onClick={() => setSign(-sign)} onClick={() => setSign(-sign)}
> >
{sign > 0 ? '+' : '-'} {sign > 0 ? '+' : '-'}
@ -118,7 +118,7 @@ export const SetAngleLengthModal = ({
type="text" type="text"
name="val" name="val"
id="val" id="val"
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1" className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1 text-gray-900"
value={value} value={value}
onChange={(e) => { onChange={(e) => {
setValue(e.target.value) setValue(e.target.value)

View File

@ -87,7 +87,7 @@ export const GetInfoModal = ({
leaveFrom="opacity-100 scale-100" leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95" leaveTo="opacity-0 scale-95"
> >
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all"> <Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white/90 p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Title <Dialog.Title
as="h3" as="h3"
className="text-lg font-medium leading-6 text-gray-900" className="text-lg font-medium leading-6 text-gray-900"
@ -109,7 +109,7 @@ export const GetInfoModal = ({
</label> </label>
<div className="mt-1 flex"> <div className="mt-1 flex">
<button <button
className="border border-gray-300 px-2 mr-1" className="border border-gray-400 px-2 mr-1 text-gray-900"
onClick={() => setSign(-sign)} onClick={() => setSign(-sign)}
> >
{sign > 0 ? '+' : '-'} {sign > 0 ? '+' : '-'}
@ -119,7 +119,7 @@ export const GetInfoModal = ({
name="val" name="val"
id="val" id="val"
ref={inputRef} ref={inputRef}
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono" className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm text-gray-900 border-gray-300 rounded-md font-mono"
value={value} value={value}
onChange={(e) => { onChange={(e) => {
setValue(e.target.value) setValue(e.target.value)
@ -139,7 +139,7 @@ export const GetInfoModal = ({
name="segName" name="segName"
id="segName" id="segName"
disabled={!isSegNameEditable} disabled={!isSegNameEditable}
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono" className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm text-gray-900 border-gray-300 rounded-md font-mono"
value={segName} value={segName}
onChange={(e) => { onChange={(e) => {
setSegName(e.target.value) setSegName(e.target.value)

View File

@ -14,7 +14,7 @@ import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models' import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
import { Models } from '@kittycad/lib' import { Models } from '@kittycad/lib'
import { getNodeFromPath } from 'lang/queryAst' import { getNodeFromPath } from 'lang/queryAst'
import { VariableDeclarator, recast, parse, CallExpression } from 'lang/wasm' import { VariableDeclarator, recast, CallExpression } from 'lang/wasm'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
import { useModelingContext } from 'hooks/useModelingContext' import { useModelingContext } from 'hooks/useModelingContext'
import { kclManager, useKclContext } from 'lang/KclSinglton' import { kclManager, useKclContext } from 'lang/KclSinglton'
@ -267,11 +267,11 @@ export const Stream = ({ className = '' }) => {
} }
engineCommandManager.sendSceneCommand(command).then(async () => { engineCommandManager.sendSceneCommand(command).then(async () => {
if (!context.sketchPathToNode) return if (!context.sketchPathToNode) return
const varDec = getNodeFromPath<VariableDeclarator>( getNodeFromPath<VariableDeclarator>(
kclManager.ast, kclManager.ast,
context.sketchPathToNode, context.sketchPathToNode,
'VariableDeclarator' 'VariableDeclarator'
).node )
// Get the current plane string for plane we are on. // Get the current plane string for plane we are on.
let currentPlaneString = '' let currentPlaneString = ''
if (context.sketchPlaneId === kclManager.getPlaneId('xy')) { if (context.sketchPlaneId === kclManager.getPlaneId('xy')) {
@ -342,7 +342,8 @@ export const Stream = ({ className = '' }) => {
// update artifact map ranges now that we have updated the ast. // update artifact map ranges now that we have updated the ast.
code = recast(modded.modifiedAst) code = recast(modded.modifiedAst)
const astWithCurrentRanges = parse(code) const astWithCurrentRanges = kclManager.safeParse(code)
if (!astWithCurrentRanges) return
const updateNode = getNodeFromPath<CallExpression>( const updateNode = getNodeFromPath<CallExpression>(
astWithCurrentRanges, astWithCurrentRanges,
modded.pathToNode modded.pathToNode

View File

@ -17,15 +17,7 @@ import { useStore } from 'useStore'
import { processCodeMirrorRanges } from 'lib/selections' import { processCodeMirrorRanges } from 'lib/selections'
import { LanguageServerClient } from 'editor/lsp' import { LanguageServerClient } from 'editor/lsp'
import kclLanguage from 'editor/lsp/language' import kclLanguage from 'editor/lsp/language'
import { isTauri } from 'lib/isTauri' import { EditorView, lineHighlightField } from 'editor/highlightextension'
import { useParams } from 'react-router-dom'
import { writeTextFile } from '@tauri-apps/api/fs'
import { toast } from 'react-hot-toast'
import {
EditorView,
addLineHighlight,
lineHighlightField,
} from 'editor/highlightextension'
import { roundOff } from 'lib/utils' import { roundOff } from 'lib/utils'
import { kclErrToDiagnostic } from 'lang/errors' import { kclErrToDiagnostic } from 'lang/errors'
import { CSSRuleObject } from 'tailwindcss/types/config' import { CSSRuleObject } from 'tailwindcss/types/config'
@ -50,7 +42,6 @@ export const TextEditor = ({
}: { }: {
theme: Themes.Light | Themes.Dark theme: Themes.Light | Themes.Dark
}) => { }) => {
const pathParams = useParams()
const { editorView, isLSPServerReady, setEditorView, setIsLSPServerReady } = const { editorView, isLSPServerReady, setEditorView, setIsLSPServerReady } =
useStore((s) => ({ useStore((s) => ({
editorView: s.editorView, editorView: s.editorView,
@ -92,7 +83,7 @@ export const TextEditor = ({
// Here we initialize the plugin which will start the client. // Here we initialize the plugin which will start the client.
// When we have multi-file support the name of the file will be a dep of // When we have multi-file support the name of the file will be a dep of
// this use memo, as well as the directory structure, which I think is // this use memo, as well as the directory structure, which I think is
// a good setup becuase it will restart the client but not the server :) // a good setup because it will restart the client but not the server :)
// We do not want to restart the server, its just wasteful. // We do not want to restart the server, its just wasteful.
const kclLSP = useMemo(() => { const kclLSP = useMemo(() => {
let plugin = null let plugin = null
@ -113,18 +104,6 @@ export const TextEditor = ({
// const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => { // const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => {
const onChange = (newCode: string) => { const onChange = (newCode: string) => {
kclManager.setCodeAndExecute(newCode) kclManager.setCodeAndExecute(newCode)
if (isTauri() && pathParams.id) {
// Save the file to disk
// Note that PROJECT_ENTRYPOINT is hardcoded until we support multiple files
writeTextFile(pathParams.id, newCode).catch((err) => {
// TODO: add Sentry per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254)
console.error('error saving file', err)
toast.error('Error saving file, please check file permissions')
})
}
if (editorView) {
editorView?.dispatch({ effects: addLineHighlight.of([0, 0]) })
}
} //, []); } //, []);
const onUpdate = (viewUpdate: ViewUpdate) => { const onUpdate = (viewUpdate: ViewUpdate) => {
if (!editorView) { if (!editorView) {

View File

@ -69,7 +69,7 @@ export function applyConstraintEqualLength({
modifiedAst: Program modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} { } {
const { enabled, transforms } = setEqualLengthInfo({ selectionRanges }) const { transforms } = setEqualLengthInfo({ selectionRanges })
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({ const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
ast: kclManager.ast, ast: kclManager.ast,
selectionRanges, selectionRanges,

View File

@ -108,6 +108,7 @@ export default class Client extends jsrpc.JSONRPCServerAndClient {
break break
} }
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
messageString += message messageString += message
return return
}) })

View File

@ -26,7 +26,7 @@ export class Codec {
} }
} }
// FIXME: tracing effiency // FIXME: tracing efficiency
export class IntoServer export class IntoServer
extends Queue<Uint8Array> extends Queue<Uint8Array>
implements AsyncGenerator<Uint8Array, never, void> implements AsyncGenerator<Uint8Array, never, void>

View File

@ -2,8 +2,6 @@ import { useEffect } from 'react'
import { useStore } from 'useStore' import { useStore } from 'useStore'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
import { useModelingContext } from './useModelingContext' import { useModelingContext } from './useModelingContext'
import { v4 as uuidv4 } from 'uuid'
import { SourceRange } from 'lang/wasm'
import { getEventForSelectWithPoint } from 'lib/selections' import { getEventForSelectWithPoint } from 'lib/selections'
export function useEngineConnectionSubscriptions() { export function useEngineConnectionSubscriptions() {
@ -13,11 +11,6 @@ export function useEngineConnectionSubscriptions() {
})) }))
const { send, context } = useModelingContext() const { send, context } = useModelingContext()
interface RangeAndId {
id: string
range: SourceRange
}
useEffect(() => { useEffect(() => {
if (!engineCommandManager) return if (!engineCommandManager) return
@ -42,7 +35,7 @@ export function useEngineConnectionSubscriptions() {
const event = await getEventForSelectWithPoint(engineEvent, { const event = await getEventForSelectWithPoint(engineEvent, {
sketchEnginePathId: context.sketchEnginePathId, sketchEnginePathId: context.sketchEnginePathId,
}) })
send(event) event && send(event)
}, },
}) })
return () => { return () => {

View File

@ -1,5 +1,5 @@
import { useLayoutEffect, useEffect, useRef } from 'react' import { useLayoutEffect, useEffect, useRef } from 'react'
import { _executor, parse } from '../lang/wasm' import { parse } from '../lang/wasm'
import { useStore } from '../useStore' import { useStore } from '../useStore'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
import { deferExecution } from 'lib/utils' import { deferExecution } from 'lib/utils'
@ -26,10 +26,6 @@ export function useSetupEngineManager(
const hasSetNonZeroDimensions = useRef<boolean>(false) const hasSetNonZeroDimensions = useRef<boolean>(false)
useEffect(() => {
kclManager.executeCode()
}, [])
useLayoutEffect(() => { useLayoutEffect(() => {
// Load the engine command manager once with the initial width and height, // Load the engine command manager once with the initial width and height,
// then we do not want to reload it. // then we do not want to reload it.

View File

@ -18,7 +18,11 @@ import { bracket } from 'lib/exampleKcl'
import { createContext, useContext, useEffect, useState } from 'react' import { createContext, useContext, useEffect, useState } from 'react'
import { getNodeFromPath } from './queryAst' import { getNodeFromPath } from './queryAst'
import { IndexLoaderData } from 'Router' import { IndexLoaderData } from 'Router'
import { useLoaderData } from 'react-router-dom' import { Params, useLoaderData } from 'react-router-dom'
import { isTauri } from 'lib/isTauri'
import { writeTextFile } from '@tauri-apps/api/fs'
import { toast } from 'react-hot-toast'
import { useParams } from 'react-router-dom'
const PERSIST_CODE_TOKEN = 'persistCode' const PERSIST_CODE_TOKEN = 'persistCode'
@ -41,10 +45,20 @@ class KclManager {
private _kclErrors: KCLError[] = [] private _kclErrors: KCLError[] = []
private _isExecuting = false private _isExecuting = false
private _wasmInitFailed = true private _wasmInitFailed = true
private _params: Params<string> = {}
engineCommandManager: EngineCommandManager engineCommandManager: EngineCommandManager
private _defferer = deferExecution((code: string) => { private _defferer = deferExecution((code: string) => {
const ast = parse(code) const ast = this.safeParse(code)
if (!ast) return
try {
const fmtAndStringify = (ast: Program) =>
JSON.stringify(parse(recast(ast)))
const isAstTheSame = fmtAndStringify(ast) === fmtAndStringify(this._ast)
if (isAstTheSame) return
} catch (e) {
console.error(e)
}
this.executeAst(ast) this.executeAst(ast)
}, 600) }, 600)
@ -71,6 +85,21 @@ class KclManager {
set code(code) { set code(code) {
this._code = code this._code = code
this._codeCallBack(code) this._codeCallBack(code)
if (isTauri()) {
setTimeout(() => {
// Wait one event loop to give a chance for params to be set
// Save the file to disk
// Note that PROJECT_ENTRYPOINT is hardcoded until we support multiple files
this._params.id &&
writeTextFile(this._params.id, code).catch((err) => {
// TODO: add Sentry per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254)
console.error('error saving file', err)
toast.error('Error saving file, please check file permissions')
})
})
} else {
localStorage.setItem(PERSIST_CODE_TOKEN, code)
}
} }
get programMemory() { get programMemory() {
@ -117,10 +146,19 @@ class KclManager {
this._wasmInitFailedCallback(wasmInitFailed) this._wasmInitFailedCallback(wasmInitFailed)
} }
setParams(params: Params<string>) {
this._params = params
}
constructor(engineCommandManager: EngineCommandManager) { constructor(engineCommandManager: EngineCommandManager) {
this.engineCommandManager = engineCommandManager this.engineCommandManager = engineCommandManager
if (isTauri()) {
this.code = ''
return
}
const storedCode = localStorage.getItem(PERSIST_CODE_TOKEN) const storedCode = localStorage.getItem(PERSIST_CODE_TOKEN)
// TODO #819 remove zustand persistance logic in a few months // TODO #819 remove zustand persistence logic in a few months
// short term migration, shouldn't make a difference for tauri app users // short term migration, shouldn't make a difference for tauri app users
// anyway since that's filesystem based. // anyway since that's filesystem based.
const zustandStore = JSON.parse(localStorage.getItem('store') || '{}') const zustandStore = JSON.parse(localStorage.getItem('store') || '{}')
@ -130,6 +168,7 @@ class KclManager {
zustandStore.state.code = '' zustandStore.state.code = ''
localStorage.setItem('store', JSON.stringify(zustandStore)) localStorage.setItem('store', JSON.stringify(zustandStore))
} else if (storedCode === null) { } else if (storedCode === null) {
console.log('stored brack thing')
this.code = bracket this.code = bracket
} else { } else {
this.code = storedCode this.code = storedCode
@ -164,6 +203,21 @@ class KclManager {
this._executeCallback = callback this._executeCallback = callback
} }
safeParse(code: string): Program | null {
try {
const ast = parse(code)
this.kclErrors = []
return ast
} catch (e) {
console.error('error parsing code', e)
if (e instanceof KCLError) {
this.kclErrors = [e]
if (e.msg === 'file is empty') engineCommandManager.endSession()
}
return null
}
}
async ensureWasmInit() { async ensureWasmInit() {
try { try {
await initPromise await initPromise
@ -184,20 +238,20 @@ class KclManager {
defaultPlanes: this.defaultPlanes, defaultPlanes: this.defaultPlanes,
}) })
this.isExecuting = false this.isExecuting = false
this._logs = logs this.logs = logs
this._kclErrors = errors this.kclErrors = errors
this._programMemory = programMemory this.programMemory = programMemory
this._ast = { ...ast } this.ast = { ...ast }
if (updateCode) { if (updateCode) {
this._code = recast(ast) this.code = recast(ast)
this._codeCallBack(this._code)
} }
this._executeCallback() this._executeCallback()
} }
async executeAstMock(ast: Program = this._ast, updateCode = false) { async executeAstMock(ast: Program = this._ast, updateCode = false) {
await this.ensureWasmInit() await this.ensureWasmInit()
const newCode = recast(ast) const newCode = recast(ast)
const newAst = parse(newCode) const newAst = this.safeParse(newCode)
if (!newAst) return
await this?.engineCommandManager?.waitForReady await this?.engineCommandManager?.waitForReady
if (updateCode) { if (updateCode) {
this.setCode(recast(ast)) this.setCode(recast(ast))
@ -233,13 +287,17 @@ class KclManager {
this.ast = ast this.ast = ast
if (code) this.code = code if (code) this.code = code
} }
setCode(code: string) { setCode(code: string, shouldWriteFile = true) {
if (shouldWriteFile) {
// use the normal code setter
this.code = code
return
}
this._code = code this._code = code
this._codeCallBack(code) this._codeCallBack(code)
localStorage.setItem(PERSIST_CODE_TOKEN, code)
} }
setCodeAndExecute(code: string) { setCodeAndExecute(code: string, shouldWriteFile = true) {
this.setCode(code) this.setCode(code, shouldWriteFile)
if (code.trim()) { if (code.trim()) {
this._defferer(code) this._defferer(code)
return return
@ -260,9 +318,11 @@ class KclManager {
this.engineCommandManager.endSession() this.engineCommandManager.endSession()
} }
format() { format() {
this.code = recast(parse(kclManager.code)) const ast = this.safeParse(this.code)
if (!ast) return
this.code = recast(ast)
} }
// There's overlapping resposibility between updateAst and executeAst. // There's overlapping responsibility between updateAst and executeAst.
// updateAst was added as it was used a lot before xState migration so makes the port easier. // updateAst was added as it was used a lot before xState migration so makes the port easier.
// but should probably have think about which of the function to keep // but should probably have think about which of the function to keep
async updateAst( async updateAst(
@ -270,15 +330,13 @@ class KclManager {
execute: boolean, execute: boolean,
optionalParams?: { optionalParams?: {
focusPath?: PathToNode focusPath?: PathToNode
callBack?: (ast: Program) => void
} }
): Promise<Selections | null> { ): Promise<Selections | null> {
const newCode = recast(ast) const newCode = recast(ast)
const astWithUpdatedSource = parse(newCode) const astWithUpdatedSource = this.safeParse(newCode)
optionalParams?.callBack?.(astWithUpdatedSource) if (!astWithUpdatedSource) return null
let returnVal: Selections | null = null let returnVal: Selections | null = null
this.code = newCode
if (optionalParams?.focusPath) { if (optionalParams?.focusPath) {
const { node } = getNodeFromPath<any>( const { node } = getNodeFromPath<any>(
astWithUpdatedSource, astWithUpdatedSource,
@ -299,12 +357,12 @@ class KclManager {
if (execute) { if (execute) {
// Call execute on the set ast. // Call execute on the set ast.
await this.executeAst(astWithUpdatedSource) await this.executeAst(astWithUpdatedSource, true)
} else { } else {
// When we don't re-execute, we still want to update the program // When we don't re-execute, we still want to update the program
// memory with the new ast. So we will hit the mock executor // memory with the new ast. So we will hit the mock executor
// instead. // instead.
await this.executeAstMock(astWithUpdatedSource) await this.executeAstMock(astWithUpdatedSource, true)
} }
return returnVal return returnVal
} }
@ -369,6 +427,11 @@ export function KclContextProvider({
setWasmInitFailed, setWasmInitFailed,
}) })
}, []) }, [])
const params = useParams()
useEffect(() => {
kclManager.setParams(params)
}, [params])
return ( return (
<KclContext.Provider <KclContext.Provider
value={{ value={{

View File

@ -331,9 +331,6 @@ const myVar = funcN(1, 2)`
raw: '2', raw: '2',
}, },
], ],
function: {
type: 'InMemory',
},
optional: false, optional: false,
}, },
}, },
@ -403,7 +400,6 @@ describe('testing pipe operator special', () => {
], ],
}, },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
{ {
@ -440,7 +436,6 @@ describe('testing pipe operator special', () => {
}, },
{ type: 'PipeSubstitution', start: 59, end: 60 }, { type: 'PipeSubstitution', start: 59, end: 60 },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
{ {
@ -513,7 +508,6 @@ describe('testing pipe operator special', () => {
}, },
{ type: 'PipeSubstitution', start: 105, end: 106 }, { type: 'PipeSubstitution', start: 105, end: 106 },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
{ {
@ -550,7 +544,6 @@ describe('testing pipe operator special', () => {
}, },
{ type: 'PipeSubstitution', start: 128, end: 129 }, { type: 'PipeSubstitution', start: 128, end: 129 },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
{ {
@ -573,9 +566,6 @@ describe('testing pipe operator special', () => {
}, },
{ type: 'PipeSubstitution', start: 143, end: 144 }, { type: 'PipeSubstitution', start: 143, end: 144 },
], ],
function: {
type: 'InMemory',
},
optional: false, optional: false,
}, },
], ],
@ -655,9 +645,6 @@ describe('testing pipe operator special', () => {
end: 35, end: 35,
}, },
], ],
function: {
type: 'InMemory',
},
optional: false, optional: false,
}, },
], ],
@ -1345,7 +1332,7 @@ describe('nests binary expressions correctly', () => {
], ],
}) })
}) })
it('should nest properly with two opperators of equal precedence', () => { it('should nest properly with two operators of equal precedence', () => {
const code = `const yo = 1 + 2 - 3` const code = `const yo = 1 + 2 - 3`
const { body } = parse(code) const { body } = parse(code)
expect((body[0] as any).declarations[0].init).toEqual({ expect((body[0] as any).declarations[0].init).toEqual({
@ -1382,7 +1369,7 @@ describe('nests binary expressions correctly', () => {
}, },
}) })
}) })
it('should nest properly with two opperators of equal (but higher) precedence', () => { it('should nest properly with two operators of equal (but higher) precedence', () => {
const code = `const yo = 1 * 2 / 3` const code = `const yo = 1 * 2 / 3`
const { body } = parse(code) const { body } = parse(code)
expect((body[0] as any).declarations[0].init).toEqual({ expect((body[0] as any).declarations[0].init).toEqual({
@ -1443,7 +1430,7 @@ describe('nests binary expressions correctly', () => {
type: 'BinaryExpression', type: 'BinaryExpression',
operator: '*', operator: '*',
start: 15, start: 15,
end: 26, end: 25,
left: { type: 'Literal', value: 2, raw: '2', start: 15, end: 16 }, left: { type: 'Literal', value: 2, raw: '2', start: 15, end: 16 },
right: { right: {
type: 'BinaryExpression', type: 'BinaryExpression',
@ -1567,7 +1554,6 @@ describe('test UnaryExpression', () => {
{ type: 'Literal', start: 19, end: 20, value: 4, raw: '4' }, { type: 'Literal', start: 19, end: 20, value: 4, raw: '4' },
{ type: 'Literal', start: 22, end: 25, value: 100, raw: '100' }, { type: 'Literal', start: 22, end: 25, value: 100, raw: '100' },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
}) })
@ -1601,12 +1587,10 @@ describe('testing nested call expressions', () => {
{ type: 'Literal', start: 34, end: 35, value: 5, raw: '5' }, { type: 'Literal', start: 34, end: 35, value: 5, raw: '5' },
{ type: 'Literal', start: 37, end: 38, value: 3, raw: '3' }, { type: 'Literal', start: 37, end: 38, value: 3, raw: '3' },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
}, },
], ],
function: expect.any(Object),
optional: false, optional: false,
}) })
}) })
@ -1638,7 +1622,6 @@ describe('should recognise callExpresions in binaryExpressions', () => {
}, },
{ type: 'PipeSubstitution', start: 25, end: 26 }, { type: 'PipeSubstitution', start: 25, end: 26 },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
right: { type: 'Literal', value: 1, raw: '1', start: 30, end: 31 }, right: { type: 'Literal', value: 1, raw: '1', start: 30, end: 31 },

View File

@ -18,6 +18,20 @@ export class KCLError {
} }
} }
export class KCLLexicalError extends KCLError {
constructor(msg: string, sourceRanges: [number, number][]) {
super('lexical', msg, sourceRanges)
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
}
}
export class KCLInternalError extends KCLError {
constructor(msg: string, sourceRanges: [number, number][]) {
super('internal', msg, sourceRanges)
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
}
}
export class KCLSyntaxError extends KCLError { export class KCLSyntaxError extends KCLError {
constructor(msg: string, sourceRanges: [number, number][]) { constructor(msg: string, sourceRanges: [number, number][]) {
super('syntax', msg, sourceRanges) super('syntax', msg, sourceRanges)

View File

@ -310,7 +310,7 @@ export function extrudeSketch(
const name = findUniqueName(node, 'part') const name = findUniqueName(node, 'part')
const VariableDeclaration = createVariableDeclaration(name, extrudeCall) const VariableDeclaration = createVariableDeclaration(name, extrudeCall)
let showCallIndex = getShowIndex(_node) let showCallIndex = getShowIndex(_node)
if (showCallIndex == -1) { if (showCallIndex === -1) {
// We didn't find a show, so let's just append everything // We didn't find a show, so let's just append everything
showCallIndex = _node.body.length showCallIndex = _node.body.length
} }
@ -480,21 +480,6 @@ export function createCallExpressionStdLib(
end: 0, end: 0,
name, name,
}, },
function: {
type: 'StdLib',
func: {
// We only need the name here to map it back when it serializes
// to rust, don't worry about the rest.
name,
summary: '',
description: '',
tags: [],
returnValue: { type: '', required: false, name: '', schema: {} },
args: [],
unpublished: false,
deprecated: false,
},
},
optional: false, optional: false,
arguments: args, arguments: args,
} }
@ -514,9 +499,6 @@ export function createCallExpression(
end: 0, end: 0,
name, name,
}, },
function: {
type: 'InMemory',
},
optional: false, optional: false,
arguments: args, arguments: args,
} }

View File

@ -2,5 +2,5 @@ The std is as expected, tools that are provided with the language.
For this language that means functions. For this language that means functions.
However because programatically changing the source code is a first class citizen in this lang, there needs to be helpes for adding and modifying these function calls, However because programmatically changing the source code is a first class citizen in this lang, there needs to be helpers for adding and modifying these function calls,
So it makes sense to group some of these together. So it makes sense to group some of these together.

View File

@ -289,6 +289,7 @@ export class EngineConnection {
) )
} else { } else {
console.error(`Error from server:\n${errorsString}`) console.error(`Error from server:\n${errorsString}`)
console.log(message)
} }
return return
} }
@ -664,7 +665,7 @@ export class EngineCommandManager {
}, },
}) })
// Inisialize the planes. // Initialize the planes.
this.initPlanes().then(() => { this.initPlanes().then(() => {
// We execute the code here to make sure if the stream was to // We execute the code here to make sure if the stream was to
// restart in a session, we want to make sure to execute the code. // restart in a session, we want to make sure to execute the code.
@ -887,8 +888,9 @@ export class EngineCommandManager {
} }
endSession() { endSession() {
// TODO: instead of sending a single command with `object_ids: Object.keys(this.artifactMap)` // TODO: instead of sending a single command with `object_ids: Object.keys(this.artifactMap)`
// we need to loop over them each individualy because if the engine doesn't recognise a single // we need to loop over them each individually because if the engine doesn't recognise a single
// id the whole command fails. // id the whole command fails.
const artifactsToDelete: any = {}
Object.entries(this.artifactMap).forEach(([id, artifact]) => { Object.entries(this.artifactMap).forEach(([id, artifact]) => {
const artifactTypesToDelete: ArtifactMap[string]['commandType'][] = [ const artifactTypesToDelete: ArtifactMap[string]['commandType'][] = [
// 'start_path' creates a new scene object for the path, which is why it needs to be deleted, // 'start_path' creates a new scene object for the path, which is why it needs to be deleted,
@ -898,7 +900,9 @@ export class EngineCommandManager {
'start_path', 'start_path',
] ]
if (!artifactTypesToDelete.includes(artifact.commandType)) return if (!artifactTypesToDelete.includes(artifact.commandType)) return
artifactsToDelete[id] = artifact
})
Object.keys(artifactsToDelete).forEach((id) => {
const deletCmd: EngineCommand = { const deletCmd: EngineCommand = {
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
cmd_id: uuidv4(), cmd_id: uuidv4(),
@ -982,7 +986,7 @@ export class EngineCommandManager {
if (parseCommand.type === 'modeling_cmd_req') if (parseCommand.type === 'modeling_cmd_req')
return this.handlePendingCommand(id, parseCommand?.cmd, range) return this.handlePendingCommand(id, parseCommand?.cmd, range)
} }
throw 'shouldnt reach here' throw Error('shouldnt reach here')
} }
handlePendingCommand( handlePendingCommand(
id: string, id: string,

View File

@ -20,7 +20,6 @@ import {
import { isLiteralArrayOrStatic } from './sketchcombos' import { isLiteralArrayOrStatic } from './sketchcombos'
import { toolTips, ToolTip } from '../../useStore' import { toolTips, ToolTip } from '../../useStore'
import { createPipeExpression, splitPathAtPipeExpression } from '../modifyAst' import { createPipeExpression, splitPathAtPipeExpression } from '../modifyAst'
import { generateUuidFromHashSeed } from '../../lib/uuid'
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes' import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
@ -92,18 +91,12 @@ export function createFirstArg(
throw new Error('all sketch line types should have been covered') throw new Error('all sketch line types should have been covered')
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type LineData = { type LineData = {
from: [number, number, number] from: [number, number, number]
to: [number, number, number] to: [number, number, number]
} }
function makeId(seed: string | any) {
if (typeof seed === 'string') {
return generateUuidFromHashSeed(seed)
}
return generateUuidFromHashSeed(JSON.stringify(seed))
}
export const lineTo: SketchLineHelper = { export const lineTo: SketchLineHelper = {
add: ({ add: ({
node, node,
@ -250,9 +243,6 @@ export const line: SketchLineHelper = {
]) ])
if (callExpression.arguments?.[0].type === 'ObjectExpression') { if (callExpression.arguments?.[0].type === 'ObjectExpression') {
const toProp = callExpression.arguments?.[0].properties?.find(
({ key }) => key.name === 'to'
)
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to') mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
} else { } else {
mutateArrExp(callExpression.arguments?.[0], toArrExp) mutateArrExp(callExpression.arguments?.[0], toArrExp)
@ -956,7 +946,7 @@ export function compareVec2Epsilon(
) { ) {
const compareEpsilon = 0.015625 // or 2^-6 const compareEpsilon = 0.015625 // or 2^-6
const xDifference = Math.abs(vec1[0] - vec2[0]) const xDifference = Math.abs(vec1[0] - vec2[0])
const yDifference = Math.abs(vec1[0] - vec2[0]) const yDifference = Math.abs(vec1[1] - vec2[1])
return xDifference < compareEpsilon && yDifference < compareEpsilon return xDifference < compareEpsilon && yDifference < compareEpsilon
} }
@ -974,14 +964,12 @@ export function addNewSketchLn({
const node = JSON.parse(JSON.stringify(_node)) const node = JSON.parse(JSON.stringify(_node))
const { add, updateArgs } = sketchLineHelperMap?.[fnName] || {} const { add, updateArgs } = sketchLineHelperMap?.[fnName] || {}
if (!add || !updateArgs) throw new Error('not a sketch line helper') if (!add || !updateArgs) throw new Error('not a sketch line helper')
const { node: varDec } = getNodeFromPath<VariableDeclarator>( getNodeFromPath<VariableDeclarator>(node, pathToNode, 'VariableDeclarator')
getNodeFromPath<PipeExpression | CallExpression>(
node, node,
pathToNode, pathToNode,
'VariableDeclarator' 'PipeExpression'
) )
const { node: pipeExp, shallowPath: pipePath } = getNodeFromPath<
PipeExpression | CallExpression
>(node, pathToNode, 'PipeExpression')
return add({ return add({
node, node,
previousProgramMemory, previousProgramMemory,

View File

@ -50,7 +50,7 @@ async function testingSwapSketchFnCall({
} }
} }
describe('testing swaping out sketch calls with xLine/xLineTo', () => { describe('testing swapping out sketch calls with xLine/xLineTo', () => {
const bigExampleArr = [ const bigExampleArr = [
`const part001 = startSketchOn('XY')`, `const part001 = startSketchOn('XY')`,
` |> startProfileAt([0, 0], %)`, ` |> startProfileAt([0, 0], %)`,
@ -178,7 +178,7 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
constraintType: 'horizontal', constraintType: 'horizontal',
}) })
const expectedLine = "xLine({ length: -0.86, tag: 'abc4' }, %)" const expectedLine = "xLine({ length: -0.86, tag: 'abc4' }, %)"
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatiable `-myVar` // hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatible `-myVar`
expect(newCode).toContain(expectedLine) expect(newCode).toContain(expectedLine)
// new line should start at the same place as the old line // new line should start at the same place as the old line
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine)) expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
@ -268,7 +268,7 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
}) })
}) })
describe('testing swaping out sketch calls with xLine/xLineTo while keeping variable/identifiers intact', () => { describe('testing swapping out sketch calls with xLine/xLineTo while keeping variable/identifiers intact', () => {
// Enable rotations #152 // Enable rotations #152
const variablesExampleArr = [ const variablesExampleArr = [
`const lineX = -1`, `const lineX = -1`,

View File

@ -108,7 +108,7 @@ const part001 = startSketchOn('XY')
|> line([myVar, 1], %) // ln-should use legLen for y |> line([myVar, 1], %) // ln-should use legLen for y
|> line([myVar, -1], %) // ln-legLen but negative |> line([myVar, -1], %) // ln-legLen but negative
|> line([-0.62, -1.54], %) // ln-should become angledLine |> line([-0.62, -1.54], %) // ln-should become angledLine
|> angledLine([myVar, 1.04], %) // ln-use segLen for secound arg |> angledLine([myVar, 1.04], %) // ln-use segLen for second arg
|> angledLine([45, 1.04], %) // ln-segLen again |> angledLine([45, 1.04], %) // ln-segLen again
|> angledLineOfXLength([54, 2.35], %) // ln-should be transformed to angledLine |> angledLineOfXLength([54, 2.35], %) // ln-should be transformed to angledLine
|> angledLineOfXLength([50, myVar], %) // ln-should use legAngX to calculate angle |> angledLineOfXLength([50, myVar], %) // ln-should use legAngX to calculate angle
@ -163,7 +163,7 @@ const part001 = startSketchOn('XY')
-legLen(segLen('seg01', %), myVar) -legLen(segLen('seg01', %), myVar)
], %) // ln-legLen but negative ], %) // ln-legLen but negative
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine |> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for secound arg |> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for second arg
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again |> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine |> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|> angledLineOfXLength([ |> angledLineOfXLength([
@ -471,7 +471,7 @@ async function helperThing(
} }
describe('testing getConstraintLevelFromSourceRange', () => { describe('testing getConstraintLevelFromSourceRange', () => {
it('should devide up lines into free, partial and fully contrained', () => { it('should divide up lines into free, partial and fully contrained', () => {
const code = `const baseLength = 3 const code = `const baseLength = 3
const baseThick = 1 const baseThick = 1
const armThick = 0.5 const armThick = 0.5

View File

@ -26,5 +26,4 @@ const bracket = startSketchOn('XY')
|> close(%) |> close(%)
|> extrude(width, %) |> extrude(width, %)
show(bracket)
` `

View File

@ -15,7 +15,7 @@ app needs these selections to be based on cursors, therefore the app must
be in control of selections. On top of that because we need to set cursor be in control of selections. On top of that because we need to set cursor
positions in code-mirror for selections, both from app logic, and still positions in code-mirror for selections, both from app logic, and still
allow the user to add multiple cursors like a normal editor, it's best to allow the user to add multiple cursors like a normal editor, it's best to
let code mirror control cursor positions and assosiate those source ranges let code mirror control cursor positions and associate those source ranges
with entity ids from code-mirror events later. with entity ids from code-mirror events later.
So it's a lot of back and forth. conceptually the back and forth is: So it's a lot of back and forth. conceptually the back and forth is:
@ -43,7 +43,7 @@ In detail:
1) Click commands are mostly sent in stream.tsx search for 1) Click commands are mostly sent in stream.tsx search for
"select_with_point" "select_with_point"
2) The handler for when the engine sends back entitiy ids calls 2) The handler for when the engine sends back entity ids calls
getEventForSelectWithPoint, it fires an XState event to update our getEventForSelectWithPoint, it fires an XState event to update our
selections is xstate context selections is xstate context
3 and 4) The XState handler for the above uses handleSelectionBatch and 3 and 4) The XState handler for the above uses handleSelectionBatch and
@ -102,8 +102,8 @@ export async function getEventForSelectWithPoint(
Models['OkModelingCmdResponse_type'], Models['OkModelingCmdResponse_type'],
{ type: 'select_with_point' } { type: 'select_with_point' }
>, >,
{ sketchEnginePathId }: { sketchEnginePathId: string } { sketchEnginePathId }: { sketchEnginePathId?: string }
): Promise<ModelingMachineEvent> { ): Promise<ModelingMachineEvent | null> {
if (!data?.entity_id) { if (!data?.entity_id) {
return { return {
type: 'Set selection', type: 'Set selection',
@ -120,6 +120,7 @@ export async function getEventForSelectWithPoint(
}, },
} }
} }
// if (!sketchEnginePathId) return null
// selected a vertex // selected a vertex
const res = await engineCommandManager.sendSceneCommand({ const res = await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
@ -127,7 +128,7 @@ export async function getEventForSelectWithPoint(
cmd: { cmd: {
type: 'path_get_curve_uuids_for_vertices', type: 'path_get_curve_uuids_for_vertices',
vertex_ids: [data.entity_id], vertex_ids: [data.entity_id],
path_id: sketchEnginePathId, path_id: sketchEnginePathId || '',
}, },
}) })
const curveIds = res?.data?.data?.curve_ids const curveIds = res?.data?.data?.curve_ids
@ -303,7 +304,7 @@ export function resetAndSetEngineEntitySelectionCmds(
selections: SelectionToEngine[] selections: SelectionToEngine[]
): Models['WebSocketRequest_type'][] { ): Models['WebSocketRequest_type'][] {
if (!engineCommandManager.engineConnection?.isReady()) { if (!engineCommandManager.engineConnection?.isReady()) {
console.log('engine connection isnt ready') console.log('engine connection is not ready')
return [] return []
} }
return [ return [

View File

@ -9,7 +9,6 @@ import { documentDir, homeDir, sep } from '@tauri-apps/api/path'
import { isTauri } from './isTauri' import { isTauri } from './isTauri'
import { ProjectWithEntryPointMetadata } from '../Router' import { ProjectWithEntryPointMetadata } from '../Router'
import { metadata } from 'tauri-plugin-fs-extra-api' import { metadata } from 'tauri-plugin-fs-extra-api'
import { bracket } from './exampleKcl'
const PROJECT_FOLDER = 'kittycad-modeling-projects' const PROJECT_FOLDER = 'kittycad-modeling-projects'
export const FILE_EXT = '.kcl' export const FILE_EXT = '.kcl'
@ -211,7 +210,8 @@ export function sortProject(project: FileEntry[]): FileEntry[] {
// Creates a new file in the default directory with the default project name // Creates a new file in the default directory with the default project name
// Returns the path to the new file // Returns the path to the new file
export async function createNewProject( export async function createNewProject(
path: string path: string,
initCode = ''
): Promise<ProjectWithEntryPointMetadata> { ): Promise<ProjectWithEntryPointMetadata> {
if (!isTauri) { if (!isTauri) {
throw new Error('createNewProject() can only be called from a Tauri app') throw new Error('createNewProject() can only be called from a Tauri app')
@ -225,10 +225,12 @@ export async function createNewProject(
}) })
} }
await writeTextFile(path + sep + PROJECT_ENTRYPOINT, bracket).catch((err) => { await writeTextFile(path + sep + PROJECT_ENTRYPOINT, initCode).catch(
(err) => {
console.error('Error creating new file:', err) console.error('Error creating new file:', err)
throw err throw err
}) }
)
const m = await metadata(path) const m = await metadata(path)

View File

@ -9,6 +9,7 @@ import { v4 as uuidv4 } from 'uuid'
type WebSocketResponse = Models['OkWebSocketResponseData_type'] type WebSocketResponse = Models['OkWebSocketResponseData_type']
class MockEngineCommandManager { class MockEngineCommandManager {
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor(mockParams: { constructor(mockParams: {
setIsStreamReady: (isReady: boolean) => void setIsStreamReady: (isReady: boolean) => void
setMediaStream: (stream: MediaStream) => void setMediaStream: (stream: MediaStream) => void

View File

@ -664,8 +664,8 @@ export const modelingMachine = createMachine(
on: { on: {
Cancel: { Cancel: {
target: 'idle', target: 'idle',
// TODO what if we're existing extrude equiped, should these actions still be fired? // TODO what if we're existing extrude equipped, should these actions still be fired?
// mabye cancel needs to have a guard for if else logic? // maybe cancel needs to have a guard for if else logic?
actions: [ actions: [
'edit_mode_exit', 'edit_mode_exit',
'default_camera_disable_sketch_mode', 'default_camera_disable_sketch_mode',
@ -882,7 +882,7 @@ export const modelingMachine = createMachine(
// TODO implement source ranges for all of these constraints // TODO implement source ranges for all of these constraints
// need to make the async like the modal constraints // need to make the async like the modal constraints
'Make selection horizontal': ({ selectionRanges }) => { 'Make selection horizontal': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVert( const { modifiedAst } = applyConstraintHorzVert(
selectionRanges, selectionRanges,
'horizontal', 'horizontal',
kclManager.ast, kclManager.ast,
@ -891,7 +891,7 @@ export const modelingMachine = createMachine(
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Make selection vertical': ({ selectionRanges }) => { 'Make selection vertical': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVert( const { modifiedAst } = applyConstraintHorzVert(
selectionRanges, selectionRanges,
'vertical', 'vertical',
kclManager.ast, kclManager.ast,
@ -900,33 +900,33 @@ export const modelingMachine = createMachine(
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain horizontally align': ({ selectionRanges }) => { 'Constrain horizontally align': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVertAlign({ const { modifiedAst } = applyConstraintHorzVertAlign({
selectionRanges, selectionRanges,
constraint: 'setVertDistance', constraint: 'setVertDistance',
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain vertically align': ({ selectionRanges }) => { 'Constrain vertically align': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVertAlign({ const { modifiedAst } = applyConstraintHorzVertAlign({
selectionRanges, selectionRanges,
constraint: 'setHorzDistance', constraint: 'setHorzDistance',
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain equal length': ({ selectionRanges }) => { 'Constrain equal length': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyConstraintEqualLength({ const { modifiedAst } = applyConstraintEqualLength({
selectionRanges, selectionRanges,
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain parallel': ({ selectionRanges }) => { 'Constrain parallel': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyConstraintEqualAngle({ const { modifiedAst } = applyConstraintEqualAngle({
selectionRanges, selectionRanges,
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain remove constraints': ({ selectionRanges }) => { 'Constrain remove constraints': ({ selectionRanges }) => {
const { modifiedAst, pathToNodeMap } = applyRemoveConstrainingValues({ const { modifiedAst } = applyRemoveConstrainingValues({
selectionRanges, selectionRanges,
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)

View File

@ -43,7 +43,10 @@ function OnboardingWithNewFile() {
ONBOARDING_PROJECT_NAME, ONBOARDING_PROJECT_NAME,
nextIndex nextIndex
) )
const newFile = await createNewProject(defaultDirectory + sep + name) const newFile = await createNewProject(
defaultDirectory + sep + name,
bracket
)
navigate( navigate(
`${paths.FILE}/${encodeURIComponent( `${paths.FILE}/${encodeURIComponent(
newFile.path + sep + PROJECT_ENTRYPOINT newFile.path + sep + PROJECT_ENTRYPOINT
@ -79,7 +82,7 @@ function OnboardingWithNewFile() {
<ActionButton <ActionButton
Element="button" Element="button"
onClick={() => { onClick={() => {
kclManager.setCode(bracket) kclManager.setCodeAndExecute(bracket)
next() next()
}} }}
icon={{ icon: faArrowRight }} icon={{ icon: faArrowRight }}
@ -118,7 +121,7 @@ function OnboardingWithNewFile() {
Element="button" Element="button"
onClick={() => { onClick={() => {
createAndOpenNewProject() createAndOpenNewProject()
kclManager.setCode(bracket) kclManager.setCode(bracket, false)
dismiss() dismiss()
}} }}
icon={{ icon: faArrowRight }} icon={{ icon: faArrowRight }}

View File

@ -32,6 +32,7 @@ import {
} from 'lib/tauriFS' } from 'lib/tauriFS'
import { ONBOARDING_PROJECT_NAME } from './Onboarding' import { ONBOARDING_PROJECT_NAME } from './Onboarding'
import { sep } from '@tauri-apps/api/path' import { sep } from '@tauri-apps/api/path'
import { bracket } from 'lib/exampleKcl'
export const Settings = () => { export const Settings = () => {
const loaderData = const loaderData =
@ -96,7 +97,10 @@ export const Settings = () => {
ONBOARDING_PROJECT_NAME, ONBOARDING_PROJECT_NAME,
nextIndex nextIndex
) )
const newFile = await createNewProject(defaultDirectory + sep + name) const newFile = await createNewProject(
defaultDirectory + sep + name,
bracket
)
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`) navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)
} }

View File

@ -67,6 +67,7 @@ const SignIn = () => {
onClick={signInTauri} onClick={signInTauri}
icon={{ icon: faSignInAlt }} icon={{ icon: faSignInAlt }}
className="w-fit mt-4" className="w-fit mt-4"
id="signin"
> >
Sign in Sign in
</ActionButton> </ActionButton>

View File

@ -253,11 +253,13 @@ export async function executeAst({
engineCommandManager, engineCommandManager,
defaultPlanes, defaultPlanes,
useFakeExecutor = false, useFakeExecutor = false,
programMemoryOverride,
}: { }: {
ast: Program ast: Program
engineCommandManager: EngineCommandManager engineCommandManager: EngineCommandManager
defaultPlanes: DefaultPlanes defaultPlanes: DefaultPlanes
useFakeExecutor?: boolean useFakeExecutor?: boolean
programMemoryOverride?: ProgramMemory
}): Promise<{ }): Promise<{
logs: string[] logs: string[]
errors: KCLError[] errors: KCLError[]
@ -269,10 +271,13 @@ export async function executeAst({
engineCommandManager.startNewSession() engineCommandManager.startNewSession()
} }
const programMemory = await (useFakeExecutor const programMemory = await (useFakeExecutor
? enginelessExecutor(ast, { ? enginelessExecutor(
ast,
programMemoryOverride || {
root: defaultProgramMemory, root: defaultProgramMemory,
return: null, return: null,
}) }
)
: _executor( : _executor(
ast, ast,
{ {

View File

@ -6,10 +6,10 @@
serial-integration = { max-threads = 4 } serial-integration = { max-threads = 4 }
[profile.default] [profile.default]
slow-timeout = { period = "60s", terminate-after = 1 } slow-timeout = { period = "10s", terminate-after = 1 }
[profile.ci] [profile.ci]
slow-timeout = { period = "120s", terminate-after = 10 } slow-timeout = { period = "30s", terminate-after = 5 }
[[profile.default.overrides]] [[profile.default.overrides]]
filter = "test(serial_test_)" filter = "test(serial_test_)"
@ -20,3 +20,7 @@ threads-required = 4
filter = "test(serial_test_)" filter = "test(serial_test_)"
test-group = "serial-integration" test-group = "serial-integration"
threads-required = 4 threads-required = 4
[[profile.default.overrides]]
filter = "test(parser::parser_impl::snapshot_tests)"
slow-timeout = { period = "1s", terminate-after = 5 }

628
src/wasm-lib/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@
name = "wasm-lib" name = "wasm-lib"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.73"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib] [lib]
@ -11,28 +13,28 @@ crate-type = ["cdylib"]
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] } bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
gloo-utils = "0.2.0" gloo-utils = "0.2.0"
kcl-lib = { path = "kcl" } kcl-lib = { path = "kcl" }
kittycad = { version = "0.2.33", default-features = false, features = ["js"] } kittycad = { workspace = true }
serde_json = "1.0.107" serde_json = "1.0.108"
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] } uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
wasm-bindgen = "0.2.87" wasm-bindgen = "0.2.88"
wasm-bindgen-futures = "0.4.37" wasm-bindgen-futures = "0.4.37"
[dev-dependencies] [dev-dependencies]
anyhow = "1" anyhow = "1"
image = "0.24.7" image = "0.24.7"
kittycad = "0.2.33" kittycad = { workspace = true, default-features = true }
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"
reqwest = { version = "0.11.22", default-features = false } reqwest = { version = "0.11.22", default-features = false }
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }
twenty-twenty = "0.6.1" twenty-twenty = "0.6.1"
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] } uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
futures = "0.3.28" futures = "0.3.29"
js-sys = "0.3.64" js-sys = "0.3.65"
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] } tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
wasm-bindgen-futures = { version = "0.4.37", features = ["futures-core-03-stream"] } wasm-bindgen-futures = { version = "0.4.37", features = ["futures-core-03-stream"] }
wasm-streams = "0.3.0" wasm-streams = "0.4.0"
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
version = "0.3.57" version = "0.3.57"
@ -53,6 +55,9 @@ members = [
"kcl", "kcl",
] ]
[workspace.dependencies]
kittycad = { version = "0.2.41", default-features = false, features = ["js"] }
[[test]] [[test]]
name = "executor" name = "executor"
path = "tests/executor/main.rs" path = "tests/executor/main.rs"

View File

@ -4,6 +4,8 @@ description = "A tool for generating documentation from Rust derive macros"
version = "0.1.4" version = "0.1.4"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.73"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -14,9 +16,9 @@ proc-macro = true
convert_case = "0.6.0" convert_case = "0.6.0"
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"
serde = { version = "1.0.189", features = ["derive"] } serde = { version = "1.0.192", features = ["derive"] }
serde_tokenstream = "0.2" serde_tokenstream = "0.2"
syn = { version = "2.0.38", features = ["full"] } syn = { version = "2.0.39", features = ["full"] }
[dev-dependencies] [dev-dependencies]
expectorate = "1.1.0" expectorate = "1.1.0"

View File

@ -4,6 +4,8 @@ description = "KittyCAD Language"
version = "0.1.35" version = "0.1.35"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.73"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -11,31 +13,31 @@ license = "MIT"
anyhow = { version = "1.0.75", features = ["backtrace"] } anyhow = { version = "1.0.75", features = ["backtrace"] }
async-recursion = "1.0.5" async-recursion = "1.0.5"
async-trait = "0.1.73" async-trait = "0.1.73"
clap = { version = "4.4.6", features = ["cargo", "derive", "env", "unicode"], optional = true } clap = { version = "4.4.7", features = ["cargo", "derive", "env", "unicode"], optional = true }
dashmap = "5.5.3" dashmap = "5.5.3"
derive-docs = { version = "0.1.4" } derive-docs = { version = "0.1.4" }
#derive-docs = { path = "../derive-docs" } #derive-docs = { path = "../derive-docs" }
kittycad = { version = "0.2.33", default-features = false, features = ["js"] } kittycad = { workspace = true }
lazy_static = "1.4.0" lazy_static = "1.4.0"
parse-display = "0.8.2" parse-display = "0.8.2"
schemars = { version = "0.8", features = ["impl_json_schema", "url", "uuid1"] } schemars = { version = "0.8", features = ["impl_json_schema", "url", "uuid1"] }
serde = { version = "1.0.189", features = ["derive"] } serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.107" serde_json = "1.0.108"
thiserror = "1.0.49" thiserror = "1.0.50"
ts-rs = { version = "7", package = "ts-rs-json-value", features = ["serde-json-impl", "schemars-impl", "uuid-impl"] } ts-rs = { version = "7", package = "ts-rs-json-value", features = ["serde-json-impl", "schemars-impl", "uuid-impl"] }
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] } uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
winnow = "0.5.16" winnow = "0.5.18"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = { version = "0.3.64" } js-sys = { version = "0.3.65" }
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] } tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
wasm-bindgen = "0.2.87" wasm-bindgen = "0.2.88"
wasm-bindgen-futures = "0.4.37" wasm-bindgen-futures = "0.4.37"
web-sys = { version = "0.3.64", features = ["console"] } web-sys = { version = "0.3.64", features = ["console"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] } bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
futures = { version = "0.3.28" } futures = { version = "0.3.29" }
reqwest = { version = "0.11.22", default-features = false } reqwest = { version = "0.11.22", default-features = false }
tokio = { version = "1.33.0", features = ["full"] } tokio = { version = "1.33.0", features = ["full"] }
tokio-tungstenite = { version = "0.20.0", features = ["rustls-tls-native-roots"] } tokio-tungstenite = { version = "0.20.0", features = ["rustls-tls-native-roots"] }
@ -50,9 +52,13 @@ engine = []
panic = "abort" panic = "abort"
debug = true debug = true
[profile.bench]
debug = true # Flamegraphs of benchmarks require accurate debug symbols
[dev-dependencies] [dev-dependencies]
criterion = "0.5.1" criterion = "0.5.1"
expectorate = "1.1.0" expectorate = "1.1.0"
insta = { version = "1.34.0", features = ["json"] }
itertools = "0.11.0" itertools = "0.11.0"
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }

View File

@ -11,6 +11,7 @@ pub fn bench_parse(c: &mut Criterion) {
("pipes_on_pipes", PIPES_PROGRAM), ("pipes_on_pipes", PIPES_PROGRAM),
("big_kitt", KITT_PROGRAM), ("big_kitt", KITT_PROGRAM),
("cube", CUBE_PROGRAM), ("cube", CUBE_PROGRAM),
("math", MATH_PROGRAM),
] { ] {
let tokens = kcl_lib::token::lexer(file); let tokens = kcl_lib::token::lexer(file);
c.bench_function(&format!("parse_{name}"), move |b| { c.bench_function(&format!("parse_{name}"), move |b| {
@ -33,3 +34,4 @@ criterion_main!(benches);
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl"); const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl"); const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl");
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl"); const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");

View File

@ -3,6 +3,8 @@ name = "kcl-lib-fuzz"
version = "0.0.0" version = "0.0.0"
publish = false publish = false
edition = "2021" edition = "2021"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.73"
[package.metadata] [package.metadata]
cargo-fuzz = true cargo-fuzz = true

View File

@ -136,7 +136,7 @@ pub async fn modify_ast_for_sketch(
})?; })?;
let mut additional_lines = Vec::new(); let mut additional_lines = Vec::new();
let mut last_point = first_control_points.points[1].clone(); let mut last_point = first_control_points.points[1];
for control_point in control_points[1..].iter() { for control_point in control_points[1..].iter() {
additional_lines.push([ additional_lines.push([
(control_point.points[1].x - last_point.x), (control_point.points[1].x - last_point.x),

View File

@ -6,15 +6,20 @@ use anyhow::Result;
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Map; use serde_json::{Map, Value as JValue};
use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, DocumentSymbol, Range as LspRange, SymbolKind}; use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, DocumentSymbol, Range as LspRange, SymbolKind};
pub use self::literal_value::LiteralValue;
use crate::{ use crate::{
docs::StdLibFn,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
executor::{ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, UserVal}, executor::{BodyType, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, UserVal},
parser::PIPE_OPERATOR, parser::PIPE_OPERATOR,
std::{kcl_stdlib::KclStdLibFn, FunctionKind},
}; };
mod literal_value;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -371,13 +376,13 @@ impl BodyItem {
} }
} }
impl From<BodyItem> for crate::executor::SourceRange { impl From<BodyItem> for SourceRange {
fn from(item: BodyItem) -> Self { fn from(item: BodyItem) -> Self {
Self([item.start(), item.end()]) Self([item.start(), item.end()])
} }
} }
impl From<&BodyItem> for crate::executor::SourceRange { impl From<&BodyItem> for SourceRange {
fn from(item: &BodyItem) -> Self { fn from(item: &BodyItem) -> Self {
Self([item.start(), item.end()]) Self([item.start(), item.end()])
} }
@ -534,13 +539,13 @@ impl Value {
} }
} }
impl From<Value> for crate::executor::SourceRange { impl From<Value> for SourceRange {
fn from(value: Value) -> Self { fn from(value: Value) -> Self {
Self([value.start(), value.end()]) Self([value.start(), value.end()])
} }
} }
impl From<&Value> for crate::executor::SourceRange { impl From<&Value> for SourceRange {
fn from(value: &Value) -> Self { fn from(value: &Value) -> Self {
Self([value.start(), value.end()]) Self([value.start(), value.end()])
} }
@ -558,13 +563,13 @@ pub enum BinaryPart {
MemberExpression(Box<MemberExpression>), MemberExpression(Box<MemberExpression>),
} }
impl From<BinaryPart> for crate::executor::SourceRange { impl From<BinaryPart> for SourceRange {
fn from(value: BinaryPart) -> Self { fn from(value: BinaryPart) -> Self {
Self([value.start(), value.end()]) Self([value.start(), value.end()])
} }
} }
impl From<&BinaryPart> for crate::executor::SourceRange { impl From<&BinaryPart> for SourceRange {
fn from(value: &BinaryPart) -> Self { fn from(value: &BinaryPart) -> Self {
Self([value.start(), value.end()]) Self([value.start(), value.end()])
} }
@ -640,7 +645,7 @@ impl BinaryPart {
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this globally because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
@ -780,7 +785,7 @@ pub enum NonCodeValue {
/// 1 + 1 /// 1 + 1
/// ``` /// ```
/// Now this is important. The block comment is attached to the next line. /// Now this is important. The block comment is attached to the next line.
/// This is always the case. Also the block comment doesnt have a new line above it. /// This is always the case. Also the block comment doesn't have a new line above it.
/// If it did it would be a `NewLineBlockComment`. /// If it did it would be a `NewLineBlockComment`.
BlockComment { BlockComment {
value: String, value: String,
@ -858,7 +863,6 @@ pub struct CallExpression {
pub callee: Identifier, pub callee: Identifier,
pub arguments: Vec<Value>, pub arguments: Vec<Value>,
pub optional: bool, pub optional: bool,
pub function: Function,
} }
impl_value_meta!(CallExpression); impl_value_meta!(CallExpression);
@ -871,22 +875,12 @@ impl From<CallExpression> for Value {
impl CallExpression { impl CallExpression {
pub fn new(name: &str, arguments: Vec<Value>) -> Result<Self, KclError> { pub fn new(name: &str, arguments: Vec<Value>) -> Result<Self, KclError> {
// Create our stdlib.
let stdlib = crate::std::StdLib::new();
let func = stdlib.get(name).ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails {
message: format!("Function {} is not defined", name),
source_ranges: vec![],
})
})?;
Ok(Self { Ok(Self {
start: 0, start: 0,
end: 0, end: 0,
callee: Identifier::new(name), callee: Identifier::new(name),
arguments, arguments,
optional: false, optional: false,
function: Function::StdLib { func },
}) })
} }
@ -930,7 +924,7 @@ impl CallExpression {
binary_expression.get_result(memory, pipe_info, ctx).await? binary_expression.get_result(memory, pipe_info, ctx).await?
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this globally because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
@ -968,8 +962,8 @@ impl CallExpression {
fn_args.push(result); fn_args.push(result);
} }
match &self.function { match ctx.stdlib.get_either(&self.callee.name) {
Function::StdLib { func } => { FunctionKind::Core(func) => {
// Attempt to call the function. // Attempt to call the function.
let args = crate::std::Args::new(fn_args, self.into(), ctx.clone()); let args = crate::std::Args::new(fn_args, self.into(), ctx.clone());
let result = func.std_lib_fn()(args).await?; let result = func.std_lib_fn()(args).await?;
@ -981,14 +975,54 @@ impl CallExpression {
Ok(result) Ok(result)
} }
} }
Function::InMemory => { FunctionKind::Std(func) => {
let function_expression = func.function();
if fn_args.len() != function_expression.params.len() {
return Err(KclError::Semantic(KclErrorDetails {
message: format!(
"Expected {} arguments, got {}",
function_expression.params.len(),
fn_args.len(),
),
source_ranges: vec![(function_expression).into()],
}));
}
// Add the arguments to the memory.
let mut fn_memory = memory.clone();
for (index, param) in function_expression.params.iter().enumerate() {
fn_memory.add(&param.name, fn_args.get(index).unwrap().clone(), param.into())?;
}
// Call the stdlib function
let p = func.function().clone().body;
let results = crate::executor::execute(p, &mut fn_memory, BodyType::Block, ctx).await?;
let out = results.return_;
let result = out.ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails {
message: format!("Result of stdlib function {} is undefined", fn_name),
source_ranges: vec![self.into()],
})
})?;
let result = result.get_value()?;
if pipe_info.is_in_pipe {
pipe_info.index += 1;
pipe_info.previous_results.push(result);
execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), ctx).await
} else {
Ok(result)
}
}
FunctionKind::UserDefined => {
let func = memory.get(&fn_name, self.into())?; let func = memory.get(&fn_name, self.into())?;
let result = func let result = func
.call_fn(fn_args, memory.clone(), ctx.clone()) .call_fn(fn_args, memory.clone(), ctx.clone())
.await? .await?
.ok_or_else(|| { .ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails { KclError::UndefinedValue(KclErrorDetails {
message: format!("Result of function {} is undefined", fn_name), message: format!("Result of user-defined function {} is undefined", fn_name),
source_ranges: vec![self.into()], source_ranges: vec![self.into()],
}) })
})?; })?;
@ -1063,10 +1097,15 @@ impl CallExpression {
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Function { pub enum Function {
/// A stdlib function. /// A stdlib function written in Rust (aka core lib).
StdLib { StdLib {
/// The function. /// The function.
func: Box<dyn crate::docs::StdLibFn>, func: Box<dyn StdLibFn>,
},
/// A stdlib function written in KCL.
StdLibKcl {
/// The function.
func: Box<dyn KclStdLibFn>,
}, },
/// A function that is defined in memory. /// A function that is defined in memory.
#[default] #[default]
@ -1312,24 +1351,18 @@ impl VariableDeclarator {
pub struct Literal { pub struct Literal {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
pub value: serde_json::Value, pub value: LiteralValue,
pub raw: String, pub raw: String,
} }
impl_value_meta!(Literal); impl_value_meta!(Literal);
impl From<Literal> for Value {
fn from(literal: Literal) -> Self {
Value::Literal(Box::new(literal))
}
}
impl Literal { impl Literal {
pub fn new(value: serde_json::Value) -> Self { pub fn new(value: LiteralValue) -> Self {
Self { Self {
start: 0, start: 0,
end: 0, end: 0,
raw: value.to_string(), raw: JValue::from(value.clone()).to_string(),
value, value,
} }
} }
@ -1343,11 +1376,19 @@ impl Literal {
} }
fn recast(&self) -> String { fn recast(&self) -> String {
if let serde_json::Value::String(value) = &self.value { match self.value {
let quote = if self.raw.trim().starts_with('"') { '"' } else { '\'' }; LiteralValue::Fractional(x) => {
format!("{}{}{}", quote, value, quote) if x.fract() == 0.0 {
format!("{x:?}")
} else { } else {
self.value.to_string() self.raw.clone()
}
}
LiteralValue::IInteger(_) => self.raw.clone(),
LiteralValue::String(ref s) => {
let quote = if self.raw.trim().starts_with('"') { '"' } else { '\'' };
format!("{quote}{s}{quote}")
}
} }
} }
} }
@ -1355,7 +1396,7 @@ impl Literal {
impl From<Literal> for MemoryItem { impl From<Literal> for MemoryItem {
fn from(literal: Literal) -> Self { fn from(literal: Literal) -> Self {
MemoryItem::UserVal(UserVal { MemoryItem::UserVal(UserVal {
value: literal.value.clone(), value: JValue::from(literal.value.clone()),
meta: vec![Metadata { meta: vec![Metadata {
source_range: literal.into(), source_range: literal.into(),
}], }],
@ -1366,7 +1407,7 @@ impl From<Literal> for MemoryItem {
impl From<&Box<Literal>> for MemoryItem { impl From<&Box<Literal>> for MemoryItem {
fn from(literal: &Box<Literal>) -> Self { fn from(literal: &Box<Literal>) -> Self {
MemoryItem::UserVal(UserVal { MemoryItem::UserVal(UserVal {
value: literal.value.clone(), value: JValue::from(literal.value.clone()),
meta: vec![Metadata { meta: vec![Metadata {
source_range: literal.into(), source_range: literal.into(),
}], }],
@ -1552,7 +1593,7 @@ impl ArrayExpression {
binary_expression.get_result(memory, pipe_info, ctx).await? binary_expression.get_result(memory, pipe_info, ctx).await?
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this globally because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
@ -1703,7 +1744,7 @@ impl ObjectExpression {
binary_expression.get_result(memory, pipe_info, ctx).await? binary_expression.get_result(memory, pipe_info, ctx).await?
} }
Value::CallExpression(call_expression) => { Value::CallExpression(call_expression) => {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this globally because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
@ -1831,13 +1872,13 @@ impl MemberObject {
} }
} }
impl From<MemberObject> for crate::executor::SourceRange { impl From<MemberObject> for SourceRange {
fn from(obj: MemberObject) -> Self { fn from(obj: MemberObject) -> Self {
Self([obj.start(), obj.end()]) Self([obj.start(), obj.end()])
} }
} }
impl From<&MemberObject> for crate::executor::SourceRange { impl From<&MemberObject> for SourceRange {
fn from(obj: &MemberObject) -> Self { fn from(obj: &MemberObject) -> Self {
Self([obj.start(), obj.end()]) Self([obj.start(), obj.end()])
} }
@ -1867,13 +1908,13 @@ impl LiteralIdentifier {
} }
} }
impl From<LiteralIdentifier> for crate::executor::SourceRange { impl From<LiteralIdentifier> for SourceRange {
fn from(id: LiteralIdentifier) -> Self { fn from(id: LiteralIdentifier) -> Self {
Self([id.start(), id.end()]) Self([id.start(), id.end()])
} }
} }
impl From<&LiteralIdentifier> for crate::executor::SourceRange { impl From<&LiteralIdentifier> for SourceRange {
fn from(id: &LiteralIdentifier) -> Self { fn from(id: &LiteralIdentifier) -> Self {
Self([id.start(), id.end()]) Self([id.start(), id.end()])
} }
@ -1967,17 +2008,21 @@ impl MemberExpression {
LiteralIdentifier::Identifier(identifier) => identifier.name.to_string(), LiteralIdentifier::Identifier(identifier) => identifier.name.to_string(),
LiteralIdentifier::Literal(literal) => { LiteralIdentifier::Literal(literal) => {
let value = literal.value.clone(); let value = literal.value.clone();
// Parse this as a string. match value {
if let serde_json::Value::String(string) = value { LiteralValue::IInteger(x) if x >= 0 => return self.get_result_array(memory, x as usize),
string LiteralValue::IInteger(x) => {
} else if let serde_json::Value::Number(_) = &value { return Err(KclError::Syntax(KclErrorDetails {
// It can also be a number if we are getting a member of an array. source_ranges: vec![self.into()],
return self.get_result_array(memory, parse_json_number_as_usize(&value, self.into())?); message: format!("invalid index: {x}"),
} else { }))
return Err(KclError::Semantic(KclErrorDetails { }
message: format!("Expected string literal or number for property name, found {:?}", value), LiteralValue::Fractional(x) => {
source_ranges: vec![literal.into()], return Err(KclError::Syntax(KclErrorDetails {
})); source_ranges: vec![self.into()],
message: format!("invalid index: {x}"),
}))
}
LiteralValue::String(s) => s,
} }
} }
}; };
@ -2133,7 +2178,7 @@ impl BinaryExpression {
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this globally because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
@ -2175,6 +2220,7 @@ impl BinaryExpression {
BinaryOperator::Mul => (left * right).into(), BinaryOperator::Mul => (left * right).into(),
BinaryOperator::Div => (left / right).into(), BinaryOperator::Div => (left / right).into(),
BinaryOperator::Mod => (left % right).into(), BinaryOperator::Mod => (left % right).into(),
BinaryOperator::Pow => (left.powf(right)).into(),
}; };
Ok(MemoryItem::UserVal(UserVal { Ok(MemoryItem::UserVal(UserVal {
@ -2208,22 +2254,6 @@ pub fn parse_json_number_as_f64(j: &serde_json::Value, source_range: SourceRange
} }
} }
pub fn parse_json_number_as_usize(j: &serde_json::Value, source_range: SourceRange) -> Result<usize, KclError> {
if let serde_json::Value::Number(n) = &j {
Ok(n.as_i64().ok_or_else(|| {
KclError::Syntax(KclErrorDetails {
source_ranges: vec![source_range],
message: format!("Invalid index: {}", j),
})
})? as usize)
} else {
Err(KclError::Syntax(KclErrorDetails {
source_ranges: vec![source_range],
message: format!("Invalid index: {}", j),
}))
}
}
pub fn parse_json_value_as_string(j: &serde_json::Value) -> Option<String> { pub fn parse_json_value_as_string(j: &serde_json::Value) -> Option<String> {
if let serde_json::Value::String(n) = &j { if let serde_json::Value::String(n) = &j {
Some(n.clone()) Some(n.clone())
@ -2257,13 +2287,46 @@ pub enum BinaryOperator {
#[serde(rename = "%")] #[serde(rename = "%")]
#[display("%")] #[display("%")]
Mod, Mod,
/// Raise a number to a power.
#[serde(rename = "^")]
#[display("^")]
Pow,
}
/// Mathematical associativity.
/// Should a . b . c be read as (a . b) . c, or a . (b . c)
/// See <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#precedence_and_associativity> for more.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum Associativity {
/// Read a . b . c as (a . b) . c
Left,
/// Read a . b . c as a . (b . c)
Right,
}
impl Associativity {
pub fn is_left(&self) -> bool {
matches!(self, Self::Left)
}
} }
impl BinaryOperator { impl BinaryOperator {
/// Follow JS definitions of each operator.
/// Taken from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table>
pub fn precedence(&self) -> u8 { pub fn precedence(&self) -> u8 {
match &self { match &self {
BinaryOperator::Add | BinaryOperator::Sub => 11, BinaryOperator::Add | BinaryOperator::Sub => 11,
BinaryOperator::Mul | BinaryOperator::Div | BinaryOperator::Mod => 12, BinaryOperator::Mul | BinaryOperator::Div | BinaryOperator::Mod => 12,
BinaryOperator::Pow => 6,
}
}
/// Follow JS definitions of each operator.
/// Taken from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table>
pub fn associativity(&self) -> Associativity {
match self {
Self::Add | Self::Sub | Self::Mul | Self::Div | Self::Mod => Associativity::Left,
Self::Pow => Associativity::Right,
} }
} }
} }
@ -2307,7 +2370,7 @@ impl UnaryExpression {
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would // We DO NOT set this globally because if we did and this was called inside a pipe it would
// stop the execution of the pipe. // stop the execution of the pipe.
// THIS IS IMPORTANT. // THIS IS IMPORTANT.
let mut new_pipe_info = pipe_info.clone(); let mut new_pipe_info = pipe_info.clone();
@ -3255,4 +3318,40 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#;
let recasted = program.recast(&Default::default(), 0); let recasted = program.recast(&Default::default(), 0);
assert_eq!(recasted.trim(), some_program_string); assert_eq!(recasted.trim(), some_program_string);
} }
#[test]
fn recast_literal() {
use winnow::Parser;
for (i, (raw, expected, reason)) in [
(
"5.0",
"5.0",
"fractional numbers should stay fractional, i.e. don't reformat this to '5'",
),
(
"5",
"5",
"integers should stay integral, i.e. don't reformat this to '5.0'",
),
(
"5.0000000",
"5.0",
"if the number is f64 but not fractional, use its canonical format",
),
("5.1", "5.1", "straightforward case works"),
]
.into_iter()
.enumerate()
{
let tokens = crate::token::lexer(raw);
let literal = crate::parser::parser_impl::unsigned_number_literal
.parse(&tokens)
.unwrap();
assert_eq!(
literal.recast(),
expected,
"failed test {i}, which is testing that {reason}"
);
}
}
} }

View File

@ -0,0 +1,70 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value as JValue;
use super::{Literal, Value};
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(untagged, rename_all = "snake_case")]
pub enum LiteralValue {
IInteger(i64),
Fractional(f64),
String(String),
}
impl From<Literal> for Value {
fn from(literal: Literal) -> Self {
Value::Literal(Box::new(literal))
}
}
impl From<LiteralValue> for JValue {
fn from(value: LiteralValue) -> Self {
match value {
LiteralValue::IInteger(x) => x.into(),
LiteralValue::Fractional(x) => x.into(),
LiteralValue::String(x) => x.into(),
}
}
}
impl From<f64> for LiteralValue {
fn from(value: f64) -> Self {
Self::Fractional(value)
}
}
impl From<i64> for LiteralValue {
fn from(value: i64) -> Self {
Self::IInteger(value)
}
}
impl From<String> for LiteralValue {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<u32> for LiteralValue {
fn from(value: u32) -> Self {
Self::IInteger(value as i64)
}
}
impl From<u16> for LiteralValue {
fn from(value: u16) -> Self {
Self::IInteger(value as i64)
}
}
impl From<u8> for LiteralValue {
fn from(value: u8) -> Self {
Self::IInteger(value as i64)
}
}
impl From<&'static str> for LiteralValue {
fn from(value: &'static str) -> Self {
// TODO: Make this Cow<str>
Self::String(value.to_owned())
}
}

View File

@ -193,7 +193,7 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
} }
fn to_signature_help(&self) -> SignatureHelp { fn to_signature_help(&self) -> SignatureHelp {
// Fill this in based on the current positon of the cursor. // Fill this in based on the current position of the cursor.
let active_parameter = None; let active_parameter = None;
SignatureHelp { SignatureHelp {

View File

@ -8,6 +8,8 @@ use crate::executor::SourceRange;
#[ts(export)] #[ts(export)]
#[serde(tag = "kind", rename_all = "snake_case")] #[serde(tag = "kind", rename_all = "snake_case")]
pub enum KclError { pub enum KclError {
#[error("lexical: {0:?}")]
Lexical(KclErrorDetails),
#[error("syntax: {0:?}")] #[error("syntax: {0:?}")]
Syntax(KclErrorDetails), Syntax(KclErrorDetails),
#[error("semantic: {0:?}")] #[error("semantic: {0:?}")]
@ -26,6 +28,8 @@ pub enum KclError {
InvalidExpression(KclErrorDetails), InvalidExpression(KclErrorDetails),
#[error("engine: {0:?}")] #[error("engine: {0:?}")]
Engine(KclErrorDetails), Engine(KclErrorDetails),
#[error("internal error, please report to KittyCAD team: {0:?}")]
Internal(KclErrorDetails),
} }
#[derive(Debug, Serialize, Deserialize, ts_rs::TS, Clone)] #[derive(Debug, Serialize, Deserialize, ts_rs::TS, Clone)]
@ -40,20 +44,8 @@ pub struct KclErrorDetails {
impl KclError { impl KclError {
/// Get the error message, line and column from the error and input code. /// Get the error message, line and column from the error and input code.
pub fn get_message_line_column(&self, input: &str) -> (String, Option<usize>, Option<usize>) { pub fn get_message_line_column(&self, input: &str) -> (String, Option<usize>, Option<usize>) {
let (type_, source_range, message) = match &self {
KclError::Syntax(e) => ("syntax", e.source_ranges.clone(), e.message.clone()),
KclError::Semantic(e) => ("semantic", e.source_ranges.clone(), e.message.clone()),
KclError::Type(e) => ("type", e.source_ranges.clone(), e.message.clone()),
KclError::Unimplemented(e) => ("unimplemented", e.source_ranges.clone(), e.message.clone()),
KclError::Unexpected(e) => ("unexpected", e.source_ranges.clone(), e.message.clone()),
KclError::ValueAlreadyDefined(e) => ("value already defined", e.source_ranges.clone(), e.message.clone()),
KclError::UndefinedValue(e) => ("undefined value", e.source_ranges.clone(), e.message.clone()),
KclError::InvalidExpression(e) => ("invalid expression", e.source_ranges.clone(), e.message.clone()),
KclError::Engine(e) => ("engine", e.source_ranges.clone(), e.message.clone()),
};
// Calculate the line and column of the error from the source range. // Calculate the line and column of the error from the source range.
let (line, column) = if let Some(range) = source_range.first() { let (line, column) = if let Some(range) = self.source_ranges().first() {
let line = input[..range.0[0]].lines().count(); let line = input[..range.0[0]].lines().count();
let column = input[..range.0[0]].lines().last().map(|l| l.len()).unwrap_or_default(); let column = input[..range.0[0]].lines().last().map(|l| l.len()).unwrap_or_default();
@ -62,11 +54,28 @@ impl KclError {
(None, None) (None, None)
}; };
(format!("{}: {}", type_, message), line, column) (format!("{}: {}", self.error_type(), self.message()), line, column)
}
pub fn error_type(&self) -> &'static str {
match self {
KclError::Lexical(_) => "lexical",
KclError::Syntax(_) => "syntax",
KclError::Semantic(_) => "semantic",
KclError::Type(_) => "type",
KclError::Unimplemented(_) => "unimplemented",
KclError::Unexpected(_) => "unexpected",
KclError::ValueAlreadyDefined(_) => "value already defined",
KclError::UndefinedValue(_) => "undefined value",
KclError::InvalidExpression(_) => "invalid expression",
KclError::Engine(_) => "engine",
KclError::Internal(_) => "internal",
}
} }
pub fn source_ranges(&self) -> Vec<SourceRange> { pub fn source_ranges(&self) -> Vec<SourceRange> {
match &self { match &self {
KclError::Lexical(e) => e.source_ranges.clone(),
KclError::Syntax(e) => e.source_ranges.clone(), KclError::Syntax(e) => e.source_ranges.clone(),
KclError::Semantic(e) => e.source_ranges.clone(), KclError::Semantic(e) => e.source_ranges.clone(),
KclError::Type(e) => e.source_ranges.clone(), KclError::Type(e) => e.source_ranges.clone(),
@ -76,12 +85,14 @@ impl KclError {
KclError::UndefinedValue(e) => e.source_ranges.clone(), KclError::UndefinedValue(e) => e.source_ranges.clone(),
KclError::InvalidExpression(e) => e.source_ranges.clone(), KclError::InvalidExpression(e) => e.source_ranges.clone(),
KclError::Engine(e) => e.source_ranges.clone(), KclError::Engine(e) => e.source_ranges.clone(),
KclError::Internal(e) => e.source_ranges.clone(),
} }
} }
/// Get the inner error message. /// Get the inner error message.
pub fn message(&self) -> &str { pub fn message(&self) -> &str {
match &self { match &self {
KclError::Lexical(e) => &e.message,
KclError::Syntax(e) => &e.message, KclError::Syntax(e) => &e.message,
KclError::Semantic(e) => &e.message, KclError::Semantic(e) => &e.message,
KclError::Type(e) => &e.message, KclError::Type(e) => &e.message,
@ -91,6 +102,7 @@ impl KclError {
KclError::UndefinedValue(e) => &e.message, KclError::UndefinedValue(e) => &e.message,
KclError::InvalidExpression(e) => &e.message, KclError::InvalidExpression(e) => &e.message,
KclError::Engine(e) => &e.message, KclError::Engine(e) => &e.message,
KclError::Internal(e) => &e.message,
} }
} }

View File

@ -1,8 +1,9 @@
//! The executor for the AST. //! The executor for the AST.
use std::collections::HashMap; use std::{collections::HashMap, sync::Arc};
use anyhow::Result; use anyhow::Result;
use async_recursion::async_recursion;
use kittycad::types::{Color, ModelingCmd, Point3D}; use kittycad::types::{Color, ModelingCmd, Point3D};
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
@ -10,9 +11,10 @@ use serde::{Deserialize, Serialize};
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
use crate::{ use crate::{
ast::types::{BodyItem, Function, FunctionExpression, Value}, ast::types::{BodyItem, FunctionExpression, Value},
engine::{EngineConnection, EngineManager}, engine::{EngineConnection, EngineManager},
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
std::{FunctionKind, StdLib},
}; };
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
@ -183,7 +185,7 @@ impl DefaultPlanes {
SourceRange::default(), SourceRange::default(),
ModelingCmd::MakePlane { ModelingCmd::MakePlane {
clobber: false, clobber: false,
origin: default_origin.clone(), origin: default_origin,
size: default_size, size: default_size,
x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 }, x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 },
y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 }, y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
@ -216,7 +218,7 @@ impl DefaultPlanes {
SourceRange::default(), SourceRange::default(),
ModelingCmd::MakePlane { ModelingCmd::MakePlane {
clobber: false, clobber: false,
origin: default_origin.clone(), origin: default_origin,
size: default_size, size: default_size,
x_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 }, x_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
y_axis: Point3D { x: 0.0, y: 0.0, z: 1.0 }, y_axis: Point3D { x: 0.0, y: 0.0, z: 1.0 },
@ -347,27 +349,27 @@ impl MemoryItem {
} }
} }
/// If this memory item is a function, call it with the given arguments, return its val as Ok.
/// If it's not a function, return Err.
pub async fn call_fn( pub async fn call_fn(
&self, &self,
args: Vec<MemoryItem>, args: Vec<MemoryItem>,
memory: ProgramMemory, memory: ProgramMemory,
ctx: ExecutorContext, ctx: ExecutorContext,
) -> Result<Option<ProgramReturn>, KclError> { ) -> Result<Option<ProgramReturn>, KclError> {
if let MemoryItem::Function { func, expression, meta } = &self { let MemoryItem::Function { func, expression, meta } = &self else {
if let Some(func) = func { return Err(KclError::Semantic(KclErrorDetails {
func(args, memory, expression.clone(), meta.clone(), ctx).await
} else {
Err(KclError::Semantic(KclErrorDetails {
message: format!("Not a function: {:?}", expression),
source_ranges: vec![],
}))
}
} else {
Err(KclError::Semantic(KclErrorDetails {
message: "not a in memory function".to_string(), message: "not a in memory function".to_string(),
source_ranges: vec![], source_ranges: vec![],
})) }));
} };
let Some(func) = func else {
return Err(KclError::Semantic(KclErrorDetails {
message: format!("Not a function: {:?}", expression),
source_ranges: vec![],
}));
};
func(args, memory, expression.clone(), meta.clone(), ctx).await
} }
} }
@ -776,9 +778,11 @@ impl Default for PipeInfo {
pub struct ExecutorContext { pub struct ExecutorContext {
pub engine: EngineConnection, pub engine: EngineConnection,
pub planes: DefaultPlanes, pub planes: DefaultPlanes,
pub stdlib: Arc<StdLib>,
} }
/// Execute a AST's program. /// Execute a AST's program.
#[async_recursion(?Send)]
pub async fn execute( pub async fn execute(
program: crate::ast::types::Program, program: crate::ast::types::Program,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
@ -826,7 +830,10 @@ pub async fn execute(
} }
} }
let _show_fn = Box::new(crate::std::Show); let _show_fn = Box::new(crate::std::Show);
if let Function::StdLib { func: _show_fn } = &call_expr.function { match ctx.stdlib.get_either(&call_expr.callee.name) {
FunctionKind::Core(func) => {
use crate::docs::StdLibFn;
if func.name() == _show_fn.name() {
if options != BodyType::Root { if options != BodyType::Root {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: "Cannot call show outside of a root".to_string(), message: "Cannot call show outside of a root".to_string(),
@ -835,7 +842,15 @@ pub async fn execute(
} }
memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone())); memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
} else if let Some(func) = memory.clone().root.get(&fn_name) { }
}
FunctionKind::Std(func) => {
let mut newmem = memory.clone();
let result = execute(func.program().to_owned(), &mut newmem, BodyType::Block, ctx).await?;
memory.return_ = result.return_;
}
FunctionKind::UserDefined => {
if let Some(func) = memory.clone().root.get(&fn_name) {
let result = func.call_fn(args.clone(), memory.clone(), ctx.clone()).await?; let result = func.call_fn(args.clone(), memory.clone(), ctx.clone()).await?;
memory.return_ = result; memory.return_ = result;
@ -847,6 +862,8 @@ pub async fn execute(
} }
} }
} }
}
}
BodyItem::VariableDeclaration(variable_declaration) => { BodyItem::VariableDeclaration(variable_declaration) => {
for declaration in &variable_declaration.declarations { for declaration in &variable_declaration.declarations {
let var_name = declaration.id.name.to_string(); let var_name = declaration.id.name.to_string();
@ -1011,7 +1028,11 @@ mod tests {
let mut mem: ProgramMemory = Default::default(); let mut mem: ProgramMemory = Default::default();
let engine = EngineConnection::new().await?; let engine = EngineConnection::new().await?;
let planes = DefaultPlanes::new(&engine).await?; let planes = DefaultPlanes::new(&engine).await?;
let ctx = ExecutorContext { engine, planes }; let ctx = ExecutorContext {
engine,
planes,
stdlib: Arc::new(StdLib::default()),
};
let memory = execute(program, &mut mem, BodyType::Root, &ctx).await?; let memory = execute(program, &mut mem, BodyType::Root, &ctx).await?;
Ok(memory) Ok(memory)

View File

@ -5,7 +5,6 @@ pub mod docs;
pub mod engine; pub mod engine;
pub mod errors; pub mod errors;
pub mod executor; pub mod executor;
pub mod math_parser;
pub mod parser; pub mod parser;
pub mod server; pub mod server;
pub mod std; pub mod std;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
use crate::{
ast::types::{BinaryExpression, BinaryOperator, BinaryPart},
errors::{KclError, KclErrorDetails},
executor::SourceRange,
};
/// Parses a list of tokens (in infix order, i.e. as the user typed them)
/// into a binary expression tree.
pub fn parse(infix_tokens: Vec<BinaryExpressionToken>) -> Result<BinaryExpression, KclError> {
let rpn = postfix(infix_tokens);
evaluate(rpn)
}
/// Parses a list of tokens (in postfix order) into a binary expression tree.
fn evaluate(rpn: Vec<BinaryExpressionToken>) -> Result<BinaryExpression, KclError> {
let source_ranges = source_range(&rpn);
let mut operand_stack: Vec<BinaryPart> = Vec::new();
let e = KclError::Internal(KclErrorDetails {
source_ranges,
message: "error parsing binary math expressions".to_owned(),
});
for item in rpn {
let expr = match item {
BinaryExpressionToken::Operator(operator) => {
let Some(right) = operand_stack.pop() else {
return Err(e);
};
let Some(left) = operand_stack.pop() else {
return Err(e);
};
BinaryPart::BinaryExpression(Box::new(BinaryExpression {
start: left.start(),
end: right.end(),
operator,
left,
right,
}))
}
BinaryExpressionToken::Operand(o) => o,
};
operand_stack.push(expr)
}
if let Some(BinaryPart::BinaryExpression(expr)) = operand_stack.pop() {
Ok(*expr)
} else {
// If this branch is used, the evaluation algorithm has a bug and must be fixed.
// This is a programmer error, not a user error.
Err(e)
}
}
fn source_range(tokens: &[BinaryExpressionToken]) -> Vec<SourceRange> {
let sources: Vec<_> = tokens
.iter()
.filter_map(|op| match op {
BinaryExpressionToken::Operator(_) => None,
BinaryExpressionToken::Operand(o) => Some((o.start(), o.end())),
})
.collect();
match (sources.first(), sources.last()) {
(Some((start, _)), Some((_, end))) => vec![SourceRange([*start, *end])],
_ => Vec::new(),
}
}
/// Reorders tokens from infix order to postfix order.
fn postfix(infix: Vec<BinaryExpressionToken>) -> Vec<BinaryExpressionToken> {
let mut operator_stack: Vec<BinaryOperator> = Vec::with_capacity(infix.len());
let mut output = Vec::with_capacity(infix.len());
for token in infix {
match token {
BinaryExpressionToken::Operator(o1) => {
// From https://en.wikipedia.org/wiki/Shunting_yard_algorithm:
// while (
// there is an operator o2 at the top of the operator stack which is not a left parenthesis,
// and (o2 has greater precedence than o1 or (o1 and o2 have the same precedence and o1 is left-associative))
// )
// pop o2 from the operator stack into the output queue
while let Some(o2) = operator_stack.pop() {
if (o2.precedence() > o1.precedence())
|| o1.precedence() == o2.precedence() && o1.associativity().is_left()
{
output.push(BinaryExpressionToken::Operator(o2));
} else {
operator_stack.push(o2);
break;
}
}
operator_stack.push(o1);
}
o @ BinaryExpressionToken::Operand(_) => output.push(o),
}
}
// After the while loop, pop the remaining items from the operator stack into the output queue.
output.extend(operator_stack.into_iter().rev().map(BinaryExpressionToken::Operator));
output
}
/// Expressions are made up of operators and operands.
#[derive(PartialEq, Debug)]
pub enum BinaryExpressionToken {
Operator(BinaryOperator),
Operand(BinaryPart),
}
impl From<BinaryPart> for BinaryExpressionToken {
fn from(value: BinaryPart) -> Self {
Self::Operand(value)
}
}
impl From<BinaryOperator> for BinaryExpressionToken {
fn from(value: BinaryOperator) -> Self {
Self::Operator(value)
}
}
#[cfg(test)]
mod tests {
use crate::ast::types::Literal;
use super::*;
#[test]
fn parse_and_evaluate() {
/// Make a literal
fn lit(n: u8) -> BinaryPart {
BinaryPart::Literal(Box::new(Literal {
start: 0,
end: 0,
value: n.into(),
raw: n.to_string(),
}))
}
let tests: Vec<Vec<BinaryExpressionToken>> = vec![
// 3 + 4 × 2 ÷ ( 1 5 ) ^ 2 ^ 3
vec![
lit(3).into(),
BinaryOperator::Add.into(),
lit(4).into(),
BinaryOperator::Mul.into(),
lit(2).into(),
BinaryOperator::Div.into(),
BinaryPart::BinaryExpression(Box::new(BinaryExpression {
start: 0,
end: 0,
operator: BinaryOperator::Sub,
left: lit(1),
right: lit(5),
}))
.into(),
BinaryOperator::Pow.into(),
lit(2).into(),
BinaryOperator::Pow.into(),
lit(3).into(),
],
];
for infix_input in tests {
let rpn = postfix(infix_input);
let _tree = evaluate(rpn).unwrap();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 5,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 4,
"end": 5,
"value": 2,
"raw": "2"
}
}

View File

@ -0,0 +1,26 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 3,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 2,
"end": 3,
"value": 2,
"raw": "2"
}
}

View File

@ -0,0 +1,26 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 4,
"operator": "-",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 3,
"end": 4,
"value": 2,
"raw": "2"
}
}

View File

@ -0,0 +1,41 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 9,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 4,
"end": 9,
"operator": "*",
"left": {
"type": "Literal",
"type": "Literal",
"start": 4,
"end": 5,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 8,
"end": 9,
"value": 3,
"raw": "3"
}
}
}

View File

@ -0,0 +1,41 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 11,
"operator": "*",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 6,
"end": 11,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 6,
"end": 7,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 10,
"end": 11,
"value": 3,
"raw": "3"
}
}
}

View File

@ -0,0 +1,56 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 17,
"operator": "/",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 0,
"end": 11,
"operator": "*",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 6,
"end": 11,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 6,
"end": 7,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 10,
"end": 11,
"value": 3,
"raw": "3"
}
}
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 16,
"end": 17,
"value": 4,
"raw": "4"
}
}

View File

@ -0,0 +1,56 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 17,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 6,
"end": 17,
"operator": "/",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 6,
"end": 11,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 6,
"end": 7,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 10,
"end": 11,
"value": 3,
"raw": "3"
}
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 16,
"end": 17,
"value": 4,
"raw": "4"
}
}
}

View File

@ -0,0 +1,71 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 22,
"operator": "*",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 7,
"end": 22,
"operator": "+",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 7,
"end": 18,
"operator": "/",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 7,
"end": 12,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 7,
"end": 8,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 11,
"end": 12,
"value": 3,
"raw": "3"
}
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 4,
"raw": "4"
}
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 21,
"end": 22,
"value": 5,
"raw": "5"
}
}
}

View File

@ -0,0 +1,41 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 13,
"operator": "*",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 1,
"raw": "1"
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 8,
"end": 13,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 8,
"end": 9,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 12,
"end": 13,
"value": 3,
"raw": "3"
}
}
}

View File

@ -0,0 +1,81 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 44,
"operator": "/",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 0,
"end": 22,
"operator": "*",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 0,
"end": 18,
"operator": "*",
"left": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 0,
"end": 12,
"operator": "*",
"left": {
"type": "Identifier",
"type": "Identifier",
"start": 0,
"end": 8,
"name": "distance"
},
"right": {
"type": "Identifier",
"type": "Identifier",
"start": 11,
"end": 12,
"name": "p"
}
},
"right": {
"type": "Identifier",
"type": "Identifier",
"start": 15,
"end": 18,
"name": "FOS"
}
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 21,
"end": 22,
"value": 6,
"raw": "6"
}
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 26,
"end": 44,
"operator": "*",
"left": {
"type": "Identifier",
"type": "Identifier",
"start": 26,
"end": 36,
"name": "sigmaAllow"
},
"right": {
"type": "Identifier",
"type": "Identifier",
"start": 39,
"end": 44,
"name": "width"
}
}
}

View File

@ -0,0 +1,26 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"type": "BinaryExpression",
"start": 0,
"end": 8,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 2,
"raw": "2"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 7,
"end": 8,
"value": 3,
"raw": "3"
}
}

View File

@ -0,0 +1,263 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 144,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 143,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 143,
"id": {
"type": "Identifier",
"start": 6,
"end": 15,
"name": "boxSketch"
},
"init": {
"type": "PipeExpression",
"type": "PipeExpression",
"start": 18,
"end": 143,
"body": [
{
"type": "CallExpression",
"type": "CallExpression",
"start": 18,
"end": 39,
"callee": {
"type": "Identifier",
"start": 18,
"end": 31,
"name": "startSketchAt"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 32,
"end": 38,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 33,
"end": 34,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 36,
"end": 37,
"value": 0,
"raw": "0"
}
]
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 47,
"end": 63,
"callee": {
"type": "Identifier",
"start": 47,
"end": 51,
"name": "line"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 52,
"end": 59,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 53,
"end": 54,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 56,
"end": 58,
"value": 10,
"raw": "10"
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 61,
"end": 62
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 71,
"end": 96,
"callee": {
"type": "Identifier",
"start": 71,
"end": 84,
"name": "tangentialArc"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 85,
"end": 92,
"elements": [
{
"type": "UnaryExpression",
"type": "UnaryExpression",
"start": 86,
"end": 88,
"operator": "-",
"argument": {
"type": "Literal",
"type": "Literal",
"start": 87,
"end": 88,
"value": 5,
"raw": "5"
}
},
{
"type": "Literal",
"type": "Literal",
"start": 90,
"end": 91,
"value": 5,
"raw": "5"
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 94,
"end": 95
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 104,
"end": 121,
"callee": {
"type": "Identifier",
"start": 104,
"end": 108,
"name": "line"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 109,
"end": 117,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 110,
"end": 111,
"value": 5,
"raw": "5"
},
{
"type": "UnaryExpression",
"type": "UnaryExpression",
"start": 113,
"end": 116,
"operator": "-",
"argument": {
"type": "Literal",
"type": "Literal",
"start": 114,
"end": 116,
"value": 15,
"raw": "15"
}
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 119,
"end": 120
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 129,
"end": 143,
"callee": {
"type": "Identifier",
"start": 129,
"end": 136,
"name": "extrude"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 137,
"end": 139,
"value": 10,
"raw": "10"
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 141,
"end": 142
}
],
"optional": false
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,48 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 17,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 17,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 17,
"id": {
"type": "Identifier",
"start": 6,
"end": 8,
"name": "sg"
},
"init": {
"type": "UnaryExpression",
"type": "UnaryExpression",
"start": 11,
"end": 17,
"operator": "-",
"argument": {
"type": "Identifier",
"type": "Identifier",
"start": 12,
"end": 17,
"name": "scale"
}
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,85 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 23,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 23,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 23,
"callee": {
"type": "Identifier",
"start": 0,
"end": 6,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 7,
"end": 22,
"properties": [
{
"type": "ObjectProperty",
"start": 9,
"end": 20,
"key": {
"type": "Identifier",
"start": 9,
"end": 11,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 13,
"end": 20,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 14,
"end": 15,
"value": 0,
"raw": "0"
},
{
"type": "UnaryExpression",
"type": "UnaryExpression",
"start": 17,
"end": 19,
"operator": "-",
"argument": {
"type": "Literal",
"type": "Literal",
"start": 18,
"end": 19,
"value": 1,
"raw": "1"
}
}
]
}
}
]
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,130 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 23,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 23,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 23,
"id": {
"type": "Identifier",
"start": 6,
"end": 13,
"name": "myArray"
},
"init": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 16,
"end": 23,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 1,
"raw": "1"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 2,
"raw": "2"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 3,
"raw": "3"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 4,
"raw": "4"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 5,
"raw": "5"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 6,
"raw": "6"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 7,
"raw": "7"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 8,
"raw": "8"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 9,
"raw": "9"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 10,
"raw": "10"
}
]
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,85 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 80,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 5,
"end": 57,
"declarations": [
{
"type": "VariableDeclarator",
"start": 8,
"end": 57,
"id": {
"type": "Identifier",
"start": 8,
"end": 24,
"name": "firstPrimeNumber"
},
"init": {
"type": "FunctionExpression",
"type": "FunctionExpression",
"start": 27,
"end": 57,
"params": [],
"body": {
"start": 33,
"end": 57,
"body": [
{
"type": "ReturnStatement",
"type": "ReturnStatement",
"start": 43,
"end": 51,
"argument": {
"type": "Literal",
"type": "Literal",
"start": 50,
"end": 51,
"value": 2,
"raw": "2"
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
}
],
"kind": "fn"
},
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 62,
"end": 80,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 62,
"end": 80,
"callee": {
"type": "Identifier",
"start": 62,
"end": 78,
"name": "firstPrimeNumber"
},
"arguments": [],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,99 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 66,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 49,
"declarations": [
{
"type": "VariableDeclarator",
"start": 3,
"end": 49,
"id": {
"type": "Identifier",
"start": 3,
"end": 8,
"name": "thing"
},
"init": {
"type": "FunctionExpression",
"type": "FunctionExpression",
"start": 11,
"end": 49,
"params": [
{
"type": "Identifier",
"start": 12,
"end": 17,
"name": "param"
}
],
"body": {
"start": 22,
"end": 49,
"body": [
{
"type": "ReturnStatement",
"type": "ReturnStatement",
"start": 32,
"end": 43,
"argument": {
"type": "Identifier",
"type": "Identifier",
"start": 39,
"end": 43,
"name": "true"
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
}
],
"kind": "fn"
},
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 54,
"end": 66,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 54,
"end": 66,
"callee": {
"type": "Identifier",
"start": 54,
"end": 59,
"name": "thing"
},
"arguments": [
{
"type": "Identifier",
"type": "Identifier",
"start": 60,
"end": 65,
"name": "false"
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,317 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 192,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 192,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 192,
"id": {
"type": "Identifier",
"start": 6,
"end": 14,
"name": "mySketch"
},
"init": {
"type": "PipeExpression",
"type": "PipeExpression",
"start": 17,
"end": 192,
"body": [
{
"type": "CallExpression",
"type": "CallExpression",
"start": 17,
"end": 37,
"callee": {
"type": "Identifier",
"start": 17,
"end": 30,
"name": "startSketchAt"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 31,
"end": 36,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 32,
"end": 33,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 34,
"end": 35,
"value": 0,
"raw": "0"
}
]
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 49,
"end": 89,
"callee": {
"type": "Identifier",
"start": 49,
"end": 55,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 56,
"end": 85,
"properties": [
{
"type": "ObjectProperty",
"start": 58,
"end": 68,
"key": {
"type": "Identifier",
"start": 58,
"end": 60,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 62,
"end": 68,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 63,
"end": 64,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 66,
"end": 67,
"value": 1,
"raw": "1"
}
]
}
},
{
"type": "ObjectProperty",
"start": 70,
"end": 83,
"key": {
"type": "Identifier",
"start": 70,
"end": 73,
"name": "tag"
},
"value": {
"type": "Literal",
"type": "Literal",
"start": 75,
"end": 83,
"value": "myPath",
"raw": "'myPath'"
}
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 87,
"end": 88
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 101,
"end": 118,
"callee": {
"type": "Identifier",
"start": 101,
"end": 107,
"name": "lineTo"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 108,
"end": 114,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 109,
"end": 110,
"value": 1,
"raw": "1"
},
{
"type": "Literal",
"type": "Literal",
"start": 112,
"end": 113,
"value": 1,
"raw": "1"
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 116,
"end": 117
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 130,
"end": 172,
"callee": {
"type": "Identifier",
"start": 130,
"end": 136,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 137,
"end": 168,
"properties": [
{
"type": "ObjectProperty",
"start": 139,
"end": 148,
"key": {
"type": "Identifier",
"start": 139,
"end": 141,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 143,
"end": 148,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 144,
"end": 145,
"value": 1,
"raw": "1"
},
{
"type": "Literal",
"type": "Literal",
"start": 146,
"end": 147,
"value": 0,
"raw": "0"
}
]
}
},
{
"type": "ObjectProperty",
"start": 150,
"end": 166,
"key": {
"type": "Identifier",
"start": 150,
"end": 153,
"name": "tag"
},
"value": {
"type": "Literal",
"type": "Literal",
"start": 155,
"end": 166,
"value": "rightPath",
"raw": "\"rightPath\""
}
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 170,
"end": 171
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 184,
"end": 192,
"callee": {
"type": "Identifier",
"start": 184,
"end": 189,
"name": "close"
},
"arguments": [
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 190,
"end": 191
}
],
"optional": false
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,151 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 70,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 70,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 70,
"id": {
"type": "Identifier",
"start": 6,
"end": 14,
"name": "mySketch"
},
"init": {
"type": "PipeExpression",
"type": "PipeExpression",
"start": 17,
"end": 70,
"body": [
{
"type": "CallExpression",
"type": "CallExpression",
"start": 17,
"end": 37,
"callee": {
"type": "Identifier",
"start": 17,
"end": 30,
"name": "startSketchAt"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 31,
"end": 36,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 32,
"end": 33,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 34,
"end": 35,
"value": 0,
"raw": "0"
}
]
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 41,
"end": 58,
"callee": {
"type": "Identifier",
"start": 41,
"end": 47,
"name": "lineTo"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 48,
"end": 54,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 49,
"end": 50,
"value": 1,
"raw": "1"
},
{
"type": "Literal",
"type": "Literal",
"start": 52,
"end": 53,
"value": 1,
"raw": "1"
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 56,
"end": 57
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 62,
"end": 70,
"callee": {
"type": "Identifier",
"start": 62,
"end": 67,
"name": "close"
},
"arguments": [
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 68,
"end": 69
}
],
"optional": false
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,56 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 30,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 30,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 30,
"id": {
"type": "Identifier",
"start": 6,
"end": 11,
"name": "myBox"
},
"init": {
"type": "CallExpression",
"type": "CallExpression",
"start": 14,
"end": 30,
"callee": {
"type": "Identifier",
"start": 14,
"end": 27,
"name": "startSketchAt"
},
"arguments": [
{
"type": "Identifier",
"type": "Identifier",
"start": 28,
"end": 29,
"name": "p"
}
],
"optional": false
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,92 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 26,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 26,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 26,
"id": {
"type": "Identifier",
"start": 6,
"end": 11,
"name": "myBox"
},
"init": {
"type": "PipeExpression",
"type": "PipeExpression",
"start": 14,
"end": 26,
"body": [
{
"type": "CallExpression",
"type": "CallExpression",
"start": 14,
"end": 18,
"callee": {
"type": "Identifier",
"start": 14,
"end": 15,
"name": "f"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 16,
"end": 17,
"value": 1,
"raw": "1"
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 22,
"end": 26,
"callee": {
"type": "Identifier",
"start": 22,
"end": 23,
"name": "g"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 24,
"end": 25,
"value": 2,
"raw": "2"
}
],
"optional": false
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,112 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 49,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 49,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 49,
"id": {
"type": "Identifier",
"start": 6,
"end": 11,
"name": "myBox"
},
"init": {
"type": "PipeExpression",
"type": "PipeExpression",
"start": 14,
"end": 49,
"body": [
{
"type": "CallExpression",
"type": "CallExpression",
"start": 14,
"end": 30,
"callee": {
"type": "Identifier",
"start": 14,
"end": 27,
"name": "startSketchAt"
},
"arguments": [
{
"type": "Identifier",
"type": "Identifier",
"start": 28,
"end": 29,
"name": "p"
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 34,
"end": 49,
"callee": {
"type": "Identifier",
"start": 34,
"end": 38,
"name": "line"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 39,
"end": 45,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 40,
"end": 41,
"value": 0,
"raw": "0"
},
{
"type": "Identifier",
"type": "Identifier",
"start": 43,
"end": 44,
"name": "l"
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 47,
"end": 48
}
],
"optional": false
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,78 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 22,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 22,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 22,
"callee": {
"type": "Identifier",
"start": 0,
"end": 6,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 7,
"end": 21,
"properties": [
{
"type": "ObjectProperty",
"start": 9,
"end": 19,
"key": {
"type": "Identifier",
"start": 9,
"end": 11,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 13,
"end": 19,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 14,
"end": 15,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 1,
"raw": "1"
}
]
}
}
]
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,113 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 36,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 36,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 36,
"callee": {
"type": "Identifier",
"start": 0,
"end": 6,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 7,
"end": 35,
"properties": [
{
"type": "ObjectProperty",
"start": 9,
"end": 19,
"key": {
"type": "Identifier",
"start": 9,
"end": 11,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 13,
"end": 19,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 14,
"end": 15,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 1,
"raw": "1"
}
]
}
},
{
"type": "ObjectProperty",
"start": 21,
"end": 33,
"key": {
"type": "Identifier",
"start": 21,
"end": 25,
"name": "from"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 27,
"end": 33,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 28,
"end": 29,
"value": 3,
"raw": "3"
},
{
"type": "Literal",
"type": "Literal",
"start": 31,
"end": 32,
"value": 3,
"raw": "3"
}
]
}
}
]
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,78 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 19,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 19,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 19,
"callee": {
"type": "Identifier",
"start": 0,
"end": 6,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 7,
"end": 18,
"properties": [
{
"type": "ObjectProperty",
"start": 8,
"end": 17,
"key": {
"type": "Identifier",
"start": 8,
"end": 10,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 11,
"end": 17,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 12,
"end": 13,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 15,
"end": 16,
"value": 1,
"raw": "1"
}
]
}
}
]
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,113 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 35,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 35,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 35,
"callee": {
"type": "Identifier",
"start": 0,
"end": 6,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 7,
"end": 34,
"properties": [
{
"type": "ObjectProperty",
"start": 9,
"end": 19,
"key": {
"type": "Identifier",
"start": 9,
"end": 11,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 13,
"end": 19,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 14,
"end": 15,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 1,
"raw": "1"
}
]
}
},
{
"type": "ObjectProperty",
"start": 21,
"end": 33,
"key": {
"type": "Identifier",
"start": 21,
"end": 25,
"name": "from"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 27,
"end": 33,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 28,
"end": 29,
"value": 3,
"raw": "3"
},
{
"type": "Literal",
"type": "Literal",
"start": 31,
"end": 32,
"value": 3,
"raw": "3"
}
]
}
}
]
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,113 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 35,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 35,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 35,
"callee": {
"type": "Identifier",
"start": 0,
"end": 6,
"name": "lineTo"
},
"arguments": [
{
"type": "ObjectExpression",
"type": "ObjectExpression",
"start": 7,
"end": 34,
"properties": [
{
"type": "ObjectProperty",
"start": 9,
"end": 19,
"key": {
"type": "Identifier",
"start": 9,
"end": 11,
"name": "to"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 13,
"end": 19,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 14,
"end": 15,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 17,
"end": 18,
"value": 1,
"raw": "1"
}
]
}
},
{
"type": "ObjectProperty",
"start": 20,
"end": 32,
"key": {
"type": "Identifier",
"start": 20,
"end": 24,
"name": "from"
},
"value": {
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 26,
"end": 32,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 27,
"end": 28,
"value": 3,
"raw": "3"
},
{
"type": "Literal",
"type": "Literal",
"start": 30,
"end": 31,
"value": 3,
"raw": "3"
}
]
}
}
]
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,73 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 37,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 37,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 37,
"id": {
"type": "Identifier",
"start": 6,
"end": 14,
"name": "mySketch"
},
"init": {
"type": "CallExpression",
"type": "CallExpression",
"start": 17,
"end": 37,
"callee": {
"type": "Identifier",
"start": 17,
"end": 30,
"name": "startSketchAt"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 31,
"end": 36,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 32,
"end": 33,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 34,
"end": 35,
"value": 0,
"raw": "0"
}
]
}
],
"optional": false
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,58 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 28,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 28,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 28,
"callee": {
"type": "Identifier",
"start": 0,
"end": 3,
"name": "log"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 4,
"end": 5,
"value": 5,
"raw": "5"
},
{
"type": "Literal",
"type": "Literal",
"start": 7,
"end": 14,
"value": "hello",
"raw": "\"hello\""
},
{
"type": "Identifier",
"type": "Identifier",
"start": 16,
"end": 27,
"name": "aIdentifier"
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,43 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 7,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 7,
"expression": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"start": 0,
"end": 7,
"operator": "+",
"left": {
"type": "Literal",
"type": "Literal",
"start": 0,
"end": 1,
"value": 5,
"raw": "5"
},
"right": {
"type": "Literal",
"type": "Literal",
"start": 4,
"end": 7,
"value": "a",
"raw": "\"a\""
}
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,64 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 15,
"body": [
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 0,
"end": 15,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 0,
"end": 15,
"callee": {
"type": "Identifier",
"start": 0,
"end": 4,
"name": "line"
},
"arguments": [
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 5,
"end": 11,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 6,
"end": 7,
"value": 0,
"raw": "0"
},
{
"type": "Identifier",
"type": "Identifier",
"start": 9,
"end": 10,
"name": "l"
}
]
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 13,
"end": 14
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,158 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 90,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 74,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 74,
"id": {
"type": "Identifier",
"start": 6,
"end": 14,
"name": "cylinder"
},
"init": {
"type": "PipeExpression",
"type": "PipeExpression",
"start": 17,
"end": 74,
"body": [
{
"type": "CallExpression",
"type": "CallExpression",
"start": 17,
"end": 56,
"callee": {
"type": "Identifier",
"start": 17,
"end": 39,
"name": "unstable_stdlib_circle"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 40,
"end": 44,
"value": "XY",
"raw": "'XY'"
},
{
"type": "ArrayExpression",
"type": "ArrayExpression",
"start": 46,
"end": 51,
"elements": [
{
"type": "Literal",
"type": "Literal",
"start": 47,
"end": 48,
"value": 0,
"raw": "0"
},
{
"type": "Literal",
"type": "Literal",
"start": 49,
"end": 50,
"value": 0,
"raw": "0"
}
]
},
{
"type": "Literal",
"type": "Literal",
"start": 53,
"end": 55,
"value": 22,
"raw": "22"
}
],
"optional": false
},
{
"type": "CallExpression",
"type": "CallExpression",
"start": 60,
"end": 74,
"callee": {
"type": "Identifier",
"start": 60,
"end": 67,
"name": "extrude"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 68,
"end": 70,
"value": 14,
"raw": "14"
},
{
"type": "PipeSubstitution",
"type": "PipeSubstitution",
"start": 72,
"end": 73
}
],
"optional": false
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}
}
],
"kind": "const"
},
{
"type": "ExpressionStatement",
"type": "ExpressionStatement",
"start": 75,
"end": 89,
"expression": {
"type": "CallExpression",
"type": "CallExpression",
"start": 75,
"end": 89,
"callee": {
"type": "Identifier",
"start": 75,
"end": 79,
"name": "show"
},
"arguments": [
{
"type": "Identifier",
"type": "Identifier",
"start": 80,
"end": 88,
"name": "cylinder"
}
],
"optional": false
}
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

View File

@ -0,0 +1,95 @@
---
source: kcl/src/parser/parser_impl.rs
expression: actual
---
{
"start": 0,
"end": 36,
"body": [
{
"type": "VariableDeclaration",
"type": "VariableDeclaration",
"start": 0,
"end": 36,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 36,
"id": {
"type": "Identifier",
"start": 6,
"end": 11,
"name": "myVar"
},
"init": {
"type": "CallExpression",
"type": "CallExpression",
"start": 14,
"end": 36,
"callee": {
"type": "Identifier",
"start": 14,
"end": 17,
"name": "min"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 18,
"end": 19,
"value": 5,
"raw": "5"
},
{
"type": "UnaryExpression",
"type": "UnaryExpression",
"start": 22,
"end": 35,
"operator": "-",
"argument": {
"type": "CallExpression",
"type": "CallExpression",
"start": 23,
"end": 35,
"callee": {
"type": "Identifier",
"start": 23,
"end": 29,
"name": "legLen"
},
"arguments": [
{
"type": "Literal",
"type": "Literal",
"start": 30,
"end": 31,
"value": 5,
"raw": "5"
},
{
"type": "Literal",
"type": "Literal",
"start": 33,
"end": 34,
"value": 4,
"raw": "4"
}
],
"optional": false
}
}
],
"optional": false
}
}
],
"kind": "const"
}
],
"nonCodeMeta": {
"nonCodeNodes": {},
"start": []
}
}

Some files were not shown because too many files have changed in this diff Show More