Compare commits
1 Commits
kcl-0.2.21
...
mike/secon
| Author | SHA1 | Date | |
|---|---|---|---|
| 828a53f215 |
17
.github/workflows/build-test-publish-apps.yml
vendored
@ -25,7 +25,6 @@ jobs:
|
||||
runs-on: ubuntu-22.04 # seperate job on Ubuntu for easy string manipulations (compared to Windows)
|
||||
outputs:
|
||||
version: ${{ steps.export_version.outputs.version }}
|
||||
notes: ${{ steps.export_version.outputs.notes }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@ -54,31 +53,20 @@ jobs:
|
||||
|
||||
# TODO: see if we need to inject updater nightly URL here https://dl.zoo.dev/releases/modeling-app/nightly/last_update.json
|
||||
|
||||
- name: Generate release notes
|
||||
env:
|
||||
NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Non-release build, commit {0}', github.sha) }}
|
||||
run: |
|
||||
echo "$NOTES" > release-notes.md
|
||||
cat release-notes.md
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: prepared-files
|
||||
path: |
|
||||
package.json
|
||||
src/wasm-lib/pkg/wasm_lib*
|
||||
release-notes.md
|
||||
|
||||
- id: export_version
|
||||
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- id: export_notes
|
||||
run: echo "notes=`cat release-notes.md'`" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Prepare electron-builder.yml file for updater test
|
||||
if: ${{ env.CUT_RELEASE_PR == 'true' }}
|
||||
run: |
|
||||
yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/updater-test-release-notes"' electron-builder.yml
|
||||
yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/updater-test"' electron-builder.yml
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@ -119,7 +107,6 @@ jobs:
|
||||
cp prepared-files/src/wasm-lib/pkg/wasm_lib_bg.wasm public
|
||||
mkdir src/wasm-lib/pkg
|
||||
cp prepared-files/src/wasm-lib/pkg/wasm_lib* src/wasm-lib/pkg
|
||||
cp prepared-files/release-notes.md release-notes.md
|
||||
|
||||
- name: Sync node version and setup cache
|
||||
uses: actions/setup-node@v4
|
||||
@ -205,7 +192,7 @@ jobs:
|
||||
VERSION_NO_V: ${{ needs.prepare-files.outputs.version }}
|
||||
VERSION: ${{ github.event_name == 'schedule' && needs.prepare-files.outputs.version || format('v{0}', needs.prepare-files.outputs.version) }}
|
||||
PUB_DATE: ${{ github.event_name == 'release' && github.event.release.created_at || github.event.repository.updated_at }}
|
||||
NOTES: ${{ needs.prepare-files.outputs.notes }}
|
||||
NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Non-release build, commit {0}', github.sha) }}
|
||||
BUCKET_DIR: ${{ github.event_name == 'schedule' && 'dl.kittycad.io/releases/modeling-app/nightly' || 'dl.kittycad.io/releases/modeling-app' }}
|
||||
WEBSITE_DIR: ${{ github.event_name == 'schedule' && 'dl.zoo.dev/releases/modeling-app/nightly' || 'dl.zoo.dev/releases/modeling-app' }}
|
||||
URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
|
||||
|
||||
25
README.md
@ -57,7 +57,7 @@ yarn install
|
||||
followed by:
|
||||
|
||||
```
|
||||
yarn build:wasm
|
||||
yarn build:wasm-dev
|
||||
```
|
||||
|
||||
or if you have the gh cli installed
|
||||
@ -66,15 +66,15 @@ or if you have the gh cli installed
|
||||
./get-latest-wasm-bundle.sh # this will download the latest main wasm bundle
|
||||
```
|
||||
|
||||
That will build the WASM binary and put in the `public` dir (though gitignored).
|
||||
That will build the WASM binary and put in the `public` dir (though gitignored)
|
||||
|
||||
Finally, to run the web app only, run:
|
||||
finally, to run the web app only, run:
|
||||
|
||||
```
|
||||
yarn start
|
||||
```
|
||||
|
||||
If you're not an KittyCAD employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to localhost:3000 again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again.
|
||||
If you're not an KittyCAD employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens ofcourse, then navigate to localhost:3000 again. Note that navigating to localhost:3000/signin removes your token so you will need to set the token again.
|
||||
|
||||
### Development environment variables
|
||||
|
||||
@ -91,13 +91,13 @@ Third-Party Cookies".
|
||||
|
||||
## Desktop
|
||||
|
||||
To spin up the desktop app, `yarn install` and `yarn build:wasm` need to have been done before hand then
|
||||
To spin up the desktop app, `yarn install` and `yarn build:wasm-dev` need to have been done before hand then
|
||||
|
||||
```
|
||||
yarn tron:start
|
||||
yarn electron:start
|
||||
```
|
||||
|
||||
This will start the application and hot-reload on changes.
|
||||
This will start the application and hot-reload on changed.
|
||||
|
||||
Devtools can be opened with the usual Cmd/Ctrl-Shift-I.
|
||||
|
||||
@ -334,16 +334,7 @@ Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testin
|
||||
|
||||
```bash
|
||||
cd src/wasm-lib
|
||||
KITTYCAD_API_TOKEN=XXX cargo test -- --test-threads=1
|
||||
```
|
||||
|
||||
Where `XXX` is an API token from the production engine (NOT the dev environment).
|
||||
|
||||
We recommend using [nextest](https://nexte.st/) to run the Rust tests (its faster and is used in CI). Once installed, run the tests using
|
||||
|
||||
```
|
||||
cd src/wasm-lib
|
||||
KITTYCAD_API_TOKEN=XXX cargo run nextest
|
||||
cargo test
|
||||
```
|
||||
|
||||
### Mapping CI CD jobs to local commands
|
||||
|
||||
@ -18,12 +18,12 @@ reduce(array: [KclValue], start: KclValue, reduce_fn: FunctionParam) -> KclValue
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `array` | [`[KclValue]`](/docs/kcl/types/KclValue) | | Yes |
|
||||
| `start` | [`KclValue`](/docs/kcl/types/KclValue) | Any KCL value. | Yes |
|
||||
| `start` | [`KclValue`](/docs/kcl/types/KclValue) | A memory item. | Yes |
|
||||
| `reduce_fn` | `FunctionParam` | | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`KclValue`](/docs/kcl/types/KclValue) - Any KCL value.
|
||||
[`KclValue`](/docs/kcl/types/KclValue) - A memory item.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
@ -80912,7 +80912,7 @@
|
||||
},
|
||||
"definitions": {
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -84468,7 +84468,7 @@
|
||||
"type": "null",
|
||||
"definitions": {
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -88028,7 +88028,7 @@
|
||||
},
|
||||
"definitions": {
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -112440,7 +112440,7 @@
|
||||
},
|
||||
"definitions": {
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -115993,7 +115993,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "KclValue",
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -116389,7 +116389,7 @@
|
||||
],
|
||||
"definitions": {
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -119945,7 +119945,7 @@
|
||||
"type": "null",
|
||||
"definitions": {
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -123499,7 +123499,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "KclValue",
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -127037,7 +127037,7 @@
|
||||
}
|
||||
},
|
||||
"KclValue": {
|
||||
"description": "Any KCL value.",
|
||||
"description": "A memory item.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
---
|
||||
title: "KclValue"
|
||||
excerpt: "Any KCL value."
|
||||
excerpt: "A memory item."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Any KCL value.
|
||||
A memory item.
|
||||
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ A plane.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Plane`| | No |
|
||||
| `id` |`string`| The id of the plane. | No |
|
||||
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Any KCL value. | No |
|
||||
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| A memory item. | No |
|
||||
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
|
||||
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane’s X axis be? | No |
|
||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane’s Y axis be? | No |
|
||||
@ -183,8 +183,8 @@ Data for an imported geometry.
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Function`| | No |
|
||||
| `expression` |[`FunctionExpression`](/docs/kcl/types/FunctionExpression)| Any KCL value. | No |
|
||||
| `memory` |[`ProgramMemory`](/docs/kcl/types/ProgramMemory)| Any KCL value. | No |
|
||||
| `expression` |[`FunctionExpression`](/docs/kcl/types/FunctionExpression)| A memory item. | No |
|
||||
| `memory` |[`ProgramMemory`](/docs/kcl/types/ProgramMemory)| A memory item. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
import { getUtils, setup, tearDown } from './test-utils'
|
||||
|
||||
test.beforeEach(async ({ context, page }, testInfo) => {
|
||||
await setup(context, page, testInfo)
|
||||
})
|
||||
|
||||
test.afterEach(async ({ page }, testInfo) => {
|
||||
await tearDown(page, testInfo)
|
||||
})
|
||||
|
||||
function countNewlines(input: string): number {
|
||||
let count = 0
|
||||
for (const char of input) {
|
||||
if (char === '\n') {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
test.describe('Debug pane', () => {
|
||||
test('Artifact IDs in the artifact graph are stable across code edits', async ({
|
||||
page,
|
||||
context,
|
||||
}) => {
|
||||
const code = `sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([1, 1], %)
|
||||
`
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
const tree = page.getByTestId('debug-feature-tree')
|
||||
const segment = tree.locator('li', {
|
||||
hasText: 'segIds:',
|
||||
hasNotText: 'paths:',
|
||||
})
|
||||
|
||||
await test.step('Test setup', async () => {
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.openKclCodePanel()
|
||||
await u.openDebugPanel()
|
||||
// Set the code in the code editor.
|
||||
await u.codeLocator.click()
|
||||
await page.keyboard.type(code, { delay: 0 })
|
||||
// Scroll to the feature tree.
|
||||
await tree.scrollIntoViewIfNeeded()
|
||||
// Expand the feature tree.
|
||||
await tree.getByText('Feature Tree').click()
|
||||
// Just expanded the details, making the element taller, so scroll again.
|
||||
await tree.getByText('Plane').first().scrollIntoViewIfNeeded()
|
||||
})
|
||||
// Extract the artifact IDs from the debug feature tree.
|
||||
const initialSegmentIds = await segment.innerText({ timeout: 5_000 })
|
||||
// The artifact ID should include a UUID.
|
||||
expect(initialSegmentIds).toMatch(
|
||||
/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/
|
||||
)
|
||||
await test.step('Move cursor to the bottom of the code editor', async () => {
|
||||
// Focus on the code editor.
|
||||
await u.codeLocator.click()
|
||||
// Make sure the cursor is at the end of the code.
|
||||
const lines = countNewlines(code) + 1
|
||||
for (let i = 0; i < lines; i++) {
|
||||
await page.keyboard.press('ArrowDown')
|
||||
}
|
||||
})
|
||||
await test.step('Enter a comment', async () => {
|
||||
await page.keyboard.type('|> line([2, 2], %)', { delay: 0 })
|
||||
// Wait for keyboard input debounce and updated artifact graph.
|
||||
await page.waitForTimeout(1000)
|
||||
})
|
||||
const newSegmentIds = await segment.innerText()
|
||||
// Strip off the closing bracket.
|
||||
const initialIds = initialSegmentIds.slice(0, initialSegmentIds.length - 1)
|
||||
expect(newSegmentIds.slice(0, initialIds.length)).toEqual(initialIds)
|
||||
})
|
||||
})
|
||||
@ -1,4 +1,4 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { test, expect, Page } from '@playwright/test'
|
||||
import {
|
||||
doExport,
|
||||
executorInputPath,
|
||||
@ -618,30 +618,31 @@ test(
|
||||
'Deleting projects, can delete individual project, can still create projects after deleting all',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
const projectData = [
|
||||
['router-template-slate', 'cylinder.kcl'],
|
||||
['bracket', 'focusrite_scarlett_mounting_braket.kcl'],
|
||||
['lego', 'lego.kcl'],
|
||||
]
|
||||
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
// Do these serially to ensure the order is correct
|
||||
for (const [name, file] of projectData) {
|
||||
await fsp.mkdir(join(dir, name), { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath(file),
|
||||
join(dir, name, `main.kcl`)
|
||||
)
|
||||
// Wait 1s between each project to ensure the order is correct
|
||||
await new Promise((r) => setTimeout(r, 1_000))
|
||||
}
|
||||
},
|
||||
})
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
page.on('console', console.log)
|
||||
|
||||
const createProjectAndRenameItTest = async ({
|
||||
name,
|
||||
page,
|
||||
}: {
|
||||
name: string
|
||||
page: Page
|
||||
}) => {
|
||||
await test.step(`Create and rename project ${name}`, async () => {
|
||||
await createProjectAndRenameIt({ name, page })
|
||||
})
|
||||
}
|
||||
|
||||
// we need to create the folders so that the order is correct
|
||||
// creating them ahead of time with fs tools means they all have the same timestamp
|
||||
await createProjectAndRenameItTest({ name: 'router-template-slate', page })
|
||||
await createProjectAndRenameItTest({ name: 'bracket', page })
|
||||
await createProjectAndRenameItTest({ name: 'lego', page })
|
||||
|
||||
await test.step('delete the middle project, i.e. the bracket project', async () => {
|
||||
const project = page.getByText('bracket')
|
||||
|
||||
@ -743,26 +744,8 @@ test(
|
||||
'Can sort projects on home page',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
const projectData = [
|
||||
['router-template-slate', 'cylinder.kcl'],
|
||||
['bracket', 'focusrite_scarlett_mounting_braket.kcl'],
|
||||
['lego', 'lego.kcl'],
|
||||
]
|
||||
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
// Do these serially to ensure the order is correct
|
||||
for (const [name, file] of projectData) {
|
||||
await fsp.mkdir(join(dir, name), { recursive: true })
|
||||
await fsp.copyFile(
|
||||
executorInputPath(file),
|
||||
join(dir, name, `main.kcl`)
|
||||
)
|
||||
// Wait 1s between each project to ensure the order is correct
|
||||
await new Promise((r) => setTimeout(r, 1_000))
|
||||
}
|
||||
},
|
||||
})
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
@ -770,6 +753,24 @@ test(
|
||||
|
||||
page.on('console', console.log)
|
||||
|
||||
const createProjectAndRenameItTest = async ({
|
||||
name,
|
||||
page,
|
||||
}: {
|
||||
name: string
|
||||
page: Page
|
||||
}) => {
|
||||
await test.step(`Create and rename project ${name}`, async () => {
|
||||
await createProjectAndRenameIt({ name, page })
|
||||
})
|
||||
}
|
||||
|
||||
// we need to create the folders so that the order is correct
|
||||
// creating them ahead of time with fs tools means they all have the same timestamp
|
||||
await createProjectAndRenameItTest({ name: 'router-template-slate', page })
|
||||
await createProjectAndRenameItTest({ name: 'bracket', page })
|
||||
await createProjectAndRenameItTest({ name: 'lego', page })
|
||||
|
||||
await test.step('should be shorted by modified initially', async () => {
|
||||
const lastModifiedButton = page.getByRole('button', {
|
||||
name: 'Last Modified',
|
||||
|
||||
@ -521,6 +521,7 @@ test(
|
||||
const startXPx = 600
|
||||
|
||||
// Equip the rectangle tool
|
||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||
await page
|
||||
.getByRole('button', { name: 'rectangle Corner rectangle', exact: true })
|
||||
.click()
|
||||
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
@ -1208,12 +1208,6 @@ extrude001 = extrude(50, sketch001)
|
||||
test('Deselecting line tool should mean nothing happens on click', async ({
|
||||
page,
|
||||
}) => {
|
||||
/**
|
||||
* If the line tool is clicked when the state is 'No Points' it will exit Sketch mode.
|
||||
* This is the same exact workflow as pressing ESC.
|
||||
*
|
||||
* To continue to test this workflow, we now enter sketch mode and place a single point before exiting the line tool.
|
||||
*/
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
@ -1234,7 +1228,6 @@ extrude001 = extrude(50, sketch001)
|
||||
200
|
||||
)
|
||||
|
||||
// Clicks the XZ Plane in the page
|
||||
await page.mouse.click(700, 200)
|
||||
|
||||
await expect(page.locator('.cm-content')).toHaveText(
|
||||
@ -1243,11 +1236,6 @@ extrude001 = extrude(50, sketch001)
|
||||
|
||||
await page.waitForTimeout(600)
|
||||
|
||||
// Place a point because the line tool will exit if no points are pressed
|
||||
await page.mouse.click(650, 200)
|
||||
await page.waitForTimeout(600)
|
||||
|
||||
// Code before exiting the tool
|
||||
let previousCodeContent = await page.locator('.cm-content').innerText()
|
||||
|
||||
// deselect the line tool by clicking it
|
||||
|
||||
@ -73,5 +73,3 @@ publish:
|
||||
- provider: generic
|
||||
url: https://dl.zoo.dev/releases/modeling-app
|
||||
channel: latest
|
||||
releaseInfo:
|
||||
releaseNotesFile: release-notes.md
|
||||
|
||||
4
interface.d.ts
vendored
@ -69,13 +69,9 @@ export interface IElectronAPI {
|
||||
kittycad: (access: string, args: any) => any
|
||||
listMachines: () => Promise<MachinesListing>
|
||||
getMachineApiIp: () => Promise<string | null>
|
||||
onUpdateDownloadStart: (
|
||||
callback: (value: { version: string }) => void
|
||||
) => Electron.IpcRenderer
|
||||
onUpdateDownloaded: (
|
||||
callback: (value: string) => void
|
||||
) => Electron.IpcRenderer
|
||||
onUpdateError: (callback: (value: { error: Error }) => void) => Electron
|
||||
appRestart: () => void
|
||||
}
|
||||
|
||||
|
||||
@ -408,7 +408,6 @@ export async function deleteSegment({
|
||||
|
||||
const testExecute = await executeAst({
|
||||
ast: modifiedAst,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager: engineCommandManager,
|
||||
})
|
||||
|
||||
@ -391,14 +391,12 @@ export class SceneEntities {
|
||||
const { truncatedAst, programMemoryOverride, variableDeclarationName } =
|
||||
prepared
|
||||
|
||||
const { execState } = await executeAst({
|
||||
const { programMemory } = await executeAst({
|
||||
ast: truncatedAst,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
programMemoryOverride,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
})
|
||||
const programMemory = execState.memory
|
||||
const sketch = sketchFromPathToNode({
|
||||
pathToNode: sketchPathToNode,
|
||||
ast: maybeModdedAst,
|
||||
@ -803,14 +801,12 @@ export class SceneEntities {
|
||||
updateRectangleSketch(sketchInit, x, y, tags[0])
|
||||
}
|
||||
|
||||
const { execState } = await executeAst({
|
||||
const { programMemory } = await executeAst({
|
||||
ast: truncatedAst,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
programMemoryOverride,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
})
|
||||
const programMemory = execState.memory
|
||||
this.sceneProgramMemory = programMemory
|
||||
const sketch = sketchFromKclValue(
|
||||
programMemory.get(variableDeclarationName),
|
||||
@ -852,14 +848,12 @@ export class SceneEntities {
|
||||
await kclManager.executeAstMock(_ast)
|
||||
sceneInfra.modelingSend({ type: 'Finish rectangle' })
|
||||
|
||||
const { execState } = await executeAst({
|
||||
const { programMemory } = await executeAst({
|
||||
ast: _ast,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
programMemoryOverride,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
})
|
||||
const programMemory = execState.memory
|
||||
|
||||
// Prepare to update the THREEjs scene
|
||||
this.sceneProgramMemory = programMemory
|
||||
@ -971,14 +965,12 @@ export class SceneEntities {
|
||||
modded = moddedResult.modifiedAst
|
||||
}
|
||||
|
||||
const { execState } = await executeAst({
|
||||
const { programMemory } = await executeAst({
|
||||
ast: modded,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
programMemoryOverride,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
})
|
||||
const programMemory = execState.memory
|
||||
this.sceneProgramMemory = programMemory
|
||||
const sketch = sketchFromKclValue(
|
||||
programMemory.get(variableDeclarationName),
|
||||
@ -1325,14 +1317,12 @@ export class SceneEntities {
|
||||
// don't want to mod the user's code yet as they have't committed to the change yet
|
||||
// plus this would be the truncated ast being recast, it would be wrong
|
||||
codeManager.updateCodeEditor(code)
|
||||
const { execState } = await executeAst({
|
||||
const { programMemory } = await executeAst({
|
||||
ast: truncatedAst,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
programMemoryOverride,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
})
|
||||
const programMemory = execState.memory
|
||||
this.sceneProgramMemory = programMemory
|
||||
|
||||
const maybeSketch = programMemory.get(variableDeclarationName)
|
||||
|
||||
@ -157,7 +157,7 @@ export function useCalc({
|
||||
engineCommandManager,
|
||||
useFakeExecutor: true,
|
||||
programMemoryOverride: kclManager.programMemory.clone(),
|
||||
}).then(({ execState }) => {
|
||||
}).then(({ programMemory }) => {
|
||||
const resultDeclaration = ast.body.find(
|
||||
(a) =>
|
||||
a.type === 'VariableDeclaration' &&
|
||||
@ -166,7 +166,7 @@ export function useCalc({
|
||||
const init =
|
||||
resultDeclaration?.type === 'VariableDeclaration' &&
|
||||
resultDeclaration?.declarations?.[0]?.init
|
||||
const result = execState.memory?.get('__result__')?.value
|
||||
const result = programMemory?.get('__result__')?.value
|
||||
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
|
||||
init && setValueNode(init)
|
||||
})
|
||||
|
||||
@ -1,111 +0,0 @@
|
||||
import { isArray, isNonNullable } from 'lib/utils'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
type Primitive = string | number | bigint | boolean | symbol | null | undefined
|
||||
|
||||
export type GenericObj = {
|
||||
type?: string
|
||||
[key: string]: GenericObj | Primitive | Array<GenericObj | Primitive>
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an array of objects or primitives for debug purposes. Nullable values
|
||||
* are displayed so that relative indexes are preserved.
|
||||
*/
|
||||
export function DebugDisplayArray({
|
||||
arr,
|
||||
filterKeys,
|
||||
}: {
|
||||
arr: Array<GenericObj | Primitive>
|
||||
filterKeys: string[]
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{arr.map((obj, index) => {
|
||||
return (
|
||||
<div className="my-2" key={index}>
|
||||
{obj && typeof obj === 'object' ? (
|
||||
<DebugDisplayObj obj={obj} filterKeys={filterKeys} />
|
||||
) : isNonNullable(obj) ? (
|
||||
<span>{obj.toString()}</span>
|
||||
) : (
|
||||
<span>{obj}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an object as a tree for debug purposes. Nullable values are omitted.
|
||||
* The only other property treated specially is the type property, which is
|
||||
* assumed to be a string.
|
||||
*/
|
||||
export function DebugDisplayObj({
|
||||
obj,
|
||||
filterKeys,
|
||||
}: {
|
||||
obj: GenericObj
|
||||
filterKeys: string[]
|
||||
}) {
|
||||
const ref = useRef<HTMLPreElement>(null)
|
||||
const hasCursor = false
|
||||
const [isCollapsed, setIsCollapsed] = useState(false)
|
||||
return (
|
||||
<pre
|
||||
ref={ref}
|
||||
className={`ml-2 border-l border-violet-600 pl-1 ${
|
||||
hasCursor ? 'bg-violet-100/80 dark:bg-violet-100/25' : ''
|
||||
}`}
|
||||
>
|
||||
{isCollapsed ? (
|
||||
<button
|
||||
className="m-0 p-0 border-0"
|
||||
onClick={() => setIsCollapsed(false)}
|
||||
>
|
||||
{'>'}type: {obj.type}
|
||||
</button>
|
||||
) : (
|
||||
<span className="flex">
|
||||
<button
|
||||
className="m-0 p-0 border-0 mb-auto"
|
||||
onClick={() => setIsCollapsed(true)}
|
||||
>
|
||||
{'⬇️'}
|
||||
</button>
|
||||
<ul className="inline-block">
|
||||
{Object.entries(obj).map(([key, value]) => {
|
||||
if (filterKeys.includes(key)) {
|
||||
return null
|
||||
} else if (isArray(value)) {
|
||||
return (
|
||||
<li key={key}>
|
||||
{`${key}: [`}
|
||||
<DebugDisplayArray arr={value} filterKeys={filterKeys} />
|
||||
{']'}
|
||||
</li>
|
||||
)
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
return (
|
||||
<li key={key}>
|
||||
{key}:
|
||||
<DebugDisplayObj obj={value} filterKeys={filterKeys} />
|
||||
</li>
|
||||
)
|
||||
} else if (isNonNullable(value)) {
|
||||
return (
|
||||
<li key={key}>
|
||||
{key}: {value.toString()}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
return null
|
||||
})}
|
||||
</ul>
|
||||
</span>
|
||||
)}
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
import { useMemo } from 'react'
|
||||
import { engineCommandManager } from 'lib/singletons'
|
||||
import {
|
||||
ArtifactGraph,
|
||||
expandPlane,
|
||||
PlaneArtifactRich,
|
||||
} from 'lang/std/artifactGraph'
|
||||
import { DebugDisplayArray, GenericObj } from './DebugDisplayObj'
|
||||
|
||||
export function DebugFeatureTree() {
|
||||
const featureTree = useMemo(() => {
|
||||
return computeTree(engineCommandManager.artifactGraph)
|
||||
}, [engineCommandManager.artifactGraph])
|
||||
|
||||
const filterKeys: string[] = ['__meta', 'codeRef', 'pathToNode']
|
||||
return (
|
||||
<details data-testid="debug-feature-tree" className="relative">
|
||||
<summary>Feature Tree</summary>
|
||||
{featureTree.length > 0 ? (
|
||||
<pre className="text-xs">
|
||||
<DebugDisplayArray arr={featureTree} filterKeys={filterKeys} />
|
||||
</pre>
|
||||
) : (
|
||||
<p>(Empty)</p>
|
||||
)}
|
||||
</details>
|
||||
)
|
||||
}
|
||||
|
||||
function computeTree(artifactGraph: ArtifactGraph): GenericObj[] {
|
||||
let items: GenericObj[] = []
|
||||
|
||||
const planes: PlaneArtifactRich[] = []
|
||||
for (const artifact of artifactGraph.values()) {
|
||||
if (artifact.type === 'plane') {
|
||||
planes.push(expandPlane(artifact, artifactGraph))
|
||||
}
|
||||
}
|
||||
const extraRichPlanes: GenericObj[] = planes.map((plane) => {
|
||||
return plane as any as GenericObj
|
||||
})
|
||||
items = items.concat(extraRichPlanes)
|
||||
|
||||
return items
|
||||
}
|
||||
@ -149,13 +149,6 @@ export const ModelingMachineProvider = ({
|
||||
},
|
||||
'sketch exit execute': ({ context: { store } }) => {
|
||||
;(async () => {
|
||||
// When cancelling the sketch mode we should disable sketch mode within the engine.
|
||||
await engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: { type: 'sketch_mode_disable' },
|
||||
})
|
||||
|
||||
sceneInfra.camControls.syncDirection = 'clientToEngine'
|
||||
|
||||
if (cameraProjection.current === 'perspective') {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { DebugFeatureTree } from 'components/DebugFeatureTree'
|
||||
import { AstExplorer } from '../../AstExplorer'
|
||||
import { EngineCommands } from '../../EngineCommands'
|
||||
import { CamDebugSettings } from 'clientSideScene/ClientSideSceneComp'
|
||||
@ -13,7 +12,6 @@ export const DebugPane = () => {
|
||||
<EngineCommands />
|
||||
<CamDebugSettings />
|
||||
<AstExplorer />
|
||||
<DebugFeatureTree />
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
@ -29,8 +29,8 @@ describe('processMemory', () => {
|
||||
|> lineTo([2.15, 4.32], %)
|
||||
// |> rx(90, %)`
|
||||
const ast = parse(code)
|
||||
const execState = await enginelessExecutor(ast, ProgramMemory.empty())
|
||||
const output = processMemory(execState.memory)
|
||||
const programMemory = await enginelessExecutor(ast, ProgramMemory.empty())
|
||||
const output = processMemory(programMemory)
|
||||
expect(output.myVar).toEqual(5)
|
||||
expect(output.otherVar).toEqual(3)
|
||||
expect(output).toEqual({
|
||||
|
||||
@ -8,7 +8,6 @@ import ModalContainer from 'react-modal-promise'
|
||||
import { isDesktop } from 'lib/isDesktop'
|
||||
import { AppStreamProvider } from 'AppState'
|
||||
import { ToastUpdate } from 'components/ToastUpdate'
|
||||
import { AUTO_UPDATER_TOAST_ID } from 'lib/constants'
|
||||
|
||||
// uncomment for xstate inspector
|
||||
// import { DEV } from 'env'
|
||||
@ -54,22 +53,7 @@ root.render(
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals()
|
||||
|
||||
if (isDesktop()) {
|
||||
// Listen for update download progress to begin
|
||||
// to show a loading toast.
|
||||
window.electron.onUpdateDownloadStart(() => {
|
||||
const message = `Downloading app update...`
|
||||
console.log(message)
|
||||
toast.loading(message, { id: AUTO_UPDATER_TOAST_ID })
|
||||
})
|
||||
// Listen for update download errors to show
|
||||
// an error toast and clear the loading toast.
|
||||
window.electron.onUpdateError(({ error }) => {
|
||||
console.error(error)
|
||||
toast.error('An error occurred while downloading the update.', {
|
||||
id: AUTO_UPDATER_TOAST_ID,
|
||||
})
|
||||
})
|
||||
isDesktop() &&
|
||||
window.electron.onUpdateDownloaded((version: string) => {
|
||||
const message = `A new update (${version}) was downloaded and will be available next time you open the app.`
|
||||
console.log(message)
|
||||
@ -80,7 +64,6 @@ if (isDesktop()) {
|
||||
window.electron.appRestart()
|
||||
},
|
||||
}),
|
||||
{ duration: 30000, id: AUTO_UPDATER_TOAST_ID }
|
||||
{ duration: 30000 }
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,8 +8,6 @@ import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants'
|
||||
|
||||
import {
|
||||
CallExpression,
|
||||
emptyExecState,
|
||||
ExecState,
|
||||
initPromise,
|
||||
parse,
|
||||
PathToNode,
|
||||
@ -44,7 +42,6 @@ export class KclManager {
|
||||
},
|
||||
digest: null,
|
||||
}
|
||||
private _execState: ExecState = emptyExecState()
|
||||
private _programMemory: ProgramMemory = ProgramMemory.empty()
|
||||
lastSuccessfulProgramMemory: ProgramMemory = ProgramMemory.empty()
|
||||
private _logs: string[] = []
|
||||
@ -75,21 +72,11 @@ export class KclManager {
|
||||
get programMemory() {
|
||||
return this._programMemory
|
||||
}
|
||||
// This is private because callers should be setting the entire execState.
|
||||
private set programMemory(programMemory) {
|
||||
set programMemory(programMemory) {
|
||||
this._programMemory = programMemory
|
||||
this._programMemoryCallBack(programMemory)
|
||||
}
|
||||
|
||||
set execState(execState) {
|
||||
this._execState = execState
|
||||
this.programMemory = execState.memory
|
||||
}
|
||||
|
||||
get execState() {
|
||||
return this._execState
|
||||
}
|
||||
|
||||
get logs() {
|
||||
return this._logs
|
||||
}
|
||||
@ -266,9 +253,8 @@ export class KclManager {
|
||||
// Make sure we clear before starting again. End session will do this.
|
||||
this.engineCommandManager?.endSession()
|
||||
await this.ensureWasmInit()
|
||||
const { logs, errors, execState, isInterrupted } = await executeAst({
|
||||
const { logs, errors, programMemory, isInterrupted } = await executeAst({
|
||||
ast,
|
||||
idGenerator: this.execState.idGenerator,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
})
|
||||
|
||||
@ -278,7 +264,7 @@ export class KclManager {
|
||||
this.lints = await lintAst({ ast: ast })
|
||||
|
||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||
defaultSelectionFilter(execState.memory, this.engineCommandManager)
|
||||
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
||||
|
||||
if (args.zoomToFit) {
|
||||
let zoomObjectId: string | undefined = ''
|
||||
@ -309,20 +295,12 @@ export class KclManager {
|
||||
this._cancelTokens.delete(currentExecutionId)
|
||||
return
|
||||
}
|
||||
|
||||
// Exit sketch mode if the AST is empty
|
||||
if (this._isAstEmpty(ast)) {
|
||||
await this.disableSketchMode()
|
||||
}
|
||||
|
||||
this.logs = logs
|
||||
// Do not add the errors since the program was interrupted and the error is not a real KCL error
|
||||
this.addKclErrors(isInterrupted ? [] : errors)
|
||||
// Reset the next ID index so that we reuse the previous IDs next time.
|
||||
execState.idGenerator.nextId = 0
|
||||
this.execState = execState
|
||||
this.programMemory = programMemory
|
||||
if (!errors.length) {
|
||||
this.lastSuccessfulProgramMemory = execState.memory
|
||||
this.lastSuccessfulProgramMemory = programMemory
|
||||
}
|
||||
this.ast = { ...ast }
|
||||
this._executeCallback()
|
||||
@ -360,19 +338,17 @@ export class KclManager {
|
||||
await codeManager.writeToFile()
|
||||
this._ast = { ...newAst }
|
||||
|
||||
const { logs, errors, execState } = await executeAst({
|
||||
const { logs, errors, programMemory } = await executeAst({
|
||||
ast: newAst,
|
||||
idGenerator: this.execState.idGenerator,
|
||||
engineCommandManager: this.engineCommandManager,
|
||||
useFakeExecutor: true,
|
||||
})
|
||||
|
||||
this._logs = logs
|
||||
this._kclErrors = errors
|
||||
this._execState = execState
|
||||
this._programMemory = execState.memory
|
||||
this._programMemory = programMemory
|
||||
if (!errors.length) {
|
||||
this.lastSuccessfulProgramMemory = execState.memory
|
||||
this.lastSuccessfulProgramMemory = programMemory
|
||||
}
|
||||
if (updates !== 'artifactRanges') return
|
||||
|
||||
@ -577,24 +553,6 @@ export class KclManager {
|
||||
defaultSelectionFilter() {
|
||||
defaultSelectionFilter(this.programMemory, this.engineCommandManager)
|
||||
}
|
||||
|
||||
/**
|
||||
* We can send a single command of 'enable_sketch_mode' or send this in a batched request.
|
||||
* When there is no code in the KCL editor we should be sending 'sketch_mode_disable' since any previous half finished
|
||||
* code could leave the state of the application in sketch mode on the engine side.
|
||||
*/
|
||||
async disableSketchMode() {
|
||||
await this.engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: { type: 'sketch_mode_disable' },
|
||||
})
|
||||
}
|
||||
|
||||
// Determines if there is no KCL code which means it is executing a blank KCL file
|
||||
_isAstEmpty(ast: Program) {
|
||||
return ast.start === 0 && ast.end === 0 && ast.body.length === 0
|
||||
}
|
||||
}
|
||||
|
||||
function defaultSelectionFilter(
|
||||
|
||||
@ -14,9 +14,9 @@ const mySketch001 = startSketchOn('XY')
|
||||
|> lineTo([-1.59, -1.54], %)
|
||||
|> lineTo([0.46, -5.82], %)
|
||||
// |> rx(45, %)`
|
||||
const execState = await enginelessExecutor(parse(code))
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
// @ts-ignore
|
||||
const sketch001 = execState.memory.get('mySketch001')
|
||||
const sketch001 = programMemory?.get('mySketch001')
|
||||
expect(sketch001).toEqual({
|
||||
type: 'UserVal',
|
||||
__meta: [{ sourceRange: [46, 71] }],
|
||||
@ -68,9 +68,9 @@ const mySketch001 = startSketchOn('XY')
|
||||
|> lineTo([0.46, -5.82], %)
|
||||
// |> rx(45, %)
|
||||
|> extrude(2, %)`
|
||||
const execState = await enginelessExecutor(parse(code))
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
// @ts-ignore
|
||||
const sketch001 = execState.memory.get('mySketch001')
|
||||
const sketch001 = programMemory?.get('mySketch001')
|
||||
expect(sketch001).toEqual({
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
@ -148,10 +148,9 @@ const sk2 = startSketchOn('XY')
|
||||
|> extrude(2, %)
|
||||
|
||||
`
|
||||
const execState = await enginelessExecutor(parse(code))
|
||||
const programMemory = execState.memory
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
// @ts-ignore
|
||||
const geos = [programMemory.get('theExtrude'), programMemory.get('sk2')]
|
||||
const geos = [programMemory?.get('theExtrude'), programMemory?.get('sk2')]
|
||||
expect(geos).toEqual([
|
||||
{
|
||||
type: 'Solid',
|
||||
|
||||
@ -443,6 +443,6 @@ async function exe(
|
||||
) {
|
||||
const ast = parse(code)
|
||||
|
||||
const execState = await enginelessExecutor(ast, programMemory)
|
||||
return execState.memory
|
||||
const result = await enginelessExecutor(ast, programMemory)
|
||||
return result
|
||||
}
|
||||
|
||||
@ -4,14 +4,11 @@ import {
|
||||
ProgramMemory,
|
||||
programMemoryInit,
|
||||
kclLint,
|
||||
emptyExecState,
|
||||
ExecState,
|
||||
} from 'lang/wasm'
|
||||
import { enginelessExecutor } from 'lib/testHelpers'
|
||||
import { EngineCommandManager } from 'lang/std/engineConnection'
|
||||
import { KCLError } from 'lang/errors'
|
||||
import { Diagnostic } from '@codemirror/lint'
|
||||
import { IdGenerator } from 'wasm-lib/kcl/bindings/IdGenerator'
|
||||
|
||||
export type ToolTip =
|
||||
| 'lineTo'
|
||||
@ -50,18 +47,16 @@ export async function executeAst({
|
||||
engineCommandManager,
|
||||
useFakeExecutor = false,
|
||||
programMemoryOverride,
|
||||
idGenerator,
|
||||
}: {
|
||||
ast: Program
|
||||
engineCommandManager: EngineCommandManager
|
||||
useFakeExecutor?: boolean
|
||||
programMemoryOverride?: ProgramMemory
|
||||
idGenerator?: IdGenerator
|
||||
isInterrupted?: boolean
|
||||
}): Promise<{
|
||||
logs: string[]
|
||||
errors: KCLError[]
|
||||
execState: ExecState
|
||||
programMemory: ProgramMemory
|
||||
isInterrupted: boolean
|
||||
}> {
|
||||
try {
|
||||
@ -70,21 +65,15 @@ export async function executeAst({
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
engineCommandManager.startNewSession()
|
||||
}
|
||||
const execState = await (useFakeExecutor
|
||||
const programMemory = await (useFakeExecutor
|
||||
? enginelessExecutor(ast, programMemoryOverride || programMemoryInit())
|
||||
: _executor(
|
||||
ast,
|
||||
programMemoryInit(),
|
||||
idGenerator,
|
||||
engineCommandManager,
|
||||
false
|
||||
))
|
||||
: _executor(ast, programMemoryInit(), engineCommandManager, false))
|
||||
|
||||
await engineCommandManager.waitForAllCommands()
|
||||
return {
|
||||
logs: [],
|
||||
errors: [],
|
||||
execState,
|
||||
programMemory,
|
||||
isInterrupted: false,
|
||||
}
|
||||
} catch (e: any) {
|
||||
@ -100,7 +89,7 @@ export async function executeAst({
|
||||
return {
|
||||
errors: [e],
|
||||
logs: [],
|
||||
execState: emptyExecState(),
|
||||
programMemory: ProgramMemory.empty(),
|
||||
isInterrupted,
|
||||
}
|
||||
} else {
|
||||
@ -108,7 +97,7 @@ export async function executeAst({
|
||||
return {
|
||||
logs: [e],
|
||||
errors: [],
|
||||
execState: emptyExecState(),
|
||||
programMemory: ProgramMemory.empty(),
|
||||
isInterrupted,
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,11 +220,11 @@ yo2 = hmm([identifierGuy + 5])`
|
||||
it('should move a binary expression into a new variable', async () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const startIndex = code.indexOf('100 + 100') + 1
|
||||
const { modifiedAst } = moveValueIntoNewVariable(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
[startIndex, startIndex],
|
||||
'newVar'
|
||||
)
|
||||
@ -235,11 +235,11 @@ yo2 = hmm([identifierGuy + 5])`
|
||||
it('should move a value into a new variable', async () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const startIndex = code.indexOf('2.8') + 1
|
||||
const { modifiedAst } = moveValueIntoNewVariable(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
[startIndex, startIndex],
|
||||
'newVar'
|
||||
)
|
||||
@ -250,11 +250,11 @@ yo2 = hmm([identifierGuy + 5])`
|
||||
it('should move a callExpression into a new variable', async () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const startIndex = code.indexOf('def(')
|
||||
const { modifiedAst } = moveValueIntoNewVariable(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
[startIndex, startIndex],
|
||||
'newVar'
|
||||
)
|
||||
@ -265,11 +265,11 @@ yo2 = hmm([identifierGuy + 5])`
|
||||
it('should move a binary expression with call expression into a new variable', async () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const startIndex = code.indexOf('jkl(') + 1
|
||||
const { modifiedAst } = moveValueIntoNewVariable(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
[startIndex, startIndex],
|
||||
'newVar'
|
||||
)
|
||||
@ -280,11 +280,11 @@ yo2 = hmm([identifierGuy + 5])`
|
||||
it('should move a identifier into a new variable', async () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const startIndex = code.indexOf('identifierGuy +') + 1
|
||||
const { modifiedAst } = moveValueIntoNewVariable(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
[startIndex, startIndex],
|
||||
'newVar'
|
||||
)
|
||||
@ -465,7 +465,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
||||
|> line([306.21, 198.87], %)`
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const lineOfInterest = 'line([306.21, 198.85], %, $a)'
|
||||
const range: [number, number] = [
|
||||
code.indexOf(lineOfInterest),
|
||||
@ -475,7 +475,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
||||
const modifiedAst = deleteSegmentFromPipeExpression(
|
||||
[],
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
code,
|
||||
pathToNode
|
||||
)
|
||||
@ -543,7 +543,7 @@ ${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
||||
const code = makeCode(line)
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const lineOfInterest = line
|
||||
const range: [number, number] = [
|
||||
code.indexOf(lineOfInterest),
|
||||
@ -554,7 +554,7 @@ ${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
||||
const modifiedAst = deleteSegmentFromPipeExpression(
|
||||
dependentSegments,
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
code,
|
||||
pathToNode
|
||||
)
|
||||
@ -632,7 +632,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
||||
const range: [number, number] = [
|
||||
code.indexOf(lineOfInterest) + 1,
|
||||
@ -661,7 +661,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
pathToNode,
|
||||
argPosition,
|
||||
ast,
|
||||
execState.memory
|
||||
programMemory
|
||||
)
|
||||
if (!mod) return new Error('mod is undefined')
|
||||
const recastCode = recast(mod.modifiedAst)
|
||||
@ -686,7 +686,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
||||
const range: [number, number] = [
|
||||
code.indexOf(lineOfInterest) + 1,
|
||||
@ -711,7 +711,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
||||
pathToNode,
|
||||
argPosition,
|
||||
ast,
|
||||
execState.memory
|
||||
programMemory
|
||||
)
|
||||
if (!mod) return new Error('mod is undefined')
|
||||
const recastCode = recast(mod.modifiedAst)
|
||||
@ -882,7 +882,7 @@ sketch002 = startSketchOn({
|
||||
// const lineOfInterest = 'line([-2.94, 2.7], %)'
|
||||
const ast = parse(codeBefore)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
|
||||
// deleteFromSelection
|
||||
const range: [number, number] = [
|
||||
@ -895,7 +895,7 @@ sketch002 = startSketchOn({
|
||||
range,
|
||||
type,
|
||||
},
|
||||
execState.memory,
|
||||
programMemory,
|
||||
async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||
return {
|
||||
|
||||
@ -45,11 +45,11 @@ variableBelowShouldNotBeIncluded = 3
|
||||
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
|
||||
const ast = parse(code)
|
||||
if (err(ast)) throw ast
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
|
||||
const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
[rangeStart, rangeStart]
|
||||
)
|
||||
expect(variables).toEqual([
|
||||
@ -351,11 +351,11 @@ part001 = startSketchAt([-1.41, 3.46])
|
||||
const ast = parse(exampleCode)
|
||||
if (err(ast)) throw ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const result = hasExtrudeSketch({
|
||||
ast,
|
||||
selection: { type: 'default', range: [100, 101] },
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
})
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
@ -370,11 +370,11 @@ part001 = startSketchAt([-1.41, 3.46])
|
||||
const ast = parse(exampleCode)
|
||||
if (err(ast)) throw ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const result = hasExtrudeSketch({
|
||||
ast,
|
||||
selection: { type: 'default', range: [100, 101] },
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
})
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
@ -383,11 +383,11 @@ part001 = startSketchAt([-1.41, 3.46])
|
||||
const ast = parse(exampleCode)
|
||||
if (err(ast)) throw ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const result = hasExtrudeSketch({
|
||||
ast,
|
||||
selection: { type: 'default', range: [10, 11] },
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
})
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
|
||||
@ -117,11 +117,11 @@ describe('testing changeSketchArguments', () => {
|
||||
const ast = parse(code)
|
||||
if (err(ast)) return ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const sourceStart = code.indexOf(lineToChange)
|
||||
const changeSketchArgsRetVal = changeSketchArguments(
|
||||
ast,
|
||||
execState.memory,
|
||||
programMemory,
|
||||
{
|
||||
type: 'sourceRange',
|
||||
sourceRange: [sourceStart, sourceStart + lineToChange.length],
|
||||
@ -150,12 +150,12 @@ mySketch001 = startSketchOn('XY')
|
||||
const ast = parse(code)
|
||||
if (err(ast)) return ast
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const sourceStart = code.indexOf(lineToChange)
|
||||
expect(sourceStart).toBe(89)
|
||||
const newSketchLnRetVal = addNewSketchLn({
|
||||
node: ast,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
input: {
|
||||
type: 'straight-segment',
|
||||
from: [0, 0],
|
||||
@ -186,7 +186,7 @@ mySketch001 = startSketchOn('XY')
|
||||
|
||||
const modifiedAst2 = addCloseToPipe({
|
||||
node: ast,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
pathToNode: [
|
||||
['body', ''],
|
||||
[0, 'index'],
|
||||
@ -230,7 +230,7 @@ describe('testing addTagForSketchOnFace', () => {
|
||||
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
|
||||
const sketchOnFaceRetVal = addTagForSketchOnFace(
|
||||
{
|
||||
// previousProgramMemory: execState.memory, // redundant?
|
||||
// previousProgramMemory: programMemory, // redundant?
|
||||
pathToNode,
|
||||
node: ast,
|
||||
},
|
||||
|
||||
@ -34,7 +34,7 @@ async function testingSwapSketchFnCall({
|
||||
const ast = parse(inputCode)
|
||||
if (err(ast)) return Promise.reject(ast)
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const selections = {
|
||||
codeBasedSelections: [range],
|
||||
otherSelections: [],
|
||||
@ -45,7 +45,7 @@ async function testingSwapSketchFnCall({
|
||||
return Promise.reject(new Error('transformInfos undefined'))
|
||||
const ast2 = transformAstSketchLines({
|
||||
ast,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
selectionRanges: selections,
|
||||
transformInfos,
|
||||
referenceSegName: '',
|
||||
@ -360,10 +360,10 @@ part001 = startSketchOn('XY')
|
||||
|> line([2.14, 1.35], %) // normal-segment
|
||||
|> xLine(3.54, %)`
|
||||
it('normal case works', async () => {
|
||||
const execState = await enginelessExecutor(parse(code))
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
const index = code.indexOf('// normal-segment') - 7
|
||||
const sg = sketchFromKclValue(
|
||||
execState.memory.get('part001'),
|
||||
programMemory.get('part001'),
|
||||
'part001'
|
||||
) as Sketch
|
||||
const _segment = getSketchSegmentFromSourceRange(sg, [index, index])
|
||||
@ -377,10 +377,10 @@ part001 = startSketchOn('XY')
|
||||
})
|
||||
})
|
||||
it('verify it works when the segment is in the `start` property', async () => {
|
||||
const execState = await enginelessExecutor(parse(code))
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
const index = code.indexOf('// segment-in-start') - 7
|
||||
const _segment = getSketchSegmentFromSourceRange(
|
||||
sketchFromKclValue(execState.memory.get('part001'), 'part001') as Sketch,
|
||||
sketchFromKclValue(programMemory.get('part001'), 'part001') as Sketch,
|
||||
[index, index]
|
||||
)
|
||||
if (err(_segment)) throw _segment
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
getConstraintLevelFromSourceRange,
|
||||
} from './sketchcombos'
|
||||
import { ToolTip } from 'lang/langHelpers'
|
||||
import { Selection, Selections } from 'lib/selections'
|
||||
import { Selections } from 'lib/selections'
|
||||
import { err } from 'lib/trap'
|
||||
import { enginelessExecutor } from '../../lib/testHelpers'
|
||||
|
||||
@ -96,86 +96,6 @@ function makeSelections(
|
||||
}
|
||||
|
||||
describe('testing transformAstForSketchLines for equal length constraint', () => {
|
||||
describe(`should always reorder selections to have the base selection first`, () => {
|
||||
const inputScript = `sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([5, 5], %)
|
||||
|> line([-2, 5], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`
|
||||
|
||||
const expectedModifiedScript = `sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line([5, 5], %, $seg01)
|
||||
|> angledLine([112, segLen(seg01)], %)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`
|
||||
|
||||
const selectLine = (script: string, lineNumber: number): Selection => {
|
||||
const lines = script.split('\n')
|
||||
const codeBeforeLine = lines.slice(0, lineNumber).join('\n').length
|
||||
const line = lines.find((_, i) => i === lineNumber)
|
||||
if (!line) {
|
||||
throw new Error(
|
||||
`line index ${lineNumber} not found in test sample, friend`
|
||||
)
|
||||
}
|
||||
const start = codeBeforeLine + line.indexOf('|> ' + 5)
|
||||
const range: [number, number] = [start, start]
|
||||
return {
|
||||
type: 'default',
|
||||
range,
|
||||
}
|
||||
}
|
||||
|
||||
async function applyTransformation(
|
||||
inputCode: string,
|
||||
selectionRanges: Selections['codeBasedSelections']
|
||||
) {
|
||||
const ast = parse(inputCode)
|
||||
if (err(ast)) return Promise.reject(ast)
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const transformInfos = getTransformInfos(
|
||||
makeSelections(selectionRanges.slice(1)),
|
||||
ast,
|
||||
'equalLength'
|
||||
)
|
||||
|
||||
const transformedSelection = makeSelections(selectionRanges)
|
||||
|
||||
const newAst = transformSecondarySketchLinesTagFirst({
|
||||
ast,
|
||||
selectionRanges: transformedSelection,
|
||||
transformInfos,
|
||||
programMemory: execState.memory,
|
||||
})
|
||||
if (err(newAst)) return Promise.reject(newAst)
|
||||
|
||||
const newCode = recast(newAst.modifiedAst)
|
||||
return newCode
|
||||
}
|
||||
|
||||
it(`Should reorder when user selects first-to-last`, async () => {
|
||||
const selectionRanges: Selections['codeBasedSelections'] = [
|
||||
selectLine(inputScript, 3),
|
||||
selectLine(inputScript, 4),
|
||||
]
|
||||
|
||||
const newCode = await applyTransformation(inputScript, selectionRanges)
|
||||
expect(newCode).toBe(expectedModifiedScript)
|
||||
})
|
||||
|
||||
it(`Should reorder when user selects last-to-first`, async () => {
|
||||
const selectionRanges: Selections['codeBasedSelections'] = [
|
||||
selectLine(inputScript, 4),
|
||||
selectLine(inputScript, 3),
|
||||
]
|
||||
|
||||
const newCode = await applyTransformation(inputScript, selectionRanges)
|
||||
expect(newCode).toBe(expectedModifiedScript)
|
||||
})
|
||||
})
|
||||
const inputScript = `myVar = 3
|
||||
myVar2 = 5
|
||||
myVar3 = 6
|
||||
@ -300,7 +220,7 @@ part001 = startSketchOn('XY')
|
||||
}
|
||||
})
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const transformInfos = getTransformInfos(
|
||||
makeSelections(selectionRanges.slice(1)),
|
||||
ast,
|
||||
@ -311,7 +231,7 @@ part001 = startSketchOn('XY')
|
||||
ast,
|
||||
selectionRanges: makeSelections(selectionRanges),
|
||||
transformInfos,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
})
|
||||
if (err(newAst)) return Promise.reject(newAst)
|
||||
|
||||
@ -391,7 +311,7 @@ part001 = startSketchOn('XY')
|
||||
}
|
||||
})
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const transformInfos = getTransformInfos(
|
||||
makeSelections(selectionRanges),
|
||||
ast,
|
||||
@ -402,7 +322,7 @@ part001 = startSketchOn('XY')
|
||||
ast,
|
||||
selectionRanges: makeSelections(selectionRanges),
|
||||
transformInfos,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
referenceSegName: '',
|
||||
})
|
||||
if (err(newAst)) return Promise.reject(newAst)
|
||||
@ -453,7 +373,7 @@ part001 = startSketchOn('XY')
|
||||
}
|
||||
})
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const transformInfos = getTransformInfos(
|
||||
makeSelections(selectionRanges),
|
||||
ast,
|
||||
@ -464,7 +384,7 @@ part001 = startSketchOn('XY')
|
||||
ast,
|
||||
selectionRanges: makeSelections(selectionRanges),
|
||||
transformInfos,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
referenceSegName: '',
|
||||
})
|
||||
if (err(newAst)) return Promise.reject(newAst)
|
||||
@ -550,7 +470,7 @@ async function helperThing(
|
||||
}
|
||||
})
|
||||
|
||||
const execState = await enginelessExecutor(ast)
|
||||
const programMemory = await enginelessExecutor(ast)
|
||||
const transformInfos = getTransformInfos(
|
||||
makeSelections(selectionRanges.slice(1)),
|
||||
ast,
|
||||
@ -561,7 +481,7 @@ async function helperThing(
|
||||
ast,
|
||||
selectionRanges: makeSelections(selectionRanges),
|
||||
transformInfos,
|
||||
programMemory: execState.memory,
|
||||
programMemory,
|
||||
})
|
||||
|
||||
if (err(newAst)) return Promise.reject(newAst)
|
||||
|
||||
@ -1559,15 +1559,7 @@ export function transformSecondarySketchLinesTagFirst({
|
||||
}
|
||||
| Error {
|
||||
// let node = structuredClone(ast)
|
||||
|
||||
// We need to sort the selections by their start position
|
||||
// so that we can process them in dependency order and not write invalid KCL.
|
||||
const sortedCodeBasedSelections =
|
||||
selectionRanges.codeBasedSelections.toSorted(
|
||||
(a, b) => a.range[0] - b.range[0]
|
||||
)
|
||||
const primarySelection = sortedCodeBasedSelections[0].range
|
||||
const secondarySelections = sortedCodeBasedSelections.slice(1)
|
||||
const primarySelection = selectionRanges.codeBasedSelections[0].range
|
||||
|
||||
const _tag = giveSketchFnCallTag(ast, primarySelection, forceSegName)
|
||||
if (err(_tag)) return _tag
|
||||
@ -1577,7 +1569,7 @@ export function transformSecondarySketchLinesTagFirst({
|
||||
ast: modifiedAst,
|
||||
selectionRanges: {
|
||||
...selectionRanges,
|
||||
codeBasedSelections: secondarySelections,
|
||||
codeBasedSelections: selectionRanges.codeBasedSelections.slice(1),
|
||||
},
|
||||
referencedSegmentRange: primarySelection,
|
||||
transformInfos,
|
||||
|
||||
@ -17,9 +17,9 @@ describe('testing angledLineThatIntersects', () => {
|
||||
offset: ${offset},
|
||||
}, %, $yo2)
|
||||
intersect = segEndX(yo2)`
|
||||
const execState = await enginelessExecutor(parse(code('-1')))
|
||||
expect(execState.memory.get('intersect')?.value).toBe(1 + Math.sqrt(2))
|
||||
const mem = await enginelessExecutor(parse(code('-1')))
|
||||
expect(mem.get('intersect')?.value).toBe(1 + Math.sqrt(2))
|
||||
const noOffset = await enginelessExecutor(parse(code('0')))
|
||||
expect(noOffset.memory.get('intersect')?.value).toBeCloseTo(1)
|
||||
expect(noOffset.get('intersect')?.value).toBeCloseTo(1)
|
||||
})
|
||||
})
|
||||
|
||||
@ -37,11 +37,6 @@ import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
||||
import { DeepPartial } from 'lib/types'
|
||||
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
||||
import { Sketch } from '../wasm-lib/kcl/bindings/Sketch'
|
||||
import { IdGenerator } from 'wasm-lib/kcl/bindings/IdGenerator'
|
||||
import { ExecState as RawExecState } from '../wasm-lib/kcl/bindings/ExecState'
|
||||
import { ProgramMemory as RawProgramMemory } from '../wasm-lib/kcl/bindings/ProgramMemory'
|
||||
import { EnvironmentRef } from '../wasm-lib/kcl/bindings/EnvironmentRef'
|
||||
import { Environment } from '../wasm-lib/kcl/bindings/Environment'
|
||||
|
||||
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
||||
@ -141,46 +136,29 @@ export const parse = (code: string | Error): Program | Error => {
|
||||
|
||||
export type PathToNode = [string | number, string][]
|
||||
|
||||
export interface ExecState {
|
||||
memory: ProgramMemory
|
||||
idGenerator: IdGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty ExecState. This is useful on init to prevent needing an
|
||||
* Option.
|
||||
*/
|
||||
export function emptyExecState(): ExecState {
|
||||
return {
|
||||
memory: ProgramMemory.empty(),
|
||||
idGenerator: defaultIdGenerator(),
|
||||
}
|
||||
}
|
||||
|
||||
function execStateFromRaw(raw: RawExecState): ExecState {
|
||||
return {
|
||||
memory: ProgramMemory.fromRaw(raw.memory),
|
||||
idGenerator: raw.idGenerator,
|
||||
}
|
||||
}
|
||||
|
||||
export function defaultIdGenerator(): IdGenerator {
|
||||
return {
|
||||
nextId: 0,
|
||||
ids: [],
|
||||
}
|
||||
}
|
||||
|
||||
interface Memory {
|
||||
[key: string]: KclValue | undefined
|
||||
[key: string]: KclValue
|
||||
}
|
||||
|
||||
type EnvironmentRef = number
|
||||
|
||||
const ROOT_ENVIRONMENT_REF: EnvironmentRef = 0
|
||||
|
||||
interface Environment {
|
||||
bindings: Memory
|
||||
parent: EnvironmentRef | null
|
||||
}
|
||||
|
||||
function emptyEnvironment(): Environment {
|
||||
return { bindings: {}, parent: null }
|
||||
}
|
||||
|
||||
interface RawProgramMemory {
|
||||
environments: Environment[]
|
||||
currentEnv: EnvironmentRef
|
||||
return: KclValue | null
|
||||
}
|
||||
|
||||
/**
|
||||
* This duplicates logic in Rust. The hope is to keep ProgramMemory internals
|
||||
* isolated from the rest of the TypeScript code so that we can move it to Rust
|
||||
@ -239,7 +217,7 @@ export class ProgramMemory {
|
||||
while (true) {
|
||||
const env = this.environments[envRef]
|
||||
if (env.bindings.hasOwnProperty(name)) {
|
||||
return env.bindings[name] ?? null
|
||||
return env.bindings[name]
|
||||
}
|
||||
if (!env.parent) {
|
||||
break
|
||||
@ -282,7 +260,6 @@ export class ProgramMemory {
|
||||
}
|
||||
|
||||
for (const [name, value] of Object.entries(env.bindings)) {
|
||||
if (value === undefined) continue
|
||||
// Check the predicate.
|
||||
if (!predicate(value)) {
|
||||
continue
|
||||
@ -316,7 +293,6 @@ export class ProgramMemory {
|
||||
while (true) {
|
||||
const env = this.environments[envRef]
|
||||
for (const [name, value] of Object.entries(env.bindings)) {
|
||||
if (value === undefined) continue
|
||||
// Don't include shadowed variables.
|
||||
if (!map.has(name)) {
|
||||
map.set(name, value)
|
||||
@ -380,10 +356,9 @@ export function sketchFromKclValue(
|
||||
export const executor = async (
|
||||
node: Program,
|
||||
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
||||
idGenerator: IdGenerator = defaultIdGenerator(),
|
||||
engineCommandManager: EngineCommandManager,
|
||||
isMock: boolean = false
|
||||
): Promise<ExecState> => {
|
||||
): Promise<ProgramMemory> => {
|
||||
if (err(programMemory)) return Promise.reject(programMemory)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
@ -391,7 +366,6 @@ export const executor = async (
|
||||
const _programMemory = await _executor(
|
||||
node,
|
||||
programMemory,
|
||||
idGenerator,
|
||||
engineCommandManager,
|
||||
isMock
|
||||
)
|
||||
@ -404,10 +378,9 @@ export const executor = async (
|
||||
export const _executor = async (
|
||||
node: Program,
|
||||
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
||||
idGenerator: IdGenerator = defaultIdGenerator(),
|
||||
engineCommandManager: EngineCommandManager,
|
||||
isMock: boolean
|
||||
): Promise<ExecState> => {
|
||||
): Promise<ProgramMemory> => {
|
||||
if (err(programMemory)) return Promise.reject(programMemory)
|
||||
|
||||
try {
|
||||
@ -419,16 +392,15 @@ export const _executor = async (
|
||||
baseUnit =
|
||||
(await getSettingsState)()?.modeling.defaultUnit.current || 'mm'
|
||||
}
|
||||
const execState: RawExecState = await execute_wasm(
|
||||
const memory: RawProgramMemory = await execute_wasm(
|
||||
JSON.stringify(node),
|
||||
JSON.stringify(programMemory.toRaw()),
|
||||
JSON.stringify(idGenerator),
|
||||
baseUnit,
|
||||
engineCommandManager,
|
||||
fileSystemManager,
|
||||
isMock
|
||||
)
|
||||
return execStateFromRaw(execState)
|
||||
return ProgramMemory.fromRaw(memory)
|
||||
} catch (e: any) {
|
||||
console.log(e)
|
||||
const parsed: RustKclError = JSON.parse(e.toString())
|
||||
|
||||
@ -102,6 +102,3 @@ export const KCL_SAMPLES_MANIFEST_URLS = {
|
||||
'https://raw.githubusercontent.com/KittyCAD/kcl-samples/main/manifest.json',
|
||||
localFallback: '/kcl-samples-manifest-fallback.json',
|
||||
} as const
|
||||
|
||||
/** Toast id for the app auto-updater toast */
|
||||
export const AUTO_UPDATER_TOAST_ID = 'auto-updater-toast'
|
||||
|
||||
@ -1,11 +1,4 @@
|
||||
import {
|
||||
Program,
|
||||
ProgramMemory,
|
||||
_executor,
|
||||
SourceRange,
|
||||
ExecState,
|
||||
defaultIdGenerator,
|
||||
} from '../lang/wasm'
|
||||
import { Program, ProgramMemory, _executor, SourceRange } from '../lang/wasm'
|
||||
import {
|
||||
EngineCommandManager,
|
||||
EngineCommandManagerEvents,
|
||||
@ -16,7 +9,6 @@ import { v4 as uuidv4 } from 'uuid'
|
||||
import { DefaultPlanes } from 'wasm-lib/kcl/bindings/DefaultPlanes'
|
||||
import { err, reportRejection } from 'lib/trap'
|
||||
import { toSync } from './utils'
|
||||
import { IdGenerator } from 'wasm-lib/kcl/bindings/IdGenerator'
|
||||
|
||||
type WebSocketResponse = Models['WebSocketResponse_type']
|
||||
|
||||
@ -85,9 +77,8 @@ class MockEngineCommandManager {
|
||||
|
||||
export async function enginelessExecutor(
|
||||
ast: Program | Error,
|
||||
pm: ProgramMemory | Error = ProgramMemory.empty(),
|
||||
idGenerator: IdGenerator = defaultIdGenerator()
|
||||
): Promise<ExecState> {
|
||||
pm: ProgramMemory | Error = ProgramMemory.empty()
|
||||
): Promise<ProgramMemory> {
|
||||
if (err(ast)) return Promise.reject(ast)
|
||||
if (err(pm)) return Promise.reject(pm)
|
||||
|
||||
@ -97,22 +88,15 @@ export async function enginelessExecutor(
|
||||
}) as any as EngineCommandManager
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
mockEngineCommandManager.startNewSession()
|
||||
const execState = await _executor(
|
||||
ast,
|
||||
pm,
|
||||
idGenerator,
|
||||
mockEngineCommandManager,
|
||||
true
|
||||
)
|
||||
const programMemory = await _executor(ast, pm, mockEngineCommandManager, true)
|
||||
await mockEngineCommandManager.waitForAllCommands()
|
||||
return execState
|
||||
return programMemory
|
||||
}
|
||||
|
||||
export async function executor(
|
||||
ast: Program,
|
||||
pm: ProgramMemory = ProgramMemory.empty(),
|
||||
idGenerator: IdGenerator = defaultIdGenerator()
|
||||
): Promise<ExecState> {
|
||||
pm: ProgramMemory = ProgramMemory.empty()
|
||||
): Promise<ProgramMemory> {
|
||||
const engineCommandManager = new EngineCommandManager()
|
||||
engineCommandManager.start({
|
||||
setIsStreamReady: () => {},
|
||||
@ -133,15 +117,14 @@ export async function executor(
|
||||
toSync(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
engineCommandManager.startNewSession()
|
||||
const execState = await _executor(
|
||||
const programMemory = await _executor(
|
||||
ast,
|
||||
pm,
|
||||
idGenerator,
|
||||
engineCommandManager,
|
||||
false
|
||||
)
|
||||
await engineCommandManager.waitForAllCommands()
|
||||
resolve(execState)
|
||||
resolve(programMemory)
|
||||
}, reportRejection)
|
||||
)
|
||||
})
|
||||
|
||||
@ -295,24 +295,15 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
||||
'break',
|
||||
{
|
||||
id: 'line',
|
||||
onClick: ({ modelingState, modelingSend }) => {
|
||||
if (modelingState.matches({ Sketch: { 'Line tool': 'No Points' } })) {
|
||||
// Exit the sketch state if there are no points and they press ESC
|
||||
modelingSend({
|
||||
type: 'Cancel',
|
||||
})
|
||||
} else {
|
||||
// Exit the tool if there are points and they press ESC
|
||||
modelingSend({
|
||||
type: 'change tool',
|
||||
data: {
|
||||
tool: !modelingState.matches({ Sketch: 'Line tool' })
|
||||
? 'line'
|
||||
: 'none',
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
onClick: ({ modelingState, modelingSend }) =>
|
||||
modelingSend({
|
||||
type: 'change tool',
|
||||
data: {
|
||||
tool: !modelingState.matches({ Sketch: 'Line tool' })
|
||||
? 'line'
|
||||
: 'none',
|
||||
},
|
||||
}),
|
||||
icon: 'line',
|
||||
status: 'available',
|
||||
disabled: (state) =>
|
||||
|
||||
@ -97,7 +97,7 @@ export function useCalculateKclExpression({
|
||||
})
|
||||
if (trap(error, { suppress: true })) return
|
||||
}
|
||||
const { execState } = await executeAst({
|
||||
const { programMemory } = await executeAst({
|
||||
ast,
|
||||
engineCommandManager,
|
||||
useFakeExecutor: true,
|
||||
@ -111,7 +111,7 @@ export function useCalculateKclExpression({
|
||||
const init =
|
||||
resultDeclaration?.type === 'VariableDeclaration' &&
|
||||
resultDeclaration?.declarations?.[0]?.init
|
||||
const result = execState.memory?.get('__result__')?.value
|
||||
const result = programMemory?.get('__result__')?.value
|
||||
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
|
||||
init && setValueNode(init)
|
||||
}
|
||||
|
||||
@ -666,7 +666,6 @@ export const modelingMachine = setup({
|
||||
|
||||
const testExecute = await executeAst({
|
||||
ast: modifiedAst,
|
||||
idGenerator: kclManager.execState.idGenerator,
|
||||
useFakeExecutor: true,
|
||||
engineCommandManager,
|
||||
})
|
||||
|
||||
20
src/main.ts
@ -261,30 +261,10 @@ app.on('ready', () => {
|
||||
autoUpdater.checkForUpdates().catch(reportRejection)
|
||||
}, fifteenMinutes)
|
||||
|
||||
autoUpdater.on('error', (error) => {
|
||||
console.error('updater-error', error)
|
||||
mainWindow?.webContents.send('updater-error', error)
|
||||
})
|
||||
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
console.log('update-available', info)
|
||||
})
|
||||
|
||||
autoUpdater.prependOnceListener('download-progress', (progress) => {
|
||||
// For now, we'll send nothing and just start a loading spinner.
|
||||
// See below for a TODO to send progress data to the renderer.
|
||||
console.log('update-download-start', {
|
||||
version: '',
|
||||
})
|
||||
mainWindow?.webContents.send('update-download-start', progress)
|
||||
})
|
||||
|
||||
autoUpdater.on('download-progress', (progress) => {
|
||||
// TODO: in a future PR (https://github.com/KittyCAD/modeling-app/issues/3994)
|
||||
// send this data to mainWindow to show a progress bar for the download.
|
||||
console.log('download-progress', progress)
|
||||
})
|
||||
|
||||
autoUpdater.on('update-downloaded', (info) => {
|
||||
console.log('update-downloaded', info)
|
||||
mainWindow?.webContents.send('update-downloaded', info.version)
|
||||
|
||||
@ -16,13 +16,8 @@ const startDeviceFlow = (host: string): Promise<string> =>
|
||||
ipcRenderer.invoke('startDeviceFlow', host)
|
||||
const loginWithDeviceFlow = (): Promise<string> =>
|
||||
ipcRenderer.invoke('loginWithDeviceFlow')
|
||||
const onUpdateDownloadStart = (
|
||||
callback: (value: { version: string }) => void
|
||||
) => ipcRenderer.on('update-download-start', (_event, value) => callback(value))
|
||||
const onUpdateDownloaded = (callback: (value: string) => void) =>
|
||||
ipcRenderer.on('update-downloaded', (_event, value) => callback(value))
|
||||
const onUpdateError = (callback: (value: Error) => void) =>
|
||||
ipcRenderer.on('update-error', (_event, value) => callback(value))
|
||||
const appRestart = () => ipcRenderer.invoke('app.restart')
|
||||
|
||||
const isMac = os.platform() === 'darwin'
|
||||
@ -149,8 +144,6 @@ contextBridge.exposeInMainWorld('electron', {
|
||||
kittycad,
|
||||
listMachines,
|
||||
getMachineApiIp,
|
||||
onUpdateDownloadStart,
|
||||
onUpdateDownloaded,
|
||||
onUpdateError,
|
||||
appRestart,
|
||||
})
|
||||
|
||||
38
src/wasm-lib/Cargo.lock
generated
@ -434,9 +434,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
version = "4.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
|
||||
checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@ -444,9 +444,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.20"
|
||||
version = "4.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
|
||||
checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@ -1533,16 +1533,16 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.71"
|
||||
version = "0.3.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cb94a0ffd3f3ee755c20f7d8752f45cac88605a4dcf808abcff72873296ec7b"
|
||||
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.21"
|
||||
version = "0.2.20"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -3907,9 +3907,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.94"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef073ced962d62984fb38a36e5fdc1a2b23c9e0e1fa0689bb97afa4202ef6887"
|
||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@ -3918,9 +3918,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.94"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4bfab14ef75323f4eb75fa52ee0a3fb59611977fd3240da19b2cf36ff85030e"
|
||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@ -3933,9 +3933,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.44"
|
||||
version = "0.4.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65471f79c1022ffa5291d33520cbbb53b7687b01c2f8e83b57d102eed7ed479d"
|
||||
checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-core",
|
||||
@ -3946,9 +3946,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.94"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7bec9830f60924d9ceb3ef99d55c155be8afa76954edffbb5936ff4509474e7"
|
||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -3956,9 +3956,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.94"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c74f6e152a76a2ad448e223b0fc0b6b5747649c3d769cc6bf45737bf97d0ed6"
|
||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3969,9 +3969,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.94"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a42f6c679374623f295a8623adfe63d9284091245c3504bde47c17a3ce2777d9"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-lib"
|
||||
|
||||
@ -20,7 +20,7 @@ tokio = { version = "1.40.0", features = ["sync"] }
|
||||
toml = "0.8.19"
|
||||
uuid = { version = "1.10.0", features = ["v4", "js", "serde"] }
|
||||
wasm-bindgen = "0.2.91"
|
||||
wasm-bindgen-futures = "0.4.44"
|
||||
wasm-bindgen-futures = "0.4.42"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1"
|
||||
@ -36,9 +36,9 @@ uuid = { version = "1.10.0", features = ["v4", "js", "serde"] }
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.31"
|
||||
js-sys = "0.3.71"
|
||||
js-sys = "0.3.69"
|
||||
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
||||
wasm-bindgen-futures = { version = "0.4.44", features = ["futures-core-03-stream"] }
|
||||
wasm-bindgen-futures = { version = "0.4.41", features = ["futures-core-03-stream"] }
|
||||
wasm-streams = "0.4.1"
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
|
||||
|
||||
@ -753,7 +753,6 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
||||
let tokens = crate::token::lexer(#code_block).unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(crate::engine::conn_mock::EngineConnection::new().await.unwrap())),
|
||||
fs: std::sync::Arc::new(crate::fs::FileManager::new()),
|
||||
@ -762,7 +761,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_someFn {
|
||||
let tokens = crate::token::lexer("someFn()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_someFn {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_someFn {
|
||||
let tokens = crate::token::lexer("someFn()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_someFn {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_show {
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nshow").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -39,7 +38,6 @@ mod test_examples_show {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -51,7 +49,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_show {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -6,7 +6,6 @@ mod test_examples_my_func {
|
||||
crate::token::lexer("This is another code block.\nyes sirrr.\nmyFunc").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -18,7 +17,7 @@ mod test_examples_my_func {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -40,7 +39,6 @@ mod test_examples_my_func {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmyFunc").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -52,7 +50,7 @@ mod test_examples_my_func {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -6,7 +6,6 @@ mod test_examples_line_to {
|
||||
crate::token::lexer("This is another code block.\nyes sirrr.\nlineTo").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -18,7 +17,7 @@ mod test_examples_line_to {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -40,7 +39,6 @@ mod test_examples_line_to {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nlineTo").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -52,7 +50,7 @@ mod test_examples_line_to {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_min {
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nmin").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_min {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -39,7 +38,6 @@ mod test_examples_min {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmin").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -51,7 +49,7 @@ mod test_examples_min {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_show {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_import {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_import {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_import {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_show {
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -5,7 +5,6 @@ mod test_examples_some_function {
|
||||
let tokens = crate::token::lexer("someFunction()").unwrap();
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +16,7 @@ mod test_examples_some_function {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
||||
@ -166,19 +166,15 @@ async fn snapshot_endpoint(body: Bytes, state: ExecutorContext) -> Response<Body
|
||||
Err(e) => return bad_request(format!("Parse error: {e}")),
|
||||
};
|
||||
eprintln!("Executing {test_name}");
|
||||
let mut id_generator = kcl_lib::executor::IdGenerator::default();
|
||||
// This is a shitty source range, I don't know what else to use for it though.
|
||||
// There's no actual KCL associated with this reset_scene call.
|
||||
if let Err(e) = state
|
||||
.reset_scene(&mut id_generator, kcl_lib::executor::SourceRange::default())
|
||||
.await
|
||||
{
|
||||
if let Err(e) = state.reset_scene(kcl_lib::executor::SourceRange::default()).await {
|
||||
return kcl_err(e);
|
||||
}
|
||||
// Let users know if the test is taking a long time.
|
||||
let (done_tx, done_rx) = oneshot::channel::<()>();
|
||||
let timer = time_until(done_rx);
|
||||
let snapshot = match state.execute_and_prepare_snapshot(&program, id_generator).await {
|
||||
let snapshot = match state.execute_and_prepare_snapshot(&program).await {
|
||||
Ok(sn) => sn,
|
||||
Err(e) => return kcl_err(e),
|
||||
};
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use indexmap::IndexMap;
|
||||
use kcl_lib::{
|
||||
errors::KclError,
|
||||
executor::{DefaultPlanes, IdGenerator},
|
||||
};
|
||||
use kcl_lib::{errors::KclError, executor::DefaultPlanes};
|
||||
use kittycad_modeling_cmds::{
|
||||
self as kcmc,
|
||||
id::ModelingCmdId,
|
||||
@ -360,11 +357,7 @@ impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
self.batch_end.clone()
|
||||
}
|
||||
|
||||
async fn default_planes(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: kcl_lib::executor::SourceRange,
|
||||
) -> Result<DefaultPlanes, KclError> {
|
||||
async fn default_planes(&self, source_range: kcl_lib::executor::SourceRange) -> Result<DefaultPlanes, KclError> {
|
||||
if NEED_PLANES {
|
||||
{
|
||||
let opt = self.default_planes.read().await.as_ref().cloned();
|
||||
@ -373,7 +366,7 @@ impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
}
|
||||
} // drop the read lock
|
||||
|
||||
let new_planes = self.new_default_planes(id_generator, source_range).await?;
|
||||
let new_planes = self.new_default_planes(source_range).await?;
|
||||
*self.default_planes.write().await = Some(new_planes.clone());
|
||||
|
||||
Ok(new_planes)
|
||||
@ -382,11 +375,7 @@ impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
}
|
||||
}
|
||||
|
||||
async fn clear_scene_post_hook(
|
||||
&self,
|
||||
_id_generator: &mut IdGenerator,
|
||||
_source_range: kcl_lib::executor::SourceRange,
|
||||
) -> Result<(), KclError> {
|
||||
async fn clear_scene_post_hook(&self, _source_range: kcl_lib::executor::SourceRange) -> Result<(), KclError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::executor::{ExecutorContext, IdGenerator};
|
||||
use kcl_lib::executor::ExecutorContext;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -23,7 +23,7 @@ pub async fn kcl_to_engine_core(code: &str) -> Result<String> {
|
||||
settings: Default::default(),
|
||||
context_type: kcl_lib::executor::ContextType::MockCustomForwarded,
|
||||
};
|
||||
let _memory = ctx.run(&program, None, IdGenerator::default()).await?;
|
||||
let _memory = ctx.run(&program, None).await?;
|
||||
|
||||
let result = result.lock().expect("mutex lock").clone();
|
||||
Ok(result)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.21"
|
||||
version = "0.2.20"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -16,7 +16,7 @@ async-recursion = "1.1.1"
|
||||
async-trait = "0.1.83"
|
||||
base64 = "0.22.1"
|
||||
chrono = "0.4.38"
|
||||
clap = { version = "4.5.20", default-features = false, optional = true, features = ["std", "derive"] }
|
||||
clap = { version = "4.5.19", default-features = false, optional = true, features = ["std", "derive"] }
|
||||
convert_case = "0.6.0"
|
||||
dashmap = "6.1.0"
|
||||
databake = { version = "0.1.8", features = ["derive"] }
|
||||
@ -53,11 +53,11 @@ winnow = "0.6.18"
|
||||
zip = { version = "2.0.0", default-features = false }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
js-sys = { version = "0.3.71" }
|
||||
js-sys = { version = "0.3.69" }
|
||||
tokio = { version = "1.40.0", features = ["sync", "time"] }
|
||||
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
||||
wasm-bindgen = "0.2.91"
|
||||
wasm-bindgen-futures = "0.4.44"
|
||||
wasm-bindgen-futures = "0.4.42"
|
||||
web-sys = { version = "0.3.69", features = ["console"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
|
||||
@ -21,7 +21,7 @@ use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||
use crate::{
|
||||
engine::EngineManager,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{DefaultPlanes, IdGenerator},
|
||||
executor::DefaultPlanes,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -314,11 +314,7 @@ impl EngineManager for EngineConnection {
|
||||
self.batch_end.clone()
|
||||
}
|
||||
|
||||
async fn default_planes(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<DefaultPlanes, KclError> {
|
||||
async fn default_planes(&self, source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> {
|
||||
{
|
||||
let opt = self.default_planes.read().await.as_ref().cloned();
|
||||
if let Some(planes) = opt {
|
||||
@ -326,19 +322,15 @@ impl EngineManager for EngineConnection {
|
||||
}
|
||||
} // drop the read lock
|
||||
|
||||
let new_planes = self.new_default_planes(id_generator, source_range).await?;
|
||||
let new_planes = self.new_default_planes(source_range).await?;
|
||||
*self.default_planes.write().await = Some(new_planes.clone());
|
||||
|
||||
Ok(new_planes)
|
||||
}
|
||||
|
||||
async fn clear_scene_post_hook(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<(), KclError> {
|
||||
async fn clear_scene_post_hook(&self, source_range: crate::executor::SourceRange) -> Result<(), KclError> {
|
||||
// Remake the default planes, since they would have been removed after the scene was cleared.
|
||||
let new_planes = self.new_default_planes(id_generator, source_range).await?;
|
||||
let new_planes = self.new_default_planes(source_range).await?;
|
||||
*self.default_planes.write().await = Some(new_planes);
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -17,10 +17,7 @@ use kcmc::{
|
||||
};
|
||||
use kittycad_modeling_cmds::{self as kcmc};
|
||||
|
||||
use crate::{
|
||||
errors::KclError,
|
||||
executor::{DefaultPlanes, IdGenerator},
|
||||
};
|
||||
use crate::{errors::KclError, executor::DefaultPlanes};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EngineConnection {
|
||||
@ -47,19 +44,11 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
self.batch_end.clone()
|
||||
}
|
||||
|
||||
async fn default_planes(
|
||||
&self,
|
||||
_id_generator: &mut IdGenerator,
|
||||
_source_range: crate::executor::SourceRange,
|
||||
) -> Result<DefaultPlanes, KclError> {
|
||||
async fn default_planes(&self, _source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> {
|
||||
Ok(DefaultPlanes::default())
|
||||
}
|
||||
|
||||
async fn clear_scene_post_hook(
|
||||
&self,
|
||||
_id_generator: &mut IdGenerator,
|
||||
_source_range: crate::executor::SourceRange,
|
||||
) -> Result<(), KclError> {
|
||||
async fn clear_scene_post_hook(&self, _source_range: crate::executor::SourceRange) -> Result<(), KclError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{DefaultPlanes, IdGenerator},
|
||||
executor::DefaultPlanes,
|
||||
};
|
||||
|
||||
#[wasm_bindgen(module = "/../../lang/std/engineConnection.ts")]
|
||||
@ -68,11 +68,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
self.batch_end.clone()
|
||||
}
|
||||
|
||||
async fn default_planes(
|
||||
&self,
|
||||
_id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<DefaultPlanes, KclError> {
|
||||
async fn default_planes(&self, source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> {
|
||||
// Get the default planes.
|
||||
let promise = self.manager.get_default_planes().map_err(|e| {
|
||||
KclError::Engine(KclErrorDetails {
|
||||
@ -110,11 +106,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
Ok(default_planes)
|
||||
}
|
||||
|
||||
async fn clear_scene_post_hook(
|
||||
&self,
|
||||
_id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<(), KclError> {
|
||||
async fn clear_scene_post_hook(&self, source_range: crate::executor::SourceRange) -> Result<(), KclError> {
|
||||
self.manager.clear_default_planes().map_err(|e| {
|
||||
KclError::Engine(KclErrorDetails {
|
||||
message: e.to_string().into(),
|
||||
|
||||
@ -32,7 +32,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{DefaultPlanes, IdGenerator, Point3d},
|
||||
executor::{DefaultPlanes, Point3d},
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@ -52,7 +52,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
/// Get the default planes.
|
||||
async fn default_planes(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
_source_range: crate::executor::SourceRange,
|
||||
) -> Result<DefaultPlanes, crate::errors::KclError>;
|
||||
|
||||
@ -60,7 +59,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
/// (These really only apply to wasm for now).
|
||||
async fn clear_scene_post_hook(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<(), crate::errors::KclError>;
|
||||
|
||||
@ -73,11 +71,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
id_to_source_range: HashMap<uuid::Uuid, crate::executor::SourceRange>,
|
||||
) -> Result<kcmc::websocket::WebSocketResponse, crate::errors::KclError>;
|
||||
|
||||
async fn clear_scene(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<(), crate::errors::KclError> {
|
||||
async fn clear_scene(&self, source_range: crate::executor::SourceRange) -> Result<(), crate::errors::KclError> {
|
||||
self.batch_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
source_range,
|
||||
@ -90,7 +84,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
self.flush_batch(false, source_range).await?;
|
||||
|
||||
// Do the after clear scene hook.
|
||||
self.clear_scene_post_hook(id_generator, source_range).await?;
|
||||
self.clear_scene_post_hook(source_range).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -271,7 +265,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
|
||||
async fn make_default_plane(
|
||||
&self,
|
||||
plane_id: uuid::Uuid,
|
||||
x_axis: Point3d,
|
||||
y_axis: Point3d,
|
||||
color: Option<Color>,
|
||||
@ -281,6 +274,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
let default_size = 100.0;
|
||||
let default_origin = Point3d { x: 0.0, y: 0.0, z: 0.0 }.into();
|
||||
|
||||
let plane_id = uuid::Uuid::new_v4();
|
||||
self.batch_modeling_cmd(
|
||||
plane_id,
|
||||
source_range,
|
||||
@ -308,16 +302,11 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
Ok(plane_id)
|
||||
}
|
||||
|
||||
async fn new_default_planes(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<DefaultPlanes, KclError> {
|
||||
let plane_settings: HashMap<PlaneName, (Uuid, Point3d, Point3d, Option<Color>)> = HashMap::from([
|
||||
async fn new_default_planes(&self, source_range: crate::executor::SourceRange) -> Result<DefaultPlanes, KclError> {
|
||||
let plane_settings: HashMap<PlaneName, (Point3d, Point3d, Option<Color>)> = HashMap::from([
|
||||
(
|
||||
PlaneName::Xy,
|
||||
(
|
||||
id_generator.next_uuid(),
|
||||
Point3d { x: 1.0, y: 0.0, z: 0.0 },
|
||||
Point3d { x: 0.0, y: 1.0, z: 0.0 },
|
||||
Some(Color {
|
||||
@ -331,7 +320,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
(
|
||||
PlaneName::Yz,
|
||||
(
|
||||
id_generator.next_uuid(),
|
||||
Point3d { x: 0.0, y: 1.0, z: 0.0 },
|
||||
Point3d { x: 0.0, y: 0.0, z: 1.0 },
|
||||
Some(Color {
|
||||
@ -345,7 +333,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
(
|
||||
PlaneName::Xz,
|
||||
(
|
||||
id_generator.next_uuid(),
|
||||
Point3d { x: 1.0, y: 0.0, z: 0.0 },
|
||||
Point3d { x: 0.0, y: 0.0, z: 1.0 },
|
||||
Some(Color {
|
||||
@ -359,7 +346,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
(
|
||||
PlaneName::NegXy,
|
||||
(
|
||||
id_generator.next_uuid(),
|
||||
Point3d {
|
||||
x: -1.0,
|
||||
y: 0.0,
|
||||
@ -372,7 +358,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
(
|
||||
PlaneName::NegYz,
|
||||
(
|
||||
id_generator.next_uuid(),
|
||||
Point3d {
|
||||
x: 0.0,
|
||||
y: -1.0,
|
||||
@ -385,7 +370,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
(
|
||||
PlaneName::NegXz,
|
||||
(
|
||||
id_generator.next_uuid(),
|
||||
Point3d {
|
||||
x: -1.0,
|
||||
y: 0.0,
|
||||
@ -398,11 +382,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
]);
|
||||
|
||||
let mut planes = HashMap::new();
|
||||
for (name, (plane_id, x_axis, y_axis, color)) in plane_settings {
|
||||
for (name, (x_axis, y_axis, color)) in plane_settings {
|
||||
planes.insert(
|
||||
name,
|
||||
self.make_default_plane(plane_id, x_axis, y_axis, color, source_range)
|
||||
.await?,
|
||||
self.make_default_plane(x_axis, y_axis, color, source_range).await?,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -40,8 +40,6 @@ use crate::{
|
||||
pub struct ExecState {
|
||||
/// Program variable bindings.
|
||||
pub memory: ProgramMemory,
|
||||
/// The stable artifact ID generator.
|
||||
pub id_generator: IdGenerator,
|
||||
/// Dynamic state that follows dynamic flow of the program.
|
||||
pub dynamic_state: DynamicState,
|
||||
/// The current value of the pipe operator returned from the previous
|
||||
@ -294,34 +292,7 @@ impl DynamicState {
|
||||
}
|
||||
}
|
||||
|
||||
/// A generator for ArtifactIds that can be stable across executions.
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IdGenerator {
|
||||
next_id: usize,
|
||||
ids: Vec<uuid::Uuid>,
|
||||
}
|
||||
|
||||
impl IdGenerator {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn next_uuid(&mut self) -> uuid::Uuid {
|
||||
if let Some(id) = self.ids.get(self.next_id) {
|
||||
self.next_id += 1;
|
||||
*id
|
||||
} else {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
self.ids.push(id);
|
||||
self.next_id += 1;
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Any KCL value.
|
||||
/// A memory item.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
@ -628,82 +599,6 @@ pub struct Plane {
|
||||
pub meta: Vec<Metadata>,
|
||||
}
|
||||
|
||||
impl Plane {
|
||||
pub(crate) fn from_plane_data(value: crate::std::sketch::PlaneData, exec_state: &mut ExecState) -> Self {
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
match value {
|
||||
crate::std::sketch::PlaneData::XY => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
z_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
value: PlaneType::XY,
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::NegXY => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
z_axis: Point3d::new(0.0, 0.0, -1.0),
|
||||
value: PlaneType::XY,
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::XZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(0.0, -1.0, 0.0),
|
||||
value: PlaneType::XZ,
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::NegXZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(-1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
value: PlaneType::XZ,
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::YZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
value: PlaneType::YZ,
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::NegYZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(-1.0, 0.0, 0.0),
|
||||
value: PlaneType::YZ,
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::Plane {
|
||||
origin,
|
||||
x_axis,
|
||||
y_axis,
|
||||
z_axis,
|
||||
} => Plane {
|
||||
id,
|
||||
origin: *origin,
|
||||
x_axis: *x_axis,
|
||||
y_axis: *y_axis,
|
||||
z_axis: *z_axis,
|
||||
value: PlaneType::Custom,
|
||||
meta: vec![],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -1941,12 +1836,8 @@ impl ExecutorContext {
|
||||
Ok(ctx)
|
||||
}
|
||||
|
||||
pub async fn reset_scene(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<()> {
|
||||
self.engine.clear_scene(id_generator, source_range).await?;
|
||||
pub async fn reset_scene(&self, source_range: crate::executor::SourceRange) -> Result<()> {
|
||||
self.engine.clear_scene(source_range).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1957,11 +1848,8 @@ impl ExecutorContext {
|
||||
&self,
|
||||
program: &crate::ast::types::Program,
|
||||
memory: Option<ProgramMemory>,
|
||||
id_generator: IdGenerator,
|
||||
) -> Result<ExecState, KclError> {
|
||||
self.run_with_session_data(program, memory, id_generator)
|
||||
.await
|
||||
.map(|x| x.0)
|
||||
self.run_with_session_data(program, memory).await.map(|x| x.0)
|
||||
}
|
||||
/// Perform the execution of a program.
|
||||
/// You can optionally pass in some initialization memory.
|
||||
@ -1970,22 +1858,11 @@ impl ExecutorContext {
|
||||
&self,
|
||||
program: &crate::ast::types::Program,
|
||||
memory: Option<ProgramMemory>,
|
||||
id_generator: IdGenerator,
|
||||
) -> Result<(ExecState, Option<ModelingSessionData>), KclError> {
|
||||
let memory = if let Some(memory) = memory {
|
||||
memory.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let mut exec_state = ExecState {
|
||||
memory,
|
||||
id_generator,
|
||||
..Default::default()
|
||||
};
|
||||
// Before we even start executing the program, set the units.
|
||||
self.engine
|
||||
.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
SourceRange::default(),
|
||||
&ModelingCmd::from(mcmd::SetSceneUnits {
|
||||
unit: match self.settings.units {
|
||||
@ -1999,7 +1876,15 @@ impl ExecutorContext {
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let memory = if let Some(memory) = memory {
|
||||
memory.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let mut exec_state = ExecState {
|
||||
memory,
|
||||
..Default::default()
|
||||
};
|
||||
self.inner_execute(program, &mut exec_state, crate::executor::BodyType::Root)
|
||||
.await?;
|
||||
let session_data = self.engine.get_session_data();
|
||||
@ -2144,12 +2029,8 @@ impl ExecutorContext {
|
||||
}
|
||||
|
||||
/// Execute the program, then get a PNG screenshot.
|
||||
pub async fn execute_and_prepare_snapshot(
|
||||
&self,
|
||||
program: &Program,
|
||||
id_generator: IdGenerator,
|
||||
) -> Result<TakeSnapshot> {
|
||||
let _ = self.run(program, None, id_generator).await?;
|
||||
pub async fn execute_and_prepare_snapshot(&self, program: &Program) -> Result<TakeSnapshot> {
|
||||
let _ = self.run(program, None).await?;
|
||||
|
||||
// Zoom to fit.
|
||||
self.engine
|
||||
@ -2294,7 +2175,7 @@ mod tests {
|
||||
settings: Default::default(),
|
||||
context_type: ContextType::Mock,
|
||||
};
|
||||
let exec_state = ctx.run(&program, None, IdGenerator::default()).await?;
|
||||
let exec_state = ctx.run(&program, None).await?;
|
||||
|
||||
Ok(exec_state.memory)
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ use tower_lsp::{
|
||||
|
||||
use crate::{
|
||||
ast::types::{Expr, VariableKind},
|
||||
executor::{IdGenerator, SourceRange},
|
||||
executor::SourceRange,
|
||||
lsp::{backend::Backend as _, util::IntoDiagnostic},
|
||||
parser::PIPE_OPERATOR,
|
||||
token::TokenType,
|
||||
@ -588,15 +588,10 @@ impl Backend {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut id_generator = IdGenerator::default();
|
||||
|
||||
// Clear the scene, before we execute so it's not fugly as shit.
|
||||
executor_ctx
|
||||
.engine
|
||||
.clear_scene(&mut id_generator, SourceRange::default())
|
||||
.await?;
|
||||
executor_ctx.engine.clear_scene(SourceRange::default()).await?;
|
||||
|
||||
let exec_state = match executor_ctx.run(ast, None, id_generator).await {
|
||||
let exec_state = match executor_ctx.run(ast, None).await {
|
||||
Ok(exec_state) => exec_state,
|
||||
Err(err) => {
|
||||
self.memory_map.remove(params.uri.as_str());
|
||||
|
||||
@ -133,7 +133,7 @@ async fn inner_chamfer(
|
||||
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
|
||||
};
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_end_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::Solid3dFilletEdge {
|
||||
|
||||
@ -18,10 +18,10 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Extrudes by a given amount.
|
||||
pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (length, sketch_set) = args.get_number_sketch_set()?;
|
||||
|
||||
let result = inner_extrude(length, sketch_set, exec_state, args).await?;
|
||||
let result = inner_extrude(length, sketch_set, args).await?;
|
||||
|
||||
Ok(result.into())
|
||||
}
|
||||
@ -75,13 +75,8 @@ pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
#[stdlib {
|
||||
name = "extrude"
|
||||
}]
|
||||
async fn inner_extrude(
|
||||
length: f64,
|
||||
sketch_set: SketchSet,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<SolidSet, KclError> {
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
async fn inner_extrude(length: f64, sketch_set: SketchSet, args: Args) -> Result<SolidSet, KclError> {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
// Extrude the element(s).
|
||||
let sketches: Vec<Sketch> = sketch_set.into();
|
||||
@ -90,7 +85,7 @@ async fn inner_extrude(
|
||||
// Before we extrude, we need to enable the sketch mode.
|
||||
// We do this here in case extrude is called out of order.
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::EnableSketchMode {
|
||||
animated: false,
|
||||
ortho: false,
|
||||
@ -117,26 +112,21 @@ async fn inner_extrude(
|
||||
|
||||
// Disable the sketch mode.
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
||||
)
|
||||
.await?;
|
||||
solids.push(do_post_extrude(sketch.clone(), length, exec_state, args.clone()).await?);
|
||||
solids.push(do_post_extrude(sketch.clone(), length, args.clone()).await?);
|
||||
}
|
||||
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
pub(crate) async fn do_post_extrude(
|
||||
sketch: Sketch,
|
||||
length: f64,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Box<Solid>, KclError> {
|
||||
pub(crate) async fn do_post_extrude(sketch: Sketch, length: f64, args: Args) -> Result<Box<Solid>, KclError> {
|
||||
// Bring the object to the front of the scene.
|
||||
// See: https://github.com/KittyCAD/modeling-app/issues/806
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::ObjectBringToFront { object_id: sketch.id }),
|
||||
)
|
||||
.await?;
|
||||
@ -169,7 +159,7 @@ pub(crate) async fn do_post_extrude(
|
||||
|
||||
let solid3d_info = args
|
||||
.send_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dGetExtrusionFaceInfo {
|
||||
edge_id,
|
||||
object_id: sketch.id,
|
||||
@ -202,7 +192,7 @@ pub(crate) async fn do_post_extrude(
|
||||
// Instead, the Typescript codebases (which handles WebSocket sends when compiled via Wasm)
|
||||
// uses this to build the artifact graph, which the UI needs.
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
|
||||
edge_id: curve_id,
|
||||
object_id: sketch.id,
|
||||
@ -212,7 +202,7 @@ pub(crate) async fn do_post_extrude(
|
||||
.await?;
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
|
||||
edge_id: curve_id,
|
||||
object_id: sketch.id,
|
||||
@ -226,7 +216,7 @@ pub(crate) async fn do_post_extrude(
|
||||
sides: face_id_map,
|
||||
start_cap_id,
|
||||
end_cap_id,
|
||||
} = analyze_faces(exec_state, &args, face_infos);
|
||||
} = analyze_faces(&args, face_infos);
|
||||
// Iterate over the sketch.value array and add face_id to GeoMeta
|
||||
let new_value = sketch
|
||||
.value
|
||||
@ -262,7 +252,7 @@ pub(crate) async fn do_post_extrude(
|
||||
|
||||
let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::executor::ExtrudePlane {
|
||||
// pushing this values with a fake face_id to make extrudes mock-execute safe
|
||||
face_id: exec_state.id_generator.next_uuid(),
|
||||
face_id: Uuid::new_v4(),
|
||||
tag: path.get_base().tag.clone(),
|
||||
geo_meta: GeoMeta {
|
||||
id: path.get_base().geo_meta.id,
|
||||
@ -301,15 +291,15 @@ struct Faces {
|
||||
start_cap_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
fn analyze_faces(exec_state: &mut ExecState, args: &Args, face_infos: Vec<ExtrusionFaceInfo>) -> Faces {
|
||||
fn analyze_faces(args: &Args, face_infos: Vec<ExtrusionFaceInfo>) -> Faces {
|
||||
let mut faces = Faces {
|
||||
sides: HashMap::with_capacity(face_infos.len()),
|
||||
..Default::default()
|
||||
};
|
||||
if args.ctx.is_mock() {
|
||||
// Create fake IDs for start and end caps, to make extrudes mock-execute safe
|
||||
faces.start_cap_id = Some(exec_state.id_generator.next_uuid());
|
||||
faces.end_cap_id = Some(exec_state.id_generator.next_uuid());
|
||||
faces.start_cap_id = Some(Uuid::new_v4());
|
||||
faces.end_cap_id = Some(Uuid::new_v4());
|
||||
}
|
||||
for face_info in face_infos {
|
||||
match face_info.cap {
|
||||
|
||||
@ -142,7 +142,7 @@ async fn inner_fillet(
|
||||
for edge_tag in data.tags {
|
||||
let edge_id = edge_tag.get_engine_id(exec_state, &args)?;
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_end_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::Solid3dFilletEdge {
|
||||
@ -229,16 +229,15 @@ pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result
|
||||
}]
|
||||
async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<Uuid, KclError> {
|
||||
if args.ctx.is_mock() {
|
||||
return Ok(exec_state.id_generator.next_uuid());
|
||||
return Ok(Uuid::new_v4());
|
||||
}
|
||||
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
id,
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
|
||||
edge_id: tagged_path.id,
|
||||
object_id: tagged_path.sketch,
|
||||
@ -311,16 +310,15 @@ async fn inner_get_next_adjacent_edge(
|
||||
args: Args,
|
||||
) -> Result<Uuid, KclError> {
|
||||
if args.ctx.is_mock() {
|
||||
return Ok(exec_state.id_generator.next_uuid());
|
||||
return Ok(Uuid::new_v4());
|
||||
}
|
||||
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
id,
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
|
||||
edge_id: tagged_path.id,
|
||||
object_id: tagged_path.sketch,
|
||||
@ -401,16 +399,15 @@ async fn inner_get_previous_adjacent_edge(
|
||||
args: Args,
|
||||
) -> Result<Uuid, KclError> {
|
||||
if args.ctx.is_mock() {
|
||||
return Ok(exec_state.id_generator.next_uuid());
|
||||
return Ok(Uuid::new_v4());
|
||||
}
|
||||
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
id,
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dGetPrevAdjacentEdge {
|
||||
edge_id: tagged_path.id,
|
||||
object_id: tagged_path.sketch,
|
||||
|
||||
@ -32,10 +32,10 @@ pub struct HelixData {
|
||||
}
|
||||
|
||||
/// Create a helix on a cylinder.
|
||||
pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn helix(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, solid): (HelixData, Box<Solid>) = args.get_data_and_solid()?;
|
||||
|
||||
let solid = inner_helix(data, solid, exec_state, args).await?;
|
||||
let solid = inner_helix(data, solid, args).await?;
|
||||
Ok(KclValue::Solid(solid))
|
||||
}
|
||||
|
||||
@ -54,13 +54,8 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
#[stdlib {
|
||||
name = "helix",
|
||||
}]
|
||||
async fn inner_helix(
|
||||
data: HelixData,
|
||||
solid: Box<Solid>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Box<Solid>, KclError> {
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
async fn inner_helix(data: HelixData, solid: Box<Solid>, args: Args) -> Result<Box<Solid>, KclError> {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::EntityMakeHelix {
|
||||
|
||||
@ -126,10 +126,10 @@ impl From<ImportFormat> for InputFormat {
|
||||
///
|
||||
/// Import paths are relative to the current project directory. This only works in the desktop app
|
||||
/// not in browser.
|
||||
pub async fn import(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn import(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (file_path, options): (String, Option<ImportFormat>) = args.get_import_data()?;
|
||||
|
||||
let imported_geometry = inner_import(file_path, options, exec_state, args).await?;
|
||||
let imported_geometry = inner_import(file_path, options, args).await?;
|
||||
Ok(KclValue::ImportedGeometry(imported_geometry))
|
||||
}
|
||||
|
||||
@ -170,7 +170,6 @@ pub async fn import(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
async fn inner_import(
|
||||
file_path: String,
|
||||
options: Option<ImportFormat>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<ImportedGeometry, KclError> {
|
||||
if file_path.is_empty() {
|
||||
@ -287,13 +286,13 @@ async fn inner_import(
|
||||
|
||||
if args.ctx.is_mock() {
|
||||
return Ok(ImportedGeometry {
|
||||
id: exec_state.id_generator.next_uuid(),
|
||||
id: uuid::Uuid::new_v4(),
|
||||
value: import_files.iter().map(|f| f.path.to_string()).collect(),
|
||||
meta: vec![args.source_range.into()],
|
||||
});
|
||||
}
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
id,
|
||||
|
||||
@ -50,10 +50,10 @@ impl Default for LoftData {
|
||||
}
|
||||
|
||||
/// Create a 3D surface or solid by interpolating between two or more sketches.
|
||||
pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn loft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (sketches, data): (Vec<Sketch>, Option<LoftData>) = args.get_sketches_and_data()?;
|
||||
|
||||
let solid = inner_loft(sketches, data, exec_state, args).await?;
|
||||
let solid = inner_loft(sketches, data, args).await?;
|
||||
Ok(KclValue::Solid(solid))
|
||||
}
|
||||
|
||||
@ -135,12 +135,7 @@ pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
#[stdlib {
|
||||
name = "loft",
|
||||
}]
|
||||
async fn inner_loft(
|
||||
sketches: Vec<Sketch>,
|
||||
data: Option<LoftData>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Box<Solid>, KclError> {
|
||||
async fn inner_loft(sketches: Vec<Sketch>, data: Option<LoftData>, args: Args) -> Result<Box<Solid>, KclError> {
|
||||
// Make sure we have at least two sketches.
|
||||
if sketches.len() < 2 {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
@ -155,7 +150,7 @@ async fn inner_loft(
|
||||
// Get the loft data.
|
||||
let data = data.unwrap_or_default();
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::Loft {
|
||||
@ -171,5 +166,5 @@ async fn inner_loft(
|
||||
.await?;
|
||||
|
||||
// Using the first sketch as the base curve, idk we might want to change this later.
|
||||
do_post_extrude(sketches[0].clone(), 0.0, exec_state, args).await
|
||||
do_post_extrude(sketches[0].clone(), 0.0, args).await
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ async fn inner_mirror_2d(
|
||||
let (axis, origin) = axis.axis_and_origin()?;
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::EntityMirror {
|
||||
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
||||
axis,
|
||||
@ -134,7 +134,7 @@ async fn inner_mirror_2d(
|
||||
let edge_id = edge.get_engine_id(exec_state, &args)?;
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
|
||||
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
||||
edge_id,
|
||||
|
||||
@ -296,7 +296,7 @@ async fn inner_pattern_transform<'a>(
|
||||
|
||||
let mut solids = Vec::new();
|
||||
for e in starting_solids {
|
||||
let new_solids = send_pattern_transform(transform.clone(), &e, exec_state, args).await?;
|
||||
let new_solids = send_pattern_transform(transform.clone(), &e, args).await?;
|
||||
solids.extend(new_solids);
|
||||
}
|
||||
Ok(solids)
|
||||
@ -307,10 +307,9 @@ async fn send_pattern_transform(
|
||||
// https://github.com/KittyCAD/modeling-app/issues/2821
|
||||
transform: Vec<Transform>,
|
||||
solid: &Solid,
|
||||
exec_state: &mut ExecState,
|
||||
args: &Args,
|
||||
) -> Result<Vec<Box<Solid>>, KclError> {
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
@ -474,7 +473,7 @@ mod tests {
|
||||
}
|
||||
|
||||
/// A linear pattern on a 2D sketch.
|
||||
pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn pattern_linear_2d(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_set): (LinearPattern2dData, SketchSet) = args.get_data_and_sketch_set()?;
|
||||
|
||||
if data.axis == [0.0, 0.0] {
|
||||
@ -486,7 +485,7 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
|
||||
}));
|
||||
}
|
||||
|
||||
let sketches = inner_pattern_linear_2d(data, sketch_set, exec_state, args).await?;
|
||||
let sketches = inner_pattern_linear_2d(data, sketch_set, args).await?;
|
||||
Ok(sketches.into())
|
||||
}
|
||||
|
||||
@ -510,7 +509,6 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
|
||||
async fn inner_pattern_linear_2d(
|
||||
data: LinearPattern2dData,
|
||||
sketch_set: SketchSet,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Box<Sketch>>, KclError> {
|
||||
let starting_sketches: Vec<Box<Sketch>> = sketch_set.into();
|
||||
@ -524,7 +522,6 @@ async fn inner_pattern_linear_2d(
|
||||
let geometries = pattern_linear(
|
||||
LinearPattern::TwoD(data.clone()),
|
||||
Geometry::Sketch(sketch.clone()),
|
||||
exec_state,
|
||||
args.clone(),
|
||||
)
|
||||
.await?;
|
||||
@ -603,7 +600,6 @@ async fn inner_pattern_linear_3d(
|
||||
let geometries = pattern_linear(
|
||||
LinearPattern::ThreeD(data.clone()),
|
||||
Geometry::Solid(solid.clone()),
|
||||
exec_state,
|
||||
args.clone(),
|
||||
)
|
||||
.await?;
|
||||
@ -621,13 +617,8 @@ async fn inner_pattern_linear_3d(
|
||||
Ok(solids)
|
||||
}
|
||||
|
||||
async fn pattern_linear(
|
||||
data: LinearPattern,
|
||||
geometry: Geometry,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Geometries, KclError> {
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
async fn pattern_linear(data: LinearPattern, geometry: Geometry, args: Args) -> Result<Geometries, KclError> {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
let resp = args
|
||||
.send_modeling_cmd(
|
||||
@ -754,10 +745,10 @@ impl CircularPattern {
|
||||
}
|
||||
|
||||
/// A circular pattern on a 2D sketch.
|
||||
pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn pattern_circular_2d(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_set): (CircularPattern2dData, SketchSet) = args.get_data_and_sketch_set()?;
|
||||
|
||||
let sketches = inner_pattern_circular_2d(data, sketch_set, exec_state, args).await?;
|
||||
let sketches = inner_pattern_circular_2d(data, sketch_set, args).await?;
|
||||
Ok(sketches.into())
|
||||
}
|
||||
|
||||
@ -788,7 +779,6 @@ pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Resu
|
||||
async fn inner_pattern_circular_2d(
|
||||
data: CircularPattern2dData,
|
||||
sketch_set: SketchSet,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Box<Sketch>>, KclError> {
|
||||
let starting_sketches: Vec<Box<Sketch>> = sketch_set.into();
|
||||
@ -802,7 +792,6 @@ async fn inner_pattern_circular_2d(
|
||||
let geometries = pattern_circular(
|
||||
CircularPattern::TwoD(data.clone()),
|
||||
Geometry::Sketch(sketch.clone()),
|
||||
exec_state,
|
||||
args.clone(),
|
||||
)
|
||||
.await?;
|
||||
@ -872,7 +861,6 @@ async fn inner_pattern_circular_3d(
|
||||
let geometries = pattern_circular(
|
||||
CircularPattern::ThreeD(data.clone()),
|
||||
Geometry::Solid(solid.clone()),
|
||||
exec_state,
|
||||
args.clone(),
|
||||
)
|
||||
.await?;
|
||||
@ -890,13 +878,8 @@ async fn inner_pattern_circular_3d(
|
||||
Ok(solids)
|
||||
}
|
||||
|
||||
async fn pattern_circular(
|
||||
data: CircularPattern,
|
||||
geometry: Geometry,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Geometries, KclError> {
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
async fn pattern_circular(data: CircularPattern, geometry: Geometry, args: Args) -> Result<Geometries, KclError> {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
let center = data.center();
|
||||
let resp = args
|
||||
|
||||
@ -48,10 +48,10 @@ impl From<StandardPlane> for PlaneData {
|
||||
}
|
||||
|
||||
/// Offset a plane by a distance along its normal.
|
||||
pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn offset_plane(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (std_plane, offset): (StandardPlane, f64) = args.get_data_and_float()?;
|
||||
|
||||
let plane = inner_offset_plane(std_plane, offset, exec_state).await?;
|
||||
let plane = inner_offset_plane(std_plane, offset).await?;
|
||||
|
||||
Ok(KclValue::UserVal(UserVal::new(
|
||||
vec![Metadata {
|
||||
@ -132,15 +132,11 @@ pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclV
|
||||
#[stdlib {
|
||||
name = "offsetPlane",
|
||||
}]
|
||||
async fn inner_offset_plane(
|
||||
std_plane: StandardPlane,
|
||||
offset: f64,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<PlaneData, KclError> {
|
||||
async fn inner_offset_plane(std_plane: StandardPlane, offset: f64) -> Result<PlaneData, KclError> {
|
||||
// Convert to the plane type.
|
||||
let plane_data: PlaneData = std_plane.into();
|
||||
// Convert to a plane.
|
||||
let mut plane = Plane::from_plane_data(plane_data, exec_state);
|
||||
let mut plane = Plane::from(plane_data);
|
||||
|
||||
match std_plane {
|
||||
StandardPlane::XY => {
|
||||
|
||||
@ -263,7 +263,7 @@ async fn inner_revolve(
|
||||
|
||||
let angle = Angle::from_degrees(data.angle.unwrap_or(360.0));
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
match data.axis {
|
||||
AxisOrEdgeReference::Axis(axis) => {
|
||||
let (axis, origin) = axis.axis_and_origin()?;
|
||||
@ -295,7 +295,7 @@ async fn inner_revolve(
|
||||
}
|
||||
}
|
||||
|
||||
do_post_extrude(sketch, 0.0, exec_state, args).await
|
||||
do_post_extrude(sketch, 0.0, args).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -97,7 +97,7 @@ async fn inner_circle(
|
||||
let angle_start = Angle::zero();
|
||||
let angle_end = Angle::turn();
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
|
||||
@ -229,7 +229,7 @@ async fn inner_shell(
|
||||
}
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dShellFace {
|
||||
hollow: false,
|
||||
face_ids,
|
||||
@ -314,7 +314,7 @@ async fn inner_hollow(
|
||||
args.flush_batch_for_solid_set(exec_state, solid.clone().into()).await?;
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid3dShellFace {
|
||||
hollow: true,
|
||||
face_ids: Vec::new(), // This is empty because we want to hollow the entire object.
|
||||
|
||||
@ -16,12 +16,12 @@ use crate::{
|
||||
ast::types::TagDeclarator,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{
|
||||
BasePath, ExecState, Face, GeoMeta, KclValue, Path, Plane, Point2d, Point3d, Sketch, SketchSet, SketchSurface,
|
||||
Solid, TagEngineInfo, TagIdentifier, UserVal,
|
||||
BasePath, ExecState, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d, Sketch, SketchSet,
|
||||
SketchSurface, Solid, TagEngineInfo, TagIdentifier, UserVal,
|
||||
},
|
||||
std::{
|
||||
utils::{
|
||||
arc_angles, arc_center_and_end, get_tangent_point_from_previous_arc, get_tangential_arc_to_info,
|
||||
arc_angles, arc_start_center_and_end, get_tangent_point_from_previous_arc, get_tangential_arc_to_info,
|
||||
get_x_component, get_y_component, intersection_with_parallel_line, TangentialArcInfoInput,
|
||||
},
|
||||
Args,
|
||||
@ -93,10 +93,10 @@ pub enum StartOrEnd {
|
||||
}
|
||||
|
||||
/// Draw a line to a point.
|
||||
pub async fn line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch, tag): ([f64; 2], Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_line_to(to, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line_to(to, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -119,11 +119,10 @@ async fn inner_line_to(
|
||||
to: [f64; 2],
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
@ -160,10 +159,10 @@ async fn inner_line_to(
|
||||
}
|
||||
|
||||
/// Draw a line to a point on the x-axis.
|
||||
pub async fn x_line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn x_line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch, tag): (f64, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_x_line_to(to, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_x_line_to(to, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -193,25 +192,19 @@ pub async fn x_line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
#[stdlib {
|
||||
name = "xLineTo",
|
||||
}]
|
||||
async fn inner_x_line_to(
|
||||
to: f64,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
async fn inner_x_line_to(to: f64, sketch: Sketch, tag: Option<TagDeclarator>, args: Args) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
|
||||
let new_sketch = inner_line_to([to, from.y], sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line_to([to, from.y], sketch, tag, args).await?;
|
||||
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
/// Draw a line to a point on the y-axis.
|
||||
pub async fn y_line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn y_line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch, tag): (f64, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_y_line_to(to, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_y_line_to(to, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -234,24 +227,18 @@ pub async fn y_line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
#[stdlib {
|
||||
name = "yLineTo",
|
||||
}]
|
||||
async fn inner_y_line_to(
|
||||
to: f64,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
async fn inner_y_line_to(to: f64, sketch: Sketch, tag: Option<TagDeclarator>, args: Args) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
|
||||
let new_sketch = inner_line_to([from.x, to], sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line_to([from.x, to], sketch, tag, args).await?;
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
/// Draw a line.
|
||||
pub async fn line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (delta, sketch, tag): ([f64; 2], Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_line(delta, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line(delta, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -286,13 +273,12 @@ async fn inner_line(
|
||||
delta: [f64; 2],
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
let to = [from.x + delta[0], from.y + delta[1]];
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
@ -329,10 +315,10 @@ async fn inner_line(
|
||||
}
|
||||
|
||||
/// Draw a line on the x-axis.
|
||||
pub async fn x_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn x_line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (length, sketch, tag): (f64, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_x_line(length, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_x_line(length, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -361,21 +347,15 @@ pub async fn x_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
#[stdlib {
|
||||
name = "xLine",
|
||||
}]
|
||||
async fn inner_x_line(
|
||||
length: f64,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
inner_line([length, 0.0], sketch, tag, exec_state, args).await
|
||||
async fn inner_x_line(length: f64, sketch: Sketch, tag: Option<TagDeclarator>, args: Args) -> Result<Sketch, KclError> {
|
||||
inner_line([length, 0.0], sketch, tag, args).await
|
||||
}
|
||||
|
||||
/// Draw a line on the y-axis.
|
||||
pub async fn y_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn y_line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (length, sketch, tag): (f64, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_y_line(length, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_y_line(length, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -399,14 +379,8 @@ pub async fn y_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
#[stdlib {
|
||||
name = "yLine",
|
||||
}]
|
||||
async fn inner_y_line(
|
||||
length: f64,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
inner_line([0.0, length], sketch, tag, exec_state, args).await
|
||||
async fn inner_y_line(length: f64, sketch: Sketch, tag: Option<TagDeclarator>, args: Args) -> Result<Sketch, KclError> {
|
||||
inner_line([0.0, length], sketch, tag, args).await
|
||||
}
|
||||
|
||||
/// Data to draw an angled line.
|
||||
@ -426,10 +400,10 @@ pub enum AngledLineData {
|
||||
}
|
||||
|
||||
/// Draw an angled line.
|
||||
pub async fn angled_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn angled_line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (AngledLineData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_angled_line(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_angled_line(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -457,7 +431,6 @@ async fn inner_angled_line(
|
||||
data: AngledLineData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
@ -475,7 +448,7 @@ async fn inner_angled_line(
|
||||
|
||||
let to: [f64; 2] = [from.x + delta[0], from.y + delta[1]];
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
@ -511,10 +484,10 @@ async fn inner_angled_line(
|
||||
}
|
||||
|
||||
/// Draw an angled line of a given x length.
|
||||
pub async fn angled_line_of_x_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn angled_line_of_x_length(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (AngledLineData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_angled_line_of_x_length(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_angled_line_of_x_length(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -538,7 +511,6 @@ async fn inner_angled_line_of_x_length(
|
||||
data: AngledLineData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let (angle, length) = match data {
|
||||
@ -562,7 +534,7 @@ async fn inner_angled_line_of_x_length(
|
||||
|
||||
let to = get_y_component(Angle::from_degrees(angle), length);
|
||||
|
||||
let new_sketch = inner_line(to.into(), sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line(to.into(), sketch, tag, args).await?;
|
||||
|
||||
Ok(new_sketch)
|
||||
}
|
||||
@ -579,10 +551,10 @@ pub struct AngledLineToData {
|
||||
}
|
||||
|
||||
/// Draw an angled line to a given x coordinate.
|
||||
pub async fn angled_line_to_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn angled_line_to_x(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (AngledLineToData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_angled_line_to_x(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_angled_line_to_x(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -607,7 +579,6 @@ async fn inner_angled_line_to_x(
|
||||
data: AngledLineToData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
@ -631,15 +602,15 @@ async fn inner_angled_line_to_x(
|
||||
let y_component = x_component * f64::tan(angle.to_radians());
|
||||
let y_to = from.y + y_component;
|
||||
|
||||
let new_sketch = inner_line_to([x_to, y_to], sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line_to([x_to, y_to], sketch, tag, args).await?;
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
/// Draw an angled line of a given y length.
|
||||
pub async fn angled_line_of_y_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn angled_line_of_y_length(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (AngledLineData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_angled_line_of_y_length(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_angled_line_of_y_length(data, sketch, tag, args).await?;
|
||||
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
@ -666,7 +637,6 @@ async fn inner_angled_line_of_y_length(
|
||||
data: AngledLineData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let (angle, length) = match data {
|
||||
@ -690,16 +660,16 @@ async fn inner_angled_line_of_y_length(
|
||||
|
||||
let to = get_x_component(Angle::from_degrees(angle), length);
|
||||
|
||||
let new_sketch = inner_line(to.into(), sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line(to.into(), sketch, tag, args).await?;
|
||||
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
/// Draw an angled line to a given y coordinate.
|
||||
pub async fn angled_line_to_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn angled_line_to_y(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (AngledLineToData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_angled_line_to_y(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_angled_line_to_y(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -724,7 +694,6 @@ async fn inner_angled_line_to_y(
|
||||
data: AngledLineToData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
@ -748,7 +717,7 @@ async fn inner_angled_line_to_y(
|
||||
let x_component = y_component / f64::tan(angle.to_radians());
|
||||
let x_to = from.x + x_component;
|
||||
|
||||
let new_sketch = inner_line_to([x_to, y_to], sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line_to([x_to, y_to], sketch, tag, args).await?;
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
@ -819,7 +788,7 @@ async fn inner_angled_line_that_intersects(
|
||||
from,
|
||||
);
|
||||
|
||||
let new_sketch = inner_line_to(to.into(), sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_line_to(to.into(), sketch, tag, args).await?;
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
@ -922,6 +891,82 @@ pub enum PlaneData {
|
||||
},
|
||||
}
|
||||
|
||||
impl From<PlaneData> for Plane {
|
||||
fn from(value: PlaneData) -> Self {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
match value {
|
||||
PlaneData::XY => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
z_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
value: PlaneType::XY,
|
||||
meta: vec![],
|
||||
},
|
||||
PlaneData::NegXY => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
z_axis: Point3d::new(0.0, 0.0, -1.0),
|
||||
value: PlaneType::XY,
|
||||
meta: vec![],
|
||||
},
|
||||
PlaneData::XZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(0.0, -1.0, 0.0),
|
||||
value: PlaneType::XZ,
|
||||
meta: vec![],
|
||||
},
|
||||
PlaneData::NegXZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(-1.0, 0.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
value: PlaneType::XZ,
|
||||
meta: vec![],
|
||||
},
|
||||
PlaneData::YZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
value: PlaneType::YZ,
|
||||
meta: vec![],
|
||||
},
|
||||
PlaneData::NegYZ => Plane {
|
||||
id,
|
||||
origin: Point3d::new(0.0, 0.0, 0.0),
|
||||
x_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(-1.0, 0.0, 0.0),
|
||||
value: PlaneType::YZ,
|
||||
meta: vec![],
|
||||
},
|
||||
PlaneData::Plane {
|
||||
origin,
|
||||
x_axis,
|
||||
y_axis,
|
||||
z_axis,
|
||||
} => Plane {
|
||||
id,
|
||||
origin: *origin,
|
||||
x_axis: *x_axis,
|
||||
y_axis: *y_axis,
|
||||
z_axis: *z_axis,
|
||||
value: PlaneType::Custom,
|
||||
meta: vec![],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Start a sketch on a specific plane or face.
|
||||
pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, tag): (SketchData, Option<FaceTag>) = args.get_data_and_optional_tag()?;
|
||||
@ -1044,7 +1089,7 @@ async fn inner_start_sketch_on(
|
||||
) -> Result<SketchSurface, KclError> {
|
||||
match data {
|
||||
SketchData::Plane(plane_data) => {
|
||||
let plane = start_sketch_on_plane(plane_data, exec_state, args).await?;
|
||||
let plane = start_sketch_on_plane(plane_data, args).await?;
|
||||
Ok(SketchSurface::Plane(plane))
|
||||
}
|
||||
SketchData::Solid(solid) => {
|
||||
@ -1080,19 +1125,11 @@ async fn start_sketch_on_face(
|
||||
}))
|
||||
}
|
||||
|
||||
async fn start_sketch_on_plane(
|
||||
data: PlaneData,
|
||||
exec_state: &mut ExecState,
|
||||
args: &Args,
|
||||
) -> Result<Box<Plane>, KclError> {
|
||||
let mut plane = Plane::from_plane_data(data.clone(), exec_state);
|
||||
async fn start_sketch_on_plane(data: PlaneData, args: &Args) -> Result<Box<Plane>, KclError> {
|
||||
let mut plane: Plane = data.clone().into();
|
||||
|
||||
// Get the default planes.
|
||||
let default_planes = args
|
||||
.ctx
|
||||
.engine
|
||||
.default_planes(&mut exec_state.id_generator, args.source_range)
|
||||
.await?;
|
||||
let default_planes = args.ctx.engine.default_planes(args.source_range).await?;
|
||||
|
||||
plane.id = match data {
|
||||
PlaneData::XY => default_planes.xy,
|
||||
@ -1108,7 +1145,7 @@ async fn start_sketch_on_plane(
|
||||
z_axis: _,
|
||||
} => {
|
||||
// Create the custom plane on the fly.
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::MakePlane {
|
||||
@ -1191,7 +1228,7 @@ pub(crate) async fn inner_start_profile_at(
|
||||
|
||||
// Enter sketch mode on the surface.
|
||||
// We call this here so you can reuse the sketch surface for multiple sketches.
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::EnableSketchMode {
|
||||
@ -1209,8 +1246,8 @@ pub(crate) async fn inner_start_profile_at(
|
||||
)
|
||||
.await?;
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let path_id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
let path_id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(path_id, ModelingCmd::from(mcmd::StartPath {}))
|
||||
.await?;
|
||||
@ -1338,10 +1375,10 @@ pub(crate) fn inner_profile_start(sketch: Sketch) -> Result<[f64; 2], KclError>
|
||||
}
|
||||
|
||||
/// Close the current sketch.
|
||||
pub async fn close(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn close(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (sketch, tag): (Sketch, Option<TagDeclarator>) = args.get_sketch_and_optional_tag()?;
|
||||
|
||||
let new_sketch = inner_close(sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_close(sketch, tag, args).await?;
|
||||
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
@ -1370,16 +1407,11 @@ pub async fn close(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
#[stdlib {
|
||||
name = "close",
|
||||
}]
|
||||
pub(crate) async fn inner_close(
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
pub(crate) async fn inner_close(sketch: Sketch, tag: Option<TagDeclarator>, args: Args) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
let to: Point2d = sketch.start.from.into();
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(id, ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }))
|
||||
.await?;
|
||||
@ -1388,7 +1420,7 @@ pub(crate) async fn inner_close(
|
||||
if let SketchSurface::Plane(_) = sketch.on {
|
||||
// We were on a plane, disable the sketch mode.
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
||||
)
|
||||
.await?;
|
||||
@ -1446,13 +1478,24 @@ pub enum ArcData {
|
||||
}
|
||||
|
||||
/// Draw an arc.
|
||||
pub async fn arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn arc(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (ArcData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_arc(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_arc(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
/// Squared distance between two points
|
||||
fn distance_squared(a: Point2d, b: Point2d) -> f64 {
|
||||
let v = Point2d {
|
||||
x: b.x - a.x,
|
||||
y: b.y - a.y,
|
||||
};
|
||||
let dot = v.x * v.x + v.y * v.y;
|
||||
|
||||
dot
|
||||
}
|
||||
|
||||
/// Draw a curved line segment along an imaginary circle.
|
||||
/// The arc is constructed such that the current position of the sketch is
|
||||
/// placed along an imaginary circle of the specified radius, at angleStart
|
||||
@ -1482,7 +1525,6 @@ pub(crate) async fn inner_arc(
|
||||
data: ArcData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from: Point2d = sketch.current_pen_position()?;
|
||||
@ -1493,9 +1535,31 @@ pub(crate) async fn inner_arc(
|
||||
angle_end,
|
||||
radius,
|
||||
} => {
|
||||
let a_start = Angle::from_degrees(*angle_start);
|
||||
let a_end = Angle::from_degrees(*angle_end);
|
||||
let (center, end) = arc_center_and_end(from, a_start, a_end, *radius);
|
||||
let mut a_start = Angle::from_degrees(*angle_start);
|
||||
let mut a_end = Angle::from_degrees(*angle_end);
|
||||
|
||||
//duplicating engine logic to make sure this is _exactly_ what engine is doing - mike
|
||||
// if a_start.to_degrees() > a_end.to_degrees() {
|
||||
// // this implies a clockwise arc, so swap the angles to a matching counter-clockwise arc
|
||||
// std::mem::swap(&mut a_start, &mut a_end);
|
||||
// }
|
||||
|
||||
let (mut start, center, mut end) = arc_start_center_and_end(from, a_start, a_end, *radius);
|
||||
let desired_start = from;
|
||||
let dist1 = distance_squared(start, desired_start);
|
||||
let dist2 = distance_squared(end, desired_start);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
web_sys::console::log_1(&format!("testing {dist1} vs {dist2}!").into());
|
||||
}
|
||||
|
||||
if !(dist2 < dist1) { //flipped from engine ????????????
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
web_sys::console::log_1(&format!("swapping!").into());
|
||||
std::mem::swap(&mut start, &mut end);
|
||||
}
|
||||
|
||||
(center, a_start, a_end, *radius, end)
|
||||
}
|
||||
ArcData::CenterToRadius { center, to, radius } => {
|
||||
@ -1511,7 +1575,7 @@ pub(crate) async fn inner_arc(
|
||||
}));
|
||||
}
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
@ -1565,10 +1629,10 @@ pub enum TangentialArcData {
|
||||
}
|
||||
|
||||
/// Draw a tangential arc.
|
||||
pub async fn tangential_arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn tangential_arc(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (TangentialArcData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_tangential_arc(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_tangential_arc(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -1602,7 +1666,6 @@ async fn inner_tangential_arc(
|
||||
data: TangentialArcData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from: Point2d = sketch.current_pen_position()?;
|
||||
@ -1614,7 +1677,7 @@ async fn inner_tangential_arc(
|
||||
tangent_info.center_or_tangent_point
|
||||
};
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
let (center, to, ccw) = match data {
|
||||
TangentialArcData::RadiusAndOffset { radius, offset } => {
|
||||
@ -1641,7 +1704,7 @@ async fn inner_tangential_arc(
|
||||
// but the above logic *should* capture that behavior
|
||||
let start_angle = previous_end_tangent + tangent_to_arc_start_angle;
|
||||
let end_angle = start_angle + offset;
|
||||
let (center, to) = arc_center_and_end(from, start_angle, end_angle, radius);
|
||||
let (_, center, to) = arc_start_center_and_end(from, start_angle, end_angle, radius);
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
@ -1693,18 +1756,18 @@ fn tan_arc_to(sketch: &Sketch, to: &[f64; 2]) -> ModelingCmd {
|
||||
}
|
||||
|
||||
/// Draw a tangential arc to a specific point.
|
||||
pub async fn tangential_arc_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn tangential_arc_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch, tag): ([f64; 2], Sketch, Option<TagDeclarator>) = super::args::FromArgs::from_args(&args, 0)?;
|
||||
|
||||
let new_sketch = inner_tangential_arc_to(to, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_tangential_arc_to(to, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
/// Draw a tangential arc to point some distance away..
|
||||
pub async fn tangential_arc_to_relative(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn tangential_arc_to_relative(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (delta, sketch, tag): ([f64; 2], Sketch, Option<TagDeclarator>) = super::args::FromArgs::from_args(&args, 0)?;
|
||||
|
||||
let new_sketch = inner_tangential_arc_to_relative(delta, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_tangential_arc_to_relative(delta, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -1732,7 +1795,6 @@ async fn inner_tangential_arc_to(
|
||||
to: [f64; 2],
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from: Point2d = sketch.current_pen_position()?;
|
||||
@ -1751,7 +1813,7 @@ async fn inner_tangential_arc_to(
|
||||
});
|
||||
|
||||
let delta = [to_x - from.x, to_y - from.y];
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_modeling_cmd(id, tan_arc_to(&sketch, &delta)).await?;
|
||||
|
||||
let current_path = Path::TangentialArcTo {
|
||||
@ -1802,7 +1864,6 @@ async fn inner_tangential_arc_to_relative(
|
||||
delta: [f64; 2],
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from: Point2d = sketch.current_pen_position()?;
|
||||
@ -1836,7 +1897,7 @@ async fn inner_tangential_arc_to_relative(
|
||||
}));
|
||||
}
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
args.batch_modeling_cmd(id, tan_arc_to(&sketch, &delta)).await?;
|
||||
|
||||
let current_path = Path::TangentialArcTo {
|
||||
@ -1877,10 +1938,10 @@ pub struct BezierData {
|
||||
}
|
||||
|
||||
/// Draw a bezier curve.
|
||||
pub async fn bezier_curve(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn bezier_curve(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch, tag): (BezierData, Sketch, Option<TagDeclarator>) = args.get_data_and_sketch_and_tag()?;
|
||||
|
||||
let new_sketch = inner_bezier_curve(data, sketch, tag, exec_state, args).await?;
|
||||
let new_sketch = inner_bezier_curve(data, sketch, tag, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -1909,7 +1970,6 @@ async fn inner_bezier_curve(
|
||||
data: BezierData,
|
||||
sketch: Sketch,
|
||||
tag: Option<TagDeclarator>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
@ -1918,7 +1978,7 @@ async fn inner_bezier_curve(
|
||||
let delta = data.to;
|
||||
let to = [from.x + data.to[0], from.y + data.to[1]];
|
||||
|
||||
let id = exec_state.id_generator.next_uuid();
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
@ -1957,10 +2017,10 @@ async fn inner_bezier_curve(
|
||||
}
|
||||
|
||||
/// Use a sketch to cut a hole in another sketch.
|
||||
pub async fn hole(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn hole(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (hole_sketch, sketch): (SketchSet, Sketch) = args.get_sketches()?;
|
||||
|
||||
let new_sketch = inner_hole(hole_sketch, sketch, exec_state, args).await?;
|
||||
let new_sketch = inner_hole(hole_sketch, sketch, args).await?;
|
||||
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
|
||||
}
|
||||
|
||||
@ -1998,16 +2058,11 @@ pub async fn hole(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
#[stdlib {
|
||||
name = "hole",
|
||||
}]
|
||||
async fn inner_hole(
|
||||
hole_sketch: SketchSet,
|
||||
sketch: Sketch,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Sketch, KclError> {
|
||||
async fn inner_hole(hole_sketch: SketchSet, sketch: Sketch, args: Args) -> Result<Sketch, KclError> {
|
||||
let hole_sketches: Vec<Sketch> = hole_sketch.into();
|
||||
for hole_sketch in hole_sketches {
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::Solid2dAddHole {
|
||||
object_id: sketch.id,
|
||||
hole_id: hole_sketch.id,
|
||||
@ -2018,7 +2073,7 @@ async fn inner_hole(
|
||||
// suggestion (mike)
|
||||
// we also hide the source hole since its essentially "consumed" by this operation
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.id_generator.next_uuid(),
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::from(mcmd::ObjectVisible {
|
||||
object_id: hole_sketch.id,
|
||||
hidden: true,
|
||||
|
||||
@ -204,21 +204,76 @@ pub fn get_x_component(angle: Angle, y: f64) -> Point2d {
|
||||
Point2d { x, y }.scale(sign)
|
||||
}
|
||||
|
||||
pub fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) {
|
||||
fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) {
|
||||
let (_, center, end) = arc_start_center_and_end(from, start_angle, end_angle, radius);
|
||||
(center, end)
|
||||
}
|
||||
|
||||
pub fn arc_start_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d, Point2d) {
|
||||
let start_angle = start_angle.to_radians();
|
||||
let end_angle = end_angle.to_radians();
|
||||
|
||||
let eval = |t: f64, radius: f64, center: Point2d| { //UNUSED (this didn't work either for some reason.. - mike)
|
||||
//HACK - using this as an example to demonstrate that even something as simple as an arc can be problematic to
|
||||
//duplicate this type of logic on the frontend side because of all the little edge cases
|
||||
//we must come up with a better strategy to avoid this sort of stuff in the future.
|
||||
//having to manually port this sort of code directly into rust is error-prone, and
|
||||
//really isn't a good usage of dev time - mike
|
||||
let sin_of_pi = if ((4.0*PI).sin()).abs() > PI.sin().abs() {
|
||||
4.0*PI.sin().abs()
|
||||
} else {
|
||||
PI.sin().abs()
|
||||
};
|
||||
|
||||
let cos_of_pi_over_2 = if (4.5*PI).cos().abs() > (0.5*PI).sin().abs() {
|
||||
(4.5*PI).cos().abs()
|
||||
} else {
|
||||
(0.5*PI).sin().abs()
|
||||
};
|
||||
|
||||
let mut c = t.cos();
|
||||
let mut s = t.sin();
|
||||
|
||||
if c.abs() <= cos_of_pi_over_2 {
|
||||
c = 0.0;
|
||||
s = if s < 0.0 { -1.0 } else { 1.0 };
|
||||
} else if s.abs() <= sin_of_pi {
|
||||
s = 0.0;
|
||||
c = if c < 0.0 { -1.0 } else { 1.0 };
|
||||
}
|
||||
|
||||
Point2d {
|
||||
x: center.x + radius * c,
|
||||
y: center.y + radius * s,
|
||||
}
|
||||
};
|
||||
|
||||
let center = Point2d {
|
||||
x: -1.0 * (radius * start_angle.cos() - from.x),
|
||||
y: -1.0 * (radius * start_angle.sin() - from.y),
|
||||
};
|
||||
|
||||
//let start = eval(start_angle, radius, center);
|
||||
//let end = eval(end_angle, radius, center);
|
||||
|
||||
let start = Point2d {
|
||||
x: center.x + radius * start_angle.cos(),
|
||||
y: center.y + radius * start_angle.sin(),
|
||||
};
|
||||
|
||||
let end = Point2d {
|
||||
x: center.x + radius * end_angle.cos(),
|
||||
y: center.y + radius * end_angle.sin(),
|
||||
};
|
||||
|
||||
(center, end)
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
let start_deg = start_angle.to_degrees();
|
||||
let end_deg = end_angle.to_degrees();
|
||||
web_sys::console::log_1(&format!("Arc testing {start_deg:?}, {end_deg:?} -> center: {center:?}, start: {start:?} end: {end:?}").into());
|
||||
}
|
||||
|
||||
(start, center, end)
|
||||
}
|
||||
|
||||
pub fn arc_angles(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Types used to send data to the test server.
|
||||
|
||||
use crate::{
|
||||
executor::{ExecutorContext, ExecutorSettings, IdGenerator},
|
||||
executor::{ExecutorContext, ExecutorSettings},
|
||||
settings::types::UnitLength,
|
||||
};
|
||||
|
||||
@ -29,9 +29,7 @@ async fn do_execute_and_snapshot(ctx: &ExecutorContext, code: &str) -> anyhow::R
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast()?;
|
||||
|
||||
let snapshot = ctx
|
||||
.execute_and_prepare_snapshot(&program, IdGenerator::default())
|
||||
.await?;
|
||||
let snapshot = ctx.execute_and_prepare_snapshot(&program).await?;
|
||||
|
||||
// Create a temporary file to write the output to.
|
||||
let output_file = std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
|
||||
|
||||
142
src/wasm-lib/output.txt
Normal file
@ -0,0 +1,142 @@
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 16 filtered out; finished in 0.00s
|
||||
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 824 filtered out; finished in 0.00s
|
||||
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s
|
||||
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
|
||||
running 1 test
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
test visuals::server_rack_heavy has been running for over 60 seconds
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
extrude
|
||||
test visuals::server_rack_heavy ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
failures:
|
||||
visuals::server_rack_heavy
|
||||
|
||||
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 142 filtered out; finished in 279.58s
|
||||
|
||||
@ -16,7 +16,6 @@ use wasm_bindgen::prelude::*;
|
||||
pub async fn execute_wasm(
|
||||
program_str: &str,
|
||||
memory_str: &str,
|
||||
id_generator_str: &str,
|
||||
units: &str,
|
||||
engine_manager: kcl_lib::engine::conn_wasm::EngineCommandManager,
|
||||
fs_manager: kcl_lib::fs::wasm::FileSystemManager,
|
||||
@ -27,8 +26,6 @@ pub async fn execute_wasm(
|
||||
|
||||
let program: kcl_lib::ast::types::Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
let memory: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
||||
let id_generator: kcl_lib::executor::IdGenerator =
|
||||
serde_json::from_str(id_generator_str).map_err(|e| e.to_string())?;
|
||||
let units = kcl_lib::settings::types::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||
|
||||
let engine: std::sync::Arc<Box<dyn kcl_lib::engine::EngineManager>> = if is_mock {
|
||||
@ -61,16 +58,13 @@ pub async fn execute_wasm(
|
||||
context_type,
|
||||
};
|
||||
|
||||
let exec_state = ctx
|
||||
.run(&program, Some(memory), id_generator)
|
||||
.await
|
||||
.map_err(String::from)?;
|
||||
let exec_state = ctx.run(&program, Some(memory)).await.map_err(String::from)?;
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
// DO NOT USE serde_wasm_bindgen::to_value(&exec_state).map_err(|e| e.to_string())
|
||||
// DO NOT USE serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
|
||||
// it will break the frontend.
|
||||
JsValue::from_serde(&exec_state).map_err(|e| e.to_string())
|
||||
JsValue::from_serde(&exec_state.memory).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
// wasm_bindgen wrapper for execute
|
||||
@ -99,7 +93,7 @@ pub async fn make_default_planes(
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
let default_planes = engine
|
||||
.new_default_planes(&mut kcl_lib::executor::IdGenerator::default(), Default::default())
|
||||
.new_default_planes(Default::default())
|
||||
.await
|
||||
.map_err(String::from)?;
|
||||
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
use kcl_lib::{
|
||||
ast::types::Program,
|
||||
errors::KclError,
|
||||
executor::{ExecutorContext, IdGenerator},
|
||||
};
|
||||
use kcl_lib::{ast::types::Program, errors::KclError, executor::ExecutorContext};
|
||||
|
||||
macro_rules! gen_test {
|
||||
($file:ident) => {
|
||||
@ -26,12 +22,12 @@ macro_rules! gen_test_fail {
|
||||
}
|
||||
|
||||
async fn run(code: &str) {
|
||||
let (ctx, program, id_generator) = setup(code).await;
|
||||
let (ctx, program) = setup(code).await;
|
||||
|
||||
ctx.run(&program, None, id_generator).await.unwrap();
|
||||
ctx.run(&program, None).await.unwrap();
|
||||
}
|
||||
|
||||
async fn setup(program: &str) -> (ExecutorContext, Program, IdGenerator) {
|
||||
async fn setup(program: &str) -> (ExecutorContext, Program) {
|
||||
let tokens = kcl_lib::token::lexer(program).unwrap();
|
||||
let parser = kcl_lib::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
@ -44,12 +40,12 @@ async fn setup(program: &str) -> (ExecutorContext, Program, IdGenerator) {
|
||||
settings: Default::default(),
|
||||
context_type: kcl_lib::executor::ContextType::Mock,
|
||||
};
|
||||
(ctx, program, IdGenerator::default())
|
||||
(ctx, program)
|
||||
}
|
||||
|
||||
async fn run_fail(code: &str) -> KclError {
|
||||
let (ctx, program, id_generator) = setup(code).await;
|
||||
let Err(e) = ctx.run(&program, None, id_generator).await else {
|
||||
let (ctx, program) = setup(code).await;
|
||||
let Err(e) = ctx.run(&program, None).await else {
|
||||
panic!("Expected this KCL program to fail, but it (incorrectly) never threw an error.");
|
||||
};
|
||||
e
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::{
|
||||
ast::{modify::modify_ast_for_sketch, types::Program},
|
||||
executor::{ExecutorContext, IdGenerator, KclValue, PlaneType, Sketch, SourceRange},
|
||||
executor::{ExecutorContext, KclValue, PlaneType, Sketch, SourceRange},
|
||||
};
|
||||
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, shared::Point3d, ModelingCmd};
|
||||
use pretty_assertions::assert_eq;
|
||||
@ -35,7 +35,7 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
|
||||
let parser = kcl_lib::parser::Parser::new(tokens);
|
||||
let program = parser.ast()?;
|
||||
let ctx = kcl_lib::executor::ExecutorContext::new(&client, Default::default()).await?;
|
||||
let exec_state = ctx.run(&program, None, IdGenerator::default()).await?;
|
||||
let exec_state = ctx.run(&program, None).await?;
|
||||
|
||||
// We need to get the sketch ID.
|
||||
// Get the sketch ID from memory.
|
||||
|
||||