Compare commits
10 Commits
v0.37.0
...
nightly-v2
Author | SHA1 | Date | |
---|---|---|---|
8d9dbf36c3 | |||
440704ed9f | |||
2261217a5d | |||
10da986649 | |||
10789d9c3c | |||
67cc4f5835 | |||
2692f2b73a | |||
965cb18059 | |||
a022b8ef6c | |||
4d24bf7c94 |
20425
docs/kcl/std.json
20425
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
28
docs/kcl/types/Face.md
Normal file
28
docs/kcl/types/Face.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
title: "Face"
|
||||
excerpt: "A face."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
A face.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `id` |`string`| The id of the face. | No |
|
||||
| `value` |`string`| The tag of the face. | No |
|
||||
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face’s X axis be? | No |
|
||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face’s Y axis be? | No |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A face. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
@ -20,6 +20,7 @@ A helix.
|
||||
| `revolutions` |`number`| Number of revolutions. | No |
|
||||
| `angleStart` |`number`| Start angle (in degrees). | No |
|
||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A helix. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -20,6 +20,7 @@ A helix.
|
||||
| `revolutions` |`number`| Number of revolutions. | No |
|
||||
| `angleStart` |`number`| Start angle (in degrees). | No |
|
||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A helix. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -168,7 +168,6 @@ Any KCL value.
|
||||
|
||||
|
||||
----
|
||||
A plane.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
@ -181,17 +180,10 @@ A plane.
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: [`Plane`](/docs/kcl/types/Plane)| | No |
|
||||
| `id` |`string`| The id of the plane. | No |
|
||||
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Any KCL value. | 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 |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
| `value` |[`Plane`](/docs/kcl/types/Plane)| Any KCL value. | No |
|
||||
|
||||
|
||||
----
|
||||
A face.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
@ -203,14 +195,8 @@ A face.
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Face`| | No |
|
||||
| `id` |`string`| The id of the face. | No |
|
||||
| `value` |`string`| The tag of the face. | No |
|
||||
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face’s X axis be? | No |
|
||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face’s Y axis be? | No |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
| `type` |enum: [`Face`](/docs/kcl/types/Face)| | No |
|
||||
| `value` |[`Face`](/docs/kcl/types/Face)| Any KCL value. | No |
|
||||
|
||||
|
||||
----
|
||||
@ -246,7 +232,6 @@ A face.
|
||||
|
||||
|
||||
----
|
||||
An solid is a collection of extrude surfaces.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
@ -259,14 +244,7 @@ An solid is a collection of extrude surfaces.
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: [`Solid`](/docs/kcl/types/Solid)| | No |
|
||||
| `id` |`string`| The id of the solid. | No |
|
||||
| `value` |`[` [`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface) `]`| The extrude surfaces. | No |
|
||||
| `sketch` |[`Sketch`](/docs/kcl/types/Sketch)| The sketch. | No |
|
||||
| `height` |`number`| The height of the solid. | No |
|
||||
| `startCapId` |`string`| The id of the extrusion start cap | No |
|
||||
| `endCapId` |`string`| The id of the extrusion end cap | No |
|
||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
| `value` |[`Solid`](/docs/kcl/types/Solid)| Any KCL value. | No |
|
||||
|
||||
|
||||
----
|
||||
@ -286,7 +264,6 @@ An solid is a collection of extrude surfaces.
|
||||
|
||||
|
||||
----
|
||||
A helix.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
@ -299,11 +276,7 @@ A helix.
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: [`Helix`](/docs/kcl/types/Helix)| | No |
|
||||
| `value` |`string`| The id of the helix. | No |
|
||||
| `revolutions` |`number`| Number of revolutions. | No |
|
||||
| `angleStart` |`number`| Start angle (in degrees). | No |
|
||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
| `value` |[`Helix`](/docs/kcl/types/Helix)| Any KCL value. | No |
|
||||
|
||||
|
||||
----
|
||||
|
@ -22,6 +22,7 @@ A plane.
|
||||
| `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 |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A plane. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@ A sketch is a collection of paths.
|
||||
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
|
||||
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
|
||||
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch is a collection of paths. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@ A sketch is a collection of paths.
|
||||
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
|
||||
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
|
||||
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch or a group of sketches. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@ A plane.
|
||||
| `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 |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch type. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
@ -54,6 +55,7 @@ A face.
|
||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face’s Y axis be? | No |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch type. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@ An solid is a collection of extrude surfaces.
|
||||
| `startCapId` |`string`| The id of the extrusion start cap | No |
|
||||
| `endCapId` |`string`| The id of the extrusion end cap | No |
|
||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| An solid is a collection of extrude surfaces. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ An solid is a collection of extrude surfaces.
|
||||
| `startCapId` |`string`| The id of the extrusion start cap | No |
|
||||
| `endCapId` |`string`| The id of the extrusion end cap | No |
|
||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A solid or a group of solids. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
|
107
docs/kcl/types/UnitLen.md
Normal file
107
docs/kcl/types/UnitLen.md
Normal file
@ -0,0 +1,107 @@
|
||||
---
|
||||
title: "UnitLen"
|
||||
excerpt: ""
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
**This schema accepts exactly one of the following:**
|
||||
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Mm`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Cm`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `M`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Inches`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Feet`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Yards`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
@ -38,14 +38,14 @@ test.describe('Debug pane', () => {
|
||||
// Set the code in the code editor.
|
||||
await u.codeLocator.click()
|
||||
await page.keyboard.type(code, { delay: 0 })
|
||||
// Scroll to the feature tree.
|
||||
// Scroll to the artifact graph.
|
||||
await tree.scrollIntoViewIfNeeded()
|
||||
// Expand the feature tree.
|
||||
await tree.getByText('Feature Tree').click()
|
||||
// Expand the artifact graph.
|
||||
await tree.getByText('Artifact Graph').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.
|
||||
// Extract the artifact IDs from the debug artifact graph.
|
||||
const initialSegmentIds = await segment.innerText({ timeout: 5_000 })
|
||||
// The artifact ID should include a UUID.
|
||||
expect(initialSegmentIds).toMatch(
|
||||
|
@ -963,37 +963,31 @@ sketch002 = startSketchOn('XZ')
|
||||
await toolbar.sweepButton.click()
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Sweep',
|
||||
currentArgKey: 'profile',
|
||||
currentArgKey: 'target',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Path: '',
|
||||
Profile: '',
|
||||
Target: '',
|
||||
Trajectory: '',
|
||||
},
|
||||
highlightedHeaderArg: 'profile',
|
||||
highlightedHeaderArg: 'target',
|
||||
stage: 'arguments',
|
||||
})
|
||||
await clickOnSketch1()
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Sweep',
|
||||
currentArgKey: 'path',
|
||||
currentArgKey: 'trajectory',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Path: '',
|
||||
Profile: '1 face',
|
||||
Target: '1 face',
|
||||
Trajectory: '',
|
||||
},
|
||||
highlightedHeaderArg: 'path',
|
||||
highlightedHeaderArg: 'trajectory',
|
||||
stage: 'arguments',
|
||||
})
|
||||
await clickOnSketch2()
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Sweep',
|
||||
headerArguments: {
|
||||
Path: '1 face',
|
||||
Profile: '1 face',
|
||||
},
|
||||
stage: 'review',
|
||||
})
|
||||
await page.waitForTimeout(500)
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.waitForTimeout(500)
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
@ -1020,6 +1014,75 @@ sketch002 = startSketchOn('XZ')
|
||||
})
|
||||
})
|
||||
|
||||
test(`Sweep point-and-click failing validation`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `sketch001 = startSketchOn('YZ')
|
||||
|> circle({
|
||||
center = [0, 0],
|
||||
radius = 500
|
||||
}, %)
|
||||
sketch002 = startSketchOn('XZ')
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> xLine(-500, %)
|
||||
|> lineTo([-2000, 500], %)
|
||||
`
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.waitForExecutionDone()
|
||||
|
||||
// One dumb hardcoded screen pixel value
|
||||
const testPoint = { x: 700, y: 250 }
|
||||
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||
const [clickOnSketch2] = scene.makeMouseHelpers(testPoint.x - 50, testPoint.y)
|
||||
|
||||
await test.step(`Look for sketch001`, async () => {
|
||||
await toolbar.closePane('code')
|
||||
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
|
||||
})
|
||||
|
||||
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
|
||||
await toolbar.sweepButton.click()
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Sweep',
|
||||
currentArgKey: 'target',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Target: '',
|
||||
Trajectory: '',
|
||||
},
|
||||
highlightedHeaderArg: 'target',
|
||||
stage: 'arguments',
|
||||
})
|
||||
await clickOnSketch1()
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Sweep',
|
||||
currentArgKey: 'trajectory',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Target: '1 face',
|
||||
Trajectory: '',
|
||||
},
|
||||
highlightedHeaderArg: 'trajectory',
|
||||
stage: 'arguments',
|
||||
})
|
||||
await clickOnSketch2()
|
||||
await page.waitForTimeout(500)
|
||||
await cmdBar.progressCmdBar()
|
||||
await expect(
|
||||
page.getByText('Unable to sweep with the provided selection')
|
||||
).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test(`Fillet point-and-click`, async ({
|
||||
context,
|
||||
page,
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Binary file not shown.
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 60 KiB |
@ -201,7 +201,7 @@
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.19.1",
|
||||
"vite": "^5.4.6",
|
||||
"vite": "^5.4.12",
|
||||
"vite-plugin-package-version": "^1.1.0",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^1.6.0",
|
||||
|
217
src/Toolbar.tsx
217
src/Toolbar.tsx
@ -1,4 +1,4 @@
|
||||
import { useRef, useMemo, memo } from 'react'
|
||||
import { useRef, useMemo, memo, useCallback, useState } from 'react'
|
||||
import { isCursorInSketchCommandRange } from 'lang/util'
|
||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
@ -34,8 +34,7 @@ export function Toolbar({
|
||||
const bgClassName = '!bg-transparent'
|
||||
const buttonBgClassName =
|
||||
'bg-chalkboard-transparent dark:bg-transparent disabled:bg-transparent dark:disabled:bg-transparent enabled:hover:bg-chalkboard-10 dark:enabled:hover:bg-chalkboard-100 pressed:!bg-primary pressed:enabled:hover:!text-chalkboard-10'
|
||||
const buttonBorderClassName =
|
||||
'!border-transparent hover:!border-chalkboard-20 dark:enabled:hover:!border-primary pressed:!border-primary ui-open:!border-primary'
|
||||
const buttonBorderClassName = '!border-transparent'
|
||||
|
||||
const sketchPathId = useMemo(() => {
|
||||
if (!isSingleCursorInPipe(context.selectionRanges, kclManager.ast))
|
||||
@ -50,6 +49,7 @@ export function Toolbar({
|
||||
const { overallState } = useNetworkContext()
|
||||
const { isExecuting } = useKclContext()
|
||||
const { isStreamReady } = useAppState()
|
||||
const [showRichContent, setShowRichContent] = useState(false)
|
||||
|
||||
const disableAllButtons =
|
||||
(overallState !== NetworkHealthState.Ok &&
|
||||
@ -77,6 +77,40 @@ export function Toolbar({
|
||||
[state, send, commandBarSend, sketchPathId]
|
||||
)
|
||||
|
||||
const tooltipContentClassName = !showRichContent
|
||||
? ''
|
||||
: '!text-left text-wrap !text-xs !p-0 !pb-2 flex gap-2 !max-w-none !w-72 flex-col items-stretch'
|
||||
const richContentTimeout = useRef<number | null>(null)
|
||||
const richContentClearTimeout = useRef<number | null>(null)
|
||||
// On mouse enter, show rich content after a 1s delay
|
||||
const handleMouseEnter = useCallback(() => {
|
||||
// Cancel the clear timeout if it's already set
|
||||
if (richContentClearTimeout.current) {
|
||||
clearTimeout(richContentClearTimeout.current)
|
||||
}
|
||||
// Start our own timeout to show the rich content
|
||||
richContentTimeout.current = window.setTimeout(() => {
|
||||
setShowRichContent(true)
|
||||
if (richContentClearTimeout.current) {
|
||||
clearTimeout(richContentClearTimeout.current)
|
||||
}
|
||||
}, 1000)
|
||||
}, [setShowRichContent])
|
||||
// On mouse leave, clear the timeout and hide rich content
|
||||
const handleMouseLeave = useCallback(() => {
|
||||
// Clear the timeout to show rich content
|
||||
if (richContentTimeout.current) {
|
||||
clearTimeout(richContentTimeout.current)
|
||||
}
|
||||
// Start a timeout to hide the rich content
|
||||
richContentClearTimeout.current = window.setTimeout(() => {
|
||||
setShowRichContent(false)
|
||||
if (richContentClearTimeout.current) {
|
||||
clearTimeout(richContentClearTimeout.current)
|
||||
}
|
||||
}, 500)
|
||||
}, [setShowRichContent])
|
||||
|
||||
/**
|
||||
* Resolve all the callbacks and values for the current mode,
|
||||
* so we don't need to worry about the other modes
|
||||
@ -174,44 +208,64 @@ export function Toolbar({
|
||||
status: itemConfig.status,
|
||||
}))}
|
||||
>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
id={maybeIconConfig[0].id}
|
||||
data-testid={maybeIconConfig[0].id}
|
||||
iconStart={{
|
||||
icon: maybeIconConfig[0].icon,
|
||||
className: iconClassName,
|
||||
bgClassName: bgClassName,
|
||||
}}
|
||||
className={
|
||||
'!border-transparent !px-0 pressed:!text-chalkboard-10 pressed:enabled:hovered:!text-chalkboard-10 ' +
|
||||
buttonBgClassName
|
||||
}
|
||||
aria-pressed={maybeIconConfig[0].isActive}
|
||||
disabled={
|
||||
disableAllButtons ||
|
||||
maybeIconConfig[0].status !== 'available' ||
|
||||
maybeIconConfig[0].disabled
|
||||
}
|
||||
name={maybeIconConfig[0].title}
|
||||
// aria-description is still in ARIA 1.3 draft.
|
||||
// eslint-disable-next-line jsx-a11y/aria-props
|
||||
aria-description={maybeIconConfig[0].description}
|
||||
onClick={() =>
|
||||
maybeIconConfig[0].onClick(configCallbackProps)
|
||||
}
|
||||
<div
|
||||
className="contents"
|
||||
// Mouse events do not fire on disabled buttons
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<span
|
||||
className={!maybeIconConfig[0].showTitle ? 'sr-only' : ''}
|
||||
<ActionButton
|
||||
Element="button"
|
||||
id={maybeIconConfig[0].id}
|
||||
data-testid={maybeIconConfig[0].id}
|
||||
iconStart={{
|
||||
icon: maybeIconConfig[0].icon,
|
||||
className: iconClassName,
|
||||
bgClassName: bgClassName,
|
||||
}}
|
||||
className={
|
||||
'!border-transparent !px-0 pressed:!text-chalkboard-10 pressed:enabled:hovered:!text-chalkboard-10 ' +
|
||||
buttonBgClassName
|
||||
}
|
||||
aria-pressed={maybeIconConfig[0].isActive}
|
||||
disabled={
|
||||
disableAllButtons ||
|
||||
maybeIconConfig[0].status !== 'available' ||
|
||||
maybeIconConfig[0].disabled
|
||||
}
|
||||
name={maybeIconConfig[0].title}
|
||||
// aria-description is still in ARIA 1.3 draft.
|
||||
// eslint-disable-next-line jsx-a11y/aria-props
|
||||
aria-description={maybeIconConfig[0].description}
|
||||
onClick={() =>
|
||||
maybeIconConfig[0].onClick(configCallbackProps)
|
||||
}
|
||||
>
|
||||
{maybeIconConfig[0].title}
|
||||
</span>
|
||||
</ActionButton>
|
||||
<ToolbarItemTooltip
|
||||
itemConfig={maybeIconConfig[0]}
|
||||
configCallbackProps={configCallbackProps}
|
||||
className="ui-open:!hidden"
|
||||
/>
|
||||
<span
|
||||
className={!maybeIconConfig[0].showTitle ? 'sr-only' : ''}
|
||||
>
|
||||
{maybeIconConfig[0].title}
|
||||
</span>
|
||||
<ToolbarItemTooltip
|
||||
itemConfig={maybeIconConfig[0]}
|
||||
configCallbackProps={configCallbackProps}
|
||||
wrapperClassName="ui-open:!hidden"
|
||||
contentClassName={tooltipContentClassName}
|
||||
>
|
||||
{showRichContent ? (
|
||||
<ToolbarItemTooltipRichContent
|
||||
itemConfig={maybeIconConfig[0]}
|
||||
/>
|
||||
) : (
|
||||
<ToolbarItemTooltipShortContent
|
||||
status={maybeIconConfig[0].status}
|
||||
title={maybeIconConfig[0].title}
|
||||
hotkey={maybeIconConfig[0].hotkey}
|
||||
/>
|
||||
)}
|
||||
</ToolbarItemTooltip>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</ActionButtonDropdown>
|
||||
)
|
||||
}
|
||||
@ -219,7 +273,13 @@ export function Toolbar({
|
||||
|
||||
// A single button
|
||||
return (
|
||||
<div className="relative" key={itemConfig.id}>
|
||||
<div
|
||||
className="relative"
|
||||
key={itemConfig.id}
|
||||
// Mouse events do not fire on disabled buttons
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
key={itemConfig.id}
|
||||
@ -256,7 +316,18 @@ export function Toolbar({
|
||||
<ToolbarItemTooltip
|
||||
itemConfig={itemConfig}
|
||||
configCallbackProps={configCallbackProps}
|
||||
/>
|
||||
contentClassName={tooltipContentClassName}
|
||||
>
|
||||
{showRichContent ? (
|
||||
<ToolbarItemTooltipRichContent itemConfig={itemConfig} />
|
||||
) : (
|
||||
<ToolbarItemTooltipShortContent
|
||||
status={itemConfig.status}
|
||||
title={itemConfig.title}
|
||||
hotkey={itemConfig.hotkey}
|
||||
/>
|
||||
)}
|
||||
</ToolbarItemTooltip>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@ -270,6 +341,12 @@ export function Toolbar({
|
||||
)
|
||||
}
|
||||
|
||||
interface ToolbarItemContentsProps extends React.PropsWithChildren {
|
||||
itemConfig: ToolbarItemResolved
|
||||
configCallbackProps: ToolbarItemCallbackProps
|
||||
wrapperClassName?: string
|
||||
contentClassName?: string
|
||||
}
|
||||
/**
|
||||
* The single button and dropdown button share content, so we extract it here
|
||||
* It contains a tooltip with the title, description, and links
|
||||
@ -278,14 +355,10 @@ export function Toolbar({
|
||||
const ToolbarItemTooltip = memo(function ToolbarItemContents({
|
||||
itemConfig,
|
||||
configCallbackProps,
|
||||
className,
|
||||
}: {
|
||||
itemConfig: ToolbarItemResolved
|
||||
configCallbackProps: ToolbarItemCallbackProps
|
||||
className?: string
|
||||
}) {
|
||||
const { state } = useModelingContext()
|
||||
|
||||
wrapperClassName = '',
|
||||
contentClassName = '',
|
||||
children,
|
||||
}: ToolbarItemContentsProps) {
|
||||
useHotkeys(
|
||||
itemConfig.hotkey || '',
|
||||
() => {
|
||||
@ -310,10 +383,48 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
|
||||
}
|
||||
hoverOnly
|
||||
position="bottom"
|
||||
wrapperClassName={'!p-4 !pointer-events-auto ' + className}
|
||||
contentClassName="!text-left text-wrap !text-xs !p-0 !pb-2 flex gap-2 !max-w-none !w-72 flex-col items-stretch"
|
||||
wrapperClassName={'!p-4 !pointer-events-auto ' + wrapperClassName}
|
||||
contentClassName={contentClassName}
|
||||
delay={0}
|
||||
>
|
||||
{children}
|
||||
</Tooltip>
|
||||
)
|
||||
})
|
||||
|
||||
const ToolbarItemTooltipShortContent = ({
|
||||
status,
|
||||
title,
|
||||
hotkey,
|
||||
}: {
|
||||
status: string
|
||||
title: string
|
||||
hotkey?: string | string[]
|
||||
}) => (
|
||||
<span
|
||||
className={`text-sm ${
|
||||
status !== 'available' ? 'text-chalkboard-70 dark:text-chalkboard-40' : ''
|
||||
}`}
|
||||
>
|
||||
{title}
|
||||
{hotkey && (
|
||||
<kbd className="inline-block ml-2 flex-none hotkey">{hotkey}</kbd>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
|
||||
const ToolbarItemTooltipRichContent = ({
|
||||
itemConfig,
|
||||
}: {
|
||||
itemConfig: ToolbarItemResolved
|
||||
}) => {
|
||||
const { state } = useModelingContext()
|
||||
return (
|
||||
<>
|
||||
<div className="rounded-top flex items-center gap-2 pt-3 pb-2 px-2 bg-chalkboard-20/50 dark:bg-chalkboard-80/50">
|
||||
{itemConfig.icon && (
|
||||
<CustomIcon className="w-5 h-5" name={itemConfig.icon} />
|
||||
)}
|
||||
<span
|
||||
className={`text-sm flex-1 ${
|
||||
itemConfig.status !== 'available'
|
||||
@ -382,6 +493,6 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</Tooltip>
|
||||
</>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -1398,23 +1398,23 @@ export class SceneEntities {
|
||||
|
||||
const arg0 = arg(kclCircle3PointArgs[0])
|
||||
if (!arg0) return kclManager.ast
|
||||
arg0[0].value = points[0].x
|
||||
arg0[0].value = { value: points[0].x, suffix: 'None' }
|
||||
arg0[0].raw = points[0].x.toString()
|
||||
arg0[1].value = points[0].y
|
||||
arg0[1].value = { value: points[0].y, suffix: 'None' }
|
||||
arg0[1].raw = points[0].y.toString()
|
||||
|
||||
const arg1 = arg(kclCircle3PointArgs[1])
|
||||
if (!arg1) return kclManager.ast
|
||||
arg1[0].value = points[1].x
|
||||
arg1[0].value = { value: points[1].x, suffix: 'None' }
|
||||
arg1[0].raw = points[1].x.toString()
|
||||
arg1[1].value = points[1].y
|
||||
arg1[1].value = { value: points[1].y, suffix: 'None' }
|
||||
arg1[1].raw = points[1].y.toString()
|
||||
|
||||
const arg2 = arg(kclCircle3PointArgs[2])
|
||||
if (!arg2) return kclManager.ast
|
||||
arg2[0].value = points[2].x
|
||||
arg2[0].value = { value: points[2].x, suffix: 'None' }
|
||||
arg2[0].raw = points[2].x.toString()
|
||||
arg2[1].value = points[2].y
|
||||
arg2[1].value = { value: points[2].y, suffix: 'None' }
|
||||
arg2[1].raw = points[2].y.toString()
|
||||
|
||||
const astSnapshot = structuredClone(kclManager.ast)
|
||||
@ -2051,8 +2051,8 @@ export class SceneEntities {
|
||||
)
|
||||
if (!(sk instanceof Reason)) {
|
||||
sketch = sk
|
||||
} else if ((maybeSketch as Solid).sketch) {
|
||||
sketch = (maybeSketch as Solid).sketch
|
||||
} else if (maybeSketch && (maybeSketch.value as Solid)?.sketch) {
|
||||
sketch = (maybeSketch.value as Solid).sketch
|
||||
}
|
||||
if (!sketch) return
|
||||
|
||||
@ -2541,7 +2541,7 @@ export function sketchFromPathToNode({
|
||||
const varDec = _varDec.node
|
||||
const result = programMemory.get(varDec?.id?.name || '')
|
||||
if (result?.type === 'Solid') {
|
||||
return result.sketch
|
||||
return result.value.sketch
|
||||
}
|
||||
const sg = sketchFromKclValue(result, varDec?.id?.name)
|
||||
if (err(sg)) {
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { Popover } from '@headlessui/react'
|
||||
import { ActionButtonProps } from './ActionButton'
|
||||
import { CustomIcon } from './CustomIcon'
|
||||
import Tooltip from './Tooltip'
|
||||
|
||||
type ActionButtonSplitProps = ActionButtonProps & { Element: 'button' } & {
|
||||
name?: string
|
||||
dropdownTooltipText?: string
|
||||
splitMenuItems: {
|
||||
id: string
|
||||
label: string
|
||||
@ -17,6 +19,7 @@ type ActionButtonSplitProps = ActionButtonProps & { Element: 'button' } & {
|
||||
export function ActionButtonDropdown({
|
||||
splitMenuItems,
|
||||
className,
|
||||
dropdownTooltipText = 'More tools',
|
||||
children,
|
||||
...props
|
||||
}: ActionButtonSplitProps) {
|
||||
@ -26,7 +29,14 @@ export function ActionButtonDropdown({
|
||||
{({ close }) => (
|
||||
<>
|
||||
{children}
|
||||
<Popover.Button className="border-transparent dark:border-transparent p-0 m-0 rounded-none !outline-none ui-open:border-primary ui-open:bg-primary">
|
||||
<Popover.Button
|
||||
className={
|
||||
'!border-transparent dark:!border-transparent ' +
|
||||
'bg-chalkboard-transparent dark:bg-transparent disabled:bg-transparent dark:disabled:bg-transparent ' +
|
||||
'enabled:hover:bg-chalkboard-10 dark:enabled:hover:bg-chalkboard-100 ' +
|
||||
'pressed:!bg-primary pressed:enabled:hover:!text-chalkboard-10 p-0 m-0 rounded-none !outline-none ui-open:border-primary ui-open:bg-primary'
|
||||
}
|
||||
>
|
||||
<CustomIcon
|
||||
name="caretDown"
|
||||
className={
|
||||
@ -37,6 +47,14 @@ export function ActionButtonDropdown({
|
||||
<span className="sr-only">
|
||||
{props.name ? props.name + ': ' : ''}open menu
|
||||
</span>
|
||||
<Tooltip
|
||||
delay={0}
|
||||
position="bottom"
|
||||
hoverOnly
|
||||
wrapperClassName="ui-open:!hidden"
|
||||
>
|
||||
{dropdownTooltipText}
|
||||
</Tooltip>
|
||||
</Popover.Button>
|
||||
<Popover.Panel
|
||||
as="ul"
|
||||
|
@ -4,18 +4,18 @@ import { expandPlane, PlaneArtifactRich } from 'lang/std/artifactGraph'
|
||||
import { ArtifactGraph } from 'lang/wasm'
|
||||
import { DebugDisplayArray, GenericObj } from './DebugDisplayObj'
|
||||
|
||||
export function DebugFeatureTree() {
|
||||
const featureTree = useMemo(() => {
|
||||
export function DebugArtifactGraph() {
|
||||
const artifactGraphTree = 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 ? (
|
||||
<summary>Artifact Graph</summary>
|
||||
{artifactGraphTree.length > 0 ? (
|
||||
<pre className="text-xs">
|
||||
<DebugDisplayArray arr={featureTree} filterKeys={filterKeys} />
|
||||
<DebugDisplayArray arr={artifactGraphTree} filterKeys={filterKeys} />
|
||||
</pre>
|
||||
) : (
|
||||
<p>(Empty)</p>
|
@ -1,4 +1,4 @@
|
||||
import { DebugFeatureTree } from 'components/DebugFeatureTree'
|
||||
import { DebugArtifactGraph } from 'components/DebugArtifactGraph'
|
||||
import { AstExplorer } from '../../AstExplorer'
|
||||
import { EngineCommands } from '../../EngineCommands'
|
||||
import { CamDebugSettings } from 'clientSideScene/ClientSideSceneComp'
|
||||
@ -14,7 +14,7 @@ export const DebugPane = () => {
|
||||
<EngineCommands />
|
||||
<CamDebugSettings />
|
||||
<AstExplorer />
|
||||
<DebugFeatureTree />
|
||||
<DebugArtifactGraph />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@
|
||||
@apply font-mono !no-underline text-xs font-bold select-none text-chalkboard-90;
|
||||
@apply ui-active:bg-primary/10 ui-active:text-primary ui-active:text-inherit;
|
||||
@apply transition-colors ease-out;
|
||||
@apply m-0;
|
||||
}
|
||||
|
||||
:global(.dark) .button {
|
||||
|
@ -95,9 +95,11 @@ export const processMemory = (programMemory: ProgramMemory) => {
|
||||
) {
|
||||
const sk = sketchFromKclValueOptional(val, key)
|
||||
if (val.type === 'Solid') {
|
||||
processedMemory[key] = val.value.map(({ ...rest }: ExtrudeSurface) => {
|
||||
return rest
|
||||
})
|
||||
processedMemory[key] = val.value.value.map(
|
||||
({ ...rest }: ExtrudeSurface) => {
|
||||
return rest
|
||||
}
|
||||
)
|
||||
} else if (!(sk instanceof Reason)) {
|
||||
processedMemory[key] = sk.paths.map(({ __geoMeta, ...rest }: Path) => {
|
||||
return rest
|
||||
|
@ -24,7 +24,10 @@ describe('testing AST', () => {
|
||||
type: 'Literal',
|
||||
start: 0,
|
||||
end: 1,
|
||||
value: 5,
|
||||
value: {
|
||||
suffix: 'None',
|
||||
value: 5,
|
||||
},
|
||||
raw: '5',
|
||||
},
|
||||
operator: '+',
|
||||
@ -32,7 +35,10 @@ describe('testing AST', () => {
|
||||
type: 'Literal',
|
||||
start: 3,
|
||||
end: 4,
|
||||
value: 6,
|
||||
value: {
|
||||
suffix: 'None',
|
||||
value: 6,
|
||||
},
|
||||
raw: '6',
|
||||
},
|
||||
},
|
||||
|
@ -54,6 +54,9 @@ const mySketch001 = startSketchOn('XY')
|
||||
},
|
||||
],
|
||||
id: expect.any(String),
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
__meta: [{ sourceRange: [46, 71, 0] }],
|
||||
},
|
||||
})
|
||||
@ -72,56 +75,65 @@ const mySketch001 = startSketchOn('XY')
|
||||
const sketch001 = execState.memory.get('mySketch001')
|
||||
expect(sketch001).toEqual({
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
value: [
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [77, 102, 0],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [108, 132, 0],
|
||||
},
|
||||
],
|
||||
sketch: {
|
||||
value: {
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
__meta: expect.any(Array),
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'Sketch',
|
||||
paths: [
|
||||
value: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-1.59, -1.54],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [77, 102, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [77, 102, 0],
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [-1.59, -1.54],
|
||||
to: [0.46, -5.82],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [108, 132, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [108, 132, 0],
|
||||
},
|
||||
],
|
||||
sketch: {
|
||||
id: expect.any(String),
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
__meta: expect.any(Array),
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'Sketch',
|
||||
paths: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-1.59, -1.54],
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [77, 102, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [-1.59, -1.54],
|
||||
to: [0.46, -5.82],
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [108, 132, 0],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
__meta: [{ sourceRange: [46, 71, 0] }],
|
||||
},
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
__meta: [{ sourceRange: [46, 71, 0] }],
|
||||
})
|
||||
})
|
||||
test('sketch extrude and sketch on one of the faces', async () => {
|
||||
@ -154,187 +166,205 @@ const sk2 = startSketchOn('XY')
|
||||
expect(geos).toEqual([
|
||||
{
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
value: [
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [69, 89, 0],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: {
|
||||
end: 116,
|
||||
start: 114,
|
||||
type: 'TagDeclarator',
|
||||
value: 'p',
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [95, 117, 0],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [123, 142, 0],
|
||||
},
|
||||
],
|
||||
sketch: {
|
||||
value: {
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
__meta: expect.any(Array),
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'Sketch',
|
||||
tags: {
|
||||
p: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [114, 116, 0],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'p',
|
||||
info: expect.any(Object),
|
||||
},
|
||||
},
|
||||
paths: [
|
||||
value: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-2.5, 0],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [69, 89, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [69, 89, 0],
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [-2.5, 0],
|
||||
to: [0, 10],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: {
|
||||
end: 116,
|
||||
start: 114,
|
||||
type: 'TagDeclarator',
|
||||
value: 'p',
|
||||
},
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [95, 117, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [95, 117, 0],
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 10],
|
||||
to: [2.5, 0],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [123, 142, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [123, 142, 0],
|
||||
},
|
||||
],
|
||||
sketch: {
|
||||
id: expect.any(String),
|
||||
__meta: expect.any(Array),
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'Sketch',
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
tags: {
|
||||
p: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [114, 116, 0],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'p',
|
||||
info: expect.any(Object),
|
||||
},
|
||||
},
|
||||
paths: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-2.5, 0],
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [69, 89, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [-2.5, 0],
|
||||
to: [0, 10],
|
||||
tag: {
|
||||
end: 116,
|
||||
start: 114,
|
||||
type: 'TagDeclarator',
|
||||
value: 'p',
|
||||
},
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [95, 117, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 10],
|
||||
to: [2.5, 0],
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [123, 142, 0],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
__meta: [{ sourceRange: [38, 63, 0] }],
|
||||
},
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
__meta: [{ sourceRange: [38, 63, 0] }],
|
||||
},
|
||||
{
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
value: [
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [373, 393, 0],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: {
|
||||
end: 419,
|
||||
start: 417,
|
||||
type: 'TagDeclarator',
|
||||
value: 'o',
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [399, 420, 0],
|
||||
},
|
||||
{
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
id: expect.any(String),
|
||||
sourceRange: [426, 445, 0],
|
||||
},
|
||||
],
|
||||
sketch: {
|
||||
value: {
|
||||
type: 'Solid',
|
||||
id: expect.any(String),
|
||||
__meta: expect.any(Array),
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'Sketch',
|
||||
tags: {
|
||||
o: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [417, 419, 0],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'o',
|
||||
info: expect.any(Object),
|
||||
},
|
||||
},
|
||||
paths: [
|
||||
value: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-2.5, 0],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [373, 393, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [373, 393, 0],
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [-2.5, 0],
|
||||
to: [0, 3],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: {
|
||||
end: 419,
|
||||
start: 417,
|
||||
type: 'TagDeclarator',
|
||||
value: 'o',
|
||||
},
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [399, 420, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [399, 420, 0],
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 3],
|
||||
to: [2.5, 0],
|
||||
type: 'extrudePlane',
|
||||
faceId: expect.any(String),
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [426, 445, 0],
|
||||
},
|
||||
id: expect.any(String),
|
||||
sourceRange: [426, 445, 0],
|
||||
},
|
||||
],
|
||||
sketch: {
|
||||
id: expect.any(String),
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
__meta: expect.any(Array),
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'Sketch',
|
||||
tags: {
|
||||
o: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [417, 419, 0],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'o',
|
||||
info: expect.any(Object),
|
||||
},
|
||||
},
|
||||
paths: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-2.5, 0],
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [373, 393, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [-2.5, 0],
|
||||
to: [0, 3],
|
||||
tag: {
|
||||
end: 419,
|
||||
start: 417,
|
||||
type: 'TagDeclarator',
|
||||
value: 'o',
|
||||
},
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [399, 420, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
from: [0, 3],
|
||||
to: [2.5, 0],
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
sourceRange: [426, 445, 0],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
__meta: [{ sourceRange: [342, 367, 0] }],
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
},
|
||||
height: 2,
|
||||
startCapId: expect.any(String),
|
||||
endCapId: expect.any(String),
|
||||
__meta: [{ sourceRange: [342, 367, 0] }],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
@ -221,6 +221,9 @@ const newVar = myVar + 1`
|
||||
},
|
||||
],
|
||||
id: expect.any(String),
|
||||
units: {
|
||||
type: 'Mm',
|
||||
},
|
||||
__meta: [{ sourceRange: [39, 63, 0] }],
|
||||
},
|
||||
})
|
||||
|
@ -39,7 +39,7 @@ describe('Testing createLiteral', () => {
|
||||
it('should create a literal', () => {
|
||||
const result = createLiteral(5)
|
||||
expect(result.type).toBe('Literal')
|
||||
expect(result.value).toBe(5)
|
||||
expect((result as any).value.value).toBe(5)
|
||||
})
|
||||
})
|
||||
describe('Testing createIdentifier', () => {
|
||||
@ -56,7 +56,7 @@ describe('Testing createCallExpression', () => {
|
||||
expect(result.callee.type).toBe('Identifier')
|
||||
expect(result.callee.name).toBe('myFunc')
|
||||
expect(result.arguments[0].type).toBe('Literal')
|
||||
expect((result.arguments[0] as any).value).toBe(5)
|
||||
expect((result.arguments[0] as any).value.value).toBe(5)
|
||||
})
|
||||
})
|
||||
describe('Testing createObjectExpression', () => {
|
||||
@ -68,7 +68,7 @@ describe('Testing createObjectExpression', () => {
|
||||
expect(result.properties[0].type).toBe('ObjectProperty')
|
||||
expect(result.properties[0].key.name).toBe('myProp')
|
||||
expect(result.properties[0].value.type).toBe('Literal')
|
||||
expect((result.properties[0].value as any).value).toBe(5)
|
||||
expect((result.properties[0].value as any).value.value).toBe(5)
|
||||
})
|
||||
})
|
||||
describe('Testing createArrayExpression', () => {
|
||||
@ -76,7 +76,7 @@ describe('Testing createArrayExpression', () => {
|
||||
const result = createArrayExpression([createLiteral(5)])
|
||||
expect(result.type).toBe('ArrayExpression')
|
||||
expect(result.elements[0].type).toBe('Literal')
|
||||
expect((result.elements[0] as any).value).toBe(5)
|
||||
expect((result.elements[0] as any).value.value).toBe(5)
|
||||
})
|
||||
})
|
||||
describe('Testing createPipeSubstitution', () => {
|
||||
@ -93,7 +93,7 @@ describe('Testing createVariableDeclaration', () => {
|
||||
expect(result.declaration.id.type).toBe('Identifier')
|
||||
expect(result.declaration.id.name).toBe('myVar')
|
||||
expect(result.declaration.init.type).toBe('Literal')
|
||||
expect((result.declaration.init as any).value).toBe(5)
|
||||
expect((result.declaration.init as any).value.value).toBe(5)
|
||||
})
|
||||
})
|
||||
describe('Testing createPipeExpression', () => {
|
||||
@ -101,7 +101,7 @@ describe('Testing createPipeExpression', () => {
|
||||
const result = createPipeExpression([createLiteral(5)])
|
||||
expect(result.type).toBe('PipeExpression')
|
||||
expect(result.body[0].type).toBe('Literal')
|
||||
expect((result.body[0] as any).value).toBe(5)
|
||||
expect((result.body[0] as any).value.value).toBe(5)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -743,14 +743,18 @@ export function splitPathAtPipeExpression(pathToNode: PathToNode): {
|
||||
return splitPathAtPipeExpression(pathToNode.slice(0, -1))
|
||||
}
|
||||
|
||||
export function createLiteral(value: LiteralValue): Node<Literal> {
|
||||
export function createLiteral(value: LiteralValue | number): Node<Literal> {
|
||||
const raw = `${value}`
|
||||
if (typeof value === 'number') {
|
||||
value = { value, suffix: 'None' }
|
||||
}
|
||||
return {
|
||||
type: 'Literal',
|
||||
start: 0,
|
||||
end: 0,
|
||||
moduleId: 0,
|
||||
value,
|
||||
raw: `${value}`,
|
||||
raw,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,7 +660,7 @@ myNestedVar = [
|
||||
enter: (node, path) => {
|
||||
if (
|
||||
node.type === 'Literal' &&
|
||||
String(node.value) === literalOfInterest
|
||||
String((node as any).value.value) === literalOfInterest
|
||||
) {
|
||||
pathToNode = path
|
||||
} else if (
|
||||
|
@ -717,16 +717,6 @@ function isTypeInArrayExp(
|
||||
return node.elements.some((el) => isTypeInValue(el, syntaxType))
|
||||
}
|
||||
|
||||
export function isValueZero(val?: Expr): boolean {
|
||||
return (
|
||||
(val?.type === 'Literal' && Number(val.value) === 0) ||
|
||||
(val?.type === 'UnaryExpression' &&
|
||||
val.operator === '-' &&
|
||||
val.argument.type === 'Literal' &&
|
||||
Number(val.argument.value) === 0)
|
||||
)
|
||||
}
|
||||
|
||||
export function isLinesParallelAndConstrained(
|
||||
ast: Program,
|
||||
artifactGraph: ArtifactGraph,
|
||||
|
@ -1014,6 +1014,11 @@ class EngineConnection extends EventTarget {
|
||||
this.pingPongSpan.pong = new Date()
|
||||
break
|
||||
|
||||
case 'modeling_session_data':
|
||||
let api_call_id = resp.data?.session?.api_call_id
|
||||
console.log(`API Call ID: ${api_call_id}`)
|
||||
break
|
||||
|
||||
// Only fires on successful authentication.
|
||||
case 'ice_server_info':
|
||||
let ice_servers = resp.data?.ice_servers
|
||||
|
@ -20,12 +20,12 @@ import {
|
||||
sketchFromKclValue,
|
||||
Literal,
|
||||
SourceRange,
|
||||
LiteralValue,
|
||||
} from '../wasm'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
getNodeFromPathCurry,
|
||||
getNodePathFromSourceRange,
|
||||
isValueZero,
|
||||
} from '../queryAst'
|
||||
import {
|
||||
createArrayExpression,
|
||||
@ -79,11 +79,32 @@ export type ConstraintType =
|
||||
| 'setAngleBetween'
|
||||
|
||||
const REF_NUM_ERR = new Error('Referenced segment does not have a to value')
|
||||
|
||||
function asNum(val: LiteralValue): number | Error {
|
||||
if (typeof val === 'object') return val.value
|
||||
return REF_NUM_ERR
|
||||
}
|
||||
|
||||
function forceNum(arg: Literal): number {
|
||||
if (typeof arg.value === 'boolean' || typeof arg.value === 'string') {
|
||||
return Number(arg.value)
|
||||
} else {
|
||||
return arg.value.value
|
||||
}
|
||||
}
|
||||
|
||||
function isUndef(val: any): val is undefined {
|
||||
return typeof val === 'undefined'
|
||||
}
|
||||
function isNum(val: any): val is number {
|
||||
return typeof val === 'number'
|
||||
|
||||
function isValueZero(val?: Expr): boolean {
|
||||
return (
|
||||
(val?.type === 'Literal' && forceNum(val) === 0) ||
|
||||
(val?.type === 'UnaryExpression' &&
|
||||
val.operator === '-' &&
|
||||
val.argument.type === 'Literal' &&
|
||||
Number(val.argument.value) === 0)
|
||||
)
|
||||
}
|
||||
|
||||
function createCallWrapper(
|
||||
@ -190,7 +211,7 @@ const xyLineSetLength =
|
||||
: referenceSeg
|
||||
? segRef
|
||||
: args[0].expr
|
||||
const literalARg = getArgLiteralVal(args[0].expr)
|
||||
const literalARg = asNum(args[0].expr.value)
|
||||
if (err(literalARg)) return literalARg
|
||||
return createCallWrapper(xOrY, lineVal, tag, literalARg)
|
||||
}
|
||||
@ -211,13 +232,14 @@ const basicAngledLineCreateNode =
|
||||
referencedSegment: path,
|
||||
}) => {
|
||||
const refAng = path ? getAngle(path?.from, path?.to) : 0
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const argValue = asNum(args[0].expr.value)
|
||||
if (err(argValue)) return argValue
|
||||
const nonForcedAng =
|
||||
varValToUse === 'ang'
|
||||
? inputs[0].expr
|
||||
: referenceSeg === 'ang'
|
||||
? getClosesAngleDirection(
|
||||
args[0].expr.value,
|
||||
argValue,
|
||||
refAng,
|
||||
createSegAngle(referenceSegName)
|
||||
)
|
||||
@ -230,8 +252,8 @@ const basicAngledLineCreateNode =
|
||||
: args[1].expr
|
||||
const shouldForceAng = valToForce === 'ang' && forceValueUsedInTransform
|
||||
const shouldForceLen = valToForce === 'len' && forceValueUsedInTransform
|
||||
const literalArg = getArgLiteralVal(
|
||||
valToForce === 'ang' ? args[0].expr : args[1].expr
|
||||
const literalArg = asNum(
|
||||
valToForce === 'ang' ? args[0].expr.value : args[1].expr.value
|
||||
)
|
||||
if (err(literalArg)) return literalArg
|
||||
return createCallWrapper(
|
||||
@ -283,7 +305,7 @@ const getMinAndSegAngVals = (
|
||||
}
|
||||
|
||||
const getSignedLeg = (arg: Literal, legLenVal: BinaryPart) =>
|
||||
Number(arg.value) < 0 ? createUnaryExpression(legLenVal) : legLenVal
|
||||
forceNum(arg) < 0 ? createUnaryExpression(legLenVal) : legLenVal
|
||||
|
||||
const getLegAng = (ang: number, legAngleVal: BinaryPart) => {
|
||||
const normalisedAngle = ((ang % 360) + 360) % 360 // between 0 and 360
|
||||
@ -322,8 +344,7 @@ const setHorzVertDistanceCreateNode =
|
||||
referencedSegment,
|
||||
}) => {
|
||||
const refNum = referencedSegment?.to?.[index]
|
||||
const literalArg = getArgLiteralVal(args?.[index].expr)
|
||||
if (err(literalArg)) return literalArg
|
||||
const literalArg = asNum(args?.[index].expr.value)
|
||||
if (isUndef(refNum) || err(literalArg)) return REF_NUM_ERR
|
||||
|
||||
const valueUsedInTransform = roundOff(literalArg - refNum, 2)
|
||||
@ -352,7 +373,7 @@ const setHorzVertDistanceForAngleLineCreateNode =
|
||||
referencedSegment,
|
||||
}) => {
|
||||
const refNum = referencedSegment?.to?.[index]
|
||||
const literalArg = getArgLiteralVal(args?.[1].expr)
|
||||
const literalArg = asNum(args?.[1].expr.value)
|
||||
if (isUndef(refNum) || err(literalArg)) return REF_NUM_ERR
|
||||
const valueUsedInTransform = roundOff(literalArg - refNum, 2)
|
||||
const binExp = createBinaryExpressionWithUnary([
|
||||
@ -374,8 +395,8 @@ const setAbsDistanceCreateNode =
|
||||
index = xOrY === 'x' ? 0 : 1
|
||||
): CreateStdLibSketchCallExpr =>
|
||||
({ tag, forceValueUsedInTransform, rawArgs: args }) => {
|
||||
const literalArg = getArgLiteralVal(args?.[index].expr)
|
||||
if (err(literalArg)) return REF_NUM_ERR
|
||||
const literalArg = asNum(args?.[index].expr.value)
|
||||
if (err(literalArg)) return literalArg
|
||||
const valueUsedInTransform = roundOff(literalArg, 2)
|
||||
const val = forceValueUsedInTransform || createLiteral(valueUsedInTransform)
|
||||
if (isXOrYLine) {
|
||||
@ -396,8 +417,8 @@ const setAbsDistanceCreateNode =
|
||||
const setAbsDistanceForAngleLineCreateNode =
|
||||
(xOrY: 'x' | 'y'): CreateStdLibSketchCallExpr =>
|
||||
({ tag, forceValueUsedInTransform, inputs, rawArgs: args }) => {
|
||||
const literalArg = getArgLiteralVal(args?.[1].expr)
|
||||
if (err(literalArg)) return REF_NUM_ERR
|
||||
const literalArg = asNum(args?.[1].expr.value)
|
||||
if (err(literalArg)) return literalArg
|
||||
const valueUsedInTransform = roundOff(literalArg, 2)
|
||||
const val = forceValueUsedInTransform || createLiteral(valueUsedInTransform)
|
||||
return createCallWrapper(
|
||||
@ -419,7 +440,7 @@ const setHorVertDistanceForXYLines =
|
||||
}) => {
|
||||
const index = xOrY === 'x' ? 0 : 1
|
||||
const refNum = referencedSegment?.to?.[index]
|
||||
const literalArg = getArgLiteralVal(args?.[index].expr)
|
||||
const literalArg = asNum(args?.[index].expr.value)
|
||||
if (isUndef(refNum) || err(literalArg)) return REF_NUM_ERR
|
||||
const valueUsedInTransform = roundOff(literalArg - refNum, 2)
|
||||
const makeBinExp = createBinaryExpressionWithUnary([
|
||||
@ -445,9 +466,9 @@ const setHorzVertDistanceConstraintLineCreateNode =
|
||||
])
|
||||
|
||||
const makeBinExp = (index: 0 | 1) => {
|
||||
const arg = getArgLiteralVal(args?.[index].expr)
|
||||
const arg = asNum(args?.[index].expr.value)
|
||||
const refNum = referencedSegment?.to?.[index]
|
||||
if (err(arg) || !isNum(refNum)) return REF_NUM_ERR
|
||||
if (err(arg) || isUndef(refNum)) return REF_NUM_ERR
|
||||
return createBinaryExpressionWithUnary([
|
||||
createSegEnd(referenceSegName, isX),
|
||||
createLiteral(roundOff(arg - refNum, 2)),
|
||||
@ -468,9 +489,9 @@ const setAngledIntersectLineForLines: CreateStdLibSketchCallExpr = ({
|
||||
forceValueUsedInTransform,
|
||||
rawArgs: args,
|
||||
}) => {
|
||||
const val = args[1].expr.value,
|
||||
angle = args[0].expr.value
|
||||
if (!isNum(val) || !isNum(angle)) return REF_NUM_ERR
|
||||
const val = asNum(args[1].expr.value),
|
||||
angle = asNum(args[0].expr.value)
|
||||
if (err(val) || err(angle)) return REF_NUM_ERR
|
||||
const valueUsedInTransform = roundOff(val, 2)
|
||||
const varNamMap: { [key: number]: string } = {
|
||||
0: 'ZERO',
|
||||
@ -498,8 +519,8 @@ const setAngledIntersectForAngledLines: CreateStdLibSketchCallExpr = ({
|
||||
inputs,
|
||||
rawArgs: args,
|
||||
}) => {
|
||||
const val = args[1].expr.value
|
||||
if (!isNum(val)) return REF_NUM_ERR
|
||||
const val = asNum(args[1].expr.value)
|
||||
if (err(val)) return val
|
||||
const valueUsedInTransform = roundOff(val, 2)
|
||||
return intersectCallWrapper({
|
||||
fnName: 'angledLineThatIntersects',
|
||||
@ -524,8 +545,8 @@ const setAngleBetweenCreateNode =
|
||||
const refAngle = referencedSegment
|
||||
? getAngle(referencedSegment?.from, referencedSegment?.to)
|
||||
: 0
|
||||
const val = args[0].expr.value
|
||||
if (!isNum(val)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
let valueUsedInTransform = roundOff(normaliseAngle(val - refAngle))
|
||||
let firstHalfValue = createSegAngle(referenceSegName)
|
||||
if (Math.abs(valueUsedInTransform) > 90) {
|
||||
@ -706,13 +727,11 @@ const transformMap: TransformMap = {
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
)
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineToX',
|
||||
[
|
||||
getAngleLengthSign(args[0].expr.value, angleToMatchLengthXCall),
|
||||
inputs[0].expr,
|
||||
],
|
||||
[getAngleLengthSign(val, angleToMatchLengthXCall), inputs[0].expr],
|
||||
tag
|
||||
)
|
||||
},
|
||||
@ -739,13 +758,11 @@ const transformMap: TransformMap = {
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
)
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineToY',
|
||||
[
|
||||
getAngleLengthSign(args[0].expr.value, angleToMatchLengthYCall),
|
||||
inputs[1].expr,
|
||||
],
|
||||
[getAngleLengthSign(val, angleToMatchLengthYCall), inputs[1].expr],
|
||||
tag
|
||||
)
|
||||
},
|
||||
@ -763,7 +780,7 @@ const transformMap: TransformMap = {
|
||||
forceValueUsedInTransform,
|
||||
rawArgs: args,
|
||||
}) => {
|
||||
const val = getArgLiteralVal(args[0].expr)
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineToY',
|
||||
@ -844,7 +861,7 @@ const transformMap: TransformMap = {
|
||||
tooltip: 'yLine',
|
||||
createNode: ({ inputs, tag, rawArgs: args }) => {
|
||||
const expr = inputs[1].expr
|
||||
if (Number(args[0].expr.value) >= 0)
|
||||
if (forceNum(args[0].expr) >= 0)
|
||||
return createCallWrapper('yLine', expr, tag)
|
||||
if (isExprBinaryPart(expr))
|
||||
return createCallWrapper('yLine', createUnaryExpression(expr), tag)
|
||||
@ -856,7 +873,7 @@ const transformMap: TransformMap = {
|
||||
tooltip: 'xLine',
|
||||
createNode: ({ inputs, tag, rawArgs: args }) => {
|
||||
const expr = inputs[1].expr
|
||||
if (Number(args[0].expr.value) >= 0)
|
||||
if (forceNum(args[0].expr) >= 0)
|
||||
return createCallWrapper('xLine', expr, tag)
|
||||
if (isExprBinaryPart(expr))
|
||||
return createCallWrapper('xLine', createUnaryExpression(expr), tag)
|
||||
@ -900,10 +917,11 @@ const transformMap: TransformMap = {
|
||||
referenceSegName,
|
||||
getInputOfType(inputs, 'xRelative').expr
|
||||
)
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineOfXLength',
|
||||
[getLegAng(args[0].expr.value, legAngle), minVal],
|
||||
[getLegAng(val, legAngle), minVal],
|
||||
tag
|
||||
)
|
||||
},
|
||||
@ -912,7 +930,7 @@ const transformMap: TransformMap = {
|
||||
tooltip: 'xLine',
|
||||
createNode: ({ inputs, tag, rawArgs: args }) => {
|
||||
const expr = inputs[1].expr
|
||||
if (Number(args[0].expr.value) >= 0)
|
||||
if (forceNum(args[0].expr) >= 0)
|
||||
return createCallWrapper('xLine', expr, tag)
|
||||
if (isExprBinaryPart(expr))
|
||||
return createCallWrapper('xLine', createUnaryExpression(expr), tag)
|
||||
@ -953,10 +971,11 @@ const transformMap: TransformMap = {
|
||||
inputs[1].expr,
|
||||
'legAngY'
|
||||
)
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineOfXLength',
|
||||
[getLegAng(args[0].expr.value, legAngle), minVal],
|
||||
[getLegAng(val, legAngle), minVal],
|
||||
tag
|
||||
)
|
||||
},
|
||||
@ -965,7 +984,7 @@ const transformMap: TransformMap = {
|
||||
tooltip: 'yLine',
|
||||
createNode: ({ inputs, tag, rawArgs: args }) => {
|
||||
const expr = inputs[1].expr
|
||||
if (Number(args[0].expr.value) >= 0)
|
||||
if (forceNum(args[0].expr) >= 0)
|
||||
return createCallWrapper('yLine', expr, tag)
|
||||
if (isExprBinaryPart(expr))
|
||||
return createCallWrapper('yLine', createUnaryExpression(expr), tag)
|
||||
@ -1005,13 +1024,11 @@ const transformMap: TransformMap = {
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
)
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineToX',
|
||||
[
|
||||
getAngleLengthSign(args[0].expr.value, angleToMatchLengthXCall),
|
||||
inputs[1].expr,
|
||||
],
|
||||
[getAngleLengthSign(val, angleToMatchLengthXCall), inputs[1].expr],
|
||||
tag
|
||||
)
|
||||
},
|
||||
@ -1057,13 +1074,11 @@ const transformMap: TransformMap = {
|
||||
createPipeSubstitution(),
|
||||
]
|
||||
)
|
||||
if (!isNum(args[0].expr.value)) return REF_NUM_ERR
|
||||
const val = asNum(args[0].expr.value)
|
||||
if (err(val)) return val
|
||||
return createCallWrapper(
|
||||
'angledLineToY',
|
||||
[
|
||||
getAngleLengthSign(args[0].expr.value, angleToMatchLengthXCall),
|
||||
inputs[1].expr,
|
||||
],
|
||||
[getAngleLengthSign(val, angleToMatchLengthXCall), inputs[1].expr],
|
||||
tag
|
||||
)
|
||||
},
|
||||
@ -1080,7 +1095,7 @@ const transformMap: TransformMap = {
|
||||
equalLength: {
|
||||
tooltip: 'xLine',
|
||||
createNode: ({ referenceSegName, tag, rawArgs: args }) => {
|
||||
const argVal = getArgLiteralVal(args[0].expr)
|
||||
const argVal = asNum(args[0].expr.value)
|
||||
if (err(argVal)) return argVal
|
||||
const segLen = createSegLen(referenceSegName)
|
||||
if (argVal > 0) return createCallWrapper('xLine', segLen, tag, argVal)
|
||||
@ -1118,7 +1133,7 @@ const transformMap: TransformMap = {
|
||||
equalLength: {
|
||||
tooltip: 'yLine',
|
||||
createNode: ({ referenceSegName, tag, rawArgs: args }) => {
|
||||
const argVal = getArgLiteralVal(args[0].expr)
|
||||
const argVal = asNum(args[0].expr.value)
|
||||
if (err(argVal)) return argVal
|
||||
let segLen = createSegLen(referenceSegName)
|
||||
if (argVal < 0) segLen = createUnaryExpression(segLen)
|
||||
@ -1714,7 +1729,7 @@ export function transformAstSketchLines({
|
||||
let kclVal = programMemory.get(varName)
|
||||
let sketch
|
||||
if (kclVal?.type === 'Solid') {
|
||||
sketch = kclVal.sketch
|
||||
sketch = kclVal.value.sketch
|
||||
} else {
|
||||
sketch = sketchFromKclValue(kclVal, varName)
|
||||
if (err(sketch)) {
|
||||
@ -1823,11 +1838,6 @@ function createLastSeg(isX: boolean): Node<CallExpression> {
|
||||
])
|
||||
}
|
||||
|
||||
function getArgLiteralVal(arg: Literal): number | Error {
|
||||
if (!isNum(arg.value)) return REF_NUM_ERR
|
||||
return arg.value
|
||||
}
|
||||
|
||||
export type ConstraintLevel = 'free' | 'partial' | 'full'
|
||||
|
||||
export function getConstraintLevelFromSourceRange(
|
||||
|
@ -539,7 +539,8 @@ export function sketchFromKclValueOptional(
|
||||
): Sketch | Reason {
|
||||
if (obj?.value?.type === 'Sketch') return obj.value
|
||||
if (obj?.value?.type === 'Solid') return obj.value.sketch
|
||||
if (obj?.type === 'Solid') return obj.sketch
|
||||
if (obj?.type === 'Sketch') return obj.value
|
||||
if (obj?.type === 'Solid') return obj.value.sketch
|
||||
if (!varName) {
|
||||
varName = 'a KCL value'
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
loftValidator,
|
||||
revolveAxisValidator,
|
||||
shellValidator,
|
||||
sweepValidator,
|
||||
} from './validators'
|
||||
|
||||
type OutputFormat = Models['OutputFormat_type']
|
||||
@ -42,8 +43,8 @@ export type ModelingCommandSchema = {
|
||||
distance: KclCommandValue
|
||||
}
|
||||
Sweep: {
|
||||
path: Selections
|
||||
profile: Selections
|
||||
target: Selections
|
||||
trajectory: Selections
|
||||
}
|
||||
Loft: {
|
||||
selection: Selections
|
||||
@ -308,25 +309,24 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
'Create a 3D body by moving a sketch region along an arbitrary path.',
|
||||
icon: 'sweep',
|
||||
status: 'development',
|
||||
needsReview: true,
|
||||
needsReview: false,
|
||||
args: {
|
||||
profile: {
|
||||
target: {
|
||||
inputType: 'selection',
|
||||
selectionTypes: ['solid2d'],
|
||||
required: true,
|
||||
skip: true,
|
||||
multiple: false,
|
||||
// TODO: add dry-run validation
|
||||
warningMessage:
|
||||
'The sweep workflow is new and under tested. Please break it and report issues.',
|
||||
},
|
||||
path: {
|
||||
trajectory: {
|
||||
inputType: 'selection',
|
||||
selectionTypes: ['segment', 'path'],
|
||||
required: true,
|
||||
skip: true,
|
||||
skip: false,
|
||||
multiple: false,
|
||||
// TODO: add dry-run validation
|
||||
validation: sweepValidator,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -207,3 +207,64 @@ export const shellValidator = async ({
|
||||
|
||||
return 'Unable to shell with the provided selection'
|
||||
}
|
||||
|
||||
export const sweepValidator = async ({
|
||||
context,
|
||||
data,
|
||||
}: {
|
||||
context: CommandBarContext
|
||||
data: { trajectory: Selections }
|
||||
}): Promise<boolean | string> => {
|
||||
if (!isSelections(data.trajectory)) {
|
||||
console.log('Unable to sweep, selections are missing')
|
||||
return 'Unable to sweep, selections are missing'
|
||||
}
|
||||
|
||||
// Retrieve the parent path from the segment selection directly
|
||||
const trajectoryArtifact = data.trajectory.graphSelections[0].artifact
|
||||
if (!trajectoryArtifact) {
|
||||
return "Unable to sweep, couldn't find the trajectory artifact"
|
||||
}
|
||||
if (trajectoryArtifact.type !== 'segment') {
|
||||
return "Unable to sweep, couldn't find the target from a non-segment selection"
|
||||
}
|
||||
const trajectory = trajectoryArtifact.pathId
|
||||
|
||||
// Get the former arg in the command bar flow, and retrieve the path from the solid2d directly
|
||||
const targetArg = context.argumentsToSubmit['target'] as Selections
|
||||
const targetArtifact = targetArg.graphSelections[0].artifact
|
||||
if (!targetArtifact) {
|
||||
return "Unable to sweep, couldn't find the profile artifact"
|
||||
}
|
||||
if (targetArtifact.type !== 'solid2d') {
|
||||
return "Unable to sweep, couldn't find the target from a non-solid2d selection"
|
||||
}
|
||||
const target = targetArtifact.pathId
|
||||
|
||||
const sweepCommand = async () => {
|
||||
// TODO: second look on defaults here
|
||||
const DEFAULT_TOLERANCE: Models['LengthUnit_type'] = 1e-7
|
||||
const DEFAULT_SECTIONAL = false
|
||||
const cmdArgs = {
|
||||
target,
|
||||
trajectory,
|
||||
sectional: DEFAULT_SECTIONAL,
|
||||
tolerance: DEFAULT_TOLERANCE,
|
||||
}
|
||||
return await engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'sweep',
|
||||
...cmdArgs,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const attemptSweep = await dryRunWrapper(sweepCommand)
|
||||
if (attemptSweep?.success) {
|
||||
return true
|
||||
}
|
||||
|
||||
return 'Unable to sweep with the provided selection'
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ export async function submitAndAwaitTextToKcl({
|
||||
.toLowerCase()}${FILE_EXT}`
|
||||
|
||||
if (isDesktop()) {
|
||||
// We have to pre-emptively run our unique file name logic,
|
||||
// We have to preemptively run our unique file name logic,
|
||||
// so that we can pass the unique file name to the toast,
|
||||
// and by extension the file-deletion-on-reject logic.
|
||||
newFileName = getNextFileName({
|
||||
|
@ -280,7 +280,12 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
||||
status: 'available',
|
||||
title: 'Offset plane',
|
||||
description: 'Create a plane parallel to an existing plane.',
|
||||
links: [],
|
||||
links: [
|
||||
{
|
||||
label: 'KCL docs',
|
||||
url: 'https://zoo.dev/docs/kcl/offsetPlane',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'plane-points',
|
||||
@ -305,7 +310,12 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
||||
status: 'available',
|
||||
title: 'Text-to-CAD',
|
||||
description: 'Generate geometry from a text prompt.',
|
||||
links: [],
|
||||
links: [
|
||||
{
|
||||
label: 'API docs',
|
||||
url: 'https://zoo.dev/docs/api/ml/generate-a-cad-model-from-text',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'prompt-to-edit',
|
||||
|
@ -1561,40 +1561,40 @@ export const modelingMachine = setup({
|
||||
if (!input) return new Error('No input provided')
|
||||
// Extract inputs
|
||||
const ast = kclManager.ast
|
||||
const { profile, path } = input
|
||||
const { target, trajectory } = input
|
||||
|
||||
// Find the profile declaration
|
||||
const profileNodePath = getNodePathFromSourceRange(
|
||||
const targetNodePath = getNodePathFromSourceRange(
|
||||
ast,
|
||||
profile.graphSelections[0].codeRef.range
|
||||
target.graphSelections[0].codeRef.range
|
||||
)
|
||||
const profileNode = getNodeFromPath<VariableDeclarator>(
|
||||
const targetNode = getNodeFromPath<VariableDeclarator>(
|
||||
ast,
|
||||
profileNodePath,
|
||||
targetNodePath,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(profileNode)) {
|
||||
if (err(targetNode)) {
|
||||
return new Error("Couldn't parse profile selection")
|
||||
}
|
||||
const profileDeclarator = profileNode.node
|
||||
const targetDeclarator = targetNode.node
|
||||
|
||||
// Find the path declaration
|
||||
const pathNodePath = getNodePathFromSourceRange(
|
||||
const trajectoryNodePath = getNodePathFromSourceRange(
|
||||
ast,
|
||||
path.graphSelections[0].codeRef.range
|
||||
trajectory.graphSelections[0].codeRef.range
|
||||
)
|
||||
const pathNode = getNodeFromPath<VariableDeclarator>(
|
||||
const trajectoryNode = getNodeFromPath<VariableDeclarator>(
|
||||
ast,
|
||||
pathNodePath,
|
||||
trajectoryNodePath,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(pathNode)) {
|
||||
if (err(trajectoryNode)) {
|
||||
return new Error("Couldn't parse path selection")
|
||||
}
|
||||
const pathDeclarator = pathNode.node
|
||||
const trajectoryDeclarator = trajectoryNode.node
|
||||
|
||||
// Perform the sweep
|
||||
const sweepRes = addSweep(ast, profileDeclarator, pathDeclarator)
|
||||
const sweepRes = addSweep(ast, targetDeclarator, trajectoryDeclarator)
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
sweepRes.modifiedAst,
|
||||
true,
|
||||
|
@ -370,8 +370,6 @@ impl From<KclError> for pyo3::PyErr {
|
||||
pub struct CompilationError {
|
||||
#[serde(rename = "sourceRange")]
|
||||
pub source_range: SourceRange,
|
||||
#[serde(rename = "contextRange")]
|
||||
pub context_range: Option<SourceRange>,
|
||||
pub message: String,
|
||||
pub suggestion: Option<Suggestion>,
|
||||
pub severity: Severity,
|
||||
@ -382,7 +380,6 @@ impl CompilationError {
|
||||
pub(crate) fn err(source_range: SourceRange, message: impl ToString) -> CompilationError {
|
||||
CompilationError {
|
||||
source_range,
|
||||
context_range: None,
|
||||
message: message.to_string(),
|
||||
suggestion: None,
|
||||
severity: Severity::Error,
|
||||
@ -393,7 +390,6 @@ impl CompilationError {
|
||||
pub(crate) fn fatal(source_range: SourceRange, message: impl ToString) -> CompilationError {
|
||||
CompilationError {
|
||||
source_range,
|
||||
context_range: None,
|
||||
message: message.to_string(),
|
||||
suggestion: None,
|
||||
severity: Severity::Fatal,
|
||||
@ -402,22 +398,18 @@ impl CompilationError {
|
||||
}
|
||||
|
||||
pub(crate) fn with_suggestion(
|
||||
source_range: SourceRange,
|
||||
context_range: Option<SourceRange>,
|
||||
message: impl ToString,
|
||||
suggestion: Option<(impl ToString, impl ToString)>,
|
||||
self,
|
||||
suggestion_title: impl ToString,
|
||||
suggestion_insert: impl ToString,
|
||||
tag: Tag,
|
||||
) -> CompilationError {
|
||||
CompilationError {
|
||||
source_range,
|
||||
context_range,
|
||||
message: message.to_string(),
|
||||
suggestion: suggestion.map(|(t, i)| Suggestion {
|
||||
title: t.to_string(),
|
||||
insert: i.to_string(),
|
||||
suggestion: Some(Suggestion {
|
||||
title: suggestion_title.to_string(),
|
||||
insert: suggestion_insert.to_string(),
|
||||
}),
|
||||
severity: Severity::Error,
|
||||
tag,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,11 @@ pub(super) const SETTINGS: &str = "settings";
|
||||
pub(super) const SETTINGS_UNIT_LENGTH: &str = "defaultLengthUnit";
|
||||
pub(super) const SETTINGS_UNIT_ANGLE: &str = "defaultAngleUnit";
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub(super) enum AnnotationScope {
|
||||
Module,
|
||||
}
|
||||
|
||||
pub(super) fn expect_properties<'a>(
|
||||
for_key: &'static str,
|
||||
annotation: &'a NonCodeValue,
|
||||
|
@ -121,8 +121,8 @@ impl Node<MemberExpression> {
|
||||
source_ranges: vec![self.clone().into()],
|
||||
}))
|
||||
}
|
||||
(KclValue::Solid(solid), Property::String(prop)) if prop == "sketch" => Ok(KclValue::Sketch {
|
||||
value: Box::new(solid.sketch),
|
||||
(KclValue::Solid { value }, Property::String(prop)) if prop == "sketch" => Ok(KclValue::Sketch {
|
||||
value: Box::new(value.sketch),
|
||||
}),
|
||||
(KclValue::Sketch { value: sk }, Property::String(prop)) if prop == "tags" => Ok(KclValue::Object {
|
||||
meta: vec![Metadata {
|
||||
@ -662,11 +662,11 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
||||
exec_state.mut_memory().update_tag(&tag.value, tag.clone())?;
|
||||
}
|
||||
}
|
||||
KclValue::Solid(ref mut solid) => {
|
||||
for value in &solid.value {
|
||||
if let Some(tag) = value.get_tag() {
|
||||
KclValue::Solid { ref mut value } => {
|
||||
for v in &value.value {
|
||||
if let Some(tag) = v.get_tag() {
|
||||
// Get the past tag and update it.
|
||||
let mut t = if let Some(t) = solid.sketch.tags.get(&tag.name) {
|
||||
let mut t = if let Some(t) = value.sketch.tags.get(&tag.name) {
|
||||
t.clone()
|
||||
} else {
|
||||
// It's probably a fillet or a chamfer.
|
||||
@ -674,10 +674,10 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
||||
TagIdentifier {
|
||||
value: tag.name.clone(),
|
||||
info: Some(TagEngineInfo {
|
||||
id: value.get_id(),
|
||||
surface: Some(value.clone()),
|
||||
id: v.get_id(),
|
||||
surface: Some(v.clone()),
|
||||
path: None,
|
||||
sketch: solid.id,
|
||||
sketch: value.id,
|
||||
}),
|
||||
meta: vec![Metadata {
|
||||
source_range: tag.clone().into(),
|
||||
@ -693,21 +693,21 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
||||
};
|
||||
|
||||
let mut info = info.clone();
|
||||
info.surface = Some(value.clone());
|
||||
info.sketch = solid.id;
|
||||
info.surface = Some(v.clone());
|
||||
info.sketch = value.id;
|
||||
t.info = Some(info);
|
||||
|
||||
exec_state.mut_memory().update_tag(&tag.name, t.clone())?;
|
||||
|
||||
// update the sketch tags.
|
||||
solid.sketch.tags.insert(tag.name.clone(), t);
|
||||
value.sketch.tags.insert(tag.name.clone(), t);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the stale sketch in memory and update it.
|
||||
let cur_env_index = exec_state.memory().current_env.index();
|
||||
if let Some(current_env) = exec_state.mut_memory().environments.get_mut(cur_env_index) {
|
||||
current_env.update_sketch_tags(&solid.sketch);
|
||||
current_env.update_sketch_tags(&value.sketch);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -929,13 +929,13 @@ impl Property {
|
||||
LiteralIdentifier::Literal(literal) => {
|
||||
let value = literal.value.clone();
|
||||
match value {
|
||||
LiteralValue::Number(x) => {
|
||||
if let Some(x) = crate::try_f64_to_usize(x) {
|
||||
LiteralValue::Number { value, .. } => {
|
||||
if let Some(x) = crate::try_f64_to_usize(value) {
|
||||
Ok(Property::UInt(x))
|
||||
} else {
|
||||
Err(KclError::Semantic(KclErrorDetails {
|
||||
source_ranges: property_sr,
|
||||
message: format!("{x} is not a valid index, indices must be whole numbers >= 0"),
|
||||
message: format!("{value} is not a valid index, indices must be whole numbers >= 0"),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -62,19 +62,27 @@ pub enum KclValue {
|
||||
},
|
||||
TagIdentifier(Box<TagIdentifier>),
|
||||
TagDeclarator(crate::parsing::ast::types::BoxNode<TagDeclarator>),
|
||||
Plane(Box<Plane>),
|
||||
Face(Box<Face>),
|
||||
Plane {
|
||||
value: Box<Plane>,
|
||||
},
|
||||
Face {
|
||||
value: Box<Face>,
|
||||
},
|
||||
Sketch {
|
||||
value: Box<Sketch>,
|
||||
},
|
||||
Sketches {
|
||||
value: Vec<Box<Sketch>>,
|
||||
},
|
||||
Solid(Box<Solid>),
|
||||
Solid {
|
||||
value: Box<Solid>,
|
||||
},
|
||||
Solids {
|
||||
value: Vec<Box<Solid>>,
|
||||
},
|
||||
Helix(Box<Helix>),
|
||||
Helix {
|
||||
value: Box<Helix>,
|
||||
},
|
||||
ImportedGeometry(ImportedGeometry),
|
||||
#[ts(skip)]
|
||||
Function {
|
||||
@ -120,7 +128,7 @@ impl From<Vec<Box<Sketch>>> for KclValue {
|
||||
impl From<SolidSet> for KclValue {
|
||||
fn from(eg: SolidSet) -> Self {
|
||||
match eg {
|
||||
SolidSet::Solid(eg) => KclValue::Solid(eg),
|
||||
SolidSet::Solid(eg) => KclValue::Solid { value: eg },
|
||||
SolidSet::Solids(egs) => KclValue::Solids { value: egs },
|
||||
}
|
||||
}
|
||||
@ -129,7 +137,7 @@ impl From<SolidSet> for KclValue {
|
||||
impl From<Vec<Box<Solid>>> for KclValue {
|
||||
fn from(eg: Vec<Box<Solid>>) -> Self {
|
||||
if eg.len() == 1 {
|
||||
KclValue::Solid(eg[0].clone())
|
||||
KclValue::Solid { value: eg[0].clone() }
|
||||
} else {
|
||||
KclValue::Solids { value: eg }
|
||||
}
|
||||
@ -140,15 +148,15 @@ impl From<KclValue> for Vec<SourceRange> {
|
||||
match item {
|
||||
KclValue::TagDeclarator(t) => vec![SourceRange::new(t.start, t.end, t.module_id)],
|
||||
KclValue::TagIdentifier(t) => to_vec_sr(&t.meta),
|
||||
KclValue::Solid(e) => to_vec_sr(&e.meta),
|
||||
KclValue::Solid { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Solids { value } => value.iter().flat_map(|eg| to_vec_sr(&eg.meta)).collect(),
|
||||
KclValue::Sketch { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Sketches { value } => value.iter().flat_map(|eg| to_vec_sr(&eg.meta)).collect(),
|
||||
KclValue::Helix(e) => to_vec_sr(&e.meta),
|
||||
KclValue::Helix { value } => to_vec_sr(&value.meta),
|
||||
KclValue::ImportedGeometry(i) => to_vec_sr(&i.meta),
|
||||
KclValue::Function { meta, .. } => to_vec_sr(&meta),
|
||||
KclValue::Plane(p) => to_vec_sr(&p.meta),
|
||||
KclValue::Face(f) => to_vec_sr(&f.meta),
|
||||
KclValue::Plane { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Face { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Bool { meta, .. } => to_vec_sr(&meta),
|
||||
KclValue::Number { meta, .. } => to_vec_sr(&meta),
|
||||
KclValue::Int { meta, .. } => to_vec_sr(&meta),
|
||||
@ -171,15 +179,15 @@ impl From<&KclValue> for Vec<SourceRange> {
|
||||
match item {
|
||||
KclValue::TagDeclarator(t) => vec![SourceRange::new(t.start, t.end, t.module_id)],
|
||||
KclValue::TagIdentifier(t) => to_vec_sr(&t.meta),
|
||||
KclValue::Solid(e) => to_vec_sr(&e.meta),
|
||||
KclValue::Solid { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Solids { value } => value.iter().flat_map(|eg| to_vec_sr(&eg.meta)).collect(),
|
||||
KclValue::Sketch { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Sketches { value } => value.iter().flat_map(|eg| to_vec_sr(&eg.meta)).collect(),
|
||||
KclValue::Helix(x) => to_vec_sr(&x.meta),
|
||||
KclValue::Helix { value } => to_vec_sr(&value.meta),
|
||||
KclValue::ImportedGeometry(i) => to_vec_sr(&i.meta),
|
||||
KclValue::Function { meta, .. } => to_vec_sr(meta),
|
||||
KclValue::Plane(p) => to_vec_sr(&p.meta),
|
||||
KclValue::Face(f) => to_vec_sr(&f.meta),
|
||||
KclValue::Plane { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Face { value } => to_vec_sr(&value.meta),
|
||||
KclValue::Bool { meta, .. } => to_vec_sr(meta),
|
||||
KclValue::Number { meta, .. } => to_vec_sr(meta),
|
||||
KclValue::Int { meta, .. } => to_vec_sr(meta),
|
||||
@ -205,13 +213,13 @@ impl KclValue {
|
||||
KclValue::Object { value: _, meta } => meta.clone(),
|
||||
KclValue::TagIdentifier(x) => x.meta.clone(),
|
||||
KclValue::TagDeclarator(x) => vec![x.metadata()],
|
||||
KclValue::Plane(x) => x.meta.clone(),
|
||||
KclValue::Face(x) => x.meta.clone(),
|
||||
KclValue::Plane { value } => value.meta.clone(),
|
||||
KclValue::Face { value } => value.meta.clone(),
|
||||
KclValue::Sketch { value } => value.meta.clone(),
|
||||
KclValue::Sketches { value } => value.iter().flat_map(|sketch| &sketch.meta).copied().collect(),
|
||||
KclValue::Solid(x) => x.meta.clone(),
|
||||
KclValue::Solid { value } => value.meta.clone(),
|
||||
KclValue::Solids { value } => value.iter().flat_map(|sketch| &sketch.meta).copied().collect(),
|
||||
KclValue::Helix(x) => x.meta.clone(),
|
||||
KclValue::Helix { value } => value.meta.clone(),
|
||||
KclValue::ImportedGeometry(x) => x.meta.clone(),
|
||||
KclValue::Function { meta, .. } => meta.clone(),
|
||||
KclValue::Module { meta, .. } => meta.clone(),
|
||||
@ -230,7 +238,7 @@ impl KclValue {
|
||||
|
||||
pub(crate) fn get_solid_set(&self) -> Result<SolidSet> {
|
||||
match self {
|
||||
KclValue::Solid(e) => Ok(SolidSet::Solid(e.clone())),
|
||||
KclValue::Solid { value } => Ok(SolidSet::Solid(value.clone())),
|
||||
KclValue::Solids { value } => Ok(SolidSet::Solids(value.clone())),
|
||||
KclValue::Array { value, .. } => {
|
||||
let solids: Vec<_> = value
|
||||
@ -266,15 +274,15 @@ impl KclValue {
|
||||
KclValue::Uuid { .. } => "Unique ID (uuid)",
|
||||
KclValue::TagDeclarator(_) => "TagDeclarator",
|
||||
KclValue::TagIdentifier(_) => "TagIdentifier",
|
||||
KclValue::Solid(_) => "Solid",
|
||||
KclValue::Solid { .. } => "Solid",
|
||||
KclValue::Solids { .. } => "Solids",
|
||||
KclValue::Sketch { .. } => "Sketch",
|
||||
KclValue::Sketches { .. } => "Sketches",
|
||||
KclValue::Helix(_) => "Helix",
|
||||
KclValue::Helix { .. } => "Helix",
|
||||
KclValue::ImportedGeometry(_) => "ImportedGeometry",
|
||||
KclValue::Function { .. } => "Function",
|
||||
KclValue::Plane(_) => "Plane",
|
||||
KclValue::Face(_) => "Face",
|
||||
KclValue::Plane { .. } => "Plane",
|
||||
KclValue::Face { .. } => "Face",
|
||||
KclValue::Bool { .. } => "boolean (true/false value)",
|
||||
KclValue::Number { .. } => "number",
|
||||
KclValue::Int { .. } => "integer",
|
||||
@ -288,7 +296,7 @@ impl KclValue {
|
||||
|
||||
pub(crate) fn from_literal(literal: LiteralValue, meta: Vec<Metadata>) -> Self {
|
||||
match literal {
|
||||
LiteralValue::Number(value) => KclValue::Number { value, meta },
|
||||
LiteralValue::Number { value, .. } => KclValue::Number { value, meta },
|
||||
LiteralValue::String(value) => KclValue::String { value, meta },
|
||||
LiteralValue::Bool(value) => KclValue::Bool { value, meta },
|
||||
}
|
||||
@ -383,7 +391,7 @@ impl KclValue {
|
||||
}
|
||||
|
||||
pub fn as_plane(&self) -> Option<&Plane> {
|
||||
if let KclValue::Plane(value) = &self {
|
||||
if let KclValue::Plane { value } = &self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
@ -391,7 +399,7 @@ impl KclValue {
|
||||
}
|
||||
|
||||
pub fn as_solid(&self) -> Option<&Solid> {
|
||||
if let KclValue::Solid(value) = &self {
|
||||
if let KclValue::Solid { value } = &self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
@ -614,6 +622,19 @@ impl From<crate::UnitLength> for UnitLen {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnitLen> for crate::UnitLength {
|
||||
fn from(unit: UnitLen) -> Self {
|
||||
match unit {
|
||||
UnitLen::Cm => crate::UnitLength::Cm,
|
||||
UnitLen::Feet => crate::UnitLength::Ft,
|
||||
UnitLen::Inches => crate::UnitLength::In,
|
||||
UnitLen::M => crate::UnitLength::M,
|
||||
UnitLen::Mm => crate::UnitLength::Mm,
|
||||
UnitLen::Yards => crate::UnitLength::Yd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use annotations::AnnotationScope;
|
||||
use anyhow::Result;
|
||||
use artifact::build_artifact_graph;
|
||||
use async_recursion::async_recursion;
|
||||
@ -391,7 +392,7 @@ impl ProgramMemory {
|
||||
env.bindings
|
||||
.values()
|
||||
.filter_map(|item| match item {
|
||||
KclValue::Solid(eg) if eg.sketch.id == sketch_id => Some(eg.clone()),
|
||||
KclValue::Solid { value } if value.sketch.id == sketch_id => Some(value.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
@ -505,8 +506,8 @@ impl DynamicState {
|
||||
fn append(&mut self, memory: &ProgramMemory) {
|
||||
for env in &memory.environments {
|
||||
for item in env.bindings.values() {
|
||||
if let KclValue::Solid(eg) = item {
|
||||
self.solid_ids.push(SolidLazyIds::from(eg.as_ref()));
|
||||
if let KclValue::Solid { value } = item {
|
||||
self.solid_ids.push(SolidLazyIds::from(value.as_ref()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -759,6 +760,7 @@ pub struct Helix {
|
||||
pub angle_start: f64,
|
||||
/// Is the helix rotation counter clockwise?
|
||||
pub ccw: bool,
|
||||
pub units: UnitLen,
|
||||
#[serde(rename = "__meta")]
|
||||
pub meta: Vec<Metadata>,
|
||||
}
|
||||
@ -780,6 +782,7 @@ pub struct Plane {
|
||||
pub y_axis: Point3d,
|
||||
/// The z-axis (normal).
|
||||
pub z_axis: Point3d,
|
||||
pub units: UnitLen,
|
||||
#[serde(rename = "__meta")]
|
||||
pub meta: Vec<Metadata>,
|
||||
}
|
||||
@ -795,6 +798,7 @@ impl Plane {
|
||||
y_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
z_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
value: PlaneType::XY,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::NegXY => Plane {
|
||||
@ -804,6 +808,7 @@ impl Plane {
|
||||
y_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
z_axis: Point3d::new(0.0, 0.0, -1.0),
|
||||
value: PlaneType::XY,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::XZ => Plane {
|
||||
@ -813,6 +818,7 @@ impl Plane {
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(0.0, -1.0, 0.0),
|
||||
value: PlaneType::XZ,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::NegXZ => Plane {
|
||||
@ -822,6 +828,7 @@ impl Plane {
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(0.0, 1.0, 0.0),
|
||||
value: PlaneType::XZ,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::YZ => Plane {
|
||||
@ -831,6 +838,7 @@ impl Plane {
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(1.0, 0.0, 0.0),
|
||||
value: PlaneType::YZ,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::NegYZ => Plane {
|
||||
@ -840,6 +848,7 @@ impl Plane {
|
||||
y_axis: Point3d::new(0.0, 0.0, 1.0),
|
||||
z_axis: Point3d::new(-1.0, 0.0, 0.0),
|
||||
value: PlaneType::YZ,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
crate::std::sketch::PlaneData::Plane {
|
||||
@ -854,6 +863,7 @@ impl Plane {
|
||||
y_axis: *y_axis,
|
||||
z_axis: *z_axis,
|
||||
value: PlaneType::Custom,
|
||||
units: exec_state.length_unit(),
|
||||
meta: vec![],
|
||||
},
|
||||
}
|
||||
@ -900,6 +910,7 @@ pub struct Face {
|
||||
pub z_axis: Point3d,
|
||||
/// The solid the face is on.
|
||||
pub solid: Box<Solid>,
|
||||
pub units: UnitLen,
|
||||
#[serde(rename = "__meta")]
|
||||
pub meta: Vec<Metadata>,
|
||||
}
|
||||
@ -1018,6 +1029,7 @@ pub struct Sketch {
|
||||
/// is sketched on face etc.
|
||||
#[serde(skip)]
|
||||
pub original_id: uuid::Uuid,
|
||||
pub units: UnitLen,
|
||||
/// Metadata.
|
||||
#[serde(rename = "__meta")]
|
||||
pub meta: Vec<Metadata>,
|
||||
@ -1141,6 +1153,7 @@ pub struct Solid {
|
||||
/// Chamfers or fillets on this solid.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub edge_cuts: Vec<EdgeCut>,
|
||||
pub units: UnitLen,
|
||||
/// Metadata.
|
||||
#[serde(rename = "__meta")]
|
||||
pub meta: Vec<Metadata>,
|
||||
@ -2304,6 +2317,36 @@ impl ExecutorContext {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_annotations(
|
||||
&self,
|
||||
annotations: impl Iterator<Item = (&NonCodeValue, SourceRange)>,
|
||||
scope: AnnotationScope,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<(), KclError> {
|
||||
for (annotation, source_range) in annotations {
|
||||
if annotation.annotation_name() == Some(annotations::SETTINGS) {
|
||||
if scope == AnnotationScope::Module {
|
||||
let old_units = exec_state.length_unit();
|
||||
exec_state
|
||||
.mod_local
|
||||
.settings
|
||||
.update_from_annotation(annotation, source_range)?;
|
||||
let new_units = exec_state.length_unit();
|
||||
if old_units != new_units {
|
||||
self.engine.set_units(new_units.into(), source_range).await?;
|
||||
}
|
||||
} else {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "Settings can only be modified at the top level scope of a file".to_owned(),
|
||||
source_ranges: vec![source_range],
|
||||
}));
|
||||
}
|
||||
}
|
||||
// TODO warn on unknown annotations
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Execute an AST's program.
|
||||
#[async_recursion]
|
||||
pub(crate) async fn inner_execute<'a>(
|
||||
@ -2312,21 +2355,16 @@ impl ExecutorContext {
|
||||
exec_state: &mut ExecState,
|
||||
body_type: BodyType,
|
||||
) -> Result<Option<KclValue>, KclError> {
|
||||
if let Some((annotation, source_range)) = program
|
||||
.non_code_meta
|
||||
.start_nodes
|
||||
.iter()
|
||||
.filter_map(|n| {
|
||||
n.annotation(annotations::SETTINGS)
|
||||
.map(|result| (result, n.as_source_range()))
|
||||
})
|
||||
.next()
|
||||
{
|
||||
exec_state
|
||||
.mod_local
|
||||
.settings
|
||||
.update_from_annotation(annotation, source_range)?;
|
||||
}
|
||||
self.handle_annotations(
|
||||
program
|
||||
.non_code_meta
|
||||
.start_nodes
|
||||
.iter()
|
||||
.filter_map(|n| n.annotation().map(|result| (result, n.as_source_range()))),
|
||||
AnnotationScope::Module,
|
||||
exec_state,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut last_expr = None;
|
||||
// Iterate over the body of the program.
|
||||
@ -2509,6 +2547,7 @@ impl ExecutorContext {
|
||||
exec_kind: ExecutionKind,
|
||||
source_range: SourceRange,
|
||||
) -> Result<(Option<KclValue>, ProgramMemory, Vec<String>), KclError> {
|
||||
let old_units = exec_state.length_unit();
|
||||
// TODO It sucks that we have to clone the whole module AST here
|
||||
let info = exec_state.global.module_infos[&module_id].clone();
|
||||
|
||||
@ -2525,7 +2564,11 @@ impl ExecutorContext {
|
||||
.inner_execute(&info.parsed.unwrap(), exec_state, crate::execution::BodyType::Root)
|
||||
.await;
|
||||
|
||||
let new_units = exec_state.length_unit();
|
||||
std::mem::swap(&mut exec_state.mod_local, &mut local_state);
|
||||
if new_units != old_units {
|
||||
self.engine.set_units(old_units.into(), Default::default()).await?;
|
||||
}
|
||||
self.engine.replace_execution_kind(original_execution);
|
||||
|
||||
let result = result.map_err(|err| {
|
||||
|
@ -163,7 +163,7 @@ fn get_xyz(point: &ObjectExpression) -> Option<(f64, f64, f64)> {
|
||||
|
||||
fn unlitafy(lit: &LiteralValue) -> Option<f64> {
|
||||
Some(match lit {
|
||||
LiteralValue::Number(value) => *value,
|
||||
LiteralValue::Number { value, .. } => *value,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use sha2::{Digest as DigestTrait, Sha256};
|
||||
|
||||
use super::types::{DefaultParamVal, ItemVisibility, LabelledExpression, VariableKind};
|
||||
use super::types::{DefaultParamVal, ItemVisibility, LabelledExpression, LiteralValue, VariableKind};
|
||||
use crate::parsing::ast::types::{
|
||||
ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryPart, BodyItem, CallExpression, CallExpressionKw,
|
||||
ElseIf, Expr, ExpressionStatement, FnArgType, FunctionExpression, Identifier, IfExpression, ImportItem,
|
||||
@ -277,6 +277,26 @@ impl Literal {
|
||||
});
|
||||
}
|
||||
|
||||
impl LiteralValue {
|
||||
fn digestable_id(&self) -> Vec<u8> {
|
||||
match self {
|
||||
LiteralValue::Number { value, suffix } => {
|
||||
let mut result: Vec<u8> = value.to_ne_bytes().into();
|
||||
result.extend((*suffix as u32).to_ne_bytes());
|
||||
result
|
||||
}
|
||||
LiteralValue::String(st) => st.as_bytes().into(),
|
||||
LiteralValue::Bool(b) => {
|
||||
if *b {
|
||||
vec![1]
|
||||
} else {
|
||||
vec![0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Identifier {
|
||||
compute_digest!(|slf, hasher| {
|
||||
let name = slf.name.as_bytes();
|
||||
|
@ -18,6 +18,8 @@ use crate::{
|
||||
Program,
|
||||
};
|
||||
|
||||
use super::types::LiteralValue;
|
||||
|
||||
type Point3d = kcmc::shared::Point3d<f64>;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -201,8 +203,8 @@ fn create_start_sketch_on(
|
||||
"startProfileAt",
|
||||
vec![
|
||||
ArrayExpression::new(vec![
|
||||
Literal::new(round_before_recast(start[0]).into()).into(),
|
||||
Literal::new(round_before_recast(start[1]).into()).into(),
|
||||
Literal::new(LiteralValue::from_f64_no_uom(round_before_recast(start[0]))).into(),
|
||||
Literal::new(LiteralValue::from_f64_no_uom(round_before_recast(start[1]))).into(),
|
||||
])
|
||||
.into(),
|
||||
PipeSubstitution::new().into(),
|
||||
@ -221,8 +223,8 @@ fn create_start_sketch_on(
|
||||
"line",
|
||||
vec![
|
||||
ArrayExpression::new(vec![
|
||||
Literal::new(round_before_recast(end[0]).into()).into(),
|
||||
Literal::new(round_before_recast(end[1]).into()).into(),
|
||||
Literal::new(LiteralValue::from_f64_no_uom(round_before_recast(end[0]))).into(),
|
||||
Literal::new(LiteralValue::from_f64_no_uom(round_before_recast(end[1]))).into(),
|
||||
])
|
||||
.into(),
|
||||
PipeSubstitution::new().into(),
|
||||
@ -254,8 +256,8 @@ fn create_start_sketch_on(
|
||||
"line",
|
||||
vec![
|
||||
ArrayExpression::new(vec![
|
||||
Literal::new(round_before_recast(line[0]).into()).into(),
|
||||
Literal::new(round_before_recast(line[1]).into()).into(),
|
||||
Literal::new(LiteralValue::from_f64_no_uom(round_before_recast(line[0]))).into(),
|
||||
Literal::new(LiteralValue::from_f64_no_uom(round_before_recast(line[1]))).into(),
|
||||
])
|
||||
.into(),
|
||||
PipeSubstitution::new().into(),
|
||||
|
@ -1,31 +1,49 @@
|
||||
use std::fmt;
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JValue;
|
||||
|
||||
use super::Node;
|
||||
use crate::parsing::ast::types::{Expr, Literal};
|
||||
use crate::parsing::{
|
||||
ast::types::{Expr, Literal},
|
||||
token::NumericSuffix,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(untagged, rename_all = "snake_case")]
|
||||
pub enum LiteralValue {
|
||||
Number(f64),
|
||||
Number { value: f64, suffix: NumericSuffix },
|
||||
String(String),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl LiteralValue {
|
||||
pub fn digestable_id(&self) -> Vec<u8> {
|
||||
pub fn from_f64_no_uom(value: f64) -> Self {
|
||||
LiteralValue::Number {
|
||||
value,
|
||||
suffix: NumericSuffix::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LiteralValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
LiteralValue::Number(frac) => frac.to_ne_bytes().into(),
|
||||
LiteralValue::String(st) => st.as_bytes().into(),
|
||||
LiteralValue::Bool(b) => {
|
||||
if *b {
|
||||
vec![1]
|
||||
LiteralValue::Number { value, suffix } => {
|
||||
let int_value = *value as u64;
|
||||
if int_value as f64 == *value {
|
||||
write!(f, "{int_value}")?;
|
||||
} else {
|
||||
vec![0]
|
||||
write!(f, "{value}")?;
|
||||
}
|
||||
if *suffix != NumericSuffix::None {
|
||||
write!(f, "{suffix}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
LiteralValue::String(s) => write!(f, "\"{s}\""),
|
||||
LiteralValue::Bool(b) => write!(f, "{b}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,49 +54,12 @@ impl From<Node<Literal>> for Expr {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LiteralValue> for JValue {
|
||||
fn from(value: LiteralValue) -> Self {
|
||||
match value {
|
||||
LiteralValue::Number(x) => x.into(),
|
||||
LiteralValue::String(x) => x.into(),
|
||||
LiteralValue::Bool(b) => b.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for LiteralValue {
|
||||
fn from(value: f64) -> Self {
|
||||
Self::Number(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for LiteralValue {
|
||||
fn from(value: i64) -> Self {
|
||||
Self::Number(value as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for LiteralValue {
|
||||
fn from(value: String) -> Self {
|
||||
Self::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for LiteralValue {
|
||||
fn from(value: u32) -> Self {
|
||||
Self::Number(value as f64)
|
||||
}
|
||||
}
|
||||
impl From<u16> for LiteralValue {
|
||||
fn from(value: u16) -> Self {
|
||||
Self::Number(value as f64)
|
||||
}
|
||||
}
|
||||
impl From<u8> for LiteralValue {
|
||||
fn from(value: u8) -> Self {
|
||||
Self::Number(value as f64)
|
||||
}
|
||||
}
|
||||
impl From<&'static str> for LiteralValue {
|
||||
fn from(value: &'static str) -> Self {
|
||||
// TODO: Make this Cow<str>
|
||||
|
@ -13,7 +13,6 @@ use anyhow::Result;
|
||||
use parse_display::{Display, FromStr};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JValue;
|
||||
use tower_lsp::lsp_types::{
|
||||
CompletionItem, CompletionItemKind, DocumentSymbol, FoldingRange, FoldingRangeKind, Range as LspRange, SymbolKind,
|
||||
};
|
||||
@ -1012,9 +1011,9 @@ impl NonCodeNode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn annotation(&self, expected_name: &str) -> Option<&NonCodeValue> {
|
||||
pub fn annotation(&self) -> Option<&NonCodeValue> {
|
||||
match &self.value {
|
||||
a @ NonCodeValue::Annotation { name, .. } if name.name == expected_name => Some(a),
|
||||
a @ NonCodeValue::Annotation { .. } => Some(a),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -1072,6 +1071,15 @@ pub enum NonCodeValue {
|
||||
},
|
||||
}
|
||||
|
||||
impl NonCodeValue {
|
||||
pub fn annotation_name(&self) -> Option<&str> {
|
||||
match self {
|
||||
NonCodeValue::Annotation { name, .. } => Some(&name.name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -1867,7 +1875,7 @@ impl Node<Literal> {
|
||||
impl Literal {
|
||||
pub fn new(value: LiteralValue) -> Node<Self> {
|
||||
Node::no_src(Self {
|
||||
raw: JValue::from(value.clone()).to_string(),
|
||||
raw: value.to_string(),
|
||||
value,
|
||||
digest: None,
|
||||
})
|
||||
@ -1878,7 +1886,7 @@ impl From<Node<Literal>> for KclValue {
|
||||
fn from(literal: Node<Literal>) -> Self {
|
||||
let meta = vec![literal.metadata()];
|
||||
match literal.inner.value {
|
||||
LiteralValue::Number(value) => KclValue::Number { value, meta },
|
||||
LiteralValue::Number { value, .. } => KclValue::Number { value, meta },
|
||||
LiteralValue::String(value) => KclValue::String { value, meta },
|
||||
LiteralValue::Bool(value) => KclValue::Bool { value, meta },
|
||||
}
|
||||
|
@ -126,7 +126,13 @@ impl From<BinaryOperator> for BinaryExpressionToken {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{parsing::ast::types::Literal, source_range::ModuleId};
|
||||
use crate::{
|
||||
parsing::{
|
||||
ast::types::{Literal, LiteralValue},
|
||||
token::NumericSuffix,
|
||||
},
|
||||
source_range::ModuleId,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn parse_and_evaluate() {
|
||||
@ -134,7 +140,10 @@ mod tests {
|
||||
fn lit(n: u8) -> BinaryPart {
|
||||
BinaryPart::Literal(Box::new(Node::new(
|
||||
Literal {
|
||||
value: n.into(),
|
||||
value: LiteralValue::Number {
|
||||
value: n as f64,
|
||||
suffix: NumericSuffix::None,
|
||||
},
|
||||
raw: n.to_string(),
|
||||
digest: None,
|
||||
},
|
||||
|
@ -483,7 +483,7 @@ pub(crate) fn unsigned_number_literal(i: &mut TokenSlice) -> PResult<Node<Litera
|
||||
let (value, token) = any
|
||||
.try_map(|token: Token| match token.token_type {
|
||||
TokenType::Number => {
|
||||
let x: f64 = token.numeric_value().ok_or_else(|| {
|
||||
let value: f64 = token.numeric_value().ok_or_else(|| {
|
||||
CompilationError::fatal(token.as_source_range(), format!("Invalid float: {}", token.value))
|
||||
})?;
|
||||
|
||||
@ -494,7 +494,13 @@ pub(crate) fn unsigned_number_literal(i: &mut TokenSlice) -> PResult<Node<Litera
|
||||
));
|
||||
}
|
||||
|
||||
Ok((LiteralValue::Number(x), token))
|
||||
Ok((
|
||||
LiteralValue::Number {
|
||||
value,
|
||||
suffix: token.numeric_suffix(),
|
||||
},
|
||||
token,
|
||||
))
|
||||
}
|
||||
_ => Err(CompilationError::fatal(token.as_source_range(), "invalid literal")),
|
||||
})
|
||||
@ -844,13 +850,13 @@ fn object_property(i: &mut TokenSlice) -> PResult<Node<ObjectProperty>> {
|
||||
};
|
||||
|
||||
if sep.token_type == TokenType::Colon {
|
||||
ParseContext::warn(CompilationError::with_suggestion(
|
||||
sep.into(),
|
||||
Some(result.as_source_range()),
|
||||
"Using `:` to initialize objects is deprecated, prefer using `=`.",
|
||||
Some(("Replace `:` with `=`", " =")),
|
||||
Tag::Deprecated,
|
||||
));
|
||||
ParseContext::warn(
|
||||
CompilationError::err(
|
||||
sep.into(),
|
||||
"Using `:` to initialize objects is deprecated, prefer using `=`.",
|
||||
)
|
||||
.with_suggestion("Replace `:` with `=`", " =", Tag::Deprecated),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
@ -1069,9 +1075,19 @@ fn function_expr(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
let fn_tok = opt(fun).parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
let (result, has_arrow) = function_decl.parse_next(i)?;
|
||||
if fn_tok.is_none() && !has_arrow {
|
||||
let err = CompilationError::fatal(result.as_source_range(), "Anonymous function requires `fn` before `(`");
|
||||
return Err(ErrMode::Cut(err.into()));
|
||||
if fn_tok.is_none() {
|
||||
if has_arrow {
|
||||
ParseContext::warn(
|
||||
CompilationError::err(
|
||||
result.as_source_range().start_as_range(),
|
||||
"Missing `fn` in function declaration",
|
||||
)
|
||||
.with_suggestion("Add `fn`", "fn", Tag::None),
|
||||
);
|
||||
} else {
|
||||
let err = CompilationError::fatal(result.as_source_range(), "Anonymous function requires `fn` before `(`");
|
||||
return Err(ErrMode::Cut(err.into()));
|
||||
}
|
||||
}
|
||||
Ok(Expr::FunctionExpression(Box::new(result)))
|
||||
}
|
||||
@ -1113,18 +1129,16 @@ fn function_decl(i: &mut TokenSlice) -> PResult<(Node<FunctionExpression>, bool)
|
||||
open.module_id,
|
||||
);
|
||||
|
||||
let has_arrow = if let Some(arrow) = arrow {
|
||||
ParseContext::warn(CompilationError::with_suggestion(
|
||||
arrow.as_source_range(),
|
||||
Some(result.as_source_range()),
|
||||
"Unnecessary `=>` in function declaration",
|
||||
Some(("Remove `=>`", "")),
|
||||
Tag::Unnecessary,
|
||||
));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let has_arrow =
|
||||
if let Some(arrow) = arrow {
|
||||
ParseContext::warn(
|
||||
CompilationError::err(arrow.as_source_range(), "Unnecessary `=>` in function declaration")
|
||||
.with_suggestion("Remove `=>`", "", Tag::Unnecessary),
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
Ok((result, has_arrow))
|
||||
}
|
||||
@ -1825,67 +1839,60 @@ fn declaration(i: &mut TokenSlice) -> PResult<BoxNode<VariableDeclaration>> {
|
||||
|
||||
ignore_whitespace(i);
|
||||
|
||||
let val = if kind == VariableKind::Fn {
|
||||
let eq = opt(equals).parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
let val =
|
||||
if kind == VariableKind::Fn {
|
||||
let eq = opt(equals).parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
|
||||
let val = function_decl
|
||||
.map(|t| Box::new(t.0))
|
||||
.map(Expr::FunctionExpression)
|
||||
.context(expected("a KCL function expression, like () { return 1 }"))
|
||||
.parse_next(i);
|
||||
let val = function_decl
|
||||
.map(|t| Box::new(t.0))
|
||||
.map(Expr::FunctionExpression)
|
||||
.context(expected("a KCL function expression, like () { return 1 }"))
|
||||
.parse_next(i);
|
||||
|
||||
if let Some(t) = eq {
|
||||
let ctxt_end = val.as_ref().map(|e| e.end()).unwrap_or(t.end);
|
||||
ParseContext::warn(CompilationError::with_suggestion(
|
||||
t.as_source_range(),
|
||||
Some(SourceRange::new(id.start, ctxt_end, id.module_id)),
|
||||
"Unnecessary `=` in function declaration",
|
||||
Some(("Remove `=`", "")),
|
||||
Tag::Unnecessary,
|
||||
));
|
||||
if let Some(t) = eq {
|
||||
ParseContext::warn(
|
||||
CompilationError::err(t.as_source_range(), "Unnecessary `=` in function declaration")
|
||||
.with_suggestion("Remove `=`", "", Tag::Unnecessary),
|
||||
);
|
||||
}
|
||||
|
||||
val
|
||||
} else {
|
||||
equals(i)?;
|
||||
ignore_whitespace(i);
|
||||
|
||||
let val = expression
|
||||
.try_map(|val| {
|
||||
// Function bodies can be used if and only if declaring a function.
|
||||
// Check the 'if' direction:
|
||||
if matches!(val, Expr::FunctionExpression(_)) {
|
||||
return Err(CompilationError::fatal(
|
||||
SourceRange::new(start, dec_end, id.module_id),
|
||||
format!("Expected a `fn` variable kind, found: `{}`", kind),
|
||||
));
|
||||
}
|
||||
Ok(val)
|
||||
})
|
||||
.context(expected("a KCL value, which is being bound to a variable"))
|
||||
.parse_next(i);
|
||||
|
||||
if let Some((_, tok)) = decl_token {
|
||||
ParseContext::warn(
|
||||
CompilationError::err(
|
||||
tok.as_source_range(),
|
||||
format!(
|
||||
"Using `{}` to declare constants is deprecated; no keyword is required",
|
||||
tok.value
|
||||
),
|
||||
)
|
||||
.with_suggestion(format!("Remove `{}`", tok.value), "", Tag::Deprecated),
|
||||
);
|
||||
}
|
||||
|
||||
val
|
||||
}
|
||||
|
||||
val
|
||||
} else {
|
||||
equals(i)?;
|
||||
ignore_whitespace(i);
|
||||
|
||||
let val = expression
|
||||
.try_map(|val| {
|
||||
// Function bodies can be used if and only if declaring a function.
|
||||
// Check the 'if' direction:
|
||||
if matches!(val, Expr::FunctionExpression(_)) {
|
||||
return Err(CompilationError::fatal(
|
||||
SourceRange::new(start, dec_end, id.module_id),
|
||||
format!("Expected a `fn` variable kind, found: `{}`", kind),
|
||||
));
|
||||
}
|
||||
Ok(val)
|
||||
})
|
||||
.context(expected("a KCL value, which is being bound to a variable"))
|
||||
.parse_next(i);
|
||||
|
||||
if let Some((_, tok)) = decl_token {
|
||||
ParseContext::warn(CompilationError::with_suggestion(
|
||||
tok.as_source_range(),
|
||||
Some(SourceRange::new(
|
||||
id.start,
|
||||
val.as_ref().map(|e| e.end()).unwrap_or(dec_end),
|
||||
id.module_id,
|
||||
)),
|
||||
format!(
|
||||
"Using `{}` to declare constants is deprecated; no keyword is required",
|
||||
tok.value
|
||||
),
|
||||
Some((format!("Remove `{}`", tok.value), "")),
|
||||
Tag::Deprecated,
|
||||
));
|
||||
}
|
||||
|
||||
val
|
||||
}
|
||||
.map_err(|e| e.cut())?;
|
||||
.map_err(|e| e.cut())?;
|
||||
|
||||
let end = val.end();
|
||||
Ok(Box::new(Node {
|
||||
@ -2856,7 +2863,10 @@ mySk1 = startSketchAt([0, 0])"#;
|
||||
ReturnStatement {
|
||||
argument: Expr::Literal(Box::new(Node::new(
|
||||
Literal {
|
||||
value: 2u32.into(),
|
||||
value: LiteralValue::Number {
|
||||
value: 2.0,
|
||||
suffix: NumericSuffix::None
|
||||
},
|
||||
raw: "2".to_owned(),
|
||||
digest: None,
|
||||
},
|
||||
@ -3057,7 +3067,15 @@ mySk1 = startSketchAt([0, 0])"#;
|
||||
match &rhs.right {
|
||||
BinaryPart::Literal(lit) => {
|
||||
assert!(lit.start == 9 && lit.end == 10);
|
||||
assert!(lit.value == 3u32.into() && &lit.raw == "3" && lit.digest.is_none());
|
||||
assert!(
|
||||
lit.value
|
||||
== LiteralValue::Number {
|
||||
value: 3.0,
|
||||
suffix: NumericSuffix::None
|
||||
}
|
||||
&& &lit.raw == "3"
|
||||
&& lit.digest.is_none()
|
||||
);
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
@ -3128,11 +3146,23 @@ mySk1 = startSketchAt([0, 0])"#;
|
||||
let BinaryPart::Literal(left) = actual.inner.left else {
|
||||
panic!("should be expression");
|
||||
};
|
||||
assert_eq!(left.value, 1u32.into());
|
||||
assert_eq!(
|
||||
left.value,
|
||||
LiteralValue::Number {
|
||||
value: 1.0,
|
||||
suffix: NumericSuffix::None
|
||||
}
|
||||
);
|
||||
let BinaryPart::Literal(right) = actual.inner.right else {
|
||||
panic!("should be expression");
|
||||
};
|
||||
assert_eq!(right.value, 2u32.into());
|
||||
assert_eq!(
|
||||
right.value,
|
||||
LiteralValue::Number {
|
||||
value: 2.0,
|
||||
suffix: NumericSuffix::None
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3449,7 +3479,10 @@ mySk1 = startSketchAt([0, 0])"#;
|
||||
operator: BinaryOperator::Add,
|
||||
left: BinaryPart::Literal(Box::new(Node::new(
|
||||
Literal {
|
||||
value: 5u32.into(),
|
||||
value: LiteralValue::Number {
|
||||
value: 5.0,
|
||||
suffix: NumericSuffix::None,
|
||||
},
|
||||
raw: "5".to_owned(),
|
||||
digest: None,
|
||||
},
|
||||
@ -3498,7 +3531,10 @@ mySk1 = startSketchAt([0, 0])"#;
|
||||
BinaryExpression {
|
||||
left: BinaryPart::Literal(Box::new(Node::new(
|
||||
Literal {
|
||||
value: 5u32.into(),
|
||||
value: LiteralValue::Number {
|
||||
value: 5.0,
|
||||
suffix: NumericSuffix::None,
|
||||
},
|
||||
raw: "5".to_string(),
|
||||
digest: None,
|
||||
},
|
||||
@ -3509,7 +3545,10 @@ mySk1 = startSketchAt([0, 0])"#;
|
||||
operator: BinaryOperator::Add,
|
||||
right: BinaryPart::Literal(Box::new(Node::new(
|
||||
Literal {
|
||||
value: 6u32.into(),
|
||||
value: LiteralValue::Number {
|
||||
value: 6.0,
|
||||
suffix: NumericSuffix::None,
|
||||
},
|
||||
raw: "6".to_string(),
|
||||
digest: None,
|
||||
},
|
||||
@ -4345,6 +4384,20 @@ sketch001 = startSketchOn('XZ') |> startProfileAt([90.45, 119.09, %)"#;
|
||||
return 0
|
||||
}"#
|
||||
);
|
||||
|
||||
let some_program_string = r#"myMap = map([0..5], (n) => {
|
||||
return n * 2
|
||||
})"#;
|
||||
let (_, errs) = assert_no_err(some_program_string);
|
||||
assert_eq!(errs.len(), 2);
|
||||
let replaced = errs[0].apply_suggestion(some_program_string).unwrap();
|
||||
let replaced = errs[1].apply_suggestion(&replaced).unwrap();
|
||||
assert_eq!(
|
||||
replaced,
|
||||
r#"myMap = map([0..5], fn(n) {
|
||||
return n * 2
|
||||
})"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3851
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -18,7 +19,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 4,
|
||||
"end": 5
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3852
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -18,7 +19,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 2,
|
||||
"end": 3
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3853
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -18,7 +19,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 3,
|
||||
"end": 4
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3854
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -22,7 +23,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 4,
|
||||
"end": 5
|
||||
@ -30,7 +34,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 8,
|
||||
"end": 9
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3855
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -22,7 +23,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 6,
|
||||
"end": 7
|
||||
@ -30,7 +34,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 10,
|
||||
"end": 11
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3856
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -14,7 +12,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -26,7 +27,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 6,
|
||||
"end": 7
|
||||
@ -34,7 +38,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 10,
|
||||
"end": 11
|
||||
@ -48,7 +55,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0,
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "4",
|
||||
"start": 16,
|
||||
"end": 17
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3857
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -26,7 +27,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 6,
|
||||
"end": 7
|
||||
@ -34,7 +38,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 10,
|
||||
"end": 11
|
||||
@ -45,7 +52,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0,
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "4",
|
||||
"start": 16,
|
||||
"end": 17
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3858
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -30,7 +31,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 7,
|
||||
"end": 8
|
||||
@ -38,7 +42,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 11,
|
||||
"end": 12
|
||||
@ -49,7 +56,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0,
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "4",
|
||||
"start": 17,
|
||||
"end": 18
|
||||
@ -60,7 +70,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0,
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "5",
|
||||
"start": 21,
|
||||
"end": 22
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3859
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0,
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -22,7 +23,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 8,
|
||||
"end": 9
|
||||
@ -30,7 +34,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 12,
|
||||
"end": 13
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3860
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -49,7 +47,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 6.0,
|
||||
"value": {
|
||||
"value": 6.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "6",
|
||||
"start": 21,
|
||||
"end": 22
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3861
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"type": "BinaryExpression",
|
||||
@ -10,7 +8,10 @@ snapshot_kind: text
|
||||
"left": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0,
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "2",
|
||||
"start": 0,
|
||||
"end": 1
|
||||
@ -18,7 +19,10 @@ snapshot_kind: text
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0,
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
},
|
||||
"raw": "3",
|
||||
"start": 7,
|
||||
"end": 8
|
||||
|
@ -25,7 +25,10 @@ expression: actual
|
||||
"start": 27,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 31,
|
||||
@ -33,7 +36,10 @@ expression: actual
|
||||
"start": 30,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 32,
|
||||
@ -63,7 +69,10 @@ expression: actual
|
||||
"start": 47,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 52,
|
||||
@ -71,7 +80,10 @@ expression: actual
|
||||
"start": 50,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 10.0
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 53,
|
||||
@ -108,7 +120,10 @@ expression: actual
|
||||
"start": 81,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 82,
|
||||
"operator": "-",
|
||||
@ -122,7 +137,10 @@ expression: actual
|
||||
"start": 84,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 86,
|
||||
@ -158,7 +176,10 @@ expression: actual
|
||||
"start": 104,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"argument": {
|
||||
@ -167,7 +188,10 @@ expression: actual
|
||||
"start": 108,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 15.0
|
||||
"value": {
|
||||
"value": 15.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 110,
|
||||
"operator": "-",
|
||||
@ -207,7 +231,10 @@ expression: actual
|
||||
"start": 131,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 10.0
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 136,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3964
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -31,7 +29,10 @@ snapshot_kind: text
|
||||
"start": 14,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"argument": {
|
||||
@ -40,7 +41,10 @@ snapshot_kind: text
|
||||
"start": 18,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 19,
|
||||
"operator": "-",
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 14,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 10.0
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"endInclusive": true,
|
||||
"start": 10,
|
||||
@ -31,7 +34,10 @@ expression: actual
|
||||
"start": 11,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"type": "ArrayRangeExpression",
|
||||
"type": "ArrayRangeExpression"
|
||||
|
@ -23,7 +23,10 @@ expression: actual
|
||||
"start": 50,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"end": 51,
|
||||
"start": 43,
|
||||
|
@ -25,7 +25,10 @@ expression: actual
|
||||
"start": 26,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 29,
|
||||
@ -33,7 +36,10 @@ expression: actual
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 30,
|
||||
@ -63,7 +69,10 @@ expression: actual
|
||||
"start": 51,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 55,
|
||||
@ -71,7 +80,10 @@ expression: actual
|
||||
"start": 54,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 56,
|
||||
@ -114,7 +126,10 @@ expression: actual
|
||||
"start": 89,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 93,
|
||||
@ -122,7 +137,10 @@ expression: actual
|
||||
"start": 92,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 94,
|
||||
@ -158,7 +176,10 @@ expression: actual
|
||||
"start": 118,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 122,
|
||||
@ -166,7 +187,10 @@ expression: actual
|
||||
"start": 121,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 123,
|
||||
|
@ -25,7 +25,10 @@ expression: actual
|
||||
"start": 26,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 29,
|
||||
@ -33,7 +36,10 @@ expression: actual
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 30,
|
||||
@ -63,7 +69,10 @@ expression: actual
|
||||
"start": 43,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 47,
|
||||
@ -71,7 +80,10 @@ expression: actual
|
||||
"start": 46,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 48,
|
||||
|
@ -23,7 +23,10 @@ expression: actual
|
||||
"start": 10,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
@ -45,7 +48,10 @@ expression: actual
|
||||
"start": 18,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 22,
|
||||
|
@ -46,7 +46,10 @@ expression: actual
|
||||
"start": 34,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 38,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3996
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -31,7 +29,10 @@ snapshot_kind: text
|
||||
"start": 14,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 18,
|
||||
@ -39,7 +40,10 @@ snapshot_kind: text
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 19,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3997
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -31,7 +29,10 @@ snapshot_kind: text
|
||||
"start": 14,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 18,
|
||||
@ -39,7 +40,10 @@ snapshot_kind: text
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 19,
|
||||
@ -66,7 +70,10 @@ snapshot_kind: text
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 32,
|
||||
@ -74,7 +81,10 @@ snapshot_kind: text
|
||||
"start": 31,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 33,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3998
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -31,7 +29,10 @@ snapshot_kind: text
|
||||
"start": 12,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 16,
|
||||
@ -39,7 +40,10 @@ snapshot_kind: text
|
||||
"start": 15,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 17,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 3999
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -31,7 +29,10 @@ snapshot_kind: text
|
||||
"start": 14,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 18,
|
||||
@ -39,7 +40,10 @@ snapshot_kind: text
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 19,
|
||||
@ -66,7 +70,10 @@ snapshot_kind: text
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 32,
|
||||
@ -74,7 +81,10 @@ snapshot_kind: text
|
||||
"start": 31,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 33,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 4000
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -31,7 +29,10 @@ snapshot_kind: text
|
||||
"start": 14,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 18,
|
||||
@ -39,7 +40,10 @@ snapshot_kind: text
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 19,
|
||||
@ -66,7 +70,10 @@ snapshot_kind: text
|
||||
"start": 27,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 31,
|
||||
@ -74,7 +81,10 @@ snapshot_kind: text
|
||||
"start": 30,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 32,
|
||||
|
@ -23,7 +23,10 @@ expression: actual
|
||||
"start": 26,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 29,
|
||||
@ -31,7 +34,10 @@ expression: actual
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 30,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 4002
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -16,7 +14,10 @@ snapshot_kind: text
|
||||
"start": 4,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 14,
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 4003
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -16,7 +14,10 @@ snapshot_kind: text
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
source: kcl/src/parsing/parser.rs
|
||||
assertion_line: 4004
|
||||
expression: actual
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
@ -18,7 +16,10 @@ snapshot_kind: text
|
||||
"start": 6,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 10,
|
||||
|
@ -60,7 +60,10 @@ expression: actual
|
||||
"start": 62,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 66,
|
||||
@ -68,7 +71,10 @@ expression: actual
|
||||
"start": 65,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 0.0
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 67,
|
||||
@ -93,7 +99,10 @@ expression: actual
|
||||
"start": 77,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 22.0
|
||||
"value": {
|
||||
"value": 22.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -127,7 +136,10 @@ expression: actual
|
||||
"start": 101,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 14.0
|
||||
"value": {
|
||||
"value": 14.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 106,
|
||||
|
@ -32,7 +32,10 @@ expression: actual
|
||||
"start": 43,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 360.0
|
||||
"value": {
|
||||
"value": 360.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 80,
|
||||
@ -29,7 +32,10 @@ expression: actual
|
||||
"start": 79,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 91,
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 44,
|
||||
@ -29,7 +32,10 @@ expression: actual
|
||||
"start": 43,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 91,
|
||||
|
@ -49,7 +49,10 @@ expression: actual
|
||||
"start": 29,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -68,7 +71,10 @@ expression: actual
|
||||
"start": 68,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -49,7 +49,10 @@ expression: actual
|
||||
"start": 29,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -68,7 +71,10 @@ expression: actual
|
||||
"start": 68,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 12,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"argument": {
|
||||
@ -32,7 +35,10 @@ expression: actual
|
||||
"start": 24,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 28,
|
||||
@ -40,7 +46,10 @@ expression: actual
|
||||
"start": 27,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
|
@ -23,7 +23,10 @@ expression: actual
|
||||
"start": 8,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "^",
|
||||
"right": {
|
||||
@ -32,7 +35,10 @@ expression: actual
|
||||
"start": 12,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 8,
|
||||
"type": "BinaryExpression",
|
||||
@ -49,7 +55,10 @@ expression: actual
|
||||
"start": 16,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "^",
|
||||
"right": {
|
||||
@ -58,7 +67,10 @@ expression: actual
|
||||
"start": 20,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 16,
|
||||
"type": "BinaryExpression",
|
||||
@ -71,7 +83,10 @@ expression: actual
|
||||
"start": 24,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 16,
|
||||
"type": "BinaryExpression",
|
||||
|
@ -35,7 +35,10 @@ expression: actual
|
||||
"start": 57,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 57,
|
||||
"type": "ExpressionStatement",
|
||||
@ -56,7 +59,10 @@ expression: actual
|
||||
"start": 26,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 26,
|
||||
"type": "ExpressionStatement",
|
||||
|
@ -59,7 +59,10 @@ expression: actual
|
||||
"start": 73,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 73,
|
||||
"type": "ExpressionStatement",
|
||||
@ -83,7 +86,10 @@ expression: actual
|
||||
"start": 104,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 104,
|
||||
"type": "ExpressionStatement",
|
||||
@ -104,7 +110,10 @@ expression: actual
|
||||
"start": 26,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 26,
|
||||
"type": "ExpressionStatement",
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 8,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "==",
|
||||
"right": {
|
||||
@ -30,7 +33,10 @@ expression: actual
|
||||
"start": 13,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 8,
|
||||
"type": "BinaryExpression",
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 8,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "!=",
|
||||
"right": {
|
||||
@ -30,7 +33,10 @@ expression: actual
|
||||
"start": 13,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 8,
|
||||
"type": "BinaryExpression",
|
||||
|
@ -19,7 +19,10 @@ expression: actual
|
||||
"start": 4,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
|
@ -34,7 +34,10 @@ expression: actual
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 10.0
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 23,
|
||||
@ -42,7 +45,10 @@ expression: actual
|
||||
"start": 21,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 10.0
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 24,
|
||||
@ -67,7 +73,10 @@ expression: actual
|
||||
"start": 34,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -19,7 +19,10 @@ expression: actual
|
||||
"start": 4,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
@ -76,7 +79,10 @@ expression: actual
|
||||
"start": 28,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -24,7 +24,10 @@ expression: actual
|
||||
"start": 20,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 24,
|
||||
@ -32,7 +35,10 @@ expression: actual
|
||||
"start": 23,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
@ -58,7 +64,10 @@ expression: actual
|
||||
"start": 27,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
|
@ -23,7 +23,10 @@ expression: actual
|
||||
"start": 8,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 5.0
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
@ -32,7 +35,10 @@ expression: actual
|
||||
"start": 12,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 6.0
|
||||
"value": {
|
||||
"value": 6.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 8,
|
||||
"type": "BinaryExpression",
|
||||
@ -46,7 +52,10 @@ expression: actual
|
||||
"start": 24,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 45.0
|
||||
"value": {
|
||||
"value": 45.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"end": 29,
|
||||
|
@ -21,7 +21,10 @@ expression: actual
|
||||
"start": 8,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "*",
|
||||
"right": {
|
||||
@ -32,7 +35,10 @@ expression: actual
|
||||
"start": 13,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 3.0
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
@ -41,7 +47,10 @@ expression: actual
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 4.0
|
||||
"value": {
|
||||
"value": 4.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 13,
|
||||
"type": "BinaryExpression",
|
||||
|
@ -19,7 +19,10 @@ expression: actual
|
||||
"start": 4,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
|
@ -32,7 +32,10 @@ expression: actual
|
||||
"start": 11,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -51,7 +54,10 @@ expression: actual
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -85,7 +91,10 @@ expression: actual
|
||||
"start": 34,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
|
@ -32,7 +32,10 @@ expression: actual
|
||||
"start": 11,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -51,7 +54,10 @@ expression: actual
|
||||
"start": 17,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 2.0
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -85,7 +91,10 @@ expression: actual
|
||||
"start": 35,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": 1.0
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user