Compare commits
92 Commits
v0.11.0
...
kurt-repli
Author | SHA1 | Date | |
---|---|---|---|
8210663923 | |||
7272cc9fbd | |||
b925ed9b65 | |||
0db5db2181 | |||
898e3db9d1 | |||
d337ac2546 | |||
371d8e08f7 | |||
338c43a29d | |||
52bb5a2657 | |||
1b6a06d266 | |||
c68d4778a5 | |||
a8abea4fb5 | |||
a0678d22a8 | |||
acbfae2e65 | |||
1e1bec6a8a | |||
06462b5a65 | |||
2f292fb1be | |||
8184e7b376 | |||
b1084cbf80 | |||
548b45905e | |||
141fd2f3f1 | |||
604d931962 | |||
b1668410f8 | |||
13176cec38 | |||
3a59ae13b6 | |||
57c2481943 | |||
a1c555c51e | |||
4d520541be | |||
82586f002b | |||
4bd08f7444 | |||
6b2603b1c4 | |||
af49bebde3 | |||
ca056996fd | |||
34163da361 | |||
7c22bac638 | |||
37a65b166b | |||
1189f272ba | |||
ca5bc880dc | |||
828daba304 | |||
0b9ba55bb4 | |||
2d2a85ae7d | |||
cc57a302cc | |||
fdbfd0c4b6 | |||
2e419907e6 | |||
3d0c5c10b0 | |||
4d47c067b7 | |||
3b3b5371eb | |||
3ea77f8e1e | |||
4fa7c07e54 | |||
c66a96a333 | |||
4196ff91ac | |||
cf66b93963 | |||
0b0219b810 | |||
36c7fcf6d7 | |||
023c3cbb90 | |||
387f7e0912 | |||
9b55b1fd12 | |||
4b6662169c | |||
d36abfcb3d | |||
9002ae9efb | |||
4deea25394 | |||
b5940d2cb7 | |||
932b467c1e | |||
7c7f5c81c4 | |||
066b4f3e06 | |||
c6067bfc7a | |||
2018f0d517 | |||
74aae3d15f | |||
812f419e75 | |||
5ec8cc69db | |||
a5302b6e0e | |||
2114cc0d94 | |||
2471ce1aba | |||
35772475b9 | |||
86c592c0f6 | |||
0e98973cfa | |||
7dd16fe6de | |||
478b636049 | |||
c779311a56 | |||
ca02ec1151 | |||
b271d5060e | |||
19f11fe55a | |||
f6f1574982 | |||
6dc4fbc808 | |||
8843d02380 | |||
3578ec07e6 | |||
db35f73e41 | |||
5cfc2b7941 | |||
318e4a0cc7 | |||
1e23be8f08 | |||
ef547e7db8 | |||
71b48bbd89 |
3
.codespellrc
Normal file
3
.codespellrc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[codespell]
|
||||||
|
ignore-words-list: crate,everytime
|
||||||
|
skip: **/target,node_modules,build
|
126
.github/workflows/ci.yml
vendored
126
.github/workflows/ci.yml
vendored
@ -12,27 +12,32 @@ on:
|
|||||||
# Daily at 04:00 AM UTC
|
# Daily at 04:00 AM UTC
|
||||||
# Will checkout the last commit from the default branch (main as of 2023-10-04)
|
# Will checkout the last commit from the default branch (main as of 2023-10-04)
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && contains(github.event.pull_request.title, 'Cut release v') }}
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-format:
|
check-format:
|
||||||
runs-on: 'ubuntu-20.04'
|
runs-on: 'ubuntu-latest'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
- run: yarn install
|
- run: yarn install
|
||||||
- run: yarn fmt-check
|
- run: yarn fmt-check
|
||||||
|
|
||||||
|
|
||||||
check-types:
|
check-types:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@ -44,12 +49,27 @@ jobs:
|
|||||||
- run: yarn build:wasm
|
- run: yarn build:wasm
|
||||||
- run: yarn tsc
|
- run: yarn tsc
|
||||||
|
|
||||||
|
|
||||||
|
check-typos:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
- name: Install codespell
|
||||||
|
run: |
|
||||||
|
python -m pip install codespell
|
||||||
|
- name: Run codespell
|
||||||
|
run: codespell --config .codespellrc # Edit this file to tweak the typo list and other configuration.
|
||||||
|
|
||||||
|
|
||||||
build-test-web:
|
build-test-web:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@ -68,14 +88,15 @@ jobs:
|
|||||||
|
|
||||||
- run: yarn test:cov
|
- run: yarn test:cov
|
||||||
|
|
||||||
|
|
||||||
prepare-json-files:
|
prepare-json-files:
|
||||||
runs-on: ubuntu-20.04 # seperate job on Ubuntu for easy string manipulations (compared to Windows)
|
runs-on: ubuntu-latest # seperate job on Ubuntu for easy string manipulations (compared to Windows)
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.export_version.outputs.version }}
|
version: ${{ steps.export_version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@ -84,8 +105,8 @@ jobs:
|
|||||||
if: github.event_name == 'schedule'
|
if: github.event_name == 'schedule'
|
||||||
run: |
|
run: |
|
||||||
VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons
|
VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons
|
||||||
echo "$(jq --arg url 'https://dl.kittycad.io/releases/modeling-app/test/nightly/last_update.json' \
|
echo "$(jq --arg url 'https://dl.kittycad.io/releases/modeling-app/nightly/last_update.json' \
|
||||||
'.tauri.updater.endpoints[]=$url' src-tauri/tauri.conf.json --indent 2)" > src-tauri/tauri.conf.json
|
'.tauri.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: github.event_name == 'schedule'
|
if: github.event_name == 'schedule'
|
||||||
@ -93,16 +114,18 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
package.json
|
package.json
|
||||||
src-tauri/tauri.conf.json
|
src-tauri/tauri.conf.json
|
||||||
|
src-tauri/tauri.release.conf.json
|
||||||
|
|
||||||
- id: export_version
|
- id: export_version
|
||||||
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
|
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
build-apps:
|
|
||||||
needs: [check-format, build-test-web, prepare-json-files, check-types]
|
build-test-apps:
|
||||||
|
needs: [prepare-json-files]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, ubuntu-20.04, windows-latest]
|
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -114,25 +137,32 @@ jobs:
|
|||||||
ls -l artifact
|
ls -l artifact
|
||||||
cp artifact/package.json package.json
|
cp artifact/package.json package.json
|
||||||
cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json
|
cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json
|
||||||
|
cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json
|
||||||
|
|
||||||
- name: install ubuntu system dependencies
|
- name: Install ubuntu system dependencies
|
||||||
if: matrix.os == 'ubuntu-20.04'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: |
|
run: >
|
||||||
sudo apt-get update
|
sudo apt-get update &&
|
||||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev
|
sudo apt-get install -y
|
||||||
|
libgtk-3-dev
|
||||||
|
libgtksourceview-3.0-dev
|
||||||
|
webkit2gtk-4.0
|
||||||
|
libappindicator3-dev
|
||||||
|
webkit2gtk-driver
|
||||||
|
xvfb
|
||||||
|
|
||||||
- name: Sync node version and setup cache
|
- name: Sync node version and setup cache
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'yarn' # Set this to npm, yarn or pnpm.
|
cache: 'yarn' # Set this to npm, yarn or pnpm.
|
||||||
|
|
||||||
- run: yarn install
|
- run: yarn install
|
||||||
|
|
||||||
- name: Rust setup
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
- name: Rust cache
|
- name: Setup Rust cache
|
||||||
uses: swatinem/rust-cache@v2
|
uses: swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
workspaces: './src-tauri -> target'
|
workspaces: './src-tauri -> target'
|
||||||
@ -141,24 +171,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
workspaces: './src/wasm-lib'
|
workspaces: './src/wasm-lib'
|
||||||
|
|
||||||
- name: wasm prep
|
- name: Run build:wasm manually
|
||||||
shell: bash
|
shell: bash
|
||||||
|
env:
|
||||||
|
MODE: ${{ env.BUILD_RELEASE == 'true' && '--release' || '--debug' }}
|
||||||
run: |
|
run: |
|
||||||
mkdir src/wasm-lib/pkg; cd src/wasm-lib
|
mkdir src/wasm-lib/pkg; cd src/wasm-lib
|
||||||
npx wasm-pack build --target web --out-dir pkg
|
echo "building with ${{ env.MODE }}"
|
||||||
|
npx wasm-pack build --target web --out-dir pkg ${{ env.MODE }}
|
||||||
cd ../../
|
cd ../../
|
||||||
cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
|
cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
|
||||||
|
|
||||||
- name: Fix format
|
- name: Fix format
|
||||||
run: yarn fmt
|
run: yarn fmt
|
||||||
|
|
||||||
- name: install apple silicon target mac
|
- name: Install Universal target (MacOS only)
|
||||||
if: matrix.os == 'macos-latest'
|
if: matrix.os == 'macos-latest'
|
||||||
run: |
|
run: |
|
||||||
rustup target add aarch64-apple-darwin
|
rustup target add aarch64-apple-darwin
|
||||||
|
|
||||||
- name: Prepare Windows certificate and variables
|
- name: Prepare certificate and variables (Windows only)
|
||||||
if: matrix.os == 'windows-latest'
|
if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12
|
echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12
|
||||||
cat /d/Certificate_pkcs12.p12
|
cat /d/Certificate_pkcs12.p12
|
||||||
@ -172,8 +205,8 @@ jobs:
|
|||||||
echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH
|
echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Setup Windows certicate with SSM KSP
|
- name: Setup certicate with SSM KSP (Windows only)
|
||||||
if: matrix.os == 'windows-latest'
|
if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
|
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
|
||||||
msiexec /i smtools-windows-x64.msi /quiet /qn
|
msiexec /i smtools-windows-x64.msi /quiet /qn
|
||||||
@ -183,8 +216,17 @@ jobs:
|
|||||||
smksp_cert_sync.exe
|
smksp_cert_sync.exe
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
- name: Build and sign the app for the current platform
|
- name: Build the app (debug)
|
||||||
uses: tauri-apps/tauri-action@v0
|
uses: tauri-apps/tauri-action@v0
|
||||||
|
if: ${{ env.BUILD_RELEASE == 'false' }}
|
||||||
|
with:
|
||||||
|
includeRelease: false
|
||||||
|
includeDebug: true
|
||||||
|
args: ${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }}
|
||||||
|
|
||||||
|
- name: Build the app (release) and sign
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
|
if: ${{ env.BUILD_RELEASE == 'true' }}
|
||||||
env:
|
env:
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
@ -194,17 +236,35 @@ jobs:
|
|||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
|
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
|
||||||
with:
|
with:
|
||||||
args: ${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }}
|
args: "${{ matrix.os == 'macos-latest' && '--target universal-apple-darwin' || '' }} ${{ env.TAURI_CONF_ARGS }}"
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
|
env:
|
||||||
|
PREFIX: ${{ matrix.os == 'macos-latest' && 'src-tauri/target/universal-apple-darwin' || 'src-tauri/target' }}
|
||||||
|
MODE: ${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}
|
||||||
with:
|
with:
|
||||||
path: ${{ matrix.os == 'macos-latest' && 'src-tauri/target/universal-apple-darwin/release/bundle/*/*' || 'src-tauri/target/release/bundle/*/*' }}
|
path: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*"
|
||||||
|
|
||||||
|
- name: Install tauri-driver for e2e tests (linux only)
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: install
|
||||||
|
args: tauri-driver
|
||||||
|
|
||||||
|
- name: Run e2e tests (linux only)
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
run: xvfb-run yarn test:e2e
|
||||||
|
env:
|
||||||
|
MODE: ${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}
|
||||||
|
|
||||||
|
|
||||||
publish-apps-release:
|
publish-apps-release:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
|
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
|
||||||
needs: [build-test-web, prepare-json-files, build-apps]
|
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
|
||||||
env:
|
env:
|
||||||
VERSION_NO_V: ${{ needs.prepare-json-files.outputs.version }}
|
VERSION_NO_V: ${{ needs.prepare-json-files.outputs.version }}
|
||||||
VERSION: ${{ github.event_name == 'release' && format('v{0}', needs.prepare-json-files.outputs.version) || needs.prepare-json-files.outputs.version }}
|
VERSION: ${{ github.event_name == 'release' && format('v{0}', needs.prepare-json-files.outputs.version) || needs.prepare-json-files.outputs.version }}
|
||||||
|
@ -48,7 +48,7 @@ We recommend downloading the latest application binary from [our Releases page](
|
|||||||
|
|
||||||
## Running a development build
|
## Running a development build
|
||||||
|
|
||||||
First, [install Rust via `rustup`](https://www.rust-lang.org/tools/install). This project uses a lot of Rust compiled to [WASM](https://webassembly.org/) within it. Then, run:
|
First, [install Rust via `rustup`](https://www.rust-lang.org/tools/install). This project uses a lot of Rust compiled to [WASM](https://webassembly.org/) within it. We always use the latest stable version of Rust, so you may need to run `rustup update stable`. Then, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn install
|
yarn install
|
||||||
@ -104,7 +104,7 @@ To spin up up tauri dev, `yarn install` and `yarn build:wasm-dev` need to have b
|
|||||||
yarn tauri dev
|
yarn tauri dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Will spin up the web app before opening up the tauri dev desktop app. Note that it's probably a good idea to close the browser tab that gets opened since at the time of writting they can conflict.
|
Will spin up the web app before opening up the tauri dev desktop app. Note that it's probably a good idea to close the browser tab that gets opened since at the time of writing they can conflict.
|
||||||
|
|
||||||
The dev instance automatically opens up the browser devtools which can be disabled by [commenting it out](https://github.com/KittyCAD/modeling-app/blob/main/src-tauri/src/main.rs#L92.)
|
The dev instance automatically opens up the browser devtools which can be disabled by [commenting it out](https://github.com/KittyCAD/modeling-app/blob/main/src-tauri/src/main.rs#L92.)
|
||||||
|
|
||||||
|
@ -3812,7 +3812,7 @@
|
|||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "data",
|
"name": "data",
|
||||||
"type": "AngeledLineThatIntersectsData",
|
"type": "AngledLineThatIntersectsData",
|
||||||
"schema": {
|
"schema": {
|
||||||
"description": "Data for drawing an angled line that intersects with a given line.",
|
"description": "Data for drawing an angled line that intersects with a given line.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -763,12 +763,12 @@ Draw an angled line that intersects with a given line.
|
|||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
angledLineThatIntersects(data: AngeledLineThatIntersectsData, sketch_group: SketchGroup) -> SketchGroup
|
angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch_group: SketchGroup) -> SketchGroup
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Arguments
|
#### Arguments
|
||||||
|
|
||||||
* `data`: `AngeledLineThatIntersectsData` - Data for drawing an angled line that intersects with a given line.
|
* `data`: `AngledLineThatIntersectsData` - Data for drawing an angled line that intersects with a given line.
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
// The angle of the line.
|
// The angle of the line.
|
||||||
|
11
e2e/tauri/specs/signin.e2e.js
Normal file
11
e2e/tauri/specs/signin.e2e.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
describe('Modeling App', () => {
|
||||||
|
it('open the sign in page', async () => {
|
||||||
|
const button = await $('#signin')
|
||||||
|
expect(button).toHaveText('Sign in')
|
||||||
|
|
||||||
|
// Workaround for .click(), see https://github.com/tauri-apps/tauri/issues/6541
|
||||||
|
await button.waitForClickable()
|
||||||
|
await browser.execute('arguments[0].click();', button)
|
||||||
|
// TODO: handle auth
|
||||||
|
})
|
||||||
|
})
|
49
package.json
49
package.json
@ -1,33 +1,33 @@
|
|||||||
{
|
{
|
||||||
"name": "untitled-app",
|
"name": "untitled-app",
|
||||||
"version": "0.11.0",
|
"version": "0.11.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.9.0",
|
"@codemirror/autocomplete": "^6.10.2",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.4.2",
|
"@fortawesome/free-brands-svg-icons": "^6.4.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@headlessui/react": "^1.7.13",
|
"@headlessui/react": "^1.7.13",
|
||||||
"@headlessui/tailwindcss": "^0.2.0",
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
"@kittycad/lib": "^0.0.43",
|
"@kittycad/lib": "^0.0.45",
|
||||||
"@lezer/javascript": "^1.4.7",
|
"@lezer/javascript": "^1.4.7",
|
||||||
"@open-rpc/client-js": "^1.8.1",
|
"@open-rpc/client-js": "^1.8.1",
|
||||||
"@react-hook/resize-observer": "^1.2.6",
|
"@react-hook/resize-observer": "^1.2.6",
|
||||||
"@replit/codemirror-interact": "^6.3.0",
|
"@replit/codemirror-interact": "^6.3.0",
|
||||||
"@sentry/react": "^7.65.0",
|
"@sentry/react": "^7.77.0",
|
||||||
"@tauri-apps/api": "^1.5.0",
|
"@tauri-apps/api": "^1.5.1",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^13.0.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@testing-library/user-event": "^13.2.1",
|
"@testing-library/user-event": "^14.5.1",
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
"@ts-stack/markdown": "^1.5.0",
|
||||||
"@types/node": "^16.7.13",
|
"@types/node": "^16.7.13",
|
||||||
"@types/react": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react-dom": "^18.0.0",
|
||||||
"@uiw/react-codemirror": "^4.21.13",
|
"@uiw/react-codemirror": "^4.21.20",
|
||||||
"@xstate/inspect": "^0.8.0",
|
"@xstate/inspect": "^0.8.0",
|
||||||
"@xstate/react": "^3.2.2",
|
"@xstate/react": "^3.2.2",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.2.0",
|
||||||
"debounce-promise": "^3.1.2",
|
"debounce-promise": "^3.1.2",
|
||||||
"formik": "^2.4.3",
|
"formik": "^2.4.3",
|
||||||
"fuse.js": "^6.6.2",
|
"fuse.js": "^6.6.2",
|
||||||
@ -43,20 +43,20 @@
|
|||||||
"react-modal-promise": "^1.0.2",
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-router-dom": "^6.14.2",
|
"react-router-dom": "^6.14.2",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"swr": "^2.0.4",
|
"swr": "^2.2.2",
|
||||||
"tauri-plugin-fs-extra-api": "https://github.com/tauri-apps/tauri-plugin-fs-extra#v1",
|
"tauri-plugin-fs-extra-api": "https://github.com/tauri-apps/tauri-plugin-fs-extra#v1",
|
||||||
"toml": "^3.0.0",
|
"toml": "^3.0.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^4.4.2",
|
"typescript": "^5.2.2",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.1",
|
||||||
"vitest": "^0.34.6",
|
"vitest": "^0.34.6",
|
||||||
"vscode-jsonrpc": "^8.1.0",
|
"vscode-jsonrpc": "^8.1.0",
|
||||||
"vscode-languageserver-protocol": "^3.17.3",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"wasm-pack": "^0.12.1",
|
"wasm-pack": "^0.12.1",
|
||||||
"web-vitals": "^2.1.0",
|
"web-vitals": "^3.5.0",
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
"xstate": "^4.38.2",
|
"xstate": "^4.38.2",
|
||||||
"zustand": "^4.1.4"
|
"zustand": "^4.4.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
@ -69,6 +69,7 @@
|
|||||||
"test:nowatch": "vitest run --mode development",
|
"test:nowatch": "vitest run --mode development",
|
||||||
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
|
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
|
||||||
"test:cov": "vitest run --coverage --mode development",
|
"test:cov": "vitest run --coverage --mode development",
|
||||||
|
"test:e2e": "wdio run wdio.conf.js",
|
||||||
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
|
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
|
||||||
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
|
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
|
||||||
"fmt": "prettier --write ./src",
|
"fmt": "prettier --write ./src",
|
||||||
@ -102,18 +103,18 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.22.9",
|
"@babel/preset-env": "^7.22.9",
|
||||||
"@tauri-apps/cli": "^1.5.0",
|
"@tauri-apps/cli": "^1.5.6",
|
||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/debounce-promise": "^3.1.6",
|
"@types/debounce-promise": "^3.1.8",
|
||||||
"@types/isomorphic-fetch": "^0.0.36",
|
"@types/isomorphic-fetch": "^0.0.36",
|
||||||
"@types/react-modal": "^3.16.0",
|
"@types/react-modal": "^3.16.0",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.4",
|
||||||
"@types/wicg-file-system-access": "^2020.9.6",
|
"@types/wicg-file-system-access": "^2020.9.6",
|
||||||
"@types/ws": "^8.5.5",
|
"@types/ws": "^8.5.5",
|
||||||
"@vitejs/plugin-react": "^4.0.3",
|
"@vitejs/plugin-react": "^4.0.3",
|
||||||
"@vitest/coverage-istanbul": "^0.34.1",
|
"@vitest/coverage-istanbul": "^0.34.1",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"eslint": "^8.44.0",
|
"eslint": "^8.53.0",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"eslint-plugin-css-modules": "^2.11.0",
|
"eslint-plugin-css-modules": "^2.11.0",
|
||||||
"happy-dom": "^10.8.0",
|
"happy-dom": "^10.8.0",
|
||||||
@ -122,9 +123,13 @@
|
|||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
"vite": "^4.4.3",
|
"vite": "^4.5.0",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vite-tsconfig-paths": "^4.2.0",
|
"vite-tsconfig-paths": "^4.2.1",
|
||||||
"yarn": "^1.22.19"
|
"yarn": "^1.22.19",
|
||||||
|
"@wdio/cli": "^7.7.3",
|
||||||
|
"@wdio/local-runner": "^7.7.3",
|
||||||
|
"@wdio/mocha-framework": "^7.7.3",
|
||||||
|
"@wdio/spec-reporter": "^7.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
69
src-tauri/Cargo.lock
generated
69
src-tauri/Cargo.lock
generated
@ -122,6 +122,12 @@ dependencies = [
|
|||||||
"system-deps 6.1.0",
|
"system-deps 6.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -1567,7 +1573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.3.1",
|
"hermit-abi 0.3.1",
|
||||||
"rustix 0.38.13",
|
"rustix 0.38.21",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1658,9 +1664,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad"
|
name = "kittycad"
|
||||||
version = "0.2.33"
|
version = "0.2.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d341a81a4dfef43460d395c87d86c17e24affb96db0e7f4a35e8688f0e092344"
|
checksum = "874914cd40bfd43674406683bb3f0924d41780698a4ade96f2e180a73678bdd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -1759,9 +1765,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.7"
|
version = "0.4.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
|
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@ -2833,9 +2839,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.20"
|
version = "0.11.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
|
checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.2",
|
"base64 0.21.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -2862,6 +2868,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
@ -3011,9 +3018,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.37.19"
|
version = "0.37.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
|
checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"errno",
|
"errno",
|
||||||
@ -3025,14 +3032,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.13"
|
version = "0.38.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662"
|
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.0",
|
"bitflags 2.4.0",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.4.7",
|
"linux-raw-sys 0.4.10",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3208,9 +3215,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.189"
|
version = "1.0.192"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
|
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
@ -3226,9 +3233,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.189"
|
version = "1.0.192"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
|
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3248,9 +3255,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.107"
|
version = "1.0.108"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 1.0.6",
|
"itoa 1.0.6",
|
||||||
"ryu",
|
"ryu",
|
||||||
@ -3600,6 +3607,27 @@ dependencies = [
|
|||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation",
|
||||||
|
"system-configuration-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-deps"
|
name = "system-deps"
|
||||||
version = "5.0.0"
|
version = "5.0.0"
|
||||||
@ -3828,7 +3856,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-fs-extra"
|
name = "tauri-plugin-fs-extra"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#9b20f28d747f6ec3ba5a80bfcd5edc1d573b4c90"
|
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#6865299149ffd183365e3ff291acf3edac78ca61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
@ -3927,7 +3955,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"redox_syscall 0.3.5",
|
"redox_syscall 0.3.5",
|
||||||
"rustix 0.37.19",
|
"rustix 0.37.27",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4292,6 +4320,7 @@ version = "1.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
|
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic",
|
||||||
"getrandom 0.2.9",
|
"getrandom 0.2.9",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
license = ""
|
license = ""
|
||||||
repository = ""
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
default-run = "app"
|
default-run = "app"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.60"
|
rust-version = "1.60"
|
||||||
@ -16,7 +16,7 @@ tauri-build = { version = "1.5.0", features = [] }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
kittycad = "0.2.33"
|
kittycad = "0.2.41"
|
||||||
oauth2 = "4.4.2"
|
oauth2 = "4.4.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -68,7 +68,7 @@ async fn login(app: tauri::AppHandle, host: &str) -> Result<String, InvokeError>
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Open the system browser with the auth_uri.
|
// Open the system browser with the auth_uri.
|
||||||
// We do this in the browser and not a seperate window because we want 1password and
|
// We do this in the browser and not a separate window because we want 1password and
|
||||||
// other crap to work well.
|
// other crap to work well.
|
||||||
tauri::api::shell::open(&app.shell_scope(), auth_uri.secret(), None)
|
tauri::api::shell::open(&app.shell_scope(), auth_uri.secret(), None)
|
||||||
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
||||||
@ -129,10 +129,10 @@ async fn get_user(
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|app| {
|
.setup(|_app| {
|
||||||
#[cfg(debug_assertions)] // only include this code on debug builds
|
#[cfg(debug_assertions)] // only include this code on debug builds
|
||||||
{
|
{
|
||||||
let window = app.get_window("main").unwrap();
|
let window = _app.get_window("main").unwrap();
|
||||||
// comment out the below if you don't devtools to open everytime.
|
// comment out the below if you don't devtools to open everytime.
|
||||||
// it's useful because otherwise devtools shuts everytime rust code changes.
|
// it's useful because otherwise devtools shuts everytime rust code changes.
|
||||||
window.open_devtools();
|
window.open_devtools();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "kittycad-modeling",
|
"productName": "kittycad-modeling",
|
||||||
"version": "0.11.0"
|
"version": "0.11.3"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
@ -72,23 +72,13 @@
|
|||||||
},
|
},
|
||||||
"resources": [],
|
"resources": [],
|
||||||
"shortDescription": "",
|
"shortDescription": "",
|
||||||
"targets": "all",
|
"targets": "all"
|
||||||
"windows": {
|
|
||||||
"certificateThumbprint": "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D",
|
|
||||||
"digestAlgorithm": "sha256",
|
|
||||||
"timestampUrl": "http://timestamp.digicert.com"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"security": {
|
"security": {
|
||||||
"csp": null
|
"csp": null
|
||||||
},
|
},
|
||||||
"updater": {
|
"updater": {
|
||||||
"active": true,
|
"active": false
|
||||||
"endpoints": [
|
|
||||||
"https://dl.kittycad.io/releases/modeling-app/last_update.json"
|
|
||||||
],
|
|
||||||
"dialog": true,
|
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
|
|
||||||
},
|
},
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
"package": {
|
"package": {
|
||||||
|
21
src-tauri/tauri.release.conf.json
Normal file
21
src-tauri/tauri.release.conf.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
|
"tauri": {
|
||||||
|
"updater": {
|
||||||
|
"active": true,
|
||||||
|
"endpoints": [
|
||||||
|
"https://dl.kittycad.io/releases/modeling-app/last_update.json"
|
||||||
|
],
|
||||||
|
"dialog": true,
|
||||||
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"identifier": "io.kittycad.modeling-app",
|
||||||
|
"windows": {
|
||||||
|
"certificateThumbprint": "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D",
|
||||||
|
"digestAlgorithm": "sha256",
|
||||||
|
"timestampUrl": "http://timestamp.digicert.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
"package": {
|
"package": {
|
||||||
|
28
src/App.tsx
28
src/App.tsx
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useCallback, MouseEventHandler } from 'react'
|
import { useCallback, MouseEventHandler } from 'react'
|
||||||
import { DebugPanel } from './components/DebugPanel'
|
import { DebugPanel } from './components/DebugPanel'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { PaneType, useStore } from './useStore'
|
import { PaneType, useStore } from './useStore'
|
||||||
@ -19,7 +19,6 @@ import {
|
|||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { getNormalisedCoordinates } from './lib/utils'
|
import { getNormalisedCoordinates } from './lib/utils'
|
||||||
import { isTauri } from './lib/isTauri'
|
|
||||||
import { useLoaderData } from 'react-router-dom'
|
import { useLoaderData } from 'react-router-dom'
|
||||||
import { IndexLoaderData } from './Router'
|
import { IndexLoaderData } from './Router'
|
||||||
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
||||||
@ -31,11 +30,10 @@ import { TextEditor } from 'components/TextEditor'
|
|||||||
import { Themes, getSystemTheme } from 'lib/theme'
|
import { Themes, getSystemTheme } from 'lib/theme'
|
||||||
import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions'
|
import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions'
|
||||||
import { engineCommandManager } from './lang/std/engineConnection'
|
import { engineCommandManager } from './lang/std/engineConnection'
|
||||||
import { kclManager } from 'lang/KclSinglton'
|
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const { code: loadedCode, project, file } = useLoaderData() as IndexLoaderData
|
const { project, file } = useLoaderData() as IndexLoaderData
|
||||||
|
|
||||||
useHotKeyListener()
|
useHotKeyListener()
|
||||||
const {
|
const {
|
||||||
@ -82,26 +80,6 @@ export function App() {
|
|||||||
? 'opacity-40'
|
? 'opacity-40'
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
// Use file code loaded from disk
|
|
||||||
// on mount, and overwrite any locally-stored code
|
|
||||||
useEffect(() => {
|
|
||||||
if (isTauri() && loadedCode !== null) {
|
|
||||||
if (kclManager.engineCommandManager.engineConnection?.isReady()) {
|
|
||||||
// If the engine is ready, promptly execute the loaded code
|
|
||||||
kclManager.setCodeAndExecute(loadedCode)
|
|
||||||
} else {
|
|
||||||
// Otherwise, just set the code and wait for the connection to complete
|
|
||||||
kclManager.setCode(loadedCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
// Clear code on unmount if in desktop app
|
|
||||||
if (isTauri()) {
|
|
||||||
kclManager.setCode('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [loadedCode])
|
|
||||||
|
|
||||||
useEngineConnectionSubscriptions()
|
useEngineConnectionSubscriptions()
|
||||||
|
|
||||||
const debounceSocketSend = throttle<EngineCommand>((message) => {
|
const debounceSocketSend = throttle<EngineCommand>((message) => {
|
||||||
@ -248,7 +226,7 @@ export function App() {
|
|||||||
<Stream className="absolute inset-0 z-0" />
|
<Stream className="absolute inset-0 z-0" />
|
||||||
{showDebugPanel && (
|
{showDebugPanel && (
|
||||||
<DebugPanel
|
<DebugPanel
|
||||||
title="Debug"
|
title="Debug (AST Explorer)"
|
||||||
className={
|
className={
|
||||||
'transition-opacity transition-duration-75 ' +
|
'transition-opacity transition-duration-75 ' +
|
||||||
paneOpacity +
|
paneOpacity +
|
||||||
|
@ -42,7 +42,7 @@ import CommandBarProvider from 'components/CommandBar'
|
|||||||
import { TEST, VITE_KC_SENTRY_DSN } from './env'
|
import { TEST, VITE_KC_SENTRY_DSN } from './env'
|
||||||
import * as Sentry from '@sentry/react'
|
import * as Sentry from '@sentry/react'
|
||||||
import ModelingMachineProvider from 'components/ModelingMachineProvider'
|
import ModelingMachineProvider from 'components/ModelingMachineProvider'
|
||||||
import { KclContextProvider } from 'lang/KclSinglton'
|
import { KclContextProvider, kclManager } from 'lang/KclSinglton'
|
||||||
import FileMachineProvider from 'components/FileMachineProvider'
|
import FileMachineProvider from 'components/FileMachineProvider'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { sep } from '@tauri-apps/api/path'
|
||||||
|
|
||||||
@ -207,6 +207,7 @@ const router = createBrowserRouter(
|
|||||||
projectPath + sep + PROJECT_ENTRYPOINT
|
projectPath + sep + PROJECT_ENTRYPOINT
|
||||||
)
|
)
|
||||||
const children = await readDir(projectPath, { recursive: true })
|
const children = await readDir(projectPath, { recursive: true })
|
||||||
|
kclManager.setCodeAndExecute(code, false)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code,
|
code,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { ToolTip } from './useStore'
|
|
||||||
import { Fragment, WheelEvent, useRef, useMemo } from 'react'
|
import { Fragment, WheelEvent, useRef, useMemo } from 'react'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
||||||
@ -15,23 +14,6 @@ export const sketchButtonClassnames = {
|
|||||||
icon: 'text-fern-20 h-auto group-hover:text-fern-10 hover:text-fern-10 dark:text-chalkboard-100 dark:group-hover:text-chalkboard-100 dark:hover:text-chalkboard-100 group-disabled:bg-chalkboard-60 hover:group-disabled:text-inherit',
|
icon: 'text-fern-20 h-auto group-hover:text-fern-10 hover:text-fern-10 dark:text-chalkboard-100 dark:group-hover:text-chalkboard-100 dark:hover:text-chalkboard-100 group-disabled:bg-chalkboard-60 hover:group-disabled:text-inherit',
|
||||||
}
|
}
|
||||||
|
|
||||||
const sketchFnLabels: Record<ToolTip | 'sketch_line' | 'move', string> = {
|
|
||||||
sketch_line: 'Line',
|
|
||||||
line: 'Line',
|
|
||||||
move: 'Move',
|
|
||||||
angledLine: 'Angled Line',
|
|
||||||
angledLineThatIntersects: 'Angled Line That Intersects',
|
|
||||||
angledLineOfXLength: 'Angled Line Of X Length',
|
|
||||||
angledLineOfYLength: 'Angled Line Of Y Length',
|
|
||||||
angledLineToX: 'Angled Line To X',
|
|
||||||
angledLineToY: 'Angled Line To Y',
|
|
||||||
lineTo: 'Line to Point',
|
|
||||||
xLine: 'Horizontal Line',
|
|
||||||
yLine: 'Vertical Line',
|
|
||||||
xLineTo: 'Horizontal Line to Point',
|
|
||||||
yLineTo: 'Vertical Line to Point',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Toolbar = () => {
|
export const Toolbar = () => {
|
||||||
const { state, send, context } = useModelingContext()
|
const { state, send, context } = useModelingContext()
|
||||||
const toolbarButtonsRef = useRef<HTMLSpanElement>(null)
|
const toolbarButtonsRef = useRef<HTMLSpanElement>(null)
|
||||||
|
@ -184,6 +184,7 @@ function DisplayObj({
|
|||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState, useRef } from 'react'
|
import { useEffect, useState, useRef } from 'react'
|
||||||
import { parse, BinaryPart, Value, executor } from '../lang/wasm'
|
import { parse, BinaryPart, Value } from '../lang/wasm'
|
||||||
import {
|
import {
|
||||||
createIdentifier,
|
createIdentifier,
|
||||||
createLiteral,
|
createLiteral,
|
||||||
@ -10,6 +10,7 @@ import { findAllPreviousVariables, PrevVariable } from '../lang/queryAst'
|
|||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
import { engineCommandManager } from '../lang/std/engineConnection'
|
||||||
import { kclManager, useKclContext } from 'lang/KclSinglton'
|
import { kclManager, useKclContext } from 'lang/KclSinglton'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
|
import { executeAst } from 'useStore'
|
||||||
|
|
||||||
export const AvailableVars = ({
|
export const AvailableVars = ({
|
||||||
onVarClick,
|
onVarClick,
|
||||||
@ -130,27 +131,29 @@ export function useCalc({
|
|||||||
if (!programMemory || !selectionRange) return
|
if (!programMemory || !selectionRange) return
|
||||||
const varInfo = findAllPreviousVariables(
|
const varInfo = findAllPreviousVariables(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
programMemory,
|
kclManager.programMemory,
|
||||||
selectionRange
|
selectionRange
|
||||||
)
|
)
|
||||||
setAvailableVarInfo(varInfo)
|
setAvailableVarInfo(varInfo)
|
||||||
}, [kclManager.ast, programMemory, selectionRange])
|
}, [kclManager.ast, kclManager.programMemory, selectionRange])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const code = `const __result__ = ${value}\nshow(__result__)`
|
const code = `const __result__ = ${value}`
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
const _programMem: any = { root: {}, return: null }
|
const _programMem: any = { root: {}, return: null }
|
||||||
availableVarInfo.variables.forEach(({ key, value }) => {
|
availableVarInfo.variables.forEach(({ key, value }) => {
|
||||||
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
|
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
|
||||||
})
|
})
|
||||||
|
executeAst({
|
||||||
executor(
|
|
||||||
ast,
|
ast,
|
||||||
_programMem,
|
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
kclManager.defaultPlanes
|
defaultPlanes: kclManager.defaultPlanes,
|
||||||
).then((programMemory) => {
|
useFakeExecutor: true,
|
||||||
|
programMemoryOverride: JSON.parse(
|
||||||
|
JSON.stringify(kclManager.programMemory)
|
||||||
|
),
|
||||||
|
}).then(({ programMemory }) => {
|
||||||
const resultDeclaration = ast.body.find(
|
const resultDeclaration = ast.body.find(
|
||||||
(a) =>
|
(a) =>
|
||||||
a.type === 'VariableDeclaration' &&
|
a.type === 'VariableDeclaration' &&
|
||||||
@ -167,7 +170,7 @@ export function useCalc({
|
|||||||
setCalcResult('NAN')
|
setCalcResult('NAN')
|
||||||
setValueNode(null)
|
setValueNode(null)
|
||||||
}
|
}
|
||||||
}, [value])
|
}, [value, availableVarInfo])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valueNode,
|
valueNode,
|
||||||
@ -212,7 +215,10 @@ export const CreateNewVariable = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<label htmlFor="create-new-variable" className="block mt-3 font-mono">
|
<label
|
||||||
|
htmlFor="create-new-variable"
|
||||||
|
className="block mt-3 font-mono text-gray-900"
|
||||||
|
>
|
||||||
Create new variable
|
Create new variable
|
||||||
</label>
|
</label>
|
||||||
<div className="mt-1 flex gap-2 items-center">
|
<div className="mt-1 flex gap-2 items-center">
|
||||||
@ -223,6 +229,7 @@ export const CreateNewVariable = ({
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setShouldCreateVariable(e.target.checked)
|
setShouldCreateVariable(e.target.checked)
|
||||||
}}
|
}}
|
||||||
|
className="bg-white text-gray-900"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
|
@ -1,29 +1,7 @@
|
|||||||
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
|
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import { EngineCommand } from '../lang/std/engineConnection'
|
|
||||||
import { useState } from 'react'
|
|
||||||
import { ActionButton } from '../components/ActionButton'
|
|
||||||
import { faCheck } from '@fortawesome/free-solid-svg-icons'
|
|
||||||
import { isReducedMotion } from 'lang/util'
|
|
||||||
import { AstExplorer } from './AstExplorer'
|
import { AstExplorer } from './AstExplorer'
|
||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
|
||||||
|
|
||||||
type SketchModeCmd = Extract<
|
|
||||||
Extract<EngineCommand, { type: 'modeling_cmd_req' }>['cmd'],
|
|
||||||
{ type: 'default_camera_enable_sketch_mode' }
|
|
||||||
>
|
|
||||||
|
|
||||||
export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
|
export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
|
||||||
const [sketchModeCmd, setSketchModeCmd] = useState<SketchModeCmd>({
|
|
||||||
type: 'default_camera_enable_sketch_mode',
|
|
||||||
origin: { x: 0, y: 0, z: 0 },
|
|
||||||
x_axis: { x: 1, y: 0, z: 0 },
|
|
||||||
y_axis: { x: 0, y: 1, z: 0 },
|
|
||||||
distance_to_plane: 100,
|
|
||||||
ortho: true,
|
|
||||||
animated: !isReducedMotion(),
|
|
||||||
})
|
|
||||||
if (!sketchModeCmd) return null
|
|
||||||
return (
|
return (
|
||||||
<CollapsiblePanel
|
<CollapsiblePanel
|
||||||
{...props}
|
{...props}
|
||||||
@ -34,67 +12,6 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
|
|||||||
style={{ maxHeight: 'calc(100% - 3rem - 1.25rem - 1.25rem)' }}
|
style={{ maxHeight: 'calc(100% - 3rem - 1.25rem - 1.25rem)' }}
|
||||||
>
|
>
|
||||||
<section className="p-4 flex flex-col gap-4">
|
<section className="p-4 flex flex-col gap-4">
|
||||||
<Xyz
|
|
||||||
onChange={setSketchModeCmd}
|
|
||||||
pointKey="origin"
|
|
||||||
data={sketchModeCmd}
|
|
||||||
/>
|
|
||||||
<Xyz
|
|
||||||
onChange={setSketchModeCmd}
|
|
||||||
pointKey="x_axis"
|
|
||||||
data={sketchModeCmd}
|
|
||||||
/>
|
|
||||||
<Xyz
|
|
||||||
onChange={setSketchModeCmd}
|
|
||||||
pointKey="y_axis"
|
|
||||||
data={sketchModeCmd}
|
|
||||||
/>
|
|
||||||
<div className="flex">
|
|
||||||
<div className="pr-4">distance_to_plane</div>
|
|
||||||
<input
|
|
||||||
className="w-16 dark:bg-chalkboard-90"
|
|
||||||
type="number"
|
|
||||||
value={sketchModeCmd.distance_to_plane}
|
|
||||||
onChange={({ target }) => {
|
|
||||||
setSketchModeCmd({
|
|
||||||
...sketchModeCmd,
|
|
||||||
distance_to_plane: Number(target.value),
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="pr-4">ortho</div>
|
|
||||||
<input
|
|
||||||
className="w-16"
|
|
||||||
type="checkbox"
|
|
||||||
checked={sketchModeCmd.ortho}
|
|
||||||
onChange={(a) =>
|
|
||||||
setSketchModeCmd({
|
|
||||||
...sketchModeCmd,
|
|
||||||
ortho: a.target.checked,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ActionButton
|
|
||||||
Element="button"
|
|
||||||
onClick={() => {
|
|
||||||
engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd: sketchModeCmd,
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
className="hover:border-succeed-50"
|
|
||||||
icon={{
|
|
||||||
icon: faCheck,
|
|
||||||
bgClassName:
|
|
||||||
'bg-succeed-80 group-hover:bg-succeed-70 hover:bg-succeed-70',
|
|
||||||
iconClassName:
|
|
||||||
'text-succeed-20 group-hover:text-succeed-10 hover:text-succeed-10',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Send sketch mode command
|
|
||||||
</ActionButton>
|
|
||||||
<div style={{ height: '400px' }} className="overflow-y-auto">
|
<div style={{ height: '400px' }} className="overflow-y-auto">
|
||||||
<AstExplorer />
|
<AstExplorer />
|
||||||
</div>
|
</div>
|
||||||
@ -102,41 +19,3 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
|
|||||||
</CollapsiblePanel>
|
</CollapsiblePanel>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Xyz = ({
|
|
||||||
pointKey,
|
|
||||||
data,
|
|
||||||
onChange,
|
|
||||||
}: {
|
|
||||||
pointKey: 'origin' | 'y_axis' | 'x_axis'
|
|
||||||
data: SketchModeCmd
|
|
||||||
onChange: (a: SketchModeCmd) => void
|
|
||||||
}) => {
|
|
||||||
if (!data) return null
|
|
||||||
return (
|
|
||||||
<div className="flex">
|
|
||||||
<div className="pr-4">{pointKey}</div>
|
|
||||||
{Object.entries(data[pointKey]).map(([axis, val]) => {
|
|
||||||
return (
|
|
||||||
<div key={axis} className="flex">
|
|
||||||
<div className="w-4">{axis}</div>
|
|
||||||
<input
|
|
||||||
className="w-16 dark:bg-chalkboard-90"
|
|
||||||
type="number"
|
|
||||||
value={val}
|
|
||||||
onChange={({ target }) => {
|
|
||||||
onChange({
|
|
||||||
...data,
|
|
||||||
[pointKey]: {
|
|
||||||
...data[pointKey],
|
|
||||||
[axis]: Number(target.value),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,7 @@ import { IndexLoaderData, paths } from 'Router'
|
|||||||
import { ActionButton } from './ActionButton'
|
import { ActionButton } from './ActionButton'
|
||||||
import Tooltip from './Tooltip'
|
import Tooltip from './Tooltip'
|
||||||
import { FileEntry } from '@tauri-apps/api/fs'
|
import { FileEntry } from '@tauri-apps/api/fs'
|
||||||
import { Dispatch, useEffect, useRef, useState } from 'react'
|
import { Dispatch, useRef, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { Dialog, Disclosure } from '@headlessui/react'
|
import { Dialog, Disclosure } from '@headlessui/react'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
@ -163,7 +163,6 @@ const FileTreeItem = ({
|
|||||||
|
|
||||||
function openFile() {
|
function openFile() {
|
||||||
if (fileOrDir.children !== undefined) return // Don't open directories
|
if (fileOrDir.children !== undefined) return // Don't open directories
|
||||||
kclManager.setCode('')
|
|
||||||
navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`)
|
navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`)
|
||||||
closePanel()
|
closePanel()
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import {
|
|||||||
recast,
|
recast,
|
||||||
parse,
|
parse,
|
||||||
Program,
|
Program,
|
||||||
VariableDeclarator,
|
|
||||||
PipeExpression,
|
PipeExpression,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
} from 'lang/wasm'
|
} from 'lang/wasm'
|
||||||
@ -148,7 +147,7 @@ export const ModelingMachineProvider = ({
|
|||||||
engineCommandManager.artifactMap[sketchEnginePathId] = {
|
engineCommandManager.artifactMap[sketchEnginePathId] = {
|
||||||
type: 'result',
|
type: 'result',
|
||||||
range: [startProfileAtCallExp.start, startProfileAtCallExp.end],
|
range: [startProfileAtCallExp.start, startProfileAtCallExp.end],
|
||||||
commandType: 'extend_path',
|
commandType: 'start_path',
|
||||||
data: null,
|
data: null,
|
||||||
raw: {} as any,
|
raw: {} as any,
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ export const SetAngleLengthModal = ({
|
|||||||
</label>
|
</label>
|
||||||
<div className="mt-1 flex">
|
<div className="mt-1 flex">
|
||||||
<button
|
<button
|
||||||
className="border border-gray-300 px-2"
|
className="border border-gray-300 px-2 text-gray-900"
|
||||||
onClick={() => setSign(-sign)}
|
onClick={() => setSign(-sign)}
|
||||||
>
|
>
|
||||||
{sign > 0 ? '+' : '-'}
|
{sign > 0 ? '+' : '-'}
|
||||||
@ -118,7 +118,7 @@ export const SetAngleLengthModal = ({
|
|||||||
type="text"
|
type="text"
|
||||||
name="val"
|
name="val"
|
||||||
id="val"
|
id="val"
|
||||||
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1"
|
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1 text-gray-900"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setValue(e.target.value)
|
setValue(e.target.value)
|
||||||
|
@ -87,7 +87,7 @@ export const GetInfoModal = ({
|
|||||||
leaveFrom="opacity-100 scale-100"
|
leaveFrom="opacity-100 scale-100"
|
||||||
leaveTo="opacity-0 scale-95"
|
leaveTo="opacity-0 scale-95"
|
||||||
>
|
>
|
||||||
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
|
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white/90 p-6 text-left align-middle shadow-xl transition-all">
|
||||||
<Dialog.Title
|
<Dialog.Title
|
||||||
as="h3"
|
as="h3"
|
||||||
className="text-lg font-medium leading-6 text-gray-900"
|
className="text-lg font-medium leading-6 text-gray-900"
|
||||||
@ -109,7 +109,7 @@ export const GetInfoModal = ({
|
|||||||
</label>
|
</label>
|
||||||
<div className="mt-1 flex">
|
<div className="mt-1 flex">
|
||||||
<button
|
<button
|
||||||
className="border border-gray-300 px-2 mr-1"
|
className="border border-gray-400 px-2 mr-1 text-gray-900"
|
||||||
onClick={() => setSign(-sign)}
|
onClick={() => setSign(-sign)}
|
||||||
>
|
>
|
||||||
{sign > 0 ? '+' : '-'}
|
{sign > 0 ? '+' : '-'}
|
||||||
@ -119,7 +119,7 @@ export const GetInfoModal = ({
|
|||||||
name="val"
|
name="val"
|
||||||
id="val"
|
id="val"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono"
|
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm text-gray-900 border-gray-300 rounded-md font-mono"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setValue(e.target.value)
|
setValue(e.target.value)
|
||||||
@ -139,7 +139,7 @@ export const GetInfoModal = ({
|
|||||||
name="segName"
|
name="segName"
|
||||||
id="segName"
|
id="segName"
|
||||||
disabled={!isSegNameEditable}
|
disabled={!isSegNameEditable}
|
||||||
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono"
|
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm text-gray-900 border-gray-300 rounded-md font-mono"
|
||||||
value={segName}
|
value={segName}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSegName(e.target.value)
|
setSegName(e.target.value)
|
||||||
|
@ -14,7 +14,7 @@ import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
|||||||
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
|
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import { getNodeFromPath } from 'lang/queryAst'
|
import { getNodeFromPath } from 'lang/queryAst'
|
||||||
import { VariableDeclarator, recast, parse, CallExpression } from 'lang/wasm'
|
import { VariableDeclarator, recast, CallExpression } from 'lang/wasm'
|
||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
import { engineCommandManager } from '../lang/std/engineConnection'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
import { kclManager, useKclContext } from 'lang/KclSinglton'
|
import { kclManager, useKclContext } from 'lang/KclSinglton'
|
||||||
@ -267,11 +267,11 @@ export const Stream = ({ className = '' }) => {
|
|||||||
}
|
}
|
||||||
engineCommandManager.sendSceneCommand(command).then(async () => {
|
engineCommandManager.sendSceneCommand(command).then(async () => {
|
||||||
if (!context.sketchPathToNode) return
|
if (!context.sketchPathToNode) return
|
||||||
const varDec = getNodeFromPath<VariableDeclarator>(
|
getNodeFromPath<VariableDeclarator>(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
context.sketchPathToNode,
|
context.sketchPathToNode,
|
||||||
'VariableDeclarator'
|
'VariableDeclarator'
|
||||||
).node
|
)
|
||||||
// Get the current plane string for plane we are on.
|
// Get the current plane string for plane we are on.
|
||||||
let currentPlaneString = ''
|
let currentPlaneString = ''
|
||||||
if (context.sketchPlaneId === kclManager.getPlaneId('xy')) {
|
if (context.sketchPlaneId === kclManager.getPlaneId('xy')) {
|
||||||
@ -342,7 +342,8 @@ export const Stream = ({ className = '' }) => {
|
|||||||
|
|
||||||
// update artifact map ranges now that we have updated the ast.
|
// update artifact map ranges now that we have updated the ast.
|
||||||
code = recast(modded.modifiedAst)
|
code = recast(modded.modifiedAst)
|
||||||
const astWithCurrentRanges = parse(code)
|
const astWithCurrentRanges = kclManager.safeParse(code)
|
||||||
|
if (!astWithCurrentRanges) return
|
||||||
const updateNode = getNodeFromPath<CallExpression>(
|
const updateNode = getNodeFromPath<CallExpression>(
|
||||||
astWithCurrentRanges,
|
astWithCurrentRanges,
|
||||||
modded.pathToNode
|
modded.pathToNode
|
||||||
|
@ -17,15 +17,7 @@ import { useStore } from 'useStore'
|
|||||||
import { processCodeMirrorRanges } from 'lib/selections'
|
import { processCodeMirrorRanges } from 'lib/selections'
|
||||||
import { LanguageServerClient } from 'editor/lsp'
|
import { LanguageServerClient } from 'editor/lsp'
|
||||||
import kclLanguage from 'editor/lsp/language'
|
import kclLanguage from 'editor/lsp/language'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { EditorView, lineHighlightField } from 'editor/highlightextension'
|
||||||
import { useParams } from 'react-router-dom'
|
|
||||||
import { writeTextFile } from '@tauri-apps/api/fs'
|
|
||||||
import { toast } from 'react-hot-toast'
|
|
||||||
import {
|
|
||||||
EditorView,
|
|
||||||
addLineHighlight,
|
|
||||||
lineHighlightField,
|
|
||||||
} from 'editor/highlightextension'
|
|
||||||
import { roundOff } from 'lib/utils'
|
import { roundOff } from 'lib/utils'
|
||||||
import { kclErrToDiagnostic } from 'lang/errors'
|
import { kclErrToDiagnostic } from 'lang/errors'
|
||||||
import { CSSRuleObject } from 'tailwindcss/types/config'
|
import { CSSRuleObject } from 'tailwindcss/types/config'
|
||||||
@ -50,7 +42,6 @@ export const TextEditor = ({
|
|||||||
}: {
|
}: {
|
||||||
theme: Themes.Light | Themes.Dark
|
theme: Themes.Light | Themes.Dark
|
||||||
}) => {
|
}) => {
|
||||||
const pathParams = useParams()
|
|
||||||
const { editorView, isLSPServerReady, setEditorView, setIsLSPServerReady } =
|
const { editorView, isLSPServerReady, setEditorView, setIsLSPServerReady } =
|
||||||
useStore((s) => ({
|
useStore((s) => ({
|
||||||
editorView: s.editorView,
|
editorView: s.editorView,
|
||||||
@ -92,7 +83,7 @@ export const TextEditor = ({
|
|||||||
// Here we initialize the plugin which will start the client.
|
// Here we initialize the plugin which will start the client.
|
||||||
// When we have multi-file support the name of the file will be a dep of
|
// When we have multi-file support the name of the file will be a dep of
|
||||||
// this use memo, as well as the directory structure, which I think is
|
// this use memo, as well as the directory structure, which I think is
|
||||||
// a good setup becuase it will restart the client but not the server :)
|
// a good setup because it will restart the client but not the server :)
|
||||||
// We do not want to restart the server, its just wasteful.
|
// We do not want to restart the server, its just wasteful.
|
||||||
const kclLSP = useMemo(() => {
|
const kclLSP = useMemo(() => {
|
||||||
let plugin = null
|
let plugin = null
|
||||||
@ -113,18 +104,6 @@ export const TextEditor = ({
|
|||||||
// const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => {
|
// const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => {
|
||||||
const onChange = (newCode: string) => {
|
const onChange = (newCode: string) => {
|
||||||
kclManager.setCodeAndExecute(newCode)
|
kclManager.setCodeAndExecute(newCode)
|
||||||
if (isTauri() && pathParams.id) {
|
|
||||||
// Save the file to disk
|
|
||||||
// Note that PROJECT_ENTRYPOINT is hardcoded until we support multiple files
|
|
||||||
writeTextFile(pathParams.id, newCode).catch((err) => {
|
|
||||||
// TODO: add Sentry per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254)
|
|
||||||
console.error('error saving file', err)
|
|
||||||
toast.error('Error saving file, please check file permissions')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (editorView) {
|
|
||||||
editorView?.dispatch({ effects: addLineHighlight.of([0, 0]) })
|
|
||||||
}
|
|
||||||
} //, []);
|
} //, []);
|
||||||
const onUpdate = (viewUpdate: ViewUpdate) => {
|
const onUpdate = (viewUpdate: ViewUpdate) => {
|
||||||
if (!editorView) {
|
if (!editorView) {
|
||||||
|
@ -69,7 +69,7 @@ export function applyConstraintEqualLength({
|
|||||||
modifiedAst: Program
|
modifiedAst: Program
|
||||||
pathToNodeMap: PathToNodeMap
|
pathToNodeMap: PathToNodeMap
|
||||||
} {
|
} {
|
||||||
const { enabled, transforms } = setEqualLengthInfo({ selectionRanges })
|
const { transforms } = setEqualLengthInfo({ selectionRanges })
|
||||||
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
|
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
|
||||||
ast: kclManager.ast,
|
ast: kclManager.ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
|
@ -108,6 +108,7 @@ export default class Client extends jsrpc.JSONRPCServerAndClient {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
messageString += message
|
messageString += message
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
|
@ -26,7 +26,7 @@ export class Codec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: tracing effiency
|
// FIXME: tracing efficiency
|
||||||
export class IntoServer
|
export class IntoServer
|
||||||
extends Queue<Uint8Array>
|
extends Queue<Uint8Array>
|
||||||
implements AsyncGenerator<Uint8Array, never, void>
|
implements AsyncGenerator<Uint8Array, never, void>
|
||||||
|
@ -2,8 +2,6 @@ import { useEffect } from 'react'
|
|||||||
import { useStore } from 'useStore'
|
import { useStore } from 'useStore'
|
||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
import { engineCommandManager } from '../lang/std/engineConnection'
|
||||||
import { useModelingContext } from './useModelingContext'
|
import { useModelingContext } from './useModelingContext'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import { SourceRange } from 'lang/wasm'
|
|
||||||
import { getEventForSelectWithPoint } from 'lib/selections'
|
import { getEventForSelectWithPoint } from 'lib/selections'
|
||||||
|
|
||||||
export function useEngineConnectionSubscriptions() {
|
export function useEngineConnectionSubscriptions() {
|
||||||
@ -13,11 +11,6 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
}))
|
}))
|
||||||
const { send, context } = useModelingContext()
|
const { send, context } = useModelingContext()
|
||||||
|
|
||||||
interface RangeAndId {
|
|
||||||
id: string
|
|
||||||
range: SourceRange
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!engineCommandManager) return
|
if (!engineCommandManager) return
|
||||||
|
|
||||||
@ -42,7 +35,7 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
const event = await getEventForSelectWithPoint(engineEvent, {
|
const event = await getEventForSelectWithPoint(engineEvent, {
|
||||||
sketchEnginePathId: context.sketchEnginePathId,
|
sketchEnginePathId: context.sketchEnginePathId,
|
||||||
})
|
})
|
||||||
send(event)
|
event && send(event)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useLayoutEffect, useEffect, useRef } from 'react'
|
import { useLayoutEffect, useEffect, useRef } from 'react'
|
||||||
import { _executor, parse } from '../lang/wasm'
|
import { parse } from '../lang/wasm'
|
||||||
import { useStore } from '../useStore'
|
import { useStore } from '../useStore'
|
||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
import { engineCommandManager } from '../lang/std/engineConnection'
|
||||||
import { deferExecution } from 'lib/utils'
|
import { deferExecution } from 'lib/utils'
|
||||||
@ -26,10 +26,6 @@ export function useSetupEngineManager(
|
|||||||
|
|
||||||
const hasSetNonZeroDimensions = useRef<boolean>(false)
|
const hasSetNonZeroDimensions = useRef<boolean>(false)
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
kclManager.executeCode()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
// Load the engine command manager once with the initial width and height,
|
// Load the engine command manager once with the initial width and height,
|
||||||
// then we do not want to reload it.
|
// then we do not want to reload it.
|
||||||
|
@ -18,7 +18,11 @@ import { bracket } from 'lib/exampleKcl'
|
|||||||
import { createContext, useContext, useEffect, useState } from 'react'
|
import { createContext, useContext, useEffect, useState } from 'react'
|
||||||
import { getNodeFromPath } from './queryAst'
|
import { getNodeFromPath } from './queryAst'
|
||||||
import { IndexLoaderData } from 'Router'
|
import { IndexLoaderData } from 'Router'
|
||||||
import { useLoaderData } from 'react-router-dom'
|
import { Params, useLoaderData } from 'react-router-dom'
|
||||||
|
import { isTauri } from 'lib/isTauri'
|
||||||
|
import { writeTextFile } from '@tauri-apps/api/fs'
|
||||||
|
import { toast } from 'react-hot-toast'
|
||||||
|
import { useParams } from 'react-router-dom'
|
||||||
|
|
||||||
const PERSIST_CODE_TOKEN = 'persistCode'
|
const PERSIST_CODE_TOKEN = 'persistCode'
|
||||||
|
|
||||||
@ -41,10 +45,20 @@ class KclManager {
|
|||||||
private _kclErrors: KCLError[] = []
|
private _kclErrors: KCLError[] = []
|
||||||
private _isExecuting = false
|
private _isExecuting = false
|
||||||
private _wasmInitFailed = true
|
private _wasmInitFailed = true
|
||||||
|
private _params: Params<string> = {}
|
||||||
|
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
private _defferer = deferExecution((code: string) => {
|
private _defferer = deferExecution((code: string) => {
|
||||||
const ast = parse(code)
|
const ast = this.safeParse(code)
|
||||||
|
if (!ast) return
|
||||||
|
try {
|
||||||
|
const fmtAndStringify = (ast: Program) =>
|
||||||
|
JSON.stringify(parse(recast(ast)))
|
||||||
|
const isAstTheSame = fmtAndStringify(ast) === fmtAndStringify(this._ast)
|
||||||
|
if (isAstTheSame) return
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
this.executeAst(ast)
|
this.executeAst(ast)
|
||||||
}, 600)
|
}, 600)
|
||||||
|
|
||||||
@ -71,6 +85,21 @@ class KclManager {
|
|||||||
set code(code) {
|
set code(code) {
|
||||||
this._code = code
|
this._code = code
|
||||||
this._codeCallBack(code)
|
this._codeCallBack(code)
|
||||||
|
if (isTauri()) {
|
||||||
|
setTimeout(() => {
|
||||||
|
// Wait one event loop to give a chance for params to be set
|
||||||
|
// Save the file to disk
|
||||||
|
// Note that PROJECT_ENTRYPOINT is hardcoded until we support multiple files
|
||||||
|
this._params.id &&
|
||||||
|
writeTextFile(this._params.id, code).catch((err) => {
|
||||||
|
// TODO: add Sentry per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254)
|
||||||
|
console.error('error saving file', err)
|
||||||
|
toast.error('Error saving file, please check file permissions')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(PERSIST_CODE_TOKEN, code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get programMemory() {
|
get programMemory() {
|
||||||
@ -117,10 +146,19 @@ class KclManager {
|
|||||||
this._wasmInitFailedCallback(wasmInitFailed)
|
this._wasmInitFailedCallback(wasmInitFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setParams(params: Params<string>) {
|
||||||
|
this._params = params
|
||||||
|
}
|
||||||
|
|
||||||
constructor(engineCommandManager: EngineCommandManager) {
|
constructor(engineCommandManager: EngineCommandManager) {
|
||||||
this.engineCommandManager = engineCommandManager
|
this.engineCommandManager = engineCommandManager
|
||||||
|
|
||||||
|
if (isTauri()) {
|
||||||
|
this.code = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
const storedCode = localStorage.getItem(PERSIST_CODE_TOKEN)
|
const storedCode = localStorage.getItem(PERSIST_CODE_TOKEN)
|
||||||
// TODO #819 remove zustand persistance logic in a few months
|
// TODO #819 remove zustand persistence logic in a few months
|
||||||
// short term migration, shouldn't make a difference for tauri app users
|
// short term migration, shouldn't make a difference for tauri app users
|
||||||
// anyway since that's filesystem based.
|
// anyway since that's filesystem based.
|
||||||
const zustandStore = JSON.parse(localStorage.getItem('store') || '{}')
|
const zustandStore = JSON.parse(localStorage.getItem('store') || '{}')
|
||||||
@ -130,6 +168,7 @@ class KclManager {
|
|||||||
zustandStore.state.code = ''
|
zustandStore.state.code = ''
|
||||||
localStorage.setItem('store', JSON.stringify(zustandStore))
|
localStorage.setItem('store', JSON.stringify(zustandStore))
|
||||||
} else if (storedCode === null) {
|
} else if (storedCode === null) {
|
||||||
|
console.log('stored brack thing')
|
||||||
this.code = bracket
|
this.code = bracket
|
||||||
} else {
|
} else {
|
||||||
this.code = storedCode
|
this.code = storedCode
|
||||||
@ -164,6 +203,21 @@ class KclManager {
|
|||||||
this._executeCallback = callback
|
this._executeCallback = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
safeParse(code: string): Program | null {
|
||||||
|
try {
|
||||||
|
const ast = parse(code)
|
||||||
|
this.kclErrors = []
|
||||||
|
return ast
|
||||||
|
} catch (e) {
|
||||||
|
console.error('error parsing code', e)
|
||||||
|
if (e instanceof KCLError) {
|
||||||
|
this.kclErrors = [e]
|
||||||
|
if (e.msg === 'file is empty') engineCommandManager.endSession()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async ensureWasmInit() {
|
async ensureWasmInit() {
|
||||||
try {
|
try {
|
||||||
await initPromise
|
await initPromise
|
||||||
@ -184,20 +238,20 @@ class KclManager {
|
|||||||
defaultPlanes: this.defaultPlanes,
|
defaultPlanes: this.defaultPlanes,
|
||||||
})
|
})
|
||||||
this.isExecuting = false
|
this.isExecuting = false
|
||||||
this._logs = logs
|
this.logs = logs
|
||||||
this._kclErrors = errors
|
this.kclErrors = errors
|
||||||
this._programMemory = programMemory
|
this.programMemory = programMemory
|
||||||
this._ast = { ...ast }
|
this.ast = { ...ast }
|
||||||
if (updateCode) {
|
if (updateCode) {
|
||||||
this._code = recast(ast)
|
this.code = recast(ast)
|
||||||
this._codeCallBack(this._code)
|
|
||||||
}
|
}
|
||||||
this._executeCallback()
|
this._executeCallback()
|
||||||
}
|
}
|
||||||
async executeAstMock(ast: Program = this._ast, updateCode = false) {
|
async executeAstMock(ast: Program = this._ast, updateCode = false) {
|
||||||
await this.ensureWasmInit()
|
await this.ensureWasmInit()
|
||||||
const newCode = recast(ast)
|
const newCode = recast(ast)
|
||||||
const newAst = parse(newCode)
|
const newAst = this.safeParse(newCode)
|
||||||
|
if (!newAst) return
|
||||||
await this?.engineCommandManager?.waitForReady
|
await this?.engineCommandManager?.waitForReady
|
||||||
if (updateCode) {
|
if (updateCode) {
|
||||||
this.setCode(recast(ast))
|
this.setCode(recast(ast))
|
||||||
@ -233,13 +287,17 @@ class KclManager {
|
|||||||
this.ast = ast
|
this.ast = ast
|
||||||
if (code) this.code = code
|
if (code) this.code = code
|
||||||
}
|
}
|
||||||
setCode(code: string) {
|
setCode(code: string, shouldWriteFile = true) {
|
||||||
|
if (shouldWriteFile) {
|
||||||
|
// use the normal code setter
|
||||||
|
this.code = code
|
||||||
|
return
|
||||||
|
}
|
||||||
this._code = code
|
this._code = code
|
||||||
this._codeCallBack(code)
|
this._codeCallBack(code)
|
||||||
localStorage.setItem(PERSIST_CODE_TOKEN, code)
|
|
||||||
}
|
}
|
||||||
setCodeAndExecute(code: string) {
|
setCodeAndExecute(code: string, shouldWriteFile = true) {
|
||||||
this.setCode(code)
|
this.setCode(code, shouldWriteFile)
|
||||||
if (code.trim()) {
|
if (code.trim()) {
|
||||||
this._defferer(code)
|
this._defferer(code)
|
||||||
return
|
return
|
||||||
@ -260,9 +318,11 @@ class KclManager {
|
|||||||
this.engineCommandManager.endSession()
|
this.engineCommandManager.endSession()
|
||||||
}
|
}
|
||||||
format() {
|
format() {
|
||||||
this.code = recast(parse(kclManager.code))
|
const ast = this.safeParse(this.code)
|
||||||
|
if (!ast) return
|
||||||
|
this.code = recast(ast)
|
||||||
}
|
}
|
||||||
// There's overlapping resposibility between updateAst and executeAst.
|
// There's overlapping responsibility between updateAst and executeAst.
|
||||||
// updateAst was added as it was used a lot before xState migration so makes the port easier.
|
// updateAst was added as it was used a lot before xState migration so makes the port easier.
|
||||||
// but should probably have think about which of the function to keep
|
// but should probably have think about which of the function to keep
|
||||||
async updateAst(
|
async updateAst(
|
||||||
@ -270,15 +330,13 @@ class KclManager {
|
|||||||
execute: boolean,
|
execute: boolean,
|
||||||
optionalParams?: {
|
optionalParams?: {
|
||||||
focusPath?: PathToNode
|
focusPath?: PathToNode
|
||||||
callBack?: (ast: Program) => void
|
|
||||||
}
|
}
|
||||||
): Promise<Selections | null> {
|
): Promise<Selections | null> {
|
||||||
const newCode = recast(ast)
|
const newCode = recast(ast)
|
||||||
const astWithUpdatedSource = parse(newCode)
|
const astWithUpdatedSource = this.safeParse(newCode)
|
||||||
optionalParams?.callBack?.(astWithUpdatedSource)
|
if (!astWithUpdatedSource) return null
|
||||||
let returnVal: Selections | null = null
|
let returnVal: Selections | null = null
|
||||||
|
|
||||||
this.code = newCode
|
|
||||||
if (optionalParams?.focusPath) {
|
if (optionalParams?.focusPath) {
|
||||||
const { node } = getNodeFromPath<any>(
|
const { node } = getNodeFromPath<any>(
|
||||||
astWithUpdatedSource,
|
astWithUpdatedSource,
|
||||||
@ -299,12 +357,12 @@ class KclManager {
|
|||||||
|
|
||||||
if (execute) {
|
if (execute) {
|
||||||
// Call execute on the set ast.
|
// Call execute on the set ast.
|
||||||
await this.executeAst(astWithUpdatedSource)
|
await this.executeAst(astWithUpdatedSource, true)
|
||||||
} else {
|
} else {
|
||||||
// When we don't re-execute, we still want to update the program
|
// When we don't re-execute, we still want to update the program
|
||||||
// memory with the new ast. So we will hit the mock executor
|
// memory with the new ast. So we will hit the mock executor
|
||||||
// instead.
|
// instead.
|
||||||
await this.executeAstMock(astWithUpdatedSource)
|
await this.executeAstMock(astWithUpdatedSource, true)
|
||||||
}
|
}
|
||||||
return returnVal
|
return returnVal
|
||||||
}
|
}
|
||||||
@ -369,6 +427,11 @@ export function KclContextProvider({
|
|||||||
setWasmInitFailed,
|
setWasmInitFailed,
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const params = useParams()
|
||||||
|
useEffect(() => {
|
||||||
|
kclManager.setParams(params)
|
||||||
|
}, [params])
|
||||||
return (
|
return (
|
||||||
<KclContext.Provider
|
<KclContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
@ -331,9 +331,6 @@ const myVar = funcN(1, 2)`
|
|||||||
raw: '2',
|
raw: '2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
function: {
|
|
||||||
type: 'InMemory',
|
|
||||||
},
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -403,7 +400,6 @@ describe('testing pipe operator special', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -440,7 +436,6 @@ describe('testing pipe operator special', () => {
|
|||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 59, end: 60 },
|
{ type: 'PipeSubstitution', start: 59, end: 60 },
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -513,7 +508,6 @@ describe('testing pipe operator special', () => {
|
|||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 105, end: 106 },
|
{ type: 'PipeSubstitution', start: 105, end: 106 },
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -550,7 +544,6 @@ describe('testing pipe operator special', () => {
|
|||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 128, end: 129 },
|
{ type: 'PipeSubstitution', start: 128, end: 129 },
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -573,9 +566,6 @@ describe('testing pipe operator special', () => {
|
|||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 143, end: 144 },
|
{ type: 'PipeSubstitution', start: 143, end: 144 },
|
||||||
],
|
],
|
||||||
function: {
|
|
||||||
type: 'InMemory',
|
|
||||||
},
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -655,9 +645,6 @@ describe('testing pipe operator special', () => {
|
|||||||
end: 35,
|
end: 35,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
function: {
|
|
||||||
type: 'InMemory',
|
|
||||||
},
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -1345,7 +1332,7 @@ describe('nests binary expressions correctly', () => {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
it('should nest properly with two opperators of equal precedence', () => {
|
it('should nest properly with two operators of equal precedence', () => {
|
||||||
const code = `const yo = 1 + 2 - 3`
|
const code = `const yo = 1 + 2 - 3`
|
||||||
const { body } = parse(code)
|
const { body } = parse(code)
|
||||||
expect((body[0] as any).declarations[0].init).toEqual({
|
expect((body[0] as any).declarations[0].init).toEqual({
|
||||||
@ -1382,7 +1369,7 @@ describe('nests binary expressions correctly', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
it('should nest properly with two opperators of equal (but higher) precedence', () => {
|
it('should nest properly with two operators of equal (but higher) precedence', () => {
|
||||||
const code = `const yo = 1 * 2 / 3`
|
const code = `const yo = 1 * 2 / 3`
|
||||||
const { body } = parse(code)
|
const { body } = parse(code)
|
||||||
expect((body[0] as any).declarations[0].init).toEqual({
|
expect((body[0] as any).declarations[0].init).toEqual({
|
||||||
@ -1443,7 +1430,7 @@ describe('nests binary expressions correctly', () => {
|
|||||||
type: 'BinaryExpression',
|
type: 'BinaryExpression',
|
||||||
operator: '*',
|
operator: '*',
|
||||||
start: 15,
|
start: 15,
|
||||||
end: 26,
|
end: 25,
|
||||||
left: { type: 'Literal', value: 2, raw: '2', start: 15, end: 16 },
|
left: { type: 'Literal', value: 2, raw: '2', start: 15, end: 16 },
|
||||||
right: {
|
right: {
|
||||||
type: 'BinaryExpression',
|
type: 'BinaryExpression',
|
||||||
@ -1567,7 +1554,6 @@ describe('test UnaryExpression', () => {
|
|||||||
{ type: 'Literal', start: 19, end: 20, value: 4, raw: '4' },
|
{ type: 'Literal', start: 19, end: 20, value: 4, raw: '4' },
|
||||||
{ type: 'Literal', start: 22, end: 25, value: 100, raw: '100' },
|
{ type: 'Literal', start: 22, end: 25, value: 100, raw: '100' },
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -1601,12 +1587,10 @@ describe('testing nested call expressions', () => {
|
|||||||
{ type: 'Literal', start: 34, end: 35, value: 5, raw: '5' },
|
{ type: 'Literal', start: 34, end: 35, value: 5, raw: '5' },
|
||||||
{ type: 'Literal', start: 37, end: 38, value: 3, raw: '3' },
|
{ type: 'Literal', start: 37, end: 38, value: 3, raw: '3' },
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1638,7 +1622,6 @@ describe('should recognise callExpresions in binaryExpressions', () => {
|
|||||||
},
|
},
|
||||||
{ type: 'PipeSubstitution', start: 25, end: 26 },
|
{ type: 'PipeSubstitution', start: 25, end: 26 },
|
||||||
],
|
],
|
||||||
function: expect.any(Object),
|
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
right: { type: 'Literal', value: 1, raw: '1', start: 30, end: 31 },
|
right: { type: 'Literal', value: 1, raw: '1', start: 30, end: 31 },
|
||||||
|
@ -18,6 +18,20 @@ export class KCLError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class KCLLexicalError extends KCLError {
|
||||||
|
constructor(msg: string, sourceRanges: [number, number][]) {
|
||||||
|
super('lexical', msg, sourceRanges)
|
||||||
|
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KCLInternalError extends KCLError {
|
||||||
|
constructor(msg: string, sourceRanges: [number, number][]) {
|
||||||
|
super('internal', msg, sourceRanges)
|
||||||
|
Object.setPrototypeOf(this, KCLSyntaxError.prototype)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class KCLSyntaxError extends KCLError {
|
export class KCLSyntaxError extends KCLError {
|
||||||
constructor(msg: string, sourceRanges: [number, number][]) {
|
constructor(msg: string, sourceRanges: [number, number][]) {
|
||||||
super('syntax', msg, sourceRanges)
|
super('syntax', msg, sourceRanges)
|
||||||
|
@ -310,7 +310,7 @@ export function extrudeSketch(
|
|||||||
const name = findUniqueName(node, 'part')
|
const name = findUniqueName(node, 'part')
|
||||||
const VariableDeclaration = createVariableDeclaration(name, extrudeCall)
|
const VariableDeclaration = createVariableDeclaration(name, extrudeCall)
|
||||||
let showCallIndex = getShowIndex(_node)
|
let showCallIndex = getShowIndex(_node)
|
||||||
if (showCallIndex == -1) {
|
if (showCallIndex === -1) {
|
||||||
// We didn't find a show, so let's just append everything
|
// We didn't find a show, so let's just append everything
|
||||||
showCallIndex = _node.body.length
|
showCallIndex = _node.body.length
|
||||||
}
|
}
|
||||||
@ -480,21 +480,6 @@ export function createCallExpressionStdLib(
|
|||||||
end: 0,
|
end: 0,
|
||||||
name,
|
name,
|
||||||
},
|
},
|
||||||
function: {
|
|
||||||
type: 'StdLib',
|
|
||||||
func: {
|
|
||||||
// We only need the name here to map it back when it serializes
|
|
||||||
// to rust, don't worry about the rest.
|
|
||||||
name,
|
|
||||||
summary: '',
|
|
||||||
description: '',
|
|
||||||
tags: [],
|
|
||||||
returnValue: { type: '', required: false, name: '', schema: {} },
|
|
||||||
args: [],
|
|
||||||
unpublished: false,
|
|
||||||
deprecated: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
optional: false,
|
optional: false,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
}
|
}
|
||||||
@ -514,9 +499,6 @@ export function createCallExpression(
|
|||||||
end: 0,
|
end: 0,
|
||||||
name,
|
name,
|
||||||
},
|
},
|
||||||
function: {
|
|
||||||
type: 'InMemory',
|
|
||||||
},
|
|
||||||
optional: false,
|
optional: false,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
}
|
}
|
||||||
|
@ -2,5 +2,5 @@ The std is as expected, tools that are provided with the language.
|
|||||||
|
|
||||||
For this language that means functions.
|
For this language that means functions.
|
||||||
|
|
||||||
However because programatically changing the source code is a first class citizen in this lang, there needs to be helpes for adding and modifying these function calls,
|
However because programmatically changing the source code is a first class citizen in this lang, there needs to be helpers for adding and modifying these function calls,
|
||||||
So it makes sense to group some of these together.
|
So it makes sense to group some of these together.
|
||||||
|
@ -289,6 +289,7 @@ export class EngineConnection {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
console.error(`Error from server:\n${errorsString}`)
|
console.error(`Error from server:\n${errorsString}`)
|
||||||
|
console.log(message)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -664,7 +665,7 @@ export class EngineCommandManager {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Inisialize the planes.
|
// Initialize the planes.
|
||||||
this.initPlanes().then(() => {
|
this.initPlanes().then(() => {
|
||||||
// We execute the code here to make sure if the stream was to
|
// We execute the code here to make sure if the stream was to
|
||||||
// restart in a session, we want to make sure to execute the code.
|
// restart in a session, we want to make sure to execute the code.
|
||||||
@ -887,8 +888,9 @@ export class EngineCommandManager {
|
|||||||
}
|
}
|
||||||
endSession() {
|
endSession() {
|
||||||
// TODO: instead of sending a single command with `object_ids: Object.keys(this.artifactMap)`
|
// TODO: instead of sending a single command with `object_ids: Object.keys(this.artifactMap)`
|
||||||
// we need to loop over them each individualy because if the engine doesn't recognise a single
|
// we need to loop over them each individually because if the engine doesn't recognise a single
|
||||||
// id the whole command fails.
|
// id the whole command fails.
|
||||||
|
const artifactsToDelete: any = {}
|
||||||
Object.entries(this.artifactMap).forEach(([id, artifact]) => {
|
Object.entries(this.artifactMap).forEach(([id, artifact]) => {
|
||||||
const artifactTypesToDelete: ArtifactMap[string]['commandType'][] = [
|
const artifactTypesToDelete: ArtifactMap[string]['commandType'][] = [
|
||||||
// 'start_path' creates a new scene object for the path, which is why it needs to be deleted,
|
// 'start_path' creates a new scene object for the path, which is why it needs to be deleted,
|
||||||
@ -898,7 +900,9 @@ export class EngineCommandManager {
|
|||||||
'start_path',
|
'start_path',
|
||||||
]
|
]
|
||||||
if (!artifactTypesToDelete.includes(artifact.commandType)) return
|
if (!artifactTypesToDelete.includes(artifact.commandType)) return
|
||||||
|
artifactsToDelete[id] = artifact
|
||||||
|
})
|
||||||
|
Object.keys(artifactsToDelete).forEach((id) => {
|
||||||
const deletCmd: EngineCommand = {
|
const deletCmd: EngineCommand = {
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
@ -982,7 +986,7 @@ export class EngineCommandManager {
|
|||||||
if (parseCommand.type === 'modeling_cmd_req')
|
if (parseCommand.type === 'modeling_cmd_req')
|
||||||
return this.handlePendingCommand(id, parseCommand?.cmd, range)
|
return this.handlePendingCommand(id, parseCommand?.cmd, range)
|
||||||
}
|
}
|
||||||
throw 'shouldnt reach here'
|
throw Error('shouldnt reach here')
|
||||||
}
|
}
|
||||||
handlePendingCommand(
|
handlePendingCommand(
|
||||||
id: string,
|
id: string,
|
||||||
|
@ -20,7 +20,6 @@ import {
|
|||||||
import { isLiteralArrayOrStatic } from './sketchcombos'
|
import { isLiteralArrayOrStatic } from './sketchcombos'
|
||||||
import { toolTips, ToolTip } from '../../useStore'
|
import { toolTips, ToolTip } from '../../useStore'
|
||||||
import { createPipeExpression, splitPathAtPipeExpression } from '../modifyAst'
|
import { createPipeExpression, splitPathAtPipeExpression } from '../modifyAst'
|
||||||
import { generateUuidFromHashSeed } from '../../lib/uuid'
|
|
||||||
|
|
||||||
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
|
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
|
||||||
|
|
||||||
@ -92,18 +91,12 @@ export function createFirstArg(
|
|||||||
throw new Error('all sketch line types should have been covered')
|
throw new Error('all sketch line types should have been covered')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
type LineData = {
|
type LineData = {
|
||||||
from: [number, number, number]
|
from: [number, number, number]
|
||||||
to: [number, number, number]
|
to: [number, number, number]
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeId(seed: string | any) {
|
|
||||||
if (typeof seed === 'string') {
|
|
||||||
return generateUuidFromHashSeed(seed)
|
|
||||||
}
|
|
||||||
return generateUuidFromHashSeed(JSON.stringify(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const lineTo: SketchLineHelper = {
|
export const lineTo: SketchLineHelper = {
|
||||||
add: ({
|
add: ({
|
||||||
node,
|
node,
|
||||||
@ -250,9 +243,6 @@ export const line: SketchLineHelper = {
|
|||||||
])
|
])
|
||||||
|
|
||||||
if (callExpression.arguments?.[0].type === 'ObjectExpression') {
|
if (callExpression.arguments?.[0].type === 'ObjectExpression') {
|
||||||
const toProp = callExpression.arguments?.[0].properties?.find(
|
|
||||||
({ key }) => key.name === 'to'
|
|
||||||
)
|
|
||||||
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
|
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
|
||||||
} else {
|
} else {
|
||||||
mutateArrExp(callExpression.arguments?.[0], toArrExp)
|
mutateArrExp(callExpression.arguments?.[0], toArrExp)
|
||||||
@ -956,7 +946,7 @@ export function compareVec2Epsilon(
|
|||||||
) {
|
) {
|
||||||
const compareEpsilon = 0.015625 // or 2^-6
|
const compareEpsilon = 0.015625 // or 2^-6
|
||||||
const xDifference = Math.abs(vec1[0] - vec2[0])
|
const xDifference = Math.abs(vec1[0] - vec2[0])
|
||||||
const yDifference = Math.abs(vec1[0] - vec2[0])
|
const yDifference = Math.abs(vec1[1] - vec2[1])
|
||||||
return xDifference < compareEpsilon && yDifference < compareEpsilon
|
return xDifference < compareEpsilon && yDifference < compareEpsilon
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,14 +964,12 @@ export function addNewSketchLn({
|
|||||||
const node = JSON.parse(JSON.stringify(_node))
|
const node = JSON.parse(JSON.stringify(_node))
|
||||||
const { add, updateArgs } = sketchLineHelperMap?.[fnName] || {}
|
const { add, updateArgs } = sketchLineHelperMap?.[fnName] || {}
|
||||||
if (!add || !updateArgs) throw new Error('not a sketch line helper')
|
if (!add || !updateArgs) throw new Error('not a sketch line helper')
|
||||||
const { node: varDec } = getNodeFromPath<VariableDeclarator>(
|
getNodeFromPath<VariableDeclarator>(node, pathToNode, 'VariableDeclarator')
|
||||||
|
getNodeFromPath<PipeExpression | CallExpression>(
|
||||||
node,
|
node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
'VariableDeclarator'
|
'PipeExpression'
|
||||||
)
|
)
|
||||||
const { node: pipeExp, shallowPath: pipePath } = getNodeFromPath<
|
|
||||||
PipeExpression | CallExpression
|
|
||||||
>(node, pathToNode, 'PipeExpression')
|
|
||||||
return add({
|
return add({
|
||||||
node,
|
node,
|
||||||
previousProgramMemory,
|
previousProgramMemory,
|
||||||
|
@ -50,7 +50,7 @@ async function testingSwapSketchFnCall({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
||||||
const bigExampleArr = [
|
const bigExampleArr = [
|
||||||
`const part001 = startSketchOn('XY')`,
|
`const part001 = startSketchOn('XY')`,
|
||||||
` |> startProfileAt([0, 0], %)`,
|
` |> startProfileAt([0, 0], %)`,
|
||||||
@ -178,7 +178,7 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
|||||||
constraintType: 'horizontal',
|
constraintType: 'horizontal',
|
||||||
})
|
})
|
||||||
const expectedLine = "xLine({ length: -0.86, tag: 'abc4' }, %)"
|
const expectedLine = "xLine({ length: -0.86, tag: 'abc4' }, %)"
|
||||||
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatiable `-myVar`
|
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatible `-myVar`
|
||||||
expect(newCode).toContain(expectedLine)
|
expect(newCode).toContain(expectedLine)
|
||||||
// new line should start at the same place as the old line
|
// new line should start at the same place as the old line
|
||||||
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
||||||
@ -268,7 +268,7 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('testing swaping out sketch calls with xLine/xLineTo while keeping variable/identifiers intact', () => {
|
describe('testing swapping out sketch calls with xLine/xLineTo while keeping variable/identifiers intact', () => {
|
||||||
// Enable rotations #152
|
// Enable rotations #152
|
||||||
const variablesExampleArr = [
|
const variablesExampleArr = [
|
||||||
`const lineX = -1`,
|
`const lineX = -1`,
|
||||||
|
@ -108,7 +108,7 @@ const part001 = startSketchOn('XY')
|
|||||||
|> line([myVar, 1], %) // ln-should use legLen for y
|
|> line([myVar, 1], %) // ln-should use legLen for y
|
||||||
|> line([myVar, -1], %) // ln-legLen but negative
|
|> line([myVar, -1], %) // ln-legLen but negative
|
||||||
|> line([-0.62, -1.54], %) // ln-should become angledLine
|
|> line([-0.62, -1.54], %) // ln-should become angledLine
|
||||||
|> angledLine([myVar, 1.04], %) // ln-use segLen for secound arg
|
|> angledLine([myVar, 1.04], %) // ln-use segLen for second arg
|
||||||
|> angledLine([45, 1.04], %) // ln-segLen again
|
|> angledLine([45, 1.04], %) // ln-segLen again
|
||||||
|> angledLineOfXLength([54, 2.35], %) // ln-should be transformed to angledLine
|
|> angledLineOfXLength([54, 2.35], %) // ln-should be transformed to angledLine
|
||||||
|> angledLineOfXLength([50, myVar], %) // ln-should use legAngX to calculate angle
|
|> angledLineOfXLength([50, myVar], %) // ln-should use legAngX to calculate angle
|
||||||
@ -163,7 +163,7 @@ const part001 = startSketchOn('XY')
|
|||||||
-legLen(segLen('seg01', %), myVar)
|
-legLen(segLen('seg01', %), myVar)
|
||||||
], %) // ln-legLen but negative
|
], %) // ln-legLen but negative
|
||||||
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|
||||||
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for secound arg
|
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for second arg
|
||||||
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|
||||||
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
@ -471,7 +471,7 @@ async function helperThing(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('testing getConstraintLevelFromSourceRange', () => {
|
describe('testing getConstraintLevelFromSourceRange', () => {
|
||||||
it('should devide up lines into free, partial and fully contrained', () => {
|
it('should divide up lines into free, partial and fully contrained', () => {
|
||||||
const code = `const baseLength = 3
|
const code = `const baseLength = 3
|
||||||
const baseThick = 1
|
const baseThick = 1
|
||||||
const armThick = 0.5
|
const armThick = 0.5
|
||||||
|
@ -26,5 +26,4 @@ const bracket = startSketchOn('XY')
|
|||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(width, %)
|
|> extrude(width, %)
|
||||||
|
|
||||||
show(bracket)
|
|
||||||
`
|
`
|
||||||
|
@ -15,7 +15,7 @@ app needs these selections to be based on cursors, therefore the app must
|
|||||||
be in control of selections. On top of that because we need to set cursor
|
be in control of selections. On top of that because we need to set cursor
|
||||||
positions in code-mirror for selections, both from app logic, and still
|
positions in code-mirror for selections, both from app logic, and still
|
||||||
allow the user to add multiple cursors like a normal editor, it's best to
|
allow the user to add multiple cursors like a normal editor, it's best to
|
||||||
let code mirror control cursor positions and assosiate those source ranges
|
let code mirror control cursor positions and associate those source ranges
|
||||||
with entity ids from code-mirror events later.
|
with entity ids from code-mirror events later.
|
||||||
|
|
||||||
So it's a lot of back and forth. conceptually the back and forth is:
|
So it's a lot of back and forth. conceptually the back and forth is:
|
||||||
@ -43,7 +43,7 @@ In detail:
|
|||||||
|
|
||||||
1) Click commands are mostly sent in stream.tsx search for
|
1) Click commands are mostly sent in stream.tsx search for
|
||||||
"select_with_point"
|
"select_with_point"
|
||||||
2) The handler for when the engine sends back entitiy ids calls
|
2) The handler for when the engine sends back entity ids calls
|
||||||
getEventForSelectWithPoint, it fires an XState event to update our
|
getEventForSelectWithPoint, it fires an XState event to update our
|
||||||
selections is xstate context
|
selections is xstate context
|
||||||
3 and 4) The XState handler for the above uses handleSelectionBatch and
|
3 and 4) The XState handler for the above uses handleSelectionBatch and
|
||||||
@ -102,8 +102,8 @@ export async function getEventForSelectWithPoint(
|
|||||||
Models['OkModelingCmdResponse_type'],
|
Models['OkModelingCmdResponse_type'],
|
||||||
{ type: 'select_with_point' }
|
{ type: 'select_with_point' }
|
||||||
>,
|
>,
|
||||||
{ sketchEnginePathId }: { sketchEnginePathId: string }
|
{ sketchEnginePathId }: { sketchEnginePathId?: string }
|
||||||
): Promise<ModelingMachineEvent> {
|
): Promise<ModelingMachineEvent | null> {
|
||||||
if (!data?.entity_id) {
|
if (!data?.entity_id) {
|
||||||
return {
|
return {
|
||||||
type: 'Set selection',
|
type: 'Set selection',
|
||||||
@ -120,6 +120,7 @@ export async function getEventForSelectWithPoint(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if (!sketchEnginePathId) return null
|
||||||
// selected a vertex
|
// selected a vertex
|
||||||
const res = await engineCommandManager.sendSceneCommand({
|
const res = await engineCommandManager.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
@ -127,7 +128,7 @@ export async function getEventForSelectWithPoint(
|
|||||||
cmd: {
|
cmd: {
|
||||||
type: 'path_get_curve_uuids_for_vertices',
|
type: 'path_get_curve_uuids_for_vertices',
|
||||||
vertex_ids: [data.entity_id],
|
vertex_ids: [data.entity_id],
|
||||||
path_id: sketchEnginePathId,
|
path_id: sketchEnginePathId || '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const curveIds = res?.data?.data?.curve_ids
|
const curveIds = res?.data?.data?.curve_ids
|
||||||
@ -303,7 +304,7 @@ export function resetAndSetEngineEntitySelectionCmds(
|
|||||||
selections: SelectionToEngine[]
|
selections: SelectionToEngine[]
|
||||||
): Models['WebSocketRequest_type'][] {
|
): Models['WebSocketRequest_type'][] {
|
||||||
if (!engineCommandManager.engineConnection?.isReady()) {
|
if (!engineCommandManager.engineConnection?.isReady()) {
|
||||||
console.log('engine connection isnt ready')
|
console.log('engine connection is not ready')
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
|
@ -9,7 +9,6 @@ import { documentDir, homeDir, sep } from '@tauri-apps/api/path'
|
|||||||
import { isTauri } from './isTauri'
|
import { isTauri } from './isTauri'
|
||||||
import { ProjectWithEntryPointMetadata } from '../Router'
|
import { ProjectWithEntryPointMetadata } from '../Router'
|
||||||
import { metadata } from 'tauri-plugin-fs-extra-api'
|
import { metadata } from 'tauri-plugin-fs-extra-api'
|
||||||
import { bracket } from './exampleKcl'
|
|
||||||
|
|
||||||
const PROJECT_FOLDER = 'kittycad-modeling-projects'
|
const PROJECT_FOLDER = 'kittycad-modeling-projects'
|
||||||
export const FILE_EXT = '.kcl'
|
export const FILE_EXT = '.kcl'
|
||||||
@ -211,7 +210,8 @@ export function sortProject(project: FileEntry[]): FileEntry[] {
|
|||||||
// Creates a new file in the default directory with the default project name
|
// Creates a new file in the default directory with the default project name
|
||||||
// Returns the path to the new file
|
// Returns the path to the new file
|
||||||
export async function createNewProject(
|
export async function createNewProject(
|
||||||
path: string
|
path: string,
|
||||||
|
initCode = ''
|
||||||
): Promise<ProjectWithEntryPointMetadata> {
|
): Promise<ProjectWithEntryPointMetadata> {
|
||||||
if (!isTauri) {
|
if (!isTauri) {
|
||||||
throw new Error('createNewProject() can only be called from a Tauri app')
|
throw new Error('createNewProject() can only be called from a Tauri app')
|
||||||
@ -225,10 +225,12 @@ export async function createNewProject(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await writeTextFile(path + sep + PROJECT_ENTRYPOINT, bracket).catch((err) => {
|
await writeTextFile(path + sep + PROJECT_ENTRYPOINT, initCode).catch(
|
||||||
console.error('Error creating new file:', err)
|
(err) => {
|
||||||
throw err
|
console.error('Error creating new file:', err)
|
||||||
})
|
throw err
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const m = await metadata(path)
|
const m = await metadata(path)
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import { v4 as uuidv4 } from 'uuid'
|
|||||||
type WebSocketResponse = Models['OkWebSocketResponseData_type']
|
type WebSocketResponse = Models['OkWebSocketResponseData_type']
|
||||||
|
|
||||||
class MockEngineCommandManager {
|
class MockEngineCommandManager {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
constructor(mockParams: {
|
constructor(mockParams: {
|
||||||
setIsStreamReady: (isReady: boolean) => void
|
setIsStreamReady: (isReady: boolean) => void
|
||||||
setMediaStream: (stream: MediaStream) => void
|
setMediaStream: (stream: MediaStream) => void
|
||||||
|
@ -664,8 +664,8 @@ export const modelingMachine = createMachine(
|
|||||||
on: {
|
on: {
|
||||||
Cancel: {
|
Cancel: {
|
||||||
target: 'idle',
|
target: 'idle',
|
||||||
// TODO what if we're existing extrude equiped, should these actions still be fired?
|
// TODO what if we're existing extrude equipped, should these actions still be fired?
|
||||||
// mabye cancel needs to have a guard for if else logic?
|
// maybe cancel needs to have a guard for if else logic?
|
||||||
actions: [
|
actions: [
|
||||||
'edit_mode_exit',
|
'edit_mode_exit',
|
||||||
'default_camera_disable_sketch_mode',
|
'default_camera_disable_sketch_mode',
|
||||||
@ -882,7 +882,7 @@ export const modelingMachine = createMachine(
|
|||||||
// TODO implement source ranges for all of these constraints
|
// TODO implement source ranges for all of these constraints
|
||||||
// need to make the async like the modal constraints
|
// need to make the async like the modal constraints
|
||||||
'Make selection horizontal': ({ selectionRanges }) => {
|
'Make selection horizontal': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVert(
|
const { modifiedAst } = applyConstraintHorzVert(
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
'horizontal',
|
'horizontal',
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
@ -891,7 +891,7 @@ export const modelingMachine = createMachine(
|
|||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
},
|
},
|
||||||
'Make selection vertical': ({ selectionRanges }) => {
|
'Make selection vertical': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVert(
|
const { modifiedAst } = applyConstraintHorzVert(
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
'vertical',
|
'vertical',
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
@ -900,33 +900,33 @@ export const modelingMachine = createMachine(
|
|||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
},
|
},
|
||||||
'Constrain horizontally align': ({ selectionRanges }) => {
|
'Constrain horizontally align': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVertAlign({
|
const { modifiedAst } = applyConstraintHorzVertAlign({
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
constraint: 'setVertDistance',
|
constraint: 'setVertDistance',
|
||||||
})
|
})
|
||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
},
|
},
|
||||||
'Constrain vertically align': ({ selectionRanges }) => {
|
'Constrain vertically align': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyConstraintHorzVertAlign({
|
const { modifiedAst } = applyConstraintHorzVertAlign({
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
constraint: 'setHorzDistance',
|
constraint: 'setHorzDistance',
|
||||||
})
|
})
|
||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
},
|
},
|
||||||
'Constrain equal length': ({ selectionRanges }) => {
|
'Constrain equal length': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyConstraintEqualLength({
|
const { modifiedAst } = applyConstraintEqualLength({
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
})
|
})
|
||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
},
|
},
|
||||||
'Constrain parallel': ({ selectionRanges }) => {
|
'Constrain parallel': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyConstraintEqualAngle({
|
const { modifiedAst } = applyConstraintEqualAngle({
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
})
|
})
|
||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
},
|
},
|
||||||
'Constrain remove constraints': ({ selectionRanges }) => {
|
'Constrain remove constraints': ({ selectionRanges }) => {
|
||||||
const { modifiedAst, pathToNodeMap } = applyRemoveConstrainingValues({
|
const { modifiedAst } = applyRemoveConstrainingValues({
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
})
|
})
|
||||||
kclManager.updateAst(modifiedAst, true)
|
kclManager.updateAst(modifiedAst, true)
|
||||||
|
@ -43,7 +43,10 @@ function OnboardingWithNewFile() {
|
|||||||
ONBOARDING_PROJECT_NAME,
|
ONBOARDING_PROJECT_NAME,
|
||||||
nextIndex
|
nextIndex
|
||||||
)
|
)
|
||||||
const newFile = await createNewProject(defaultDirectory + sep + name)
|
const newFile = await createNewProject(
|
||||||
|
defaultDirectory + sep + name,
|
||||||
|
bracket
|
||||||
|
)
|
||||||
navigate(
|
navigate(
|
||||||
`${paths.FILE}/${encodeURIComponent(
|
`${paths.FILE}/${encodeURIComponent(
|
||||||
newFile.path + sep + PROJECT_ENTRYPOINT
|
newFile.path + sep + PROJECT_ENTRYPOINT
|
||||||
@ -79,7 +82,7 @@ function OnboardingWithNewFile() {
|
|||||||
<ActionButton
|
<ActionButton
|
||||||
Element="button"
|
Element="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
kclManager.setCode(bracket)
|
kclManager.setCodeAndExecute(bracket)
|
||||||
next()
|
next()
|
||||||
}}
|
}}
|
||||||
icon={{ icon: faArrowRight }}
|
icon={{ icon: faArrowRight }}
|
||||||
@ -118,7 +121,7 @@ function OnboardingWithNewFile() {
|
|||||||
Element="button"
|
Element="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
createAndOpenNewProject()
|
createAndOpenNewProject()
|
||||||
kclManager.setCode(bracket)
|
kclManager.setCode(bracket, false)
|
||||||
dismiss()
|
dismiss()
|
||||||
}}
|
}}
|
||||||
icon={{ icon: faArrowRight }}
|
icon={{ icon: faArrowRight }}
|
||||||
|
@ -32,6 +32,7 @@ import {
|
|||||||
} from 'lib/tauriFS'
|
} from 'lib/tauriFS'
|
||||||
import { ONBOARDING_PROJECT_NAME } from './Onboarding'
|
import { ONBOARDING_PROJECT_NAME } from './Onboarding'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { sep } from '@tauri-apps/api/path'
|
||||||
|
import { bracket } from 'lib/exampleKcl'
|
||||||
|
|
||||||
export const Settings = () => {
|
export const Settings = () => {
|
||||||
const loaderData =
|
const loaderData =
|
||||||
@ -96,7 +97,10 @@ export const Settings = () => {
|
|||||||
ONBOARDING_PROJECT_NAME,
|
ONBOARDING_PROJECT_NAME,
|
||||||
nextIndex
|
nextIndex
|
||||||
)
|
)
|
||||||
const newFile = await createNewProject(defaultDirectory + sep + name)
|
const newFile = await createNewProject(
|
||||||
|
defaultDirectory + sep + name,
|
||||||
|
bracket
|
||||||
|
)
|
||||||
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)
|
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ const SignIn = () => {
|
|||||||
onClick={signInTauri}
|
onClick={signInTauri}
|
||||||
icon={{ icon: faSignInAlt }}
|
icon={{ icon: faSignInAlt }}
|
||||||
className="w-fit mt-4"
|
className="w-fit mt-4"
|
||||||
|
id="signin"
|
||||||
>
|
>
|
||||||
Sign in
|
Sign in
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
@ -253,11 +253,13 @@ export async function executeAst({
|
|||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
defaultPlanes,
|
defaultPlanes,
|
||||||
useFakeExecutor = false,
|
useFakeExecutor = false,
|
||||||
|
programMemoryOverride,
|
||||||
}: {
|
}: {
|
||||||
ast: Program
|
ast: Program
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
defaultPlanes: DefaultPlanes
|
defaultPlanes: DefaultPlanes
|
||||||
useFakeExecutor?: boolean
|
useFakeExecutor?: boolean
|
||||||
|
programMemoryOverride?: ProgramMemory
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
logs: string[]
|
logs: string[]
|
||||||
errors: KCLError[]
|
errors: KCLError[]
|
||||||
@ -269,10 +271,13 @@ export async function executeAst({
|
|||||||
engineCommandManager.startNewSession()
|
engineCommandManager.startNewSession()
|
||||||
}
|
}
|
||||||
const programMemory = await (useFakeExecutor
|
const programMemory = await (useFakeExecutor
|
||||||
? enginelessExecutor(ast, {
|
? enginelessExecutor(
|
||||||
root: defaultProgramMemory,
|
ast,
|
||||||
return: null,
|
programMemoryOverride || {
|
||||||
})
|
root: defaultProgramMemory,
|
||||||
|
return: null,
|
||||||
|
}
|
||||||
|
)
|
||||||
: _executor(
|
: _executor(
|
||||||
ast,
|
ast,
|
||||||
{
|
{
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
serial-integration = { max-threads = 4 }
|
serial-integration = { max-threads = 4 }
|
||||||
|
|
||||||
[profile.default]
|
[profile.default]
|
||||||
slow-timeout = { period = "60s", terminate-after = 1 }
|
slow-timeout = { period = "10s", terminate-after = 1 }
|
||||||
|
|
||||||
[profile.ci]
|
[profile.ci]
|
||||||
slow-timeout = { period = "120s", terminate-after = 10 }
|
slow-timeout = { period = "30s", terminate-after = 5 }
|
||||||
|
|
||||||
[[profile.default.overrides]]
|
[[profile.default.overrides]]
|
||||||
filter = "test(serial_test_)"
|
filter = "test(serial_test_)"
|
||||||
@ -20,3 +20,7 @@ threads-required = 4
|
|||||||
filter = "test(serial_test_)"
|
filter = "test(serial_test_)"
|
||||||
test-group = "serial-integration"
|
test-group = "serial-integration"
|
||||||
threads-required = 4
|
threads-required = 4
|
||||||
|
|
||||||
|
[[profile.default.overrides]]
|
||||||
|
filter = "test(parser::parser_impl::snapshot_tests)"
|
||||||
|
slow-timeout = { period = "1s", terminate-after = 5 }
|
||||||
|
628
src/wasm-lib/Cargo.lock
generated
628
src/wasm-lib/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,8 @@
|
|||||||
name = "wasm-lib"
|
name = "wasm-lib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
rust-version = "1.73"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
[lib]
|
[lib]
|
||||||
@ -11,28 +13,28 @@ crate-type = ["cdylib"]
|
|||||||
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
|
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
|
||||||
gloo-utils = "0.2.0"
|
gloo-utils = "0.2.0"
|
||||||
kcl-lib = { path = "kcl" }
|
kcl-lib = { path = "kcl" }
|
||||||
kittycad = { version = "0.2.33", default-features = false, features = ["js"] }
|
kittycad = { workspace = true }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.108"
|
||||||
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
|
uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
|
||||||
wasm-bindgen = "0.2.87"
|
wasm-bindgen = "0.2.88"
|
||||||
wasm-bindgen-futures = "0.4.37"
|
wasm-bindgen-futures = "0.4.37"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
image = "0.24.7"
|
image = "0.24.7"
|
||||||
kittycad = "0.2.33"
|
kittycad = { workspace = true, default-features = true }
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
reqwest = { version = "0.11.22", default-features = false }
|
reqwest = { version = "0.11.22", default-features = false }
|
||||||
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }
|
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }
|
||||||
twenty-twenty = "0.6.1"
|
twenty-twenty = "0.6.1"
|
||||||
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
|
uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
futures = "0.3.28"
|
futures = "0.3.29"
|
||||||
js-sys = "0.3.64"
|
js-sys = "0.3.65"
|
||||||
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
||||||
wasm-bindgen-futures = { version = "0.4.37", features = ["futures-core-03-stream"] }
|
wasm-bindgen-futures = { version = "0.4.37", features = ["futures-core-03-stream"] }
|
||||||
wasm-streams = "0.3.0"
|
wasm-streams = "0.4.0"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
|
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
|
||||||
version = "0.3.57"
|
version = "0.3.57"
|
||||||
@ -53,6 +55,9 @@ members = [
|
|||||||
"kcl",
|
"kcl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
kittycad = { version = "0.2.41", default-features = false, features = ["js"] }
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "executor"
|
name = "executor"
|
||||||
path = "tests/executor/main.rs"
|
path = "tests/executor/main.rs"
|
||||||
|
@ -4,6 +4,8 @@ description = "A tool for generating documentation from Rust derive macros"
|
|||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
rust-version = "1.73"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@ -14,9 +16,9 @@ proc-macro = true
|
|||||||
convert_case = "0.6.0"
|
convert_case = "0.6.0"
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
serde = { version = "1.0.189", features = ["derive"] }
|
serde = { version = "1.0.192", features = ["derive"] }
|
||||||
serde_tokenstream = "0.2"
|
serde_tokenstream = "0.2"
|
||||||
syn = { version = "2.0.38", features = ["full"] }
|
syn = { version = "2.0.39", features = ["full"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
expectorate = "1.1.0"
|
expectorate = "1.1.0"
|
||||||
|
@ -4,6 +4,8 @@ description = "KittyCAD Language"
|
|||||||
version = "0.1.35"
|
version = "0.1.35"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
rust-version = "1.73"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@ -11,31 +13,31 @@ license = "MIT"
|
|||||||
anyhow = { version = "1.0.75", features = ["backtrace"] }
|
anyhow = { version = "1.0.75", features = ["backtrace"] }
|
||||||
async-recursion = "1.0.5"
|
async-recursion = "1.0.5"
|
||||||
async-trait = "0.1.73"
|
async-trait = "0.1.73"
|
||||||
clap = { version = "4.4.6", features = ["cargo", "derive", "env", "unicode"], optional = true }
|
clap = { version = "4.4.7", features = ["cargo", "derive", "env", "unicode"], optional = true }
|
||||||
dashmap = "5.5.3"
|
dashmap = "5.5.3"
|
||||||
derive-docs = { version = "0.1.4" }
|
derive-docs = { version = "0.1.4" }
|
||||||
#derive-docs = { path = "../derive-docs" }
|
#derive-docs = { path = "../derive-docs" }
|
||||||
kittycad = { version = "0.2.33", default-features = false, features = ["js"] }
|
kittycad = { workspace = true }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
parse-display = "0.8.2"
|
parse-display = "0.8.2"
|
||||||
schemars = { version = "0.8", features = ["impl_json_schema", "url", "uuid1"] }
|
schemars = { version = "0.8", features = ["impl_json_schema", "url", "uuid1"] }
|
||||||
serde = { version = "1.0.189", features = ["derive"] }
|
serde = { version = "1.0.192", features = ["derive"] }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.108"
|
||||||
thiserror = "1.0.49"
|
thiserror = "1.0.50"
|
||||||
ts-rs = { version = "7", package = "ts-rs-json-value", features = ["serde-json-impl", "schemars-impl", "uuid-impl"] }
|
ts-rs = { version = "7", package = "ts-rs-json-value", features = ["serde-json-impl", "schemars-impl", "uuid-impl"] }
|
||||||
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
|
uuid = { version = "1.5.0", features = ["v4", "js", "serde"] }
|
||||||
winnow = "0.5.16"
|
winnow = "0.5.18"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
js-sys = { version = "0.3.64" }
|
js-sys = { version = "0.3.65" }
|
||||||
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
||||||
wasm-bindgen = "0.2.87"
|
wasm-bindgen = "0.2.88"
|
||||||
wasm-bindgen-futures = "0.4.37"
|
wasm-bindgen-futures = "0.4.37"
|
||||||
web-sys = { version = "0.3.64", features = ["console"] }
|
web-sys = { version = "0.3.64", features = ["console"] }
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
|
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
|
||||||
futures = { version = "0.3.28" }
|
futures = { version = "0.3.29" }
|
||||||
reqwest = { version = "0.11.22", default-features = false }
|
reqwest = { version = "0.11.22", default-features = false }
|
||||||
tokio = { version = "1.33.0", features = ["full"] }
|
tokio = { version = "1.33.0", features = ["full"] }
|
||||||
tokio-tungstenite = { version = "0.20.0", features = ["rustls-tls-native-roots"] }
|
tokio-tungstenite = { version = "0.20.0", features = ["rustls-tls-native-roots"] }
|
||||||
@ -50,9 +52,13 @@ engine = []
|
|||||||
panic = "abort"
|
panic = "abort"
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
debug = true # Flamegraphs of benchmarks require accurate debug symbols
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.5.1"
|
criterion = "0.5.1"
|
||||||
expectorate = "1.1.0"
|
expectorate = "1.1.0"
|
||||||
|
insta = { version = "1.34.0", features = ["json"] }
|
||||||
itertools = "0.11.0"
|
itertools = "0.11.0"
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }
|
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "time"] }
|
||||||
|
@ -11,6 +11,7 @@ pub fn bench_parse(c: &mut Criterion) {
|
|||||||
("pipes_on_pipes", PIPES_PROGRAM),
|
("pipes_on_pipes", PIPES_PROGRAM),
|
||||||
("big_kitt", KITT_PROGRAM),
|
("big_kitt", KITT_PROGRAM),
|
||||||
("cube", CUBE_PROGRAM),
|
("cube", CUBE_PROGRAM),
|
||||||
|
("math", MATH_PROGRAM),
|
||||||
] {
|
] {
|
||||||
let tokens = kcl_lib::token::lexer(file);
|
let tokens = kcl_lib::token::lexer(file);
|
||||||
c.bench_function(&format!("parse_{name}"), move |b| {
|
c.bench_function(&format!("parse_{name}"), move |b| {
|
||||||
@ -33,3 +34,4 @@ criterion_main!(benches);
|
|||||||
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
||||||
const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl");
|
const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl");
|
||||||
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
||||||
|
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
||||||
|
@ -3,6 +3,8 @@ name = "kcl-lib-fuzz"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
publish = false
|
publish = false
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
rust-version = "1.73"
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
cargo-fuzz = true
|
cargo-fuzz = true
|
||||||
|
@ -136,7 +136,7 @@ pub async fn modify_ast_for_sketch(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut additional_lines = Vec::new();
|
let mut additional_lines = Vec::new();
|
||||||
let mut last_point = first_control_points.points[1].clone();
|
let mut last_point = first_control_points.points[1];
|
||||||
for control_point in control_points[1..].iter() {
|
for control_point in control_points[1..].iter() {
|
||||||
additional_lines.push([
|
additional_lines.push([
|
||||||
(control_point.points[1].x - last_point.x),
|
(control_point.points[1].x - last_point.x),
|
||||||
|
@ -6,15 +6,20 @@ use anyhow::Result;
|
|||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Map;
|
use serde_json::{Map, Value as JValue};
|
||||||
use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, DocumentSymbol, Range as LspRange, SymbolKind};
|
use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, DocumentSymbol, Range as LspRange, SymbolKind};
|
||||||
|
|
||||||
|
pub use self::literal_value::LiteralValue;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
docs::StdLibFn,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, UserVal},
|
executor::{BodyType, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, UserVal},
|
||||||
parser::PIPE_OPERATOR,
|
parser::PIPE_OPERATOR,
|
||||||
|
std::{kcl_stdlib::KclStdLibFn, FunctionKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod literal_value;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@ -371,13 +376,13 @@ impl BodyItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BodyItem> for crate::executor::SourceRange {
|
impl From<BodyItem> for SourceRange {
|
||||||
fn from(item: BodyItem) -> Self {
|
fn from(item: BodyItem) -> Self {
|
||||||
Self([item.start(), item.end()])
|
Self([item.start(), item.end()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&BodyItem> for crate::executor::SourceRange {
|
impl From<&BodyItem> for SourceRange {
|
||||||
fn from(item: &BodyItem) -> Self {
|
fn from(item: &BodyItem) -> Self {
|
||||||
Self([item.start(), item.end()])
|
Self([item.start(), item.end()])
|
||||||
}
|
}
|
||||||
@ -534,13 +539,13 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Value> for crate::executor::SourceRange {
|
impl From<Value> for SourceRange {
|
||||||
fn from(value: Value) -> Self {
|
fn from(value: Value) -> Self {
|
||||||
Self([value.start(), value.end()])
|
Self([value.start(), value.end()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Value> for crate::executor::SourceRange {
|
impl From<&Value> for SourceRange {
|
||||||
fn from(value: &Value) -> Self {
|
fn from(value: &Value) -> Self {
|
||||||
Self([value.start(), value.end()])
|
Self([value.start(), value.end()])
|
||||||
}
|
}
|
||||||
@ -558,13 +563,13 @@ pub enum BinaryPart {
|
|||||||
MemberExpression(Box<MemberExpression>),
|
MemberExpression(Box<MemberExpression>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BinaryPart> for crate::executor::SourceRange {
|
impl From<BinaryPart> for SourceRange {
|
||||||
fn from(value: BinaryPart) -> Self {
|
fn from(value: BinaryPart) -> Self {
|
||||||
Self([value.start(), value.end()])
|
Self([value.start(), value.end()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&BinaryPart> for crate::executor::SourceRange {
|
impl From<&BinaryPart> for SourceRange {
|
||||||
fn from(value: &BinaryPart) -> Self {
|
fn from(value: &BinaryPart) -> Self {
|
||||||
Self([value.start(), value.end()])
|
Self([value.start(), value.end()])
|
||||||
}
|
}
|
||||||
@ -640,7 +645,7 @@ impl BinaryPart {
|
|||||||
pipe_info: &mut PipeInfo,
|
pipe_info: &mut PipeInfo,
|
||||||
ctx: &ExecutorContext,
|
ctx: &ExecutorContext,
|
||||||
) -> Result<MemoryItem, KclError> {
|
) -> Result<MemoryItem, KclError> {
|
||||||
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
// We DO NOT set this globally because if we did and this was called inside a pipe it would
|
||||||
// stop the execution of the pipe.
|
// stop the execution of the pipe.
|
||||||
// THIS IS IMPORTANT.
|
// THIS IS IMPORTANT.
|
||||||
let mut new_pipe_info = pipe_info.clone();
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
@ -780,7 +785,7 @@ pub enum NonCodeValue {
|
|||||||
/// 1 + 1
|
/// 1 + 1
|
||||||
/// ```
|
/// ```
|
||||||
/// Now this is important. The block comment is attached to the next line.
|
/// Now this is important. The block comment is attached to the next line.
|
||||||
/// This is always the case. Also the block comment doesnt have a new line above it.
|
/// This is always the case. Also the block comment doesn't have a new line above it.
|
||||||
/// If it did it would be a `NewLineBlockComment`.
|
/// If it did it would be a `NewLineBlockComment`.
|
||||||
BlockComment {
|
BlockComment {
|
||||||
value: String,
|
value: String,
|
||||||
@ -858,7 +863,6 @@ pub struct CallExpression {
|
|||||||
pub callee: Identifier,
|
pub callee: Identifier,
|
||||||
pub arguments: Vec<Value>,
|
pub arguments: Vec<Value>,
|
||||||
pub optional: bool,
|
pub optional: bool,
|
||||||
pub function: Function,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_value_meta!(CallExpression);
|
impl_value_meta!(CallExpression);
|
||||||
@ -871,22 +875,12 @@ impl From<CallExpression> for Value {
|
|||||||
|
|
||||||
impl CallExpression {
|
impl CallExpression {
|
||||||
pub fn new(name: &str, arguments: Vec<Value>) -> Result<Self, KclError> {
|
pub fn new(name: &str, arguments: Vec<Value>) -> Result<Self, KclError> {
|
||||||
// Create our stdlib.
|
|
||||||
let stdlib = crate::std::StdLib::new();
|
|
||||||
let func = stdlib.get(name).ok_or_else(|| {
|
|
||||||
KclError::UndefinedValue(KclErrorDetails {
|
|
||||||
message: format!("Function {} is not defined", name),
|
|
||||||
source_ranges: vec![],
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 0,
|
end: 0,
|
||||||
callee: Identifier::new(name),
|
callee: Identifier::new(name),
|
||||||
arguments,
|
arguments,
|
||||||
optional: false,
|
optional: false,
|
||||||
function: Function::StdLib { func },
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,7 +924,7 @@ impl CallExpression {
|
|||||||
binary_expression.get_result(memory, pipe_info, ctx).await?
|
binary_expression.get_result(memory, pipe_info, ctx).await?
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
// We DO NOT set this globally because if we did and this was called inside a pipe it would
|
||||||
// stop the execution of the pipe.
|
// stop the execution of the pipe.
|
||||||
// THIS IS IMPORTANT.
|
// THIS IS IMPORTANT.
|
||||||
let mut new_pipe_info = pipe_info.clone();
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
@ -968,8 +962,8 @@ impl CallExpression {
|
|||||||
fn_args.push(result);
|
fn_args.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
match &self.function {
|
match ctx.stdlib.get_either(&self.callee.name) {
|
||||||
Function::StdLib { func } => {
|
FunctionKind::Core(func) => {
|
||||||
// Attempt to call the function.
|
// Attempt to call the function.
|
||||||
let args = crate::std::Args::new(fn_args, self.into(), ctx.clone());
|
let args = crate::std::Args::new(fn_args, self.into(), ctx.clone());
|
||||||
let result = func.std_lib_fn()(args).await?;
|
let result = func.std_lib_fn()(args).await?;
|
||||||
@ -981,14 +975,54 @@ impl CallExpression {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Function::InMemory => {
|
FunctionKind::Std(func) => {
|
||||||
|
let function_expression = func.function();
|
||||||
|
if fn_args.len() != function_expression.params.len() {
|
||||||
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
|
message: format!(
|
||||||
|
"Expected {} arguments, got {}",
|
||||||
|
function_expression.params.len(),
|
||||||
|
fn_args.len(),
|
||||||
|
),
|
||||||
|
source_ranges: vec![(function_expression).into()],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the arguments to the memory.
|
||||||
|
let mut fn_memory = memory.clone();
|
||||||
|
for (index, param) in function_expression.params.iter().enumerate() {
|
||||||
|
fn_memory.add(¶m.name, fn_args.get(index).unwrap().clone(), param.into())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the stdlib function
|
||||||
|
let p = func.function().clone().body;
|
||||||
|
let results = crate::executor::execute(p, &mut fn_memory, BodyType::Block, ctx).await?;
|
||||||
|
let out = results.return_;
|
||||||
|
let result = out.ok_or_else(|| {
|
||||||
|
KclError::UndefinedValue(KclErrorDetails {
|
||||||
|
message: format!("Result of stdlib function {} is undefined", fn_name),
|
||||||
|
source_ranges: vec![self.into()],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
let result = result.get_value()?;
|
||||||
|
|
||||||
|
if pipe_info.is_in_pipe {
|
||||||
|
pipe_info.index += 1;
|
||||||
|
pipe_info.previous_results.push(result);
|
||||||
|
|
||||||
|
execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), ctx).await
|
||||||
|
} else {
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FunctionKind::UserDefined => {
|
||||||
let func = memory.get(&fn_name, self.into())?;
|
let func = memory.get(&fn_name, self.into())?;
|
||||||
let result = func
|
let result = func
|
||||||
.call_fn(fn_args, memory.clone(), ctx.clone())
|
.call_fn(fn_args, memory.clone(), ctx.clone())
|
||||||
.await?
|
.await?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::UndefinedValue(KclErrorDetails {
|
KclError::UndefinedValue(KclErrorDetails {
|
||||||
message: format!("Result of function {} is undefined", fn_name),
|
message: format!("Result of user-defined function {} is undefined", fn_name),
|
||||||
source_ranges: vec![self.into()],
|
source_ranges: vec![self.into()],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -1063,10 +1097,15 @@ impl CallExpression {
|
|||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum Function {
|
pub enum Function {
|
||||||
/// A stdlib function.
|
/// A stdlib function written in Rust (aka core lib).
|
||||||
StdLib {
|
StdLib {
|
||||||
/// The function.
|
/// The function.
|
||||||
func: Box<dyn crate::docs::StdLibFn>,
|
func: Box<dyn StdLibFn>,
|
||||||
|
},
|
||||||
|
/// A stdlib function written in KCL.
|
||||||
|
StdLibKcl {
|
||||||
|
/// The function.
|
||||||
|
func: Box<dyn KclStdLibFn>,
|
||||||
},
|
},
|
||||||
/// A function that is defined in memory.
|
/// A function that is defined in memory.
|
||||||
#[default]
|
#[default]
|
||||||
@ -1312,24 +1351,18 @@ impl VariableDeclarator {
|
|||||||
pub struct Literal {
|
pub struct Literal {
|
||||||
pub start: usize,
|
pub start: usize,
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
pub value: serde_json::Value,
|
pub value: LiteralValue,
|
||||||
pub raw: String,
|
pub raw: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_value_meta!(Literal);
|
impl_value_meta!(Literal);
|
||||||
|
|
||||||
impl From<Literal> for Value {
|
|
||||||
fn from(literal: Literal) -> Self {
|
|
||||||
Value::Literal(Box::new(literal))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Literal {
|
impl Literal {
|
||||||
pub fn new(value: serde_json::Value) -> Self {
|
pub fn new(value: LiteralValue) -> Self {
|
||||||
Self {
|
Self {
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 0,
|
end: 0,
|
||||||
raw: value.to_string(),
|
raw: JValue::from(value.clone()).to_string(),
|
||||||
value,
|
value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1343,11 +1376,19 @@ impl Literal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn recast(&self) -> String {
|
fn recast(&self) -> String {
|
||||||
if let serde_json::Value::String(value) = &self.value {
|
match self.value {
|
||||||
let quote = if self.raw.trim().starts_with('"') { '"' } else { '\'' };
|
LiteralValue::Fractional(x) => {
|
||||||
format!("{}{}{}", quote, value, quote)
|
if x.fract() == 0.0 {
|
||||||
} else {
|
format!("{x:?}")
|
||||||
self.value.to_string()
|
} else {
|
||||||
|
self.raw.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LiteralValue::IInteger(_) => self.raw.clone(),
|
||||||
|
LiteralValue::String(ref s) => {
|
||||||
|
let quote = if self.raw.trim().starts_with('"') { '"' } else { '\'' };
|
||||||
|
format!("{quote}{s}{quote}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1355,7 +1396,7 @@ impl Literal {
|
|||||||
impl From<Literal> for MemoryItem {
|
impl From<Literal> for MemoryItem {
|
||||||
fn from(literal: Literal) -> Self {
|
fn from(literal: Literal) -> Self {
|
||||||
MemoryItem::UserVal(UserVal {
|
MemoryItem::UserVal(UserVal {
|
||||||
value: literal.value.clone(),
|
value: JValue::from(literal.value.clone()),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: literal.into(),
|
source_range: literal.into(),
|
||||||
}],
|
}],
|
||||||
@ -1366,7 +1407,7 @@ impl From<Literal> for MemoryItem {
|
|||||||
impl From<&Box<Literal>> for MemoryItem {
|
impl From<&Box<Literal>> for MemoryItem {
|
||||||
fn from(literal: &Box<Literal>) -> Self {
|
fn from(literal: &Box<Literal>) -> Self {
|
||||||
MemoryItem::UserVal(UserVal {
|
MemoryItem::UserVal(UserVal {
|
||||||
value: literal.value.clone(),
|
value: JValue::from(literal.value.clone()),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: literal.into(),
|
source_range: literal.into(),
|
||||||
}],
|
}],
|
||||||
@ -1552,7 +1593,7 @@ impl ArrayExpression {
|
|||||||
binary_expression.get_result(memory, pipe_info, ctx).await?
|
binary_expression.get_result(memory, pipe_info, ctx).await?
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
// We DO NOT set this globally because if we did and this was called inside a pipe it would
|
||||||
// stop the execution of the pipe.
|
// stop the execution of the pipe.
|
||||||
// THIS IS IMPORTANT.
|
// THIS IS IMPORTANT.
|
||||||
let mut new_pipe_info = pipe_info.clone();
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
@ -1703,7 +1744,7 @@ impl ObjectExpression {
|
|||||||
binary_expression.get_result(memory, pipe_info, ctx).await?
|
binary_expression.get_result(memory, pipe_info, ctx).await?
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
// We DO NOT set this globally because if we did and this was called inside a pipe it would
|
||||||
// stop the execution of the pipe.
|
// stop the execution of the pipe.
|
||||||
// THIS IS IMPORTANT.
|
// THIS IS IMPORTANT.
|
||||||
let mut new_pipe_info = pipe_info.clone();
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
@ -1831,13 +1872,13 @@ impl MemberObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MemberObject> for crate::executor::SourceRange {
|
impl From<MemberObject> for SourceRange {
|
||||||
fn from(obj: MemberObject) -> Self {
|
fn from(obj: MemberObject) -> Self {
|
||||||
Self([obj.start(), obj.end()])
|
Self([obj.start(), obj.end()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&MemberObject> for crate::executor::SourceRange {
|
impl From<&MemberObject> for SourceRange {
|
||||||
fn from(obj: &MemberObject) -> Self {
|
fn from(obj: &MemberObject) -> Self {
|
||||||
Self([obj.start(), obj.end()])
|
Self([obj.start(), obj.end()])
|
||||||
}
|
}
|
||||||
@ -1867,13 +1908,13 @@ impl LiteralIdentifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LiteralIdentifier> for crate::executor::SourceRange {
|
impl From<LiteralIdentifier> for SourceRange {
|
||||||
fn from(id: LiteralIdentifier) -> Self {
|
fn from(id: LiteralIdentifier) -> Self {
|
||||||
Self([id.start(), id.end()])
|
Self([id.start(), id.end()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&LiteralIdentifier> for crate::executor::SourceRange {
|
impl From<&LiteralIdentifier> for SourceRange {
|
||||||
fn from(id: &LiteralIdentifier) -> Self {
|
fn from(id: &LiteralIdentifier) -> Self {
|
||||||
Self([id.start(), id.end()])
|
Self([id.start(), id.end()])
|
||||||
}
|
}
|
||||||
@ -1967,17 +2008,21 @@ impl MemberExpression {
|
|||||||
LiteralIdentifier::Identifier(identifier) => identifier.name.to_string(),
|
LiteralIdentifier::Identifier(identifier) => identifier.name.to_string(),
|
||||||
LiteralIdentifier::Literal(literal) => {
|
LiteralIdentifier::Literal(literal) => {
|
||||||
let value = literal.value.clone();
|
let value = literal.value.clone();
|
||||||
// Parse this as a string.
|
match value {
|
||||||
if let serde_json::Value::String(string) = value {
|
LiteralValue::IInteger(x) if x >= 0 => return self.get_result_array(memory, x as usize),
|
||||||
string
|
LiteralValue::IInteger(x) => {
|
||||||
} else if let serde_json::Value::Number(_) = &value {
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
// It can also be a number if we are getting a member of an array.
|
source_ranges: vec![self.into()],
|
||||||
return self.get_result_array(memory, parse_json_number_as_usize(&value, self.into())?);
|
message: format!("invalid index: {x}"),
|
||||||
} else {
|
}))
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
}
|
||||||
message: format!("Expected string literal or number for property name, found {:?}", value),
|
LiteralValue::Fractional(x) => {
|
||||||
source_ranges: vec![literal.into()],
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
}));
|
source_ranges: vec![self.into()],
|
||||||
|
message: format!("invalid index: {x}"),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
LiteralValue::String(s) => s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2133,7 +2178,7 @@ impl BinaryExpression {
|
|||||||
pipe_info: &mut PipeInfo,
|
pipe_info: &mut PipeInfo,
|
||||||
ctx: &ExecutorContext,
|
ctx: &ExecutorContext,
|
||||||
) -> Result<MemoryItem, KclError> {
|
) -> Result<MemoryItem, KclError> {
|
||||||
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
// We DO NOT set this globally because if we did and this was called inside a pipe it would
|
||||||
// stop the execution of the pipe.
|
// stop the execution of the pipe.
|
||||||
// THIS IS IMPORTANT.
|
// THIS IS IMPORTANT.
|
||||||
let mut new_pipe_info = pipe_info.clone();
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
@ -2175,6 +2220,7 @@ impl BinaryExpression {
|
|||||||
BinaryOperator::Mul => (left * right).into(),
|
BinaryOperator::Mul => (left * right).into(),
|
||||||
BinaryOperator::Div => (left / right).into(),
|
BinaryOperator::Div => (left / right).into(),
|
||||||
BinaryOperator::Mod => (left % right).into(),
|
BinaryOperator::Mod => (left % right).into(),
|
||||||
|
BinaryOperator::Pow => (left.powf(right)).into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(MemoryItem::UserVal(UserVal {
|
Ok(MemoryItem::UserVal(UserVal {
|
||||||
@ -2208,22 +2254,6 @@ pub fn parse_json_number_as_f64(j: &serde_json::Value, source_range: SourceRange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_json_number_as_usize(j: &serde_json::Value, source_range: SourceRange) -> Result<usize, KclError> {
|
|
||||||
if let serde_json::Value::Number(n) = &j {
|
|
||||||
Ok(n.as_i64().ok_or_else(|| {
|
|
||||||
KclError::Syntax(KclErrorDetails {
|
|
||||||
source_ranges: vec![source_range],
|
|
||||||
message: format!("Invalid index: {}", j),
|
|
||||||
})
|
|
||||||
})? as usize)
|
|
||||||
} else {
|
|
||||||
Err(KclError::Syntax(KclErrorDetails {
|
|
||||||
source_ranges: vec![source_range],
|
|
||||||
message: format!("Invalid index: {}", j),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_json_value_as_string(j: &serde_json::Value) -> Option<String> {
|
pub fn parse_json_value_as_string(j: &serde_json::Value) -> Option<String> {
|
||||||
if let serde_json::Value::String(n) = &j {
|
if let serde_json::Value::String(n) = &j {
|
||||||
Some(n.clone())
|
Some(n.clone())
|
||||||
@ -2257,13 +2287,46 @@ pub enum BinaryOperator {
|
|||||||
#[serde(rename = "%")]
|
#[serde(rename = "%")]
|
||||||
#[display("%")]
|
#[display("%")]
|
||||||
Mod,
|
Mod,
|
||||||
|
/// Raise a number to a power.
|
||||||
|
#[serde(rename = "^")]
|
||||||
|
#[display("^")]
|
||||||
|
Pow,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mathematical associativity.
|
||||||
|
/// Should a . b . c be read as (a . b) . c, or a . (b . c)
|
||||||
|
/// See <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#precedence_and_associativity> for more.
|
||||||
|
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
|
||||||
|
pub enum Associativity {
|
||||||
|
/// Read a . b . c as (a . b) . c
|
||||||
|
Left,
|
||||||
|
/// Read a . b . c as a . (b . c)
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Associativity {
|
||||||
|
pub fn is_left(&self) -> bool {
|
||||||
|
matches!(self, Self::Left)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryOperator {
|
impl BinaryOperator {
|
||||||
|
/// Follow JS definitions of each operator.
|
||||||
|
/// Taken from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table>
|
||||||
pub fn precedence(&self) -> u8 {
|
pub fn precedence(&self) -> u8 {
|
||||||
match &self {
|
match &self {
|
||||||
BinaryOperator::Add | BinaryOperator::Sub => 11,
|
BinaryOperator::Add | BinaryOperator::Sub => 11,
|
||||||
BinaryOperator::Mul | BinaryOperator::Div | BinaryOperator::Mod => 12,
|
BinaryOperator::Mul | BinaryOperator::Div | BinaryOperator::Mod => 12,
|
||||||
|
BinaryOperator::Pow => 6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Follow JS definitions of each operator.
|
||||||
|
/// Taken from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table>
|
||||||
|
pub fn associativity(&self) -> Associativity {
|
||||||
|
match self {
|
||||||
|
Self::Add | Self::Sub | Self::Mul | Self::Div | Self::Mod => Associativity::Left,
|
||||||
|
Self::Pow => Associativity::Right,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2307,7 +2370,7 @@ impl UnaryExpression {
|
|||||||
pipe_info: &mut PipeInfo,
|
pipe_info: &mut PipeInfo,
|
||||||
ctx: &ExecutorContext,
|
ctx: &ExecutorContext,
|
||||||
) -> Result<MemoryItem, KclError> {
|
) -> Result<MemoryItem, KclError> {
|
||||||
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
// We DO NOT set this globally because if we did and this was called inside a pipe it would
|
||||||
// stop the execution of the pipe.
|
// stop the execution of the pipe.
|
||||||
// THIS IS IMPORTANT.
|
// THIS IS IMPORTANT.
|
||||||
let mut new_pipe_info = pipe_info.clone();
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
@ -3255,4 +3318,40 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#;
|
|||||||
let recasted = program.recast(&Default::default(), 0);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted.trim(), some_program_string);
|
assert_eq!(recasted.trim(), some_program_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn recast_literal() {
|
||||||
|
use winnow::Parser;
|
||||||
|
for (i, (raw, expected, reason)) in [
|
||||||
|
(
|
||||||
|
"5.0",
|
||||||
|
"5.0",
|
||||||
|
"fractional numbers should stay fractional, i.e. don't reformat this to '5'",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"5",
|
||||||
|
"5",
|
||||||
|
"integers should stay integral, i.e. don't reformat this to '5.0'",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"5.0000000",
|
||||||
|
"5.0",
|
||||||
|
"if the number is f64 but not fractional, use its canonical format",
|
||||||
|
),
|
||||||
|
("5.1", "5.1", "straightforward case works"),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
let tokens = crate::token::lexer(raw);
|
||||||
|
let literal = crate::parser::parser_impl::unsigned_number_literal
|
||||||
|
.parse(&tokens)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
literal.recast(),
|
||||||
|
expected,
|
||||||
|
"failed test {i}, which is testing that {reason}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
70
src/wasm-lib/kcl/src/ast/types/literal_value.rs
Normal file
70
src/wasm-lib/kcl/src/ast/types/literal_value.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value as JValue;
|
||||||
|
|
||||||
|
use super::{Literal, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(untagged, rename_all = "snake_case")]
|
||||||
|
pub enum LiteralValue {
|
||||||
|
IInteger(i64),
|
||||||
|
Fractional(f64),
|
||||||
|
String(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Literal> for Value {
|
||||||
|
fn from(literal: Literal) -> Self {
|
||||||
|
Value::Literal(Box::new(literal))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LiteralValue> for JValue {
|
||||||
|
fn from(value: LiteralValue) -> Self {
|
||||||
|
match value {
|
||||||
|
LiteralValue::IInteger(x) => x.into(),
|
||||||
|
LiteralValue::Fractional(x) => x.into(),
|
||||||
|
LiteralValue::String(x) => x.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f64> for LiteralValue {
|
||||||
|
fn from(value: f64) -> Self {
|
||||||
|
Self::Fractional(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for LiteralValue {
|
||||||
|
fn from(value: i64) -> Self {
|
||||||
|
Self::IInteger(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for LiteralValue {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
Self::String(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for LiteralValue {
|
||||||
|
fn from(value: u32) -> Self {
|
||||||
|
Self::IInteger(value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<u16> for LiteralValue {
|
||||||
|
fn from(value: u16) -> Self {
|
||||||
|
Self::IInteger(value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<u8> for LiteralValue {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
Self::IInteger(value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&'static str> for LiteralValue {
|
||||||
|
fn from(value: &'static str) -> Self {
|
||||||
|
// TODO: Make this Cow<str>
|
||||||
|
Self::String(value.to_owned())
|
||||||
|
}
|
||||||
|
}
|
@ -193,7 +193,7 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_signature_help(&self) -> SignatureHelp {
|
fn to_signature_help(&self) -> SignatureHelp {
|
||||||
// Fill this in based on the current positon of the cursor.
|
// Fill this in based on the current position of the cursor.
|
||||||
let active_parameter = None;
|
let active_parameter = None;
|
||||||
|
|
||||||
SignatureHelp {
|
SignatureHelp {
|
||||||
|
@ -8,6 +8,8 @@ use crate::executor::SourceRange;
|
|||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||||
pub enum KclError {
|
pub enum KclError {
|
||||||
|
#[error("lexical: {0:?}")]
|
||||||
|
Lexical(KclErrorDetails),
|
||||||
#[error("syntax: {0:?}")]
|
#[error("syntax: {0:?}")]
|
||||||
Syntax(KclErrorDetails),
|
Syntax(KclErrorDetails),
|
||||||
#[error("semantic: {0:?}")]
|
#[error("semantic: {0:?}")]
|
||||||
@ -26,6 +28,8 @@ pub enum KclError {
|
|||||||
InvalidExpression(KclErrorDetails),
|
InvalidExpression(KclErrorDetails),
|
||||||
#[error("engine: {0:?}")]
|
#[error("engine: {0:?}")]
|
||||||
Engine(KclErrorDetails),
|
Engine(KclErrorDetails),
|
||||||
|
#[error("internal error, please report to KittyCAD team: {0:?}")]
|
||||||
|
Internal(KclErrorDetails),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, ts_rs::TS, Clone)]
|
#[derive(Debug, Serialize, Deserialize, ts_rs::TS, Clone)]
|
||||||
@ -40,20 +44,8 @@ pub struct KclErrorDetails {
|
|||||||
impl KclError {
|
impl KclError {
|
||||||
/// Get the error message, line and column from the error and input code.
|
/// Get the error message, line and column from the error and input code.
|
||||||
pub fn get_message_line_column(&self, input: &str) -> (String, Option<usize>, Option<usize>) {
|
pub fn get_message_line_column(&self, input: &str) -> (String, Option<usize>, Option<usize>) {
|
||||||
let (type_, source_range, message) = match &self {
|
|
||||||
KclError::Syntax(e) => ("syntax", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::Semantic(e) => ("semantic", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::Type(e) => ("type", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::Unimplemented(e) => ("unimplemented", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::Unexpected(e) => ("unexpected", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::ValueAlreadyDefined(e) => ("value already defined", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::UndefinedValue(e) => ("undefined value", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::InvalidExpression(e) => ("invalid expression", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
KclError::Engine(e) => ("engine", e.source_ranges.clone(), e.message.clone()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate the line and column of the error from the source range.
|
// Calculate the line and column of the error from the source range.
|
||||||
let (line, column) = if let Some(range) = source_range.first() {
|
let (line, column) = if let Some(range) = self.source_ranges().first() {
|
||||||
let line = input[..range.0[0]].lines().count();
|
let line = input[..range.0[0]].lines().count();
|
||||||
let column = input[..range.0[0]].lines().last().map(|l| l.len()).unwrap_or_default();
|
let column = input[..range.0[0]].lines().last().map(|l| l.len()).unwrap_or_default();
|
||||||
|
|
||||||
@ -62,11 +54,28 @@ impl KclError {
|
|||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
(format!("{}: {}", type_, message), line, column)
|
(format!("{}: {}", self.error_type(), self.message()), line, column)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error_type(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
KclError::Lexical(_) => "lexical",
|
||||||
|
KclError::Syntax(_) => "syntax",
|
||||||
|
KclError::Semantic(_) => "semantic",
|
||||||
|
KclError::Type(_) => "type",
|
||||||
|
KclError::Unimplemented(_) => "unimplemented",
|
||||||
|
KclError::Unexpected(_) => "unexpected",
|
||||||
|
KclError::ValueAlreadyDefined(_) => "value already defined",
|
||||||
|
KclError::UndefinedValue(_) => "undefined value",
|
||||||
|
KclError::InvalidExpression(_) => "invalid expression",
|
||||||
|
KclError::Engine(_) => "engine",
|
||||||
|
KclError::Internal(_) => "internal",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source_ranges(&self) -> Vec<SourceRange> {
|
pub fn source_ranges(&self) -> Vec<SourceRange> {
|
||||||
match &self {
|
match &self {
|
||||||
|
KclError::Lexical(e) => e.source_ranges.clone(),
|
||||||
KclError::Syntax(e) => e.source_ranges.clone(),
|
KclError::Syntax(e) => e.source_ranges.clone(),
|
||||||
KclError::Semantic(e) => e.source_ranges.clone(),
|
KclError::Semantic(e) => e.source_ranges.clone(),
|
||||||
KclError::Type(e) => e.source_ranges.clone(),
|
KclError::Type(e) => e.source_ranges.clone(),
|
||||||
@ -76,12 +85,14 @@ impl KclError {
|
|||||||
KclError::UndefinedValue(e) => e.source_ranges.clone(),
|
KclError::UndefinedValue(e) => e.source_ranges.clone(),
|
||||||
KclError::InvalidExpression(e) => e.source_ranges.clone(),
|
KclError::InvalidExpression(e) => e.source_ranges.clone(),
|
||||||
KclError::Engine(e) => e.source_ranges.clone(),
|
KclError::Engine(e) => e.source_ranges.clone(),
|
||||||
|
KclError::Internal(e) => e.source_ranges.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the inner error message.
|
/// Get the inner error message.
|
||||||
pub fn message(&self) -> &str {
|
pub fn message(&self) -> &str {
|
||||||
match &self {
|
match &self {
|
||||||
|
KclError::Lexical(e) => &e.message,
|
||||||
KclError::Syntax(e) => &e.message,
|
KclError::Syntax(e) => &e.message,
|
||||||
KclError::Semantic(e) => &e.message,
|
KclError::Semantic(e) => &e.message,
|
||||||
KclError::Type(e) => &e.message,
|
KclError::Type(e) => &e.message,
|
||||||
@ -91,6 +102,7 @@ impl KclError {
|
|||||||
KclError::UndefinedValue(e) => &e.message,
|
KclError::UndefinedValue(e) => &e.message,
|
||||||
KclError::InvalidExpression(e) => &e.message,
|
KclError::InvalidExpression(e) => &e.message,
|
||||||
KclError::Engine(e) => &e.message,
|
KclError::Engine(e) => &e.message,
|
||||||
|
KclError::Internal(e) => &e.message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
//! The executor for the AST.
|
//! The executor for the AST.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use async_recursion::async_recursion;
|
||||||
use kittycad::types::{Color, ModelingCmd, Point3D};
|
use kittycad::types::{Color, ModelingCmd, Point3D};
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
@ -10,9 +11,10 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
|
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::types::{BodyItem, Function, FunctionExpression, Value},
|
ast::types::{BodyItem, FunctionExpression, Value},
|
||||||
engine::{EngineConnection, EngineManager},
|
engine::{EngineConnection, EngineManager},
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
|
std::{FunctionKind, StdLib},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
@ -183,7 +185,7 @@ impl DefaultPlanes {
|
|||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::MakePlane {
|
ModelingCmd::MakePlane {
|
||||||
clobber: false,
|
clobber: false,
|
||||||
origin: default_origin.clone(),
|
origin: default_origin,
|
||||||
size: default_size,
|
size: default_size,
|
||||||
x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 },
|
x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 },
|
||||||
y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
|
y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
|
||||||
@ -216,7 +218,7 @@ impl DefaultPlanes {
|
|||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::MakePlane {
|
ModelingCmd::MakePlane {
|
||||||
clobber: false,
|
clobber: false,
|
||||||
origin: default_origin.clone(),
|
origin: default_origin,
|
||||||
size: default_size,
|
size: default_size,
|
||||||
x_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
|
x_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 },
|
||||||
y_axis: Point3D { x: 0.0, y: 0.0, z: 1.0 },
|
y_axis: Point3D { x: 0.0, y: 0.0, z: 1.0 },
|
||||||
@ -347,27 +349,27 @@ impl MemoryItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this memory item is a function, call it with the given arguments, return its val as Ok.
|
||||||
|
/// If it's not a function, return Err.
|
||||||
pub async fn call_fn(
|
pub async fn call_fn(
|
||||||
&self,
|
&self,
|
||||||
args: Vec<MemoryItem>,
|
args: Vec<MemoryItem>,
|
||||||
memory: ProgramMemory,
|
memory: ProgramMemory,
|
||||||
ctx: ExecutorContext,
|
ctx: ExecutorContext,
|
||||||
) -> Result<Option<ProgramReturn>, KclError> {
|
) -> Result<Option<ProgramReturn>, KclError> {
|
||||||
if let MemoryItem::Function { func, expression, meta } = &self {
|
let MemoryItem::Function { func, expression, meta } = &self else {
|
||||||
if let Some(func) = func {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
func(args, memory, expression.clone(), meta.clone(), ctx).await
|
|
||||||
} else {
|
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
message: format!("Not a function: {:?}", expression),
|
|
||||||
source_ranges: vec![],
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
message: "not a in memory function".to_string(),
|
message: "not a in memory function".to_string(),
|
||||||
source_ranges: vec![],
|
source_ranges: vec![],
|
||||||
}))
|
}));
|
||||||
}
|
};
|
||||||
|
let Some(func) = func else {
|
||||||
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
|
message: format!("Not a function: {:?}", expression),
|
||||||
|
source_ranges: vec![],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
func(args, memory, expression.clone(), meta.clone(), ctx).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,9 +778,11 @@ impl Default for PipeInfo {
|
|||||||
pub struct ExecutorContext {
|
pub struct ExecutorContext {
|
||||||
pub engine: EngineConnection,
|
pub engine: EngineConnection,
|
||||||
pub planes: DefaultPlanes,
|
pub planes: DefaultPlanes,
|
||||||
|
pub stdlib: Arc<StdLib>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute a AST's program.
|
/// Execute a AST's program.
|
||||||
|
#[async_recursion(?Send)]
|
||||||
pub async fn execute(
|
pub async fn execute(
|
||||||
program: crate::ast::types::Program,
|
program: crate::ast::types::Program,
|
||||||
memory: &mut ProgramMemory,
|
memory: &mut ProgramMemory,
|
||||||
@ -826,24 +830,37 @@ pub async fn execute(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _show_fn = Box::new(crate::std::Show);
|
let _show_fn = Box::new(crate::std::Show);
|
||||||
if let Function::StdLib { func: _show_fn } = &call_expr.function {
|
match ctx.stdlib.get_either(&call_expr.callee.name) {
|
||||||
if options != BodyType::Root {
|
FunctionKind::Core(func) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
use crate::docs::StdLibFn;
|
||||||
message: "Cannot call show outside of a root".to_string(),
|
if func.name() == _show_fn.name() {
|
||||||
source_ranges: vec![call_expr.into()],
|
if options != BodyType::Root {
|
||||||
}));
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
|
memory.return_ = result;
|
||||||
} else if let Some(func) = memory.clone().root.get(&fn_name) {
|
} else {
|
||||||
let result = func.call_fn(args.clone(), memory.clone(), ctx.clone()).await?;
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
|
message: format!("No such name {} defined", fn_name),
|
||||||
memory.return_ = result;
|
source_ranges: vec![call_expr.into()],
|
||||||
} else {
|
}));
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
}
|
||||||
message: format!("No such name {} defined", fn_name),
|
}
|
||||||
source_ranges: vec![call_expr.into()],
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1011,7 +1028,11 @@ mod tests {
|
|||||||
let mut mem: ProgramMemory = Default::default();
|
let mut mem: ProgramMemory = Default::default();
|
||||||
let engine = EngineConnection::new().await?;
|
let engine = EngineConnection::new().await?;
|
||||||
let planes = DefaultPlanes::new(&engine).await?;
|
let planes = DefaultPlanes::new(&engine).await?;
|
||||||
let ctx = ExecutorContext { engine, planes };
|
let ctx = ExecutorContext {
|
||||||
|
engine,
|
||||||
|
planes,
|
||||||
|
stdlib: Arc::new(StdLib::default()),
|
||||||
|
};
|
||||||
let memory = execute(program, &mut mem, BodyType::Root, &ctx).await?;
|
let memory = execute(program, &mut mem, BodyType::Root, &ctx).await?;
|
||||||
|
|
||||||
Ok(memory)
|
Ok(memory)
|
||||||
|
@ -5,7 +5,6 @@ pub mod docs;
|
|||||||
pub mod engine;
|
pub mod engine;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
pub mod math_parser;
|
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod std;
|
pub mod std;
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
163
src/wasm-lib/kcl/src/parser/math.rs
Normal file
163
src/wasm-lib/kcl/src/parser/math.rs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
use crate::{
|
||||||
|
ast::types::{BinaryExpression, BinaryOperator, BinaryPart},
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
executor::SourceRange,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parses a list of tokens (in infix order, i.e. as the user typed them)
|
||||||
|
/// into a binary expression tree.
|
||||||
|
pub fn parse(infix_tokens: Vec<BinaryExpressionToken>) -> Result<BinaryExpression, KclError> {
|
||||||
|
let rpn = postfix(infix_tokens);
|
||||||
|
evaluate(rpn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses a list of tokens (in postfix order) into a binary expression tree.
|
||||||
|
fn evaluate(rpn: Vec<BinaryExpressionToken>) -> Result<BinaryExpression, KclError> {
|
||||||
|
let source_ranges = source_range(&rpn);
|
||||||
|
let mut operand_stack: Vec<BinaryPart> = Vec::new();
|
||||||
|
let e = KclError::Internal(KclErrorDetails {
|
||||||
|
source_ranges,
|
||||||
|
message: "error parsing binary math expressions".to_owned(),
|
||||||
|
});
|
||||||
|
for item in rpn {
|
||||||
|
let expr = match item {
|
||||||
|
BinaryExpressionToken::Operator(operator) => {
|
||||||
|
let Some(right) = operand_stack.pop() else {
|
||||||
|
return Err(e);
|
||||||
|
};
|
||||||
|
let Some(left) = operand_stack.pop() else {
|
||||||
|
return Err(e);
|
||||||
|
};
|
||||||
|
BinaryPart::BinaryExpression(Box::new(BinaryExpression {
|
||||||
|
start: left.start(),
|
||||||
|
end: right.end(),
|
||||||
|
operator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
BinaryExpressionToken::Operand(o) => o,
|
||||||
|
};
|
||||||
|
operand_stack.push(expr)
|
||||||
|
}
|
||||||
|
if let Some(BinaryPart::BinaryExpression(expr)) = operand_stack.pop() {
|
||||||
|
Ok(*expr)
|
||||||
|
} else {
|
||||||
|
// If this branch is used, the evaluation algorithm has a bug and must be fixed.
|
||||||
|
// This is a programmer error, not a user error.
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source_range(tokens: &[BinaryExpressionToken]) -> Vec<SourceRange> {
|
||||||
|
let sources: Vec<_> = tokens
|
||||||
|
.iter()
|
||||||
|
.filter_map(|op| match op {
|
||||||
|
BinaryExpressionToken::Operator(_) => None,
|
||||||
|
BinaryExpressionToken::Operand(o) => Some((o.start(), o.end())),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
match (sources.first(), sources.last()) {
|
||||||
|
(Some((start, _)), Some((_, end))) => vec![SourceRange([*start, *end])],
|
||||||
|
_ => Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reorders tokens from infix order to postfix order.
|
||||||
|
fn postfix(infix: Vec<BinaryExpressionToken>) -> Vec<BinaryExpressionToken> {
|
||||||
|
let mut operator_stack: Vec<BinaryOperator> = Vec::with_capacity(infix.len());
|
||||||
|
let mut output = Vec::with_capacity(infix.len());
|
||||||
|
for token in infix {
|
||||||
|
match token {
|
||||||
|
BinaryExpressionToken::Operator(o1) => {
|
||||||
|
// From https://en.wikipedia.org/wiki/Shunting_yard_algorithm:
|
||||||
|
// while (
|
||||||
|
// there is an operator o2 at the top of the operator stack which is not a left parenthesis,
|
||||||
|
// and (o2 has greater precedence than o1 or (o1 and o2 have the same precedence and o1 is left-associative))
|
||||||
|
// )
|
||||||
|
// pop o2 from the operator stack into the output queue
|
||||||
|
while let Some(o2) = operator_stack.pop() {
|
||||||
|
if (o2.precedence() > o1.precedence())
|
||||||
|
|| o1.precedence() == o2.precedence() && o1.associativity().is_left()
|
||||||
|
{
|
||||||
|
output.push(BinaryExpressionToken::Operator(o2));
|
||||||
|
} else {
|
||||||
|
operator_stack.push(o2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operator_stack.push(o1);
|
||||||
|
}
|
||||||
|
o @ BinaryExpressionToken::Operand(_) => output.push(o),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// After the while loop, pop the remaining items from the operator stack into the output queue.
|
||||||
|
output.extend(operator_stack.into_iter().rev().map(BinaryExpressionToken::Operator));
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Expressions are made up of operators and operands.
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub enum BinaryExpressionToken {
|
||||||
|
Operator(BinaryOperator),
|
||||||
|
Operand(BinaryPart),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BinaryPart> for BinaryExpressionToken {
|
||||||
|
fn from(value: BinaryPart) -> Self {
|
||||||
|
Self::Operand(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BinaryOperator> for BinaryExpressionToken {
|
||||||
|
fn from(value: BinaryOperator) -> Self {
|
||||||
|
Self::Operator(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::ast::types::Literal;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_and_evaluate() {
|
||||||
|
/// Make a literal
|
||||||
|
fn lit(n: u8) -> BinaryPart {
|
||||||
|
BinaryPart::Literal(Box::new(Literal {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
value: n.into(),
|
||||||
|
raw: n.to_string(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
let tests: Vec<Vec<BinaryExpressionToken>> = vec![
|
||||||
|
// 3 + 4 × 2 ÷ ( 1 − 5 ) ^ 2 ^ 3
|
||||||
|
vec![
|
||||||
|
lit(3).into(),
|
||||||
|
BinaryOperator::Add.into(),
|
||||||
|
lit(4).into(),
|
||||||
|
BinaryOperator::Mul.into(),
|
||||||
|
lit(2).into(),
|
||||||
|
BinaryOperator::Div.into(),
|
||||||
|
BinaryPart::BinaryExpression(Box::new(BinaryExpression {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
operator: BinaryOperator::Sub,
|
||||||
|
left: lit(1),
|
||||||
|
right: lit(5),
|
||||||
|
}))
|
||||||
|
.into(),
|
||||||
|
BinaryOperator::Pow.into(),
|
||||||
|
lit(2).into(),
|
||||||
|
BinaryOperator::Pow.into(),
|
||||||
|
lit(3).into(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
for infix_input in tests {
|
||||||
|
let rpn = postfix(infix_input);
|
||||||
|
let _tree = evaluate(rpn).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 5,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 4,
|
||||||
|
"end": 5,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 3,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 2,
|
||||||
|
"end": 3,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 4,
|
||||||
|
"operator": "-",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 3,
|
||||||
|
"end": 4,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 9,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 4,
|
||||||
|
"end": 9,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 4,
|
||||||
|
"end": 5,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 8,
|
||||||
|
"end": 9,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 11,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 10,
|
||||||
|
"end": 11,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 17,
|
||||||
|
"operator": "/",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 11,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 10,
|
||||||
|
"end": 11,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 16,
|
||||||
|
"end": 17,
|
||||||
|
"value": 4,
|
||||||
|
"raw": "4"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 17,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 6,
|
||||||
|
"end": 17,
|
||||||
|
"operator": "/",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 10,
|
||||||
|
"end": 11,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 16,
|
||||||
|
"end": 17,
|
||||||
|
"value": 4,
|
||||||
|
"raw": "4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 22,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 22,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 18,
|
||||||
|
"operator": "/",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 12,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 7,
|
||||||
|
"end": 8,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 11,
|
||||||
|
"end": 12,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 4,
|
||||||
|
"raw": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 21,
|
||||||
|
"end": 22,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 13,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 8,
|
||||||
|
"end": 13,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 8,
|
||||||
|
"end": 9,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 12,
|
||||||
|
"end": 13,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 44,
|
||||||
|
"operator": "/",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 22,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 18,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 12,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 8,
|
||||||
|
"name": "distance"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 11,
|
||||||
|
"end": 12,
|
||||||
|
"name": "p"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 15,
|
||||||
|
"end": 18,
|
||||||
|
"name": "FOS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 21,
|
||||||
|
"end": 22,
|
||||||
|
"value": 6,
|
||||||
|
"raw": "6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 26,
|
||||||
|
"end": 44,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 26,
|
||||||
|
"end": 36,
|
||||||
|
"name": "sigmaAllow"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 39,
|
||||||
|
"end": 44,
|
||||||
|
"name": "width"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 8,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 7,
|
||||||
|
"end": 8,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,263 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 144,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 143,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 143,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 15,
|
||||||
|
"name": "boxSketch"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"start": 18,
|
||||||
|
"end": 143,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 18,
|
||||||
|
"end": 39,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 18,
|
||||||
|
"end": 31,
|
||||||
|
"name": "startSketchAt"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 32,
|
||||||
|
"end": 38,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 33,
|
||||||
|
"end": 34,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 36,
|
||||||
|
"end": 37,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 47,
|
||||||
|
"end": 63,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 47,
|
||||||
|
"end": 51,
|
||||||
|
"name": "line"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 52,
|
||||||
|
"end": 59,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 53,
|
||||||
|
"end": 54,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 56,
|
||||||
|
"end": 58,
|
||||||
|
"value": 10,
|
||||||
|
"raw": "10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 61,
|
||||||
|
"end": 62
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 71,
|
||||||
|
"end": 96,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 71,
|
||||||
|
"end": 84,
|
||||||
|
"name": "tangentialArc"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 85,
|
||||||
|
"end": 92,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"start": 86,
|
||||||
|
"end": 88,
|
||||||
|
"operator": "-",
|
||||||
|
"argument": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 87,
|
||||||
|
"end": 88,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 90,
|
||||||
|
"end": 91,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 94,
|
||||||
|
"end": 95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 104,
|
||||||
|
"end": 121,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 104,
|
||||||
|
"end": 108,
|
||||||
|
"name": "line"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 109,
|
||||||
|
"end": 117,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 110,
|
||||||
|
"end": 111,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"start": 113,
|
||||||
|
"end": 116,
|
||||||
|
"operator": "-",
|
||||||
|
"argument": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 114,
|
||||||
|
"end": 116,
|
||||||
|
"value": 15,
|
||||||
|
"raw": "15"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 119,
|
||||||
|
"end": 120
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 129,
|
||||||
|
"end": 143,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 129,
|
||||||
|
"end": 136,
|
||||||
|
"name": "extrude"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 137,
|
||||||
|
"end": 139,
|
||||||
|
"value": 10,
|
||||||
|
"raw": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 141,
|
||||||
|
"end": 142
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 17,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 17,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 17,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 8,
|
||||||
|
"name": "sg"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"start": 11,
|
||||||
|
"end": 17,
|
||||||
|
"operator": "-",
|
||||||
|
"argument": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 12,
|
||||||
|
"end": 17,
|
||||||
|
"name": "scale"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 23,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 23,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 23,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 6,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 22,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 9,
|
||||||
|
"end": 20,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 11,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 13,
|
||||||
|
"end": 20,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 19,
|
||||||
|
"operator": "-",
|
||||||
|
"argument": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 18,
|
||||||
|
"end": 19,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,130 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 23,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 23,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 23,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 13,
|
||||||
|
"name": "myArray"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 16,
|
||||||
|
"end": 23,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 4,
|
||||||
|
"raw": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 6,
|
||||||
|
"raw": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 7,
|
||||||
|
"raw": "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 8,
|
||||||
|
"raw": "8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 9,
|
||||||
|
"raw": "9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 10,
|
||||||
|
"raw": "10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 80,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 5,
|
||||||
|
"end": 57,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 8,
|
||||||
|
"end": 57,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 8,
|
||||||
|
"end": 24,
|
||||||
|
"name": "firstPrimeNumber"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "FunctionExpression",
|
||||||
|
"type": "FunctionExpression",
|
||||||
|
"start": 27,
|
||||||
|
"end": 57,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"start": 33,
|
||||||
|
"end": 57,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ReturnStatement",
|
||||||
|
"type": "ReturnStatement",
|
||||||
|
"start": 43,
|
||||||
|
"end": 51,
|
||||||
|
"argument": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 50,
|
||||||
|
"end": 51,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "fn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 62,
|
||||||
|
"end": 80,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 62,
|
||||||
|
"end": 80,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 62,
|
||||||
|
"end": 78,
|
||||||
|
"name": "firstPrimeNumber"
|
||||||
|
},
|
||||||
|
"arguments": [],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 66,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 49,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 3,
|
||||||
|
"end": 49,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 3,
|
||||||
|
"end": 8,
|
||||||
|
"name": "thing"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "FunctionExpression",
|
||||||
|
"type": "FunctionExpression",
|
||||||
|
"start": 11,
|
||||||
|
"end": 49,
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 12,
|
||||||
|
"end": 17,
|
||||||
|
"name": "param"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"start": 22,
|
||||||
|
"end": 49,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ReturnStatement",
|
||||||
|
"type": "ReturnStatement",
|
||||||
|
"start": 32,
|
||||||
|
"end": 43,
|
||||||
|
"argument": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 39,
|
||||||
|
"end": 43,
|
||||||
|
"name": "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "fn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 54,
|
||||||
|
"end": 66,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 54,
|
||||||
|
"end": 66,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 54,
|
||||||
|
"end": 59,
|
||||||
|
"name": "thing"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 60,
|
||||||
|
"end": 65,
|
||||||
|
"name": "false"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,317 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 192,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 192,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 192,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 14,
|
||||||
|
"name": "mySketch"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 192,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 37,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 17,
|
||||||
|
"end": 30,
|
||||||
|
"name": "startSketchAt"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 31,
|
||||||
|
"end": 36,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 32,
|
||||||
|
"end": 33,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 34,
|
||||||
|
"end": 35,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 49,
|
||||||
|
"end": 89,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 49,
|
||||||
|
"end": 55,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 56,
|
||||||
|
"end": 85,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 58,
|
||||||
|
"end": 68,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 58,
|
||||||
|
"end": 60,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 62,
|
||||||
|
"end": 68,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 63,
|
||||||
|
"end": 64,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 66,
|
||||||
|
"end": 67,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 70,
|
||||||
|
"end": 83,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 70,
|
||||||
|
"end": 73,
|
||||||
|
"name": "tag"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 75,
|
||||||
|
"end": 83,
|
||||||
|
"value": "myPath",
|
||||||
|
"raw": "'myPath'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 87,
|
||||||
|
"end": 88
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 101,
|
||||||
|
"end": 118,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 101,
|
||||||
|
"end": 107,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 108,
|
||||||
|
"end": 114,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 109,
|
||||||
|
"end": 110,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 112,
|
||||||
|
"end": 113,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 116,
|
||||||
|
"end": 117
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 130,
|
||||||
|
"end": 172,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 130,
|
||||||
|
"end": 136,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 137,
|
||||||
|
"end": 168,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 139,
|
||||||
|
"end": 148,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 139,
|
||||||
|
"end": 141,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 143,
|
||||||
|
"end": 148,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 144,
|
||||||
|
"end": 145,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 146,
|
||||||
|
"end": 147,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 150,
|
||||||
|
"end": 166,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 150,
|
||||||
|
"end": 153,
|
||||||
|
"name": "tag"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 155,
|
||||||
|
"end": 166,
|
||||||
|
"value": "rightPath",
|
||||||
|
"raw": "\"rightPath\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 170,
|
||||||
|
"end": 171
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 184,
|
||||||
|
"end": 192,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 184,
|
||||||
|
"end": 189,
|
||||||
|
"name": "close"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 190,
|
||||||
|
"end": 191
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 70,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 70,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 70,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 14,
|
||||||
|
"name": "mySketch"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 70,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 37,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 17,
|
||||||
|
"end": 30,
|
||||||
|
"name": "startSketchAt"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 31,
|
||||||
|
"end": 36,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 32,
|
||||||
|
"end": 33,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 34,
|
||||||
|
"end": 35,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 41,
|
||||||
|
"end": 58,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 41,
|
||||||
|
"end": 47,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 48,
|
||||||
|
"end": 54,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 49,
|
||||||
|
"end": 50,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 52,
|
||||||
|
"end": 53,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 56,
|
||||||
|
"end": 57
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 62,
|
||||||
|
"end": 70,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 62,
|
||||||
|
"end": 67,
|
||||||
|
"name": "close"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 68,
|
||||||
|
"end": 69
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 30,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 30,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 30,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"name": "myBox"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 30,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 14,
|
||||||
|
"end": 27,
|
||||||
|
"name": "startSketchAt"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 28,
|
||||||
|
"end": 29,
|
||||||
|
"name": "p"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 26,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 26,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 26,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"name": "myBox"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 26,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 18,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"name": "f"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 16,
|
||||||
|
"end": 17,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 22,
|
||||||
|
"end": 26,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 22,
|
||||||
|
"end": 23,
|
||||||
|
"name": "g"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 24,
|
||||||
|
"end": 25,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 49,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 49,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 49,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"name": "myBox"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 49,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 30,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 14,
|
||||||
|
"end": 27,
|
||||||
|
"name": "startSketchAt"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 28,
|
||||||
|
"end": 29,
|
||||||
|
"name": "p"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 34,
|
||||||
|
"end": 49,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 34,
|
||||||
|
"end": 38,
|
||||||
|
"name": "line"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 39,
|
||||||
|
"end": 45,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 40,
|
||||||
|
"end": 41,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 43,
|
||||||
|
"end": 44,
|
||||||
|
"name": "l"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 47,
|
||||||
|
"end": 48
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 22,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 22,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 22,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 6,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 21,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 9,
|
||||||
|
"end": 19,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 11,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 13,
|
||||||
|
"end": 19,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 36,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 36,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 36,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 6,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 35,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 9,
|
||||||
|
"end": 19,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 11,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 13,
|
||||||
|
"end": 19,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 21,
|
||||||
|
"end": 33,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 21,
|
||||||
|
"end": 25,
|
||||||
|
"name": "from"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 27,
|
||||||
|
"end": 33,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 28,
|
||||||
|
"end": 29,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 31,
|
||||||
|
"end": 32,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 19,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 19,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 19,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 6,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 18,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 8,
|
||||||
|
"end": 17,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 8,
|
||||||
|
"end": 10,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 11,
|
||||||
|
"end": 17,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 12,
|
||||||
|
"end": 13,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 15,
|
||||||
|
"end": 16,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 35,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 35,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 35,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 6,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 34,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 9,
|
||||||
|
"end": 19,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 11,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 13,
|
||||||
|
"end": 19,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 21,
|
||||||
|
"end": 33,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 21,
|
||||||
|
"end": 25,
|
||||||
|
"name": "from"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 27,
|
||||||
|
"end": 33,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 28,
|
||||||
|
"end": 29,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 31,
|
||||||
|
"end": 32,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 35,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 35,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 35,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 6,
|
||||||
|
"name": "lineTo"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start": 7,
|
||||||
|
"end": 34,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 9,
|
||||||
|
"end": 19,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 11,
|
||||||
|
"name": "to"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 13,
|
||||||
|
"end": 19,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 17,
|
||||||
|
"end": 18,
|
||||||
|
"value": 1,
|
||||||
|
"raw": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start": 20,
|
||||||
|
"end": 32,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 20,
|
||||||
|
"end": 24,
|
||||||
|
"name": "from"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 26,
|
||||||
|
"end": 32,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 27,
|
||||||
|
"end": 28,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 30,
|
||||||
|
"end": 31,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 37,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 37,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 37,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 14,
|
||||||
|
"name": "mySketch"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 37,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 17,
|
||||||
|
"end": 30,
|
||||||
|
"name": "startSketchAt"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 31,
|
||||||
|
"end": 36,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 32,
|
||||||
|
"end": 33,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 34,
|
||||||
|
"end": 35,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 28,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 28,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 28,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 3,
|
||||||
|
"name": "log"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 4,
|
||||||
|
"end": 5,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 7,
|
||||||
|
"end": 14,
|
||||||
|
"value": "hello",
|
||||||
|
"raw": "\"hello\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 16,
|
||||||
|
"end": 27,
|
||||||
|
"name": "aIdentifier"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 7,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 7,
|
||||||
|
"expression": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 7,
|
||||||
|
"operator": "+",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 4,
|
||||||
|
"end": 7,
|
||||||
|
"value": "a",
|
||||||
|
"raw": "\"a\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 15,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 15,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 15,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 4,
|
||||||
|
"name": "line"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 5,
|
||||||
|
"end": 11,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 10,
|
||||||
|
"name": "l"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 13,
|
||||||
|
"end": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 90,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 74,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 74,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 14,
|
||||||
|
"name": "cylinder"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 74,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 17,
|
||||||
|
"end": 56,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 17,
|
||||||
|
"end": 39,
|
||||||
|
"name": "unstable_stdlib_circle"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 40,
|
||||||
|
"end": 44,
|
||||||
|
"value": "XY",
|
||||||
|
"raw": "'XY'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"start": 46,
|
||||||
|
"end": 51,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 47,
|
||||||
|
"end": 48,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 49,
|
||||||
|
"end": 50,
|
||||||
|
"value": 0,
|
||||||
|
"raw": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 53,
|
||||||
|
"end": 55,
|
||||||
|
"value": 22,
|
||||||
|
"raw": "22"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 60,
|
||||||
|
"end": 74,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 60,
|
||||||
|
"end": 67,
|
||||||
|
"name": "extrude"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 68,
|
||||||
|
"end": 70,
|
||||||
|
"value": 14,
|
||||||
|
"raw": "14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"start": 72,
|
||||||
|
"end": 73
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 75,
|
||||||
|
"end": 89,
|
||||||
|
"expression": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 75,
|
||||||
|
"end": 89,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 75,
|
||||||
|
"end": 79,
|
||||||
|
"name": "show"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 80,
|
||||||
|
"end": 88,
|
||||||
|
"name": "cylinder"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 36,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 36,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 6,
|
||||||
|
"end": 36,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 11,
|
||||||
|
"name": "myVar"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 36,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 14,
|
||||||
|
"end": 17,
|
||||||
|
"name": "min"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 18,
|
||||||
|
"end": 19,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"start": 22,
|
||||||
|
"end": 35,
|
||||||
|
"operator": "-",
|
||||||
|
"argument": {
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression",
|
||||||
|
"start": 23,
|
||||||
|
"end": 35,
|
||||||
|
"callee": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 23,
|
||||||
|
"end": 29,
|
||||||
|
"name": "legLen"
|
||||||
|
},
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 30,
|
||||||
|
"end": 31,
|
||||||
|
"value": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 33,
|
||||||
|
"end": 34,
|
||||||
|
"value": 4,
|
||||||
|
"raw": "4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user