Merge branch 'main' into franknoirot/4088/create-file-url
This commit is contained in:
		
							
								
								
									
										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 |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											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  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 44 KiB  | 
							
								
								
									
										215
									
								
								src/Toolbar.tsx
									
									
									
									
									
								
							
							
						
						
									
										215
									
								
								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,43 +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}
 | 
			
		||||
                />
 | 
			
		||||
                    <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>
 | 
			
		||||
            )
 | 
			
		||||
          }
 | 
			
		||||
@ -218,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}
 | 
			
		||||
@ -255,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>
 | 
			
		||||
          )
 | 
			
		||||
        })}
 | 
			
		||||
@ -269,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
 | 
			
		||||
@ -277,12 +355,10 @@ export function Toolbar({
 | 
			
		||||
const ToolbarItemTooltip = memo(function ToolbarItemContents({
 | 
			
		||||
  itemConfig,
 | 
			
		||||
  configCallbackProps,
 | 
			
		||||
}: {
 | 
			
		||||
  itemConfig: ToolbarItemResolved
 | 
			
		||||
  configCallbackProps: ToolbarItemCallbackProps
 | 
			
		||||
}) {
 | 
			
		||||
  const { state } = useModelingContext()
 | 
			
		||||
 | 
			
		||||
  wrapperClassName = '',
 | 
			
		||||
  contentClassName = '',
 | 
			
		||||
  children,
 | 
			
		||||
}: ToolbarItemContentsProps) {
 | 
			
		||||
  useHotkeys(
 | 
			
		||||
    itemConfig.hotkey || '',
 | 
			
		||||
    () => {
 | 
			
		||||
@ -305,11 +381,50 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
 | 
			
		||||
          ? ({ '-webkit-app-region': 'no-drag' } as React.CSSProperties)
 | 
			
		||||
          : {}
 | 
			
		||||
      }
 | 
			
		||||
      hoverOnly
 | 
			
		||||
      position="bottom"
 | 
			
		||||
      wrapperClassName="!p-4 !pointer-events-auto"
 | 
			
		||||
      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'
 | 
			
		||||
@ -378,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"
 | 
			
		||||
 | 
			
		||||
@ -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'
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -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',
 | 
			
		||||
 | 
			
		||||
@ -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": {
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
@ -108,7 +114,10 @@ expression: actual
 | 
			
		||||
            "start": 45,
 | 
			
		||||
            "type": "Literal",
 | 
			
		||||
            "type": "Literal",
 | 
			
		||||
            "value": 1.0
 | 
			
		||||
            "value": {
 | 
			
		||||
              "value": 1.0,
 | 
			
		||||
              "suffix": "None"
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          "start": 34,
 | 
			
		||||
          "type": "BinaryExpression",
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
@ -87,7 +93,10 @@ expression: actual
 | 
			
		||||
                "start": 35,
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "value": 1.0
 | 
			
		||||
                "value": {
 | 
			
		||||
                  "value": 1.0,
 | 
			
		||||
                  "suffix": "None"
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
              "operator": "-",
 | 
			
		||||
              "right": {
 | 
			
		||||
@ -122,7 +131,10 @@ expression: actual
 | 
			
		||||
              "start": 49,
 | 
			
		||||
              "type": "Literal",
 | 
			
		||||
              "type": "Literal",
 | 
			
		||||
              "value": 0.0
 | 
			
		||||
              "value": {
 | 
			
		||||
                "value": 0.0,
 | 
			
		||||
                "suffix": "None"
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
          "end": 51,
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,6 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/parsing/parser.rs
 | 
			
		||||
assertion_line: 4674
 | 
			
		||||
expression: actual
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  "body": [
 | 
			
		||||
@ -23,7 +21,10 @@ snapshot_kind: text
 | 
			
		||||
              "start": 6,
 | 
			
		||||
              "type": "Literal",
 | 
			
		||||
              "type": "Literal",
 | 
			
		||||
              "value": 1.0
 | 
			
		||||
              "value": {
 | 
			
		||||
                "value": 1.0,
 | 
			
		||||
                "suffix": "None"
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              "arguments": [
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/parsing/parser.rs
 | 
			
		||||
expression: actual
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  "body": [
 | 
			
		||||
@ -24,7 +23,10 @@ snapshot_kind: text
 | 
			
		||||
                  "start": 22,
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "value": 1.0
 | 
			
		||||
                  "value": {
 | 
			
		||||
                    "value": 1.0,
 | 
			
		||||
                    "suffix": "None"
 | 
			
		||||
                  }
 | 
			
		||||
                },
 | 
			
		||||
                "end": 23,
 | 
			
		||||
                "start": 15,
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/parsing/parser.rs
 | 
			
		||||
expression: actual
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  "body": [
 | 
			
		||||
@ -24,7 +23,10 @@ snapshot_kind: text
 | 
			
		||||
                  "start": 23,
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "value": 1.0
 | 
			
		||||
                  "value": {
 | 
			
		||||
                    "value": 1.0,
 | 
			
		||||
                    "suffix": "None"
 | 
			
		||||
                  }
 | 
			
		||||
                },
 | 
			
		||||
                "end": 24,
 | 
			
		||||
                "start": 16,
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/parsing/parser.rs
 | 
			
		||||
expression: actual
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  "body": [
 | 
			
		||||
@ -24,7 +23,10 @@ snapshot_kind: text
 | 
			
		||||
                  "start": 32,
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "value": 1.0
 | 
			
		||||
                  "value": {
 | 
			
		||||
                    "value": 1.0,
 | 
			
		||||
                    "suffix": "None"
 | 
			
		||||
                  }
 | 
			
		||||
                },
 | 
			
		||||
                "end": 33,
 | 
			
		||||
                "start": 25,
 | 
			
		||||
@ -52,7 +54,10 @@ snapshot_kind: text
 | 
			
		||||
              "default_value": {
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "value": 2.0,
 | 
			
		||||
                "value": {
 | 
			
		||||
                  "value": 2.0,
 | 
			
		||||
                  "suffix": "None"
 | 
			
		||||
                },
 | 
			
		||||
                "raw": "2"
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/parsing/parser.rs
 | 
			
		||||
expression: actual
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  "body": [
 | 
			
		||||
@ -24,7 +23,10 @@ snapshot_kind: text
 | 
			
		||||
                  "start": 24,
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "type": "Literal",
 | 
			
		||||
                  "value": 1.0
 | 
			
		||||
                  "value": {
 | 
			
		||||
                    "value": 1.0,
 | 
			
		||||
                    "suffix": "None"
 | 
			
		||||
                  }
 | 
			
		||||
                },
 | 
			
		||||
                "end": 25,
 | 
			
		||||
                "start": 17,
 | 
			
		||||
@ -48,7 +50,10 @@ snapshot_kind: text
 | 
			
		||||
              "default_value": {
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "value": 2.0,
 | 
			
		||||
                "value": {
 | 
			
		||||
                  "value": 2.0,
 | 
			
		||||
                  "suffix": "None"
 | 
			
		||||
                },
 | 
			
		||||
                "raw": "2"
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
@ -110,7 +116,10 @@ expression: actual
 | 
			
		||||
                "start": 46,
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "type": "Literal",
 | 
			
		||||
                "value": 1.0
 | 
			
		||||
                "value": {
 | 
			
		||||
                  "value": 1.0,
 | 
			
		||||
                  "suffix": "None"
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
              "start": 35,
 | 
			
		||||
              "type": "BinaryExpression",
 | 
			
		||||
@ -122,7 +131,10 @@ expression: actual
 | 
			
		||||
              "start": 49,
 | 
			
		||||
              "type": "Literal",
 | 
			
		||||
              "type": "Literal",
 | 
			
		||||
              "value": 0.0
 | 
			
		||||
              "value": {
 | 
			
		||||
                "value": 0.0,
 | 
			
		||||
                "suffix": "None"
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
          "end": 51,
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user