Compare commits

..

2 Commits

Author SHA1 Message Date
c3ac4d085e No more JSON numbers in AST types 2023-10-27 13:39:57 -07:00
f60a06dffc Fix typos and unnecessary import paths 2023-10-27 11:32:43 -07:00
157 changed files with 6305 additions and 10950 deletions

View File

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

View File

@ -11,7 +11,6 @@
"semi": [ "semi": [
"error", "error",
"never" "never"
], ]
"react-hooks/exhaustive-deps": "off"
} }
} }

View File

@ -12,32 +12,27 @@ 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-latest' runs-on: 'ubuntu-20.04'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
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-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
@ -49,27 +44,12 @@ 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-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
@ -88,15 +68,14 @@ jobs:
- run: yarn test:cov - run: yarn test:cov
prepare-json-files: prepare-json-files:
runs-on: ubuntu-latest # seperate job on Ubuntu for easy string manipulations (compared to Windows) runs-on: ubuntu-20.04 # 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@v4 - uses: actions/setup-node@v3
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
@ -106,7 +85,7 @@ jobs:
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/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.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json '.tauri.updater.endpoints[]=$url' src-tauri/tauri.conf.json --indent 2)" > src-tauri/tauri.conf.json
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: github.event_name == 'schedule' if: github.event_name == 'schedule'
@ -114,18 +93,16 @@ 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:
build-test-apps: needs: [check-format, build-test-web, prepare-json-files, check-types]
needs: [prepare-json-files]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-latest, ubuntu-latest, windows-latest] os: [macos-latest, ubuntu-20.04, windows-latest]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -137,32 +114,25 @@ 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-latest' if: matrix.os == 'ubuntu-20.04'
run: > run: |
sudo apt-get update && sudo apt-get update
sudo apt-get install -y sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev
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@v4 uses: actions/setup-node@v3
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: Setup Rust - name: Rust setup
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
- name: Setup Rust cache - name: Rust cache
uses: swatinem/rust-cache@v2 uses: swatinem/rust-cache@v2
with: with:
workspaces: './src-tauri -> target' workspaces: './src-tauri -> target'
@ -171,27 +141,24 @@ jobs:
with: with:
workspaces: './src/wasm-lib' workspaces: './src/wasm-lib'
- name: Run build:wasm manually - name: wasm prep
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
echo "building with ${{ env.MODE }}" npx wasm-pack build --target web --out-dir pkg
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 Universal target (MacOS only) - name: install apple silicon target mac
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 certificate and variables (Windows only) - name: Prepare Windows certificate and variables
if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }} if: matrix.os == 'windows-latest'
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
@ -205,8 +172,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 certicate with SSM KSP (Windows only) - name: Setup Windows certicate with SSM KSP
if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }} if: matrix.os == 'windows-latest'
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
@ -216,17 +183,8 @@ jobs:
smksp_cert_sync.exe smksp_cert_sync.exe
shell: cmd shell: cmd
- name: Build the app (debug) - name: Build and sign the app for the current platform
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 }}
@ -236,35 +194,17 @@ 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' || '' }} ${{ env.TAURI_CONF_ARGS }}" args: ${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }}
- 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: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*" path: ${{ matrix.os == 'macos-latest' && 'src-tauri/target/universal-apple-darwin/release/bundle/*/*' || 'src-tauri/target/release/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-latest runs-on: ubuntu-20.04
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }} if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps] needs: [build-test-web, prepare-json-files, build-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. We always use the latest stable version of Rust, so you may need to run `rustup update stable`. 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. 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 writing 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 writting 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

@ -1,11 +0,0 @@
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,36 +1,36 @@
{ {
"name": "untitled-app", "name": "untitled-app",
"version": "0.12.0", "version": "0.11.1",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.10.2", "@codemirror/autocomplete": "^6.9.0",
"@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.17", "@headlessui/react": "^1.7.13",
"@headlessui/tailwindcss": "^0.2.0", "@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "^0.0.45", "@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.77.0", "@sentry/react": "^7.65.0",
"@tauri-apps/api": "^1.5.1", "@tauri-apps/api": "^1.5.0",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^14.0.0", "@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^14.5.1", "@testing-library/user-event": "^13.2.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.20", "@uiw/react-codemirror": "^4.21.13",
"@xstate/inspect": "^0.8.0", "@xstate/inspect": "^0.8.0",
"@xstate/react": "^3.2.2", "@xstate/react": "^3.2.2",
"crypto-js": "^4.2.0", "crypto-js": "^4.1.1",
"debounce-promise": "^3.1.2", "debounce-promise": "^3.1.2",
"formik": "^2.4.3", "formik": "^2.4.3",
"fuse.js": "^7.0.0", "fuse.js": "^6.6.2",
"http-server": "^14.1.1", "http-server": "^14.1.1",
"json-rpc-2.0": "^1.6.0", "json-rpc-2.0": "^1.6.0",
"re-resizable": "^6.9.11", "re-resizable": "^6.9.11",
@ -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.2.2", "swr": "^2.0.4",
"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": "^5.2.2", "typescript": "^4.4.2",
"uuid": "^9.0.1", "uuid": "^9.0.0",
"vitest": "^0.34.6", "vitest": "^0.34.6",
"vscode-jsonrpc": "^8.1.0", "vscode-jsonrpc": "^8.1.0",
"vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-protocol": "^3.17.3",
"wasm-pack": "^0.12.1", "wasm-pack": "^0.12.1",
"web-vitals": "^3.5.0", "web-vitals": "^2.1.0",
"ws": "^8.13.0", "ws": "^8.13.0",
"xstate": "^4.38.2", "xstate": "^4.38.2",
"zustand": "^4.4.5" "zustand": "^4.1.4"
}, },
"scripts": { "scripts": {
"start": "vite", "start": "vite",
@ -69,7 +69,6 @@
"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,34 +101,30 @@
}, },
"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.23.3", "@babel/preset-env": "^7.22.9",
"@tauri-apps/cli": "^1.5.6", "@tauri-apps/cli": "^1.5.0",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/debounce-promise": "^3.1.8", "@types/debounce-promise": "^3.1.6",
"@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.4", "@types/uuid": "^9.0.1",
"@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.1.1", "@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.53.0", "eslint": "^8.44.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-plugin-css-modules": "^2.12.0", "eslint-plugin-css-modules": "^2.11.0",
"happy-dom": "^10.8.0", "happy-dom": "^10.8.0",
"husky": "^8.0.3", "husky": "^8.0.3",
"postcss": "^8.4.31", "postcss": "^8.4.31",
"prettier": "^2.8.0", "prettier": "^2.8.0",
"setimmediate": "^1.0.5", "setimmediate": "^1.0.5",
"tailwindcss": "^3.3.5", "tailwindcss": "^3.2.4",
"vite": "^4.5.0", "vite": "^4.4.3",
"vite-plugin-eslint": "^1.8.1", "vite-plugin-eslint": "^1.8.1",
"vite-tsconfig-paths": "^4.2.1", "vite-tsconfig-paths": "^4.2.0",
"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"
} }
} }

75
src-tauri/Cargo.lock generated
View File

@ -1573,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.21", "rustix 0.38.13",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -1664,9 +1664,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.2.41" version = "0.2.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "874914cd40bfd43674406683bb3f0924d41780698a4ade96f2e180a73678bdd1" checksum = "633a728fb7209b398b7fa5b67460cb7f3cdb268c6b2a9e81967dda464cfbb5c1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1732,9 +1732,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.150" version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]] [[package]]
name = "libm" name = "libm"
@ -1765,9 +1765,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.10" version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -1913,6 +1913,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "minisign-verify"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.6.2" version = "0.6.2"
@ -1934,9 +1940,9 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.9" version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [ dependencies = [
"libc", "libc",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
@ -3012,9 +3018,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.27" version = "0.37.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"errno", "errno",
@ -3026,14 +3032,14 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.21" version = "0.38.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662"
dependencies = [ dependencies = [
"bitflags 2.4.0", "bitflags 2.4.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.10", "linux-raw-sys 0.4.7",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -3209,9 +3215,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.192" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -3227,9 +3233,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.192" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3249,9 +3255,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.108" version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [ dependencies = [
"itoa 1.0.6", "itoa 1.0.6",
"ryu", "ryu",
@ -3432,9 +3438,9 @@ dependencies = [
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.5.5" version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.48.0", "windows-sys 0.48.0",
@ -3739,6 +3745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9" checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.21.2",
"bytes", "bytes",
"cocoa", "cocoa",
"dirs-next", "dirs-next",
@ -3752,6 +3759,7 @@ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"http", "http",
"ignore", "ignore",
"minisign-verify",
"objc", "objc",
"once_cell", "once_cell",
"open", "open",
@ -3776,12 +3784,14 @@ dependencies = [
"tauri-utils", "tauri-utils",
"tempfile", "tempfile",
"thiserror", "thiserror",
"time",
"tokio", "tokio",
"url", "url",
"uuid", "uuid",
"webkit2gtk", "webkit2gtk",
"webview2-com", "webview2-com",
"windows 0.39.0", "windows 0.39.0",
"zip",
] ]
[[package]] [[package]]
@ -3846,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#61e862597e7234ddca9d9c4b07700855841888f3" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#9b20f28d747f6ec3ba5a80bfcd5edc1d573b4c90"
dependencies = [ dependencies = [
"log", "log",
"serde", "serde",
@ -3945,7 +3955,7 @@ dependencies = [
"cfg-if", "cfg-if",
"fastrand", "fastrand",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"rustix 0.37.27", "rustix 0.37.26",
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
@ -4025,9 +4035,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.34.0" version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -4035,7 +4045,7 @@ dependencies = [
"mio", "mio",
"num_cpus", "num_cpus",
"pin-project-lite", "pin-project-lite",
"socket2 0.5.5", "socket2 0.5.4",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -5002,3 +5012,14 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [ dependencies = [
"linked-hash-map", "linked-hash-map",
] ]
[[package]]
name = "zip"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
dependencies = [
"byteorder",
"crc32fast",
"crossbeam-utils",
]

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 = "https://github.com/KittyCAD/modeling-app" repository = ""
default-run = "app" default-run = "app"
edition = "2021" edition = "2021"
rust-version = "1.60" rust-version = "1.60"
@ -16,13 +16,13 @@ tauri-build = { version = "1.5.0", features = [] }
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
kittycad = "0.2.41" kittycad = "0.2.33"
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"
tauri = { version = "1.5.2", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] } tauri = { version = "1.5.2", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tokio = { version = "1.34.0", features = ["time"] } tokio = { version = "1.33.0", features = ["time"] }
toml = "0.8.2" toml = "0.8.2"
[features] [features]

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 separate window because we want 1password and // We do this in the browser and not a seperate 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.12.0" "version": "0.11.1"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {
@ -72,13 +72,23 @@
}, },
"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": false "active": true,
"endpoints": [
"https://dl.kittycad.io/releases/modeling-app/last_update.json"
],
"dialog": true,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
}, },
"windows": [ "windows": [
{ {

View File

@ -1,6 +1,7 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": { "package": {
"productName": "KittyCAD Modeling" "productName": "KittyCAD Modeling"
} }
} }

View File

@ -1,21 +0,0 @@
{
"$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,6 +1,7 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": { "package": {
"productName": "KittyCAD Modeling" "productName": "KittyCAD Modeling"
} }
} }

View File

@ -1,4 +1,4 @@
import { useCallback, MouseEventHandler } from 'react' import { useEffect, 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,6 +19,7 @@ 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'
@ -30,10 +31,11 @@ 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 { project, file } = useLoaderData() as IndexLoaderData const { code: loadedCode, project, file } = useLoaderData() as IndexLoaderData
useHotKeyListener() useHotKeyListener()
const { const {
@ -80,6 +82,26 @@ 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) => {
@ -226,7 +248,7 @@ export function App() {
<Stream className="absolute inset-0 z-0" /> <Stream className="absolute inset-0 z-0" />
{showDebugPanel && ( {showDebugPanel && (
<DebugPanel <DebugPanel
title="Debug (AST Explorer)" title="Debug"
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, kclManager } from 'lang/KclSinglton' import { KclContextProvider } 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,7 +207,6 @@ 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,3 +1,4 @@
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'
@ -14,6 +15,23 @@ 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,7 +184,6 @@ 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 } from '../lang/wasm' import { parse, BinaryPart, Value, executor } from '../lang/wasm'
import { import {
createIdentifier, createIdentifier,
createLiteral, createLiteral,
@ -10,7 +10,6 @@ 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,
@ -131,29 +130,27 @@ export function useCalc({
if (!programMemory || !selectionRange) return if (!programMemory || !selectionRange) return
const varInfo = findAllPreviousVariables( const varInfo = findAllPreviousVariables(
kclManager.ast, kclManager.ast,
kclManager.programMemory, programMemory,
selectionRange selectionRange
) )
setAvailableVarInfo(varInfo) setAvailableVarInfo(varInfo)
}, [kclManager.ast, kclManager.programMemory, selectionRange]) }, [kclManager.ast, programMemory, selectionRange])
useEffect(() => { useEffect(() => {
try { try {
const code = `const __result__ = ${value}` const code = `const __result__ = ${value}\nshow(__result__)`
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,
defaultPlanes: kclManager.defaultPlanes, kclManager.defaultPlanes
useFakeExecutor: true, ).then((programMemory) => {
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' &&
@ -170,7 +167,7 @@ export function useCalc({
setCalcResult('NAN') setCalcResult('NAN')
setValueNode(null) setValueNode(null)
} }
}, [value, availableVarInfo]) }, [value])
return { return {
valueNode, valueNode,
@ -215,10 +212,7 @@ export const CreateNewVariable = ({
}) => { }) => {
return ( return (
<> <>
<label <label htmlFor="create-new-variable" className="block mt-3 font-mono">
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">
@ -229,7 +223,6 @@ 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,7 +1,29 @@
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}
@ -12,6 +34,67 @@ 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>
@ -19,3 +102,41 @@ 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,13 +2,14 @@ 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, useRef, useState } from 'react' import { Dispatch, useEffect, 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'
import { faChevronRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons' import { faChevronRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'
import { useFileContext } from 'hooks/useFileContext' import { useFileContext } from 'hooks/useFileContext'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { kclManager } from 'lang/KclSinglton'
import styles from './FileTree.module.css' import styles from './FileTree.module.css'
import { sortProject } from 'lib/tauriFS' import { sortProject } from 'lib/tauriFS'
@ -162,6 +163,7 @@ 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,6 +20,7 @@ import {
recast, recast,
parse, parse,
Program, Program,
VariableDeclarator,
PipeExpression, PipeExpression,
CallExpression, CallExpression,
} from 'lang/wasm' } from 'lang/wasm'
@ -147,7 +148,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: 'start_path', commandType: 'extend_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 text-gray-900" className="border border-gray-300 px-2"
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 text-gray-900" 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"
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/90 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 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-400 px-2 mr-1 text-gray-900" className="border border-gray-300 px-2 mr-1"
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 text-gray-900 border-gray-300 rounded-md font-mono" className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm 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 text-gray-900 border-gray-300 rounded-md font-mono" className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm 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, CallExpression } from 'lang/wasm' import { VariableDeclarator, recast, parse, 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
getNodeFromPath<VariableDeclarator>( const varDec = 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,8 +342,7 @@ 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 = kclManager.safeParse(code) const astWithCurrentRanges = parse(code)
if (!astWithCurrentRanges) return
const updateNode = getNodeFromPath<CallExpression>( const updateNode = getNodeFromPath<CallExpression>(
astWithCurrentRanges, astWithCurrentRanges,
modded.pathToNode modded.pathToNode

View File

@ -17,7 +17,15 @@ 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 { EditorView, lineHighlightField } from 'editor/highlightextension' import { isTauri } from 'lib/isTauri'
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'
@ -42,6 +50,7 @@ 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,
@ -83,7 +92,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 because it will restart the client but not the server :) // a good setup becuase 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
@ -104,6 +113,18 @@ 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 { transforms } = setEqualLengthInfo({ selectionRanges }) const { enabled, transforms } = setEqualLengthInfo({ selectionRanges })
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({ const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
ast: kclManager.ast, ast: kclManager.ast,
selectionRanges, selectionRanges,

View File

@ -108,7 +108,6 @@ 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 efficiency // FIXME: tracing effiency
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,6 +2,8 @@ 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() {
@ -11,6 +13,11 @@ 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
@ -35,7 +42,7 @@ export function useEngineConnectionSubscriptions() {
const event = await getEventForSelectWithPoint(engineEvent, { const event = await getEventForSelectWithPoint(engineEvent, {
sketchEnginePathId: context.sketchEnginePathId, sketchEnginePathId: context.sketchEnginePathId,
}) })
event && send(event) send(event)
}, },
}) })
return () => { return () => {

View File

@ -1,5 +1,5 @@
import { useLayoutEffect, useEffect, useRef } from 'react' import { useLayoutEffect, useEffect, useRef } from 'react'
import { parse } from '../lang/wasm' import { _executor, 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,6 +26,10 @@ 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.
@ -82,14 +86,9 @@ export function useSetupEngineManager(
} }
function getDimensions(streamWidth?: number, streamHeight?: number) { function getDimensions(streamWidth?: number, streamHeight?: number) {
const maxResolution = 2000
const width = streamWidth ? streamWidth : 0 const width = streamWidth ? streamWidth : 0
const quadWidth = Math.round(width / 4) * 4
const height = streamHeight ? streamHeight : 0 const height = streamHeight ? streamHeight : 0
const ratio = Math.min( const quadHeight = Math.round(height / 4) * 4
Math.min(maxResolution / width, maxResolution / height),
1.0
)
const quadWidth = Math.round((width * ratio) / 4) * 4
const quadHeight = Math.round((height * ratio) / 4) * 4
return { width: quadWidth, height: quadHeight } return { width: quadWidth, height: quadHeight }
} }

View File

@ -18,11 +18,7 @@ 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 { Params, useLoaderData } from 'react-router-dom' import { 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'
@ -45,20 +41,10 @@ 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 = this.safeParse(code) const ast = parse(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)
@ -85,21 +71,6 @@ 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() {
@ -146,19 +117,10 @@ 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 persistence logic in a few months // TODO #819 remove zustand persistance 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') || '{}')
@ -168,7 +130,6 @@ 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
@ -203,21 +164,6 @@ 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
@ -238,20 +184,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 = this.safeParse(newCode) const newAst = parse(newCode)
if (!newAst) return
await this?.engineCommandManager?.waitForReady await this?.engineCommandManager?.waitForReady
if (updateCode) { if (updateCode) {
this.setCode(recast(ast)) this.setCode(recast(ast))
@ -287,17 +233,13 @@ class KclManager {
this.ast = ast this.ast = ast
if (code) this.code = code if (code) this.code = code
} }
setCode(code: string, shouldWriteFile = true) { setCode(code: string) {
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, shouldWriteFile = true) { setCodeAndExecute(code: string) {
this.setCode(code, shouldWriteFile) this.setCode(code)
if (code.trim()) { if (code.trim()) {
this._defferer(code) this._defferer(code)
return return
@ -318,11 +260,9 @@ class KclManager {
this.engineCommandManager.endSession() this.engineCommandManager.endSession()
} }
format() { format() {
const ast = this.safeParse(this.code) this.code = recast(parse(kclManager.code))
if (!ast) return
this.code = recast(ast)
} }
// There's overlapping responsibility between updateAst and executeAst. // There's overlapping resposibility 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(
@ -330,13 +270,15 @@ 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 = this.safeParse(newCode) const astWithUpdatedSource = parse(newCode)
if (!astWithUpdatedSource) return null optionalParams?.callBack?.(astWithUpdatedSource)
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,
@ -357,12 +299,12 @@ class KclManager {
if (execute) { if (execute) {
// Call execute on the set ast. // Call execute on the set ast.
await this.executeAst(astWithUpdatedSource, true) await this.executeAst(astWithUpdatedSource)
} 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, true) await this.executeAstMock(astWithUpdatedSource)
} }
return returnVal return returnVal
} }
@ -427,11 +369,6 @@ export function KclContextProvider({
setWasmInitFailed, setWasmInitFailed,
}) })
}, []) }, [])
const params = useParams()
useEffect(() => {
kclManager.setParams(params)
}, [params])
return ( return (
<KclContext.Provider <KclContext.Provider
value={{ value={{

View File

@ -331,6 +331,9 @@ const myVar = funcN(1, 2)`
raw: '2', raw: '2',
}, },
], ],
function: {
type: 'InMemory',
},
optional: false, optional: false,
}, },
}, },
@ -400,6 +403,7 @@ describe('testing pipe operator special', () => {
], ],
}, },
], ],
function: expect.any(Object),
optional: false, optional: false,
}, },
{ {
@ -436,6 +440,7 @@ 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,
}, },
{ {
@ -508,6 +513,7 @@ 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,
}, },
{ {
@ -544,6 +550,7 @@ 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,
}, },
{ {
@ -566,6 +573,9 @@ describe('testing pipe operator special', () => {
}, },
{ type: 'PipeSubstitution', start: 143, end: 144 }, { type: 'PipeSubstitution', start: 143, end: 144 },
], ],
function: {
type: 'InMemory',
},
optional: false, optional: false,
}, },
], ],
@ -645,6 +655,9 @@ describe('testing pipe operator special', () => {
end: 35, end: 35,
}, },
], ],
function: {
type: 'InMemory',
},
optional: false, optional: false,
}, },
], ],
@ -1332,7 +1345,7 @@ describe('nests binary expressions correctly', () => {
], ],
}) })
}) })
it('should nest properly with two operators of equal precedence', () => { it('should nest properly with two opperators 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({
@ -1369,7 +1382,7 @@ describe('nests binary expressions correctly', () => {
}, },
}) })
}) })
it('should nest properly with two operators of equal (but higher) precedence', () => { it('should nest properly with two opperators 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({
@ -1430,7 +1443,7 @@ describe('nests binary expressions correctly', () => {
type: 'BinaryExpression', type: 'BinaryExpression',
operator: '*', operator: '*',
start: 15, start: 15,
end: 25, end: 26,
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',
@ -1554,6 +1567,7 @@ 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,
}, },
}) })
@ -1587,10 +1601,12 @@ 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,
}) })
}) })
@ -1622,6 +1638,7 @@ 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,20 +18,6 @@ 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,6 +480,21 @@ 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,
} }
@ -499,6 +514,9 @@ 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 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, 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,
So it makes sense to group some of these together. So it makes sense to group some of these together.

View File

@ -216,26 +216,6 @@ export class EngineConnection {
} }
}) })
this.pc.addEventListener('icecandidateerror', (_event) => {
const event = _event as RTCPeerConnectionIceErrorEvent
console.error(
`ICE candidate returned an error: ${event.errorCode}: ${event.errorText} for ${event.url}`
)
})
this.pc.addEventListener('connectionstatechange', (event) => {
if (this.pc?.iceConnectionState === 'connected') {
if (this.shouldTrace()) {
iceSpan.resolve?.()
}
} else if (this.pc?.iceConnectionState === 'failed') {
// failed is a terminal state; let's explicitly kill the
// connection to the server at this point.
console.log('failed to negotiate ice connection; restarting')
this.close()
}
})
this.websocket.addEventListener('open', (event) => { this.websocket.addEventListener('open', (event) => {
if (this.shouldTrace()) { if (this.shouldTrace()) {
websocketSpan.resolve?.() websocketSpan.resolve?.()
@ -371,6 +351,19 @@ export class EngineConnection {
// until the end of this function is setup of our end of the // until the end of this function is setup of our end of the
// PeerConnection and waiting for events to fire our callbacks. // PeerConnection and waiting for events to fire our callbacks.
this.pc.addEventListener('connectionstatechange', (event) => {
if (this.pc?.iceConnectionState === 'connected') {
if (this.shouldTrace()) {
iceSpan.resolve?.()
}
} else if (this.pc?.iceConnectionState === 'failed') {
// failed is a terminal state; let's explicitly kill the
// connection to the server at this point.
console.log('failed to negotiate ice connection; restarting')
this.close()
}
})
this.pc.addEventListener('icecandidate', (event) => { this.pc.addEventListener('icecandidate', (event) => {
if (!this.pc || !this.websocket) return if (!this.pc || !this.websocket) return
if (event.candidate !== null) { if (event.candidate !== null) {
@ -640,10 +633,7 @@ export class EngineCommandManager {
// If we already have an engine connection, just need to resize the stream. // If we already have an engine connection, just need to resize the stream.
if (this.engineConnection) { if (this.engineConnection) {
this.handleResize({ this.handleResize({ streamWidth: width, streamHeight: height })
streamWidth: width,
streamHeight: height,
})
return return
} }
@ -674,7 +664,7 @@ export class EngineCommandManager {
}, },
}) })
// Initialize the planes. // Inisialize 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.
@ -897,9 +887,8 @@ 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 individually because if the engine doesn't recognise a single // we need to loop over them each individualy 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,
@ -909,9 +898,7 @@ 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(),
@ -995,7 +982,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 Error('shouldnt reach here') throw 'shouldnt reach here'
} }
handlePendingCommand( handlePendingCommand(
id: string, id: string,

View File

@ -20,6 +20,7 @@ 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'
@ -91,12 +92,18 @@ 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,
@ -243,6 +250,9 @@ 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)
@ -946,7 +956,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[1] - vec2[1]) const yDifference = Math.abs(vec1[0] - vec2[0])
return xDifference < compareEpsilon && yDifference < compareEpsilon return xDifference < compareEpsilon && yDifference < compareEpsilon
} }
@ -964,12 +974,14 @@ 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')
getNodeFromPath<VariableDeclarator>(node, pathToNode, 'VariableDeclarator') const { node: varDec } = getNodeFromPath<VariableDeclarator>(
getNodeFromPath<PipeExpression | CallExpression>(
node, node,
pathToNode, pathToNode,
'PipeExpression' 'VariableDeclarator'
) )
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 swapping out sketch calls with xLine/xLineTo', () => { describe('testing swaping 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 swapping 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 compatible `-myVar` // hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatiable `-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 swapping out sketch calls with xLine/xLineTo', () => {
}) })
}) })
describe('testing swapping out sketch calls with xLine/xLineTo while keeping variable/identifiers intact', () => { describe('testing swaping 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 second arg |> angledLine([myVar, 1.04], %) // ln-use segLen for secound 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 second arg |> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for secound 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 divide up lines into free, partial and fully contrained', () => { it('should devide 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,4 +26,5 @@ 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 associate those source ranges let code mirror control cursor positions and assosiate 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 entity ids calls 2) The handler for when the engine sends back entitiy 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 | null> { ): Promise<ModelingMachineEvent> {
if (!data?.entity_id) { if (!data?.entity_id) {
return { return {
type: 'Set selection', type: 'Set selection',
@ -120,7 +120,6 @@ 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',
@ -304,7 +303,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 is not ready') console.log('engine connection isnt ready')
return [] return []
} }
return [ return [

View File

@ -9,6 +9,7 @@ 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'
@ -210,8 +211,7 @@ 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,12 +225,10 @@ export async function createNewProject(
}) })
} }
await writeTextFile(path + sep + PROJECT_ENTRYPOINT, initCode).catch( await writeTextFile(path + sep + PROJECT_ENTRYPOINT, bracket).catch((err) => {
(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,7 +9,6 @@ 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 equipped, should these actions still be fired? // TODO what if we're existing extrude equiped, should these actions still be fired?
// maybe cancel needs to have a guard for if else logic? // mabye 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 } = applyConstraintHorzVert( const { modifiedAst, pathToNodeMap } = 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 } = applyConstraintHorzVert( const { modifiedAst, pathToNodeMap } = 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 } = applyConstraintHorzVertAlign({ const { modifiedAst, pathToNodeMap } = 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 } = applyConstraintHorzVertAlign({ const { modifiedAst, pathToNodeMap } = 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 } = applyConstraintEqualLength({ const { modifiedAst, pathToNodeMap } = applyConstraintEqualLength({
selectionRanges, selectionRanges,
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain parallel': ({ selectionRanges }) => { 'Constrain parallel': ({ selectionRanges }) => {
const { modifiedAst } = applyConstraintEqualAngle({ const { modifiedAst, pathToNodeMap } = applyConstraintEqualAngle({
selectionRanges, selectionRanges,
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)
}, },
'Constrain remove constraints': ({ selectionRanges }) => { 'Constrain remove constraints': ({ selectionRanges }) => {
const { modifiedAst } = applyRemoveConstrainingValues({ const { modifiedAst, pathToNodeMap } = applyRemoveConstrainingValues({
selectionRanges, selectionRanges,
}) })
kclManager.updateAst(modifiedAst, true) kclManager.updateAst(modifiedAst, true)

View File

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

View File

@ -32,7 +32,6 @@ 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 =
@ -97,10 +96,7 @@ export const Settings = () => {
ONBOARDING_PROJECT_NAME, ONBOARDING_PROJECT_NAME,
nextIndex nextIndex
) )
const newFile = await createNewProject( const newFile = await createNewProject(defaultDirectory + sep + name)
defaultDirectory + sep + name,
bracket
)
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`) navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)
} }

View File

@ -67,7 +67,6 @@ 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,13 +253,11 @@ 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[]
@ -271,13 +269,10 @@ export async function executeAst({
engineCommandManager.startNewSession() engineCommandManager.startNewSession()
} }
const programMemory = await (useFakeExecutor const programMemory = await (useFakeExecutor
? enginelessExecutor( ? enginelessExecutor(ast, {
ast, root: defaultProgramMemory,
programMemoryOverride || { return: null,
root: defaultProgramMemory, })
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 = "10s", terminate-after = 1 } slow-timeout = { period = "60s", terminate-after = 1 }
[profile.ci] [profile.ci]
slow-timeout = { period = "30s", terminate-after = 5 } slow-timeout = { period = "120s", terminate-after = 10 }
[[profile.default.overrides]] [[profile.default.overrides]]
filter = "test(serial_test_)" filter = "test(serial_test_)"
@ -20,7 +20,3 @@ 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 }

234
src/wasm-lib/Cargo.lock generated
View File

@ -157,7 +157,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -168,7 +168,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -447,9 +447,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.8" version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -457,9 +457,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.4.8" version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -472,21 +472,21 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.4.7" version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.6.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]] [[package]]
name = "color_quant" name = "color_quant"
@ -681,30 +681,6 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "databake"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "959b676312ba1aaafb2219c475560082e6b20c3bc572ec1483f93cecd748cf3d"
dependencies = [
"databake-derive",
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]]
name = "databake-derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0694dfe255f1af0289d3d1b40787bb955e8603d96e96a6b14b225926e108fb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"synstructure",
]
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.9" version = "0.3.9"
@ -726,7 +702,7 @@ dependencies = [
"quote", "quote",
"serde", "serde",
"serde_tokenstream", "serde_tokenstream",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -740,7 +716,7 @@ dependencies = [
"quote", "quote",
"serde", "serde",
"serde_tokenstream", "serde_tokenstream",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -945,9 +921,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -960,9 +936,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -970,15 +946,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@ -987,38 +963,38 @@ dependencies = [
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.29" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -1329,20 +1305,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "insta"
version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
dependencies = [
"console",
"lazy_static",
"linked-hash-map",
"serde",
"similar",
"yaml-rust",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -1407,9 +1369,9 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.65" version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1436,11 +1398,9 @@ dependencies = [
"clap", "clap",
"criterion", "criterion",
"dashmap", "dashmap",
"databake",
"derive-docs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-docs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"expectorate", "expectorate",
"futures", "futures",
"insta",
"itertools 0.11.0", "itertools 0.11.0",
"js-sys", "js-sys",
"kittycad", "kittycad",
@ -1463,18 +1423,6 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "kcl-macros"
version = "0.1.0"
dependencies = [
"databake",
"kcl-lib",
"pretty_assertions",
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.2.41" version = "0.2.41"
@ -1784,7 +1732,7 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]] [[package]]
name = "openapitor" name = "openapitor"
version = "0.0.9" version = "0.0.9"
source = "git+https://github.com/KittyCAD/kittycad.rs?branch=main#1b2562f4b3ecd26a3683c3fc48a0d33707097a36" source = "git+https://github.com/KittyCAD/kittycad.rs?branch=main#57b4d8b1688f6d13f91b538b0f107866b17bba84"
dependencies = [ dependencies = [
"Inflector", "Inflector",
"anyhow", "anyhow",
@ -1930,7 +1878,7 @@ dependencies = [
"regex", "regex",
"regex-syntax 0.7.5", "regex-syntax 0.7.5",
"structmeta", "structmeta",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -1983,7 +1931,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -2435,9 +2383,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.21" version = "0.38.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
dependencies = [ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"errno", "errno",
@ -2595,9 +2543,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.192" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -2613,13 +2561,13 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.192" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -2635,9 +2583,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.108" version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [ dependencies = [
"indexmap 2.0.2", "indexmap 2.0.2",
"itoa", "itoa",
@ -2653,7 +2601,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -2674,7 +2622,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -2885,7 +2833,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"structmeta-derive", "structmeta-derive",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -2896,7 +2844,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -2934,27 +2882,15 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.39" version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "synstructure"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"unicode-xid",
]
[[package]] [[package]]
name = "system-configuration" name = "system-configuration"
version = "0.5.1" version = "0.5.1"
@ -3057,7 +2993,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -3139,9 +3075,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.34.0" version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -3158,13 +3094,13 @@ dependencies = [
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.2.0" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -3305,7 +3241,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -3333,7 +3269,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -3419,7 +3355,7 @@ dependencies = [
"Inflector", "Inflector",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
"termcolor", "termcolor",
] ]
@ -3504,12 +3440,6 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]] [[package]]
name = "unsafe-libyaml" name = "unsafe-libyaml"
version = "0.2.9" version = "0.2.9"
@ -3603,9 +3533,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.88" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -3613,24 +3543,24 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.88" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-futures" name = "wasm-bindgen-futures"
version = "0.4.38" version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"futures-core", "futures-core",
@ -3641,9 +3571,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.88" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -3651,22 +3581,22 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.88" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.88" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]] [[package]]
name = "wasm-lib" name = "wasm-lib"
@ -3695,9 +3625,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-streams" name = "wasm-streams"
version = "0.4.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"js-sys", "js-sys",
@ -3723,9 +3653,9 @@ dependencies = [
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.65" version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
@ -3917,9 +3847,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.19" version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -3975,7 +3905,7 @@ checksum = "6b6093bc6d5265ff40b479c834cdd25d8e20784781a2a29a8106327393d0a9ff"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.38",
] ]
[[package]] [[package]]

View File

@ -2,8 +2,6 @@
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]
@ -14,10 +12,10 @@ 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 = { workspace = true } kittycad = { workspace = true }
serde_json = "1.0.108" serde_json = "1.0.107"
uuid = { version = "1.5.0", features = ["v4", "js", "serde"] } uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
wasm-bindgen = "0.2.88" wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4.38" wasm-bindgen-futures = "0.4.37"
[dev-dependencies] [dev-dependencies]
anyhow = "1" anyhow = "1"
@ -25,19 +23,19 @@ image = "0.24.7"
kittycad = { workspace = true, default-features = true } 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.34.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.5.0", 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.29" futures = "0.3.28"
js-sys = "0.3.65" js-sys = "0.3.64"
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.4.0" wasm-streams = "0.3.0"
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
version = "0.3.65" version = "0.3.57"
features = [ features = [
"console", "console",
"HtmlTextAreaElement", "HtmlTextAreaElement",
@ -53,7 +51,6 @@ debug = true
members = [ members = [
"derive-docs", "derive-docs",
"kcl", "kcl",
"kcl-macros",
] ]
[workspace.dependencies] [workspace.dependencies]

View File

@ -4,8 +4,6 @@ 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
@ -16,9 +14,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.192", features = ["derive"] } serde = { version = "1.0.189", features = ["derive"] }
serde_tokenstream = "0.2" serde_tokenstream = "0.2"
syn = { version = "2.0.39", features = ["full"] } syn = { version = "2.0.38", features = ["full"] }
[dev-dependencies] [dev-dependencies]
expectorate = "1.1.0" expectorate = "1.1.0"

View File

@ -1,22 +0,0 @@
[package]
name = "kcl-macros"
description = "Macro for compiling KCL to its AST during Rust compile-time"
version = "0.1.0"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
databake = "0.1.6"
kcl-lib = { path = "../kcl" }
proc-macro2 = "1"
quote = "1"
syn = { version = "2.0.39", features = ["full"] }
[dev-dependencies]
pretty_assertions = "1.4.0"

View File

@ -1,22 +0,0 @@
use databake::*;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, LitStr};
/// Parses KCL into its AST at compile-time.
/// This macro takes exactly one argument: A string literal containing KCL.
/// # Examples
/// ```
/// extern crate alloc;
/// use kcl_compile_macro::parse_kcl;
/// let ast: kcl_lib::ast::types::Program = parse_kcl!("const y = 4");
/// ```
#[proc_macro]
pub fn parse(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as LitStr);
let kcl_src = input.value();
let tokens = kcl_lib::token::lexer(&kcl_src);
let ast = kcl_lib::parser::Parser::new(tokens).ast().unwrap();
let ast_struct = ast.bake(&Default::default());
quote!(#ast_struct).into()
}

View File

@ -1,38 +0,0 @@
extern crate alloc;
use kcl_lib::ast::types::{
BodyItem, Identifier, Literal, LiteralValue, NonCodeMeta, Program, Value, VariableDeclaration, VariableDeclarator,
VariableKind,
};
use kcl_macros::parse;
use pretty_assertions::assert_eq;
#[test]
fn basic() {
let actual = parse!("const y = 4");
let expected = Program {
start: 0,
end: 11,
body: vec![BodyItem::VariableDeclaration(VariableDeclaration {
start: 0,
end: 11,
declarations: vec![VariableDeclarator {
start: 6,
end: 11,
id: Identifier {
start: 6,
end: 7,
name: "y".to_owned(),
},
init: Value::Literal(Box::new(Literal {
start: 10,
end: 11,
value: LiteralValue::IInteger(4),
raw: "4".to_owned(),
})),
}],
kind: VariableKind::Const,
})],
non_code_meta: NonCodeMeta::default(),
};
assert_eq!(expected, actual);
}

View File

@ -4,8 +4,6 @@ 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
@ -13,34 +11,33 @@ rust-version = "1.73"
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.8", features = ["cargo", "derive", "env", "unicode"], optional = true } clap = { version = "4.4.6", features = ["cargo", "derive", "env", "unicode"], optional = true }
dashmap = "5.5.3" dashmap = "5.5.3"
databake = { version = "0.1.6", features = ["derive"] }
derive-docs = { version = "0.1.4" } derive-docs = { version = "0.1.4" }
#derive-docs = { path = "../derive-docs" } #derive-docs = { path = "../derive-docs" }
kittycad = { workspace = true } 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.192", features = ["derive"] } serde = { version = "1.0.189", features = ["derive"] }
serde_json = "1.0.108" serde_json = "1.0.107"
thiserror = "1.0.50" 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.5.0", features = ["v4", "js", "serde"] } uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
winnow = "0.5.18" winnow = "0.5.16"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = { version = "0.3.65" } js-sys = { version = "0.3.64" }
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.88" wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4.38" wasm-bindgen-futures = "0.4.37"
web-sys = { version = "0.3.65", 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.29" } futures = { version = "0.3.28" }
reqwest = { version = "0.11.22", default-features = false } reqwest = { version = "0.11.22", default-features = false }
tokio = { version = "1.34.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"] }
tower-lsp = { version = "0.20.0", features = ["proposed"] } tower-lsp = { version = "0.20.0", features = ["proposed"] }
@ -53,16 +50,12 @@ 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.34.0", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }
[[bench]] [[bench]]
name = "compiler_benchmark" name = "compiler_benchmark"

View File

@ -11,7 +11,6 @@ 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| {
@ -34,4 +33,3 @@ 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,8 +3,6 @@ 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

@ -1,28 +1,24 @@
//! Data types for the AST. //! Data types for the AST.
use std::{collections::HashMap, fmt::Write}; use std::{
collections::HashMap,
fmt::{Formatter, Write},
};
use anyhow::Result; use anyhow::{anyhow, Result};
use databake::*;
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, Value as JValue}; use serde_json::{Map, Number as JNumber, 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::{BodyType, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, UserVal}, executor::{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, Bake)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Program { pub struct Program {
@ -351,8 +347,7 @@ macro_rules! impl_value_meta {
pub(crate) use impl_value_meta; pub(crate) use impl_value_meta;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum BodyItem { pub enum BodyItem {
@ -391,8 +386,7 @@ impl From<&BodyItem> for SourceRange {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Value { pub enum Value {
@ -555,8 +549,7 @@ impl From<&Value> for SourceRange {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum BinaryPart { pub enum BinaryPart {
@ -712,8 +705,7 @@ impl BinaryPart {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct NonCodeNode { pub struct NonCodeNode {
@ -761,8 +753,7 @@ impl NonCodeNode {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum CommentStyle { pub enum CommentStyle {
@ -772,8 +763,7 @@ pub enum CommentStyle {
Block, Block,
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")] #[serde(tag = "type", rename_all = "camelCase")]
pub enum NonCodeValue { pub enum NonCodeValue {
@ -793,7 +783,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 doesn't have a new line above it. /// This is always the case. Also the block comment doesnt 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,
@ -818,19 +808,6 @@ pub struct NonCodeMeta {
pub start: Vec<NonCodeNode>, pub start: Vec<NonCodeNode>,
} }
impl Bake for NonCodeMeta {
fn bake(&self, env: &CrateEnv) -> TokenStream {
env.insert("kcl_lib::ast::types");
let start = self.start.bake(env);
databake::quote! {
kcl_lib::ast::types::NonCodeMeta {
non_code_nodes: std::collections::HashMap::new(),
start: #start,
}
}
}
}
// implement Deserialize manually because we to force the keys of non_code_nodes to be usize // implement Deserialize manually because we to force the keys of non_code_nodes to be usize
// and by default the ts type { [statementIndex: number]: NonCodeNode } serializes to a string i.e. "0", "1", etc. // and by default the ts type { [statementIndex: number]: NonCodeNode } serializes to a string i.e. "0", "1", etc.
impl<'de> Deserialize<'de> for NonCodeMeta { impl<'de> Deserialize<'de> for NonCodeMeta {
@ -864,8 +841,7 @@ impl NonCodeMeta {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct ExpressionStatement { pub struct ExpressionStatement {
@ -876,8 +852,7 @@ pub struct ExpressionStatement {
impl_value_meta!(ExpressionStatement); impl_value_meta!(ExpressionStatement);
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct CallExpression { pub struct CallExpression {
@ -886,6 +861,7 @@ 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);
@ -898,12 +874,22 @@ 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 },
}) })
} }
@ -985,8 +971,8 @@ impl CallExpression {
fn_args.push(result); fn_args.push(result);
} }
match ctx.stdlib.get_either(&self.callee.name) { match &self.function {
FunctionKind::Core(func) => { Function::StdLib { 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?;
@ -998,54 +984,14 @@ impl CallExpression {
Ok(result) Ok(result)
} }
} }
FunctionKind::Std(func) => { Function::InMemory => {
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 user-defined function {} is undefined", fn_name), message: format!("Result of function {} is undefined", fn_name),
source_ranges: vec![self.into()], source_ranges: vec![self.into()],
}) })
})?; })?;
@ -1120,15 +1066,10 @@ impl CallExpression {
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Function { pub enum Function {
/// A stdlib function written in Rust (aka core lib). /// A stdlib function.
StdLib { StdLib {
/// The function. /// The function.
func: Box<dyn StdLibFn>, func: Box<dyn crate::docs::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]
@ -1145,8 +1086,7 @@ impl PartialEq for Function {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct VariableDeclaration { pub struct VariableDeclaration {
@ -1296,8 +1236,7 @@ impl VariableDeclaration {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[display(style = "snake_case")] #[display(style = "snake_case")]
@ -1341,8 +1280,7 @@ impl VariableKind {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct VariableDeclarator { pub struct VariableDeclarator {
@ -1371,8 +1309,7 @@ impl VariableDeclarator {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct Literal { pub struct Literal {
@ -1382,14 +1319,80 @@ pub struct Literal {
pub raw: String, pub raw: String,
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum LiteralValue {
// TODO: Use Cow<str> here so that static strings don't require alloc
String(String),
Number(JNumber),
}
impl std::fmt::Display for LiteralValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
JValue::from(self.to_owned()).fmt(f)
}
}
impl From<LiteralValue> for JValue {
fn from(value: LiteralValue) -> Self {
match value {
LiteralValue::String(x) => JValue::String(x),
LiteralValue::Number(x) => JValue::Number(x),
}
}
}
impl From<&'static str> for LiteralValue {
fn from(value: &'static str) -> Self {
Self::String(value.to_owned())
}
}
impl From<String> for LiteralValue {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<JNumber> for LiteralValue {
fn from(value: JNumber) -> Self {
Self::Number(value)
}
}
impl From<u64> for LiteralValue {
fn from(value: u64) -> Self {
Self::Number(value.into())
}
}
impl From<i64> for LiteralValue {
fn from(value: i64) -> Self {
Self::Number(value.into())
}
}
impl From<f64> for LiteralValue {
fn from(value: f64) -> Self {
JNumber::from_f64(value)
.map(Self::Number)
.expect("Cannot use NaN or Inf here. TODO stop using json numbers here")
}
}
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: LiteralValue) -> Self { pub fn new(value: LiteralValue) -> Self {
Self { Self {
start: 0, start: 0,
end: 0, end: 0,
raw: JValue::from(value.clone()).to_string(), raw: value.to_string(),
value, value,
} }
} }
@ -1403,19 +1406,11 @@ impl Literal {
} }
fn recast(&self) -> String { fn recast(&self) -> String {
match self.value { if let JValue::String(value) = &self.value {
LiteralValue::Fractional(x) => { let quote = if self.raw.trim().starts_with('"') { '"' } else { '\'' };
if x.fract() == 0.0 { format!("{}{}{}", quote, value, quote)
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}")
}
} }
} }
} }
@ -1423,7 +1418,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: JValue::from(literal.value.clone()), value: literal.value.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: literal.into(), source_range: literal.into(),
}], }],
@ -1434,7 +1429,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: JValue::from(literal.value.clone()), value: literal.value.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: literal.into(), source_range: literal.into(),
}], }],
@ -1442,8 +1437,7 @@ impl From<&Box<Literal>> for MemoryItem {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct Identifier { pub struct Identifier {
@ -1479,8 +1473,7 @@ impl Identifier {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct PipeSubstitution { pub struct PipeSubstitution {
@ -1508,8 +1501,7 @@ impl From<PipeSubstitution> for Value {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct ArrayExpression { pub struct ArrayExpression {
@ -1669,8 +1661,7 @@ impl ArrayExpression {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct ObjectExpression { pub struct ObjectExpression {
@ -1827,8 +1818,7 @@ impl ObjectExpression {
impl_value_meta!(ObjectExpression); impl_value_meta!(ObjectExpression);
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct ObjectProperty { pub struct ObjectProperty {
@ -1870,8 +1860,7 @@ impl ObjectProperty {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum MemberObject { pub enum MemberObject {
@ -1917,8 +1906,7 @@ impl From<&MemberObject> for SourceRange {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum LiteralIdentifier { pub enum LiteralIdentifier {
@ -1954,8 +1942,7 @@ impl From<&LiteralIdentifier> for SourceRange {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct MemberExpression { pub struct MemberExpression {
@ -2016,10 +2003,10 @@ impl MemberExpression {
let array_json = array.get_json_value()?; let array_json = array.get_json_value()?;
if let serde_json::Value::Array(array) = array_json { if let JValue::Array(array) = array_json {
if let Some(value) = array.get(index) { if let Some(value) = array.get(index) {
Ok(MemoryItem::UserVal(UserVal { Ok(MemoryItem::UserVal(UserVal {
value: value.clone(), value: value.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
}], }],
@ -2042,22 +2029,18 @@ impl MemberExpression {
let property_name = match &self.property { let property_name = match &self.property {
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.into();
match value { // Parse this as a string.
LiteralValue::IInteger(x) if x >= 0 => return self.get_result_array(memory, x as usize), if let JValue::String(string) = value {
LiteralValue::IInteger(x) => { string
return Err(KclError::Syntax(KclErrorDetails { } else if let JValue::Number(_) = &value {
source_ranges: vec![self.into()], // It can also be a number if we are getting a member of an array.
message: format!("invalid index: {x}"), return self.get_result_array(memory, parse_json_number_as_usize(&value, self.into())?);
})) } else {
} return Err(KclError::Semantic(KclErrorDetails {
LiteralValue::Fractional(x) => { message: format!("Expected string literal or number for property name, found {:?}", value),
return Err(KclError::Syntax(KclErrorDetails { source_ranges: vec![literal.into()],
source_ranges: vec![self.into()], }));
message: format!("invalid index: {x}"),
}))
}
LiteralValue::String(s) => s,
} }
} }
}; };
@ -2072,10 +2055,10 @@ impl MemberExpression {
let object_json = object.get_json_value()?; let object_json = object.get_json_value()?;
if let serde_json::Value::Object(map) = object_json { if let JValue::Object(map) = object_json {
if let Some(value) = map.get(&property_name) { if let Some(value) = map.get(&property_name) {
Ok(MemoryItem::UserVal(UserVal { Ok(MemoryItem::UserVal(UserVal {
value: value.clone(), value: value.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
}], }],
@ -2118,8 +2101,7 @@ pub struct ObjectKeyInfo {
pub computed: bool, pub computed: bool,
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct BinaryExpression { pub struct BinaryExpression {
@ -2237,7 +2219,7 @@ impl BinaryExpression {
parse_json_value_as_string(&left_json_value), parse_json_value_as_string(&left_json_value),
parse_json_value_as_string(&right_json_value), parse_json_value_as_string(&right_json_value),
) { ) {
let value = serde_json::Value::String(format!("{}{}", left, right)); let value = JValue::String(format!("{}{}", left, right)).into();
return Ok(MemoryItem::UserVal(UserVal { return Ok(MemoryItem::UserVal(UserVal {
value, value,
meta: vec![Metadata { meta: vec![Metadata {
@ -2250,17 +2232,16 @@ impl BinaryExpression {
let left = parse_json_number_as_f64(&left_json_value, self.left.clone().into())?; let left = parse_json_number_as_f64(&left_json_value, self.left.clone().into())?;
let right = parse_json_number_as_f64(&right_json_value, self.right.clone().into())?; let right = parse_json_number_as_f64(&right_json_value, self.right.clone().into())?;
let value: serde_json::Value = match self.operator { let value: JNumber = match self.operator {
BinaryOperator::Add => (left + right).into(), BinaryOperator::Add => (left + right).into(),
BinaryOperator::Sub => (left - right).into(), BinaryOperator::Sub => (left - right).into(),
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 {
value, value: value.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
}], }],
@ -2274,8 +2255,8 @@ impl BinaryExpression {
} }
} }
pub fn parse_json_number_as_f64(j: &serde_json::Value, source_range: SourceRange) -> Result<f64, KclError> { pub fn parse_json_number_as_f64(j: &JValue, source_range: SourceRange) -> Result<f64, KclError> {
if let serde_json::Value::Number(n) = &j { if let JValue::Number(n) = &j {
n.as_f64().ok_or_else(|| { n.as_f64().ok_or_else(|| {
KclError::Syntax(KclErrorDetails { KclError::Syntax(KclErrorDetails {
source_ranges: vec![source_range], source_ranges: vec![source_range],
@ -2290,16 +2271,31 @@ pub fn parse_json_number_as_f64(j: &serde_json::Value, source_range: SourceRange
} }
} }
pub fn parse_json_value_as_string(j: &serde_json::Value) -> Option<String> { pub fn parse_json_number_as_usize(j: &JValue, source_range: SourceRange) -> Result<usize, KclError> {
if let serde_json::Value::String(n) = &j { if let JValue::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: &JValue) -> Option<String> {
if let JValue::String(n) = &j {
Some(n.clone()) Some(n.clone())
} else { } else {
None None
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[display(style = "snake_case")] #[display(style = "snake_case")]
@ -2324,51 +2320,17 @@ 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,
} }
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct UnaryExpression { pub struct UnaryExpression {
@ -2446,8 +2408,7 @@ impl UnaryExpression {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[display(style = "snake_case")] #[display(style = "snake_case")]
@ -2462,8 +2423,7 @@ pub enum UnaryOperator {
Not, Not,
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase", tag = "type")] #[serde(rename_all = "camelCase", tag = "type")]
pub struct PipeExpression { pub struct PipeExpression {
@ -2621,8 +2581,7 @@ async fn execute_pipe_body(
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct FunctionExpression { pub struct FunctionExpression {
@ -2672,8 +2631,7 @@ impl FunctionExpression {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub struct ReturnStatement { pub struct ReturnStatement {
@ -3360,40 +3318,4 @@ 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

@ -1,72 +0,0 @@
use databake::*;
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, Bake)]
#[databake(path = kcl_lib::ast::types)]
#[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 position of the cursor. // Fill this in based on the current positon of the cursor.
let active_parameter = None; let active_parameter = None;
SignatureHelp { SignatureHelp {

View File

@ -8,8 +8,6 @@ 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:?}")]
@ -28,8 +26,6 @@ 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)]
@ -44,8 +40,20 @@ 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) = self.source_ranges().first() { let (line, column) = if let Some(range) = source_range.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();
@ -54,28 +62,11 @@ impl KclError {
(None, None) (None, None)
}; };
(format!("{}: {}", self.error_type(), self.message()), line, column) (format!("{}: {}", type_, 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(),
@ -85,14 +76,12 @@ 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,
@ -102,7 +91,6 @@ 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,9 +1,8 @@
//! The executor for the AST. //! The executor for the AST.
use std::{collections::HashMap, sync::Arc}; use std::collections::HashMap;
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;
@ -11,10 +10,9 @@ 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, FunctionExpression, Value}, ast::types::{BodyItem, Function, FunctionExpression, LiteralValue, 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)]
@ -284,7 +282,7 @@ impl DefaultPlanes {
#[ts(export)] #[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")] #[serde(tag = "type", rename_all = "camelCase")]
pub struct UserVal { pub struct UserVal {
pub value: serde_json::Value, pub value: LiteralValue,
#[serde(rename = "__meta")] #[serde(rename = "__meta")]
pub meta: Vec<Metadata>, pub meta: Vec<Metadata>,
} }
@ -338,7 +336,7 @@ impl From<MemoryItem> for Vec<SourceRange> {
impl MemoryItem { impl MemoryItem {
pub fn get_json_value(&self) -> Result<serde_json::Value, KclError> { pub fn get_json_value(&self) -> Result<serde_json::Value, KclError> {
if let MemoryItem::UserVal(user_val) = self { if let MemoryItem::UserVal(user_val) = self {
Ok(user_val.value.clone()) Ok(user_val.value.into())
} else { } else {
serde_json::to_value(self).map_err(|err| { serde_json::to_value(self).map_err(|err| {
KclError::Semantic(KclErrorDetails { KclError::Semantic(KclErrorDetails {
@ -349,27 +347,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> {
let MemoryItem::Function { func, expression, meta } = &self else { if let MemoryItem::Function { func, expression, meta } = &self {
return Err(KclError::Semantic(KclErrorDetails { if let Some(func) = func {
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
} }
} }
@ -778,11 +776,9 @@ 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,
@ -795,9 +791,7 @@ pub async fn execute(
for statement in &program.body { for statement in &program.body {
match statement { match statement {
BodyItem::ExpressionStatement(expression_statement) => { BodyItem::ExpressionStatement(expression_statement) => {
if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { if let Value::CallExpression(call_expr) = &expression_statement.expression {
pipe_expr.get_result(memory, &mut pipe_info, ctx).await?;
} else if let Value::CallExpression(call_expr) = &expression_statement.expression {
let fn_name = call_expr.callee.name.to_string(); let fn_name = call_expr.callee.name.to_string();
let mut args: Vec<MemoryItem> = Vec::new(); let mut args: Vec<MemoryItem> = Vec::new();
for arg in &call_expr.arguments { for arg in &call_expr.arguments {
@ -832,37 +826,24 @@ pub async fn execute(
} }
} }
let _show_fn = Box::new(crate::std::Show); let _show_fn = Box::new(crate::std::Show);
match ctx.stdlib.get_either(&call_expr.callee.name) { if let Function::StdLib { func: _show_fn } = &call_expr.function {
FunctionKind::Core(func) => { if options != BodyType::Root {
use crate::docs::StdLibFn; return Err(KclError::Semantic(KclErrorDetails {
if func.name() == _show_fn.name() { message: "Cannot call show outside of a root".to_string(),
if options != BodyType::Root { source_ranges: vec![call_expr.into()],
return Err(KclError::Semantic(KclErrorDetails { }));
message: "Cannot call show outside of a root".to_string(), }
source_ranges: vec![call_expr.into()],
}));
}
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) {
} let result = func.call_fn(args.clone(), memory.clone(), ctx.clone()).await?;
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?;
memory.return_ = result; memory.return_ = result;
} else { } else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("No such name {} defined", fn_name), message: format!("No such name {} defined", fn_name),
source_ranges: vec![call_expr.into()], source_ranges: vec![call_expr.into()],
})); }));
}
}
} }
} }
} }
@ -1030,11 +1011,7 @@ 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 { let ctx = ExecutorContext { engine, planes };
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,6 +5,7 @@ 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

@ -1,163 +0,0 @@
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

@ -1,26 +0,0 @@
---
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

@ -1,26 +0,0 @@
---
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

@ -1,26 +0,0 @@
---
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

@ -1,41 +0,0 @@
---
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

@ -1,41 +0,0 @@
---
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

@ -1,56 +0,0 @@
---
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

@ -1,56 +0,0 @@
---
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

@ -1,71 +0,0 @@
---
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

@ -1,41 +0,0 @@
---
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

@ -1,81 +0,0 @@
---
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

@ -1,26 +0,0 @@
---
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

@ -1,263 +0,0 @@
---
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

@ -1,48 +0,0 @@
---
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

@ -1,85 +0,0 @@
---
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

@ -1,130 +0,0 @@
---
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

@ -1,85 +0,0 @@
---
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

@ -1,99 +0,0 @@
---
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

@ -1,317 +0,0 @@
---
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

@ -1,151 +0,0 @@
---
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

@ -1,56 +0,0 @@
---
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

@ -1,92 +0,0 @@
---
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

@ -1,112 +0,0 @@
---
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

@ -1,78 +0,0 @@
---
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

@ -1,113 +0,0 @@
---
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

@ -1,78 +0,0 @@
---
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

@ -1,113 +0,0 @@
---
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

@ -1,113 +0,0 @@
---
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

@ -1,73 +0,0 @@
---
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

@ -1,58 +0,0 @@
---
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

@ -1,43 +0,0 @@
---
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

@ -1,64 +0,0 @@
---
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

@ -1,158 +0,0 @@
---
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": []
}
}

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