Move sketch functions to KCL; remove Rust decl dead code (#7335)

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-06-05 07:41:01 +12:00
committed by GitHub
parent 5ceb92d117
commit 5235a731ba
104 changed files with 1647 additions and 143019 deletions

View File

@ -1,24 +1,23 @@
---
title: "appearance::hexString"
subtitle: "Function in std::appearance"
excerpt: ""
excerpt: "Build a color from its red, green and blue components. These must be between 0 and 255."
layout: manual
---
Build a color from its red, green and blue components. These must be between 0 and 255.
```kcl
appearance::hexString(@rgb: [number(_); 3]): string
```
Build a color from its red, green and blue components.
These must be between 0 and 255.
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `rgb` | [`[number(_); 3]`](/docs/kcl-std/types/std-types-number) | | Yes |
| `rgb` | [`[number(_); 3]`](/docs/kcl-std/types/std-types-number) | The red, blue and green components of the color. Must be between 0 and 255. | Yes |
### Returns

View File

@ -1,11 +1,11 @@
---
title: "reduce"
subtitle: "Function in std::array"
excerpt: ""
excerpt: "Take a starting value. Then, for each element of an array, calculate the next value, using the previous value and the element."
layout: manual
---
Take a starting value. Then, for each element of an array, calculate the next value, using the previous value and the element.
```kcl
reduce(
@ -15,8 +15,7 @@ reduce(
): any
```
Take a starting value. Then, for each element of an array, calculate the next value,
using the previous value and the element.
### Arguments
@ -28,7 +27,7 @@ using the previous value and the element.
### Returns
[`any`](/docs/kcl-std/types/std-types-any)
[`any`](/docs/kcl-std/types/std-types-any) - The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value.
### Examples

View File

@ -1,11 +1,11 @@
---
title: "assert"
subtitle: "Function in std"
excerpt: ""
excerpt: "Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met. If you provide multiple conditions, they will all be checked and all must be met."
layout: manual
---
Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met. If you provide multiple conditions, they will all be checked and all must be met.
```kcl
assert(
@ -20,8 +20,7 @@ assert(
)
```
Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met.
If you provide multiple conditions, they will all be checked and all must be met.
### Arguments

View File

@ -1,11 +1,11 @@
---
title: "polar"
subtitle: "Function in std::math"
excerpt: ""
excerpt: "Convert polar/sphere (azimuth, elevation, distance) coordinates to cartesian (x/y/z grid) coordinates."
layout: manual
---
Convert polar/sphere (azimuth, elevation, distance) coordinates to cartesian (x/y/z grid) coordinates.
```kcl
polar(
@ -14,8 +14,7 @@ polar(
): Point2d
```
Convert polar/sphere (azimuth, elevation, distance) coordinates to
cartesian (x/y/z grid) coordinates.
### Arguments

View File

@ -1,11 +1,11 @@
---
title: "rem"
subtitle: "Function in std::math"
excerpt: ""
excerpt: "Compute the remainder after dividing `num` by `div`. If `num` is negative, the result will be too."
layout: manual
---
Compute the remainder after dividing `num` by `div`. If `num` is negative, the result will be too.
```kcl
rem(
@ -14,8 +14,7 @@ rem(
): number
```
Compute the remainder after dividing `num` by `div`.
If `num` is negative, the result will be too.
### Arguments

View File

@ -10,13 +10,13 @@ Draw a line segment relative to the current origin using the polar measure of so
```kcl
angledLine(
@sketch: Sketch,
angle: number,
length?: number,
lengthX?: number,
lengthY?: number,
endAbsoluteX?: number,
endAbsoluteY?: number,
tag?: TagDeclarator,
angle: number(Angle),
length?: number(Length),
lengthX?: number(Length),
lengthY?: number(Length),
endAbsoluteX?: number(Length),
endAbsoluteY?: number(Length),
tag?: tag,
): Sketch
```
@ -27,13 +27,13 @@ angledLine(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `lengthX` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `lengthY` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `endAbsoluteX` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `endAbsoluteY` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `lengthX` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `lengthY` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `endAbsoluteX` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `endAbsoluteY` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
### Returns
@ -46,7 +46,10 @@ angledLine(
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> yLine(endAbsolute = 15)
|> angledLine(angle = 30, length = 15)
|> angledLine(
angle = 30,
length = 15,
)
|> line(end = [8, -10])
|> yLine(endAbsolute = 0)
|> close()

View File

@ -10,10 +10,10 @@ Draw an angled line from the current origin, constructing a line segment such th
```kcl
angledLineThatIntersects(
@sketch: Sketch,
angle: number,
intersectTag: TagIdentifier,
offset?: number,
tag?: TagDeclarator,
angle: number(Angle),
intersectTag: tag,
offset?: number(Length),
tag?: tag,
): Sketch
```
@ -24,10 +24,10 @@ angledLineThatIntersects(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
| `intersectTag` | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The tag of the line to intersect with | Yes |
| `offset` | [`number`](/docs/kcl-std/types/std-types-number) | The offset from the intersecting line. Defaults to 0. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
| `intersectTag` | [`tag`](/docs/kcl-std/types/std-types-tag) | The tag of the line to intersect with. | Yes |
| `offset` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The offset from the intersecting line. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
### Returns
@ -42,7 +42,11 @@ exampleSketch = startSketchOn(XZ)
|> line(endAbsolute = [5, 10])
|> line(endAbsolute = [-10, 10], tag = $lineToIntersect)
|> line(endAbsolute = [0, 20])
|> angledLineThatIntersects(angle = 80, intersectTag = lineToIntersect, offset = 10)
|> angledLineThatIntersects(
angle = 80,
intersectTag = lineToIntersect,
offset = 10,
)
|> close()
example = extrude(exampleSketch, length = 10)

View File

@ -10,32 +10,37 @@ Draw a curved line segment along an imaginary circle.
```kcl
arc(
@sketch: Sketch,
angleStart?: number,
angleEnd?: number,
radius?: number,
diameter?: number,
angleStart?: number(Angle),
angleEnd?: number(Angle),
radius?: number(Length),
diameter?: number(Length),
interiorAbsolute?: Point2d,
endAbsolute?: Point2d,
tag?: TagDeclarator,
tag?: tag,
): Sketch
```
The arc is constructed such that the current position of the sketch is placed along an imaginary circle of the specified radius, at angleStart degrees. The resulting arc is the segment of the imaginary circle from that origin point to angleEnd, radius away from the center of the imaginary circle.
The arc is constructed such that the current position of the sketch is
placed along an imaginary circle of the specified radius, at angleStart
degrees. The resulting arc is the segment of the imaginary circle from
that origin point to angleEnd, radius away from the center of the imaginary
circle.
Unless this makes a lot of sense and feels like what you're looking for to construct your shape, you're likely looking for tangentialArc.
Unless this makes a lot of sense and feels like what you're looking
for to construct your shape, you're likely looking for tangentialArc.
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `angleStart` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc start? | No |
| `angleEnd` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc end? | No |
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `diameter`. | No |
| `diameter` | [`number`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `radius`. | No |
| `interiorAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
| `angleStart` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc start? | No |
| `angleEnd` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc end? | No |
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `diameter`. | No |
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `radius`. | No |
| `interiorAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`. | No |
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this arc. | No |
### Returns
@ -48,7 +53,11 @@ Unless this makes a lot of sense and feels like what you're looking for to const
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> line(end = [10, 0])
|> arc(angleStart = 0, angleEnd = 280, radius = 16)
|> arc(
angleStart = 0,
angleEnd = 280,
radius = 16
)
|> close()
example = extrude(exampleSketch, length = 10)
```
@ -58,7 +67,10 @@ example = extrude(exampleSketch, length = 10)
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> arc(endAbsolute = [10, 0], interiorAbsolute = [5, 5])
|> arc(
endAbsolute = [10,0],
interiorAbsolute = [5,5]
)
|> close()
example = extrude(exampleSketch, length = 10)
```

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,11 @@
---
title: "circle"
subtitle: "Function in std::sketch"
excerpt: ""
excerpt: "Construct a 2-dimensional circle, of the specified radius, centered at the provided (x, y) origin point."
layout: manual
---
Construct a 2-dimensional circle, of the specified radius, centered at the provided (x, y) origin point.
```kcl
circle(
@ -17,8 +17,7 @@ circle(
): Sketch
```
Construct a 2-dimensional circle, of the specified radius, centered at
the provided (x, y) origin point.
### Arguments

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,11 @@
---
title: "extrude"
subtitle: "Function in std::sketch"
excerpt: ""
excerpt: "Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid."
layout: manual
---
Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid.
```kcl
extrude(
@ -18,9 +18,6 @@ extrude(
): [Solid; 1+]
```
Extend a 2-dimensional sketch through a third dimension in order to
create new 3-dimensional volume, or if extruded into an existing volume,cut into an existing solid.
You can provide more than one sketch to extrude, and they will all be
extruded in the same direction.

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@ line(
@sketch: Sketch,
endAbsolute?: Point2d,
end?: Point2d,
tag?: TagDeclarator,
tag?: tag,
): Sketch
```
@ -25,7 +25,7 @@ line(
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Which absolute point should this line go to? Incompatible with `end`. | No |
| `end` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | How far away (along the X and Y axes) should this line go? Incompatible with `endAbsolute`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
### Returns

View File

@ -1,11 +1,11 @@
---
title: "patternCircular2d"
subtitle: "Function in std::sketch"
excerpt: ""
excerpt: "Repeat a 2-dimensional sketch some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained."
layout: manual
---
Repeat a 2-dimensional sketch some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained.
```kcl
patternCircular2d(
@ -18,9 +18,7 @@ patternCircular2d(
): [Sketch; 1+]
```
Repeat a 2-dimensional sketch some number of times along a partial or
complete circle some specified number of times. Each object mayadditionally be rotated along the circle, ensuring orientation of the
solid with respect to the center of the circle is maintained.
### Arguments

View File

@ -1,11 +1,11 @@
---
title: "patternLinear2d"
subtitle: "Function in std::sketch"
excerpt: ""
excerpt: "Repeat a 2-dimensional sketch along some dimension, with a dynamic amount of distance between each repetition, some specified number of times."
layout: manual
---
Repeat a 2-dimensional sketch along some dimension, with a dynamic amount of distance between each repetition, some specified number of times.
```kcl
patternLinear2d(
@ -17,8 +17,7 @@ patternLinear2d(
): [Sketch; 1+]
```
Repeat a 2-dimensional sketch along some dimension, with a dynamic amount
of distance between each repetition, some specified number of times.
### Arguments

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -9,9 +9,9 @@ Start a new profile at a given point.
```kcl
startProfile(
@sketchSurface: Plane | Face,
@startProfileOn: Plane | Face,
at: Point2d,
tag?: TagDeclarator,
tag?: tag,
): Sketch
```
@ -21,9 +21,9 @@ startProfile(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketchSurface` | [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | What to start the profile on | Yes |
| `startProfileOn` | [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | What to start the profile on. | Yes |
| `at` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where to start the profile. An absolute point. | Yes |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Tag this first starting point | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Tag this first starting point. | No |
### Returns

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,14 +12,18 @@ tangentialArc(
@sketch: Sketch,
endAbsolute?: Point2d,
end?: Point2d,
radius?: number,
diameter?: number,
angle?: number,
tag?: TagDeclarator,
radius?: number(Length),
diameter?: number(Length),
angle?: number(Angle),
tag?: tag,
): Sketch
```
When using radius and angle, draw a curved line segment along part of an imaginary circle. The arc is constructed such that the last line segment is placed tangent to the imaginary circle of the specified radius. The resulting arc is the segment of the imaginary circle from that tangent point for 'angle' degrees along the imaginary circle.
When using radius and angle, draw a curved line segment along part of an
imaginary circle. The arc is constructed such that the last line segment is
placed tangent to the imaginary circle of the specified radius. The
resulting arc is the segment of the imaginary circle from that tangent point
for 'angle' degrees along the imaginary circle.
### Arguments
@ -28,10 +32,10 @@ When using radius and angle, draw a curved line segment along part of an imagina
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Which absolute point should this arc go to? Incompatible with `end`, `radius`, and `offset`. | No |
| `end` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | How far away (along the X and Y axes) should this arc go? Incompatible with `endAbsolute`, `radius`, and `offset`. | No |
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `diameter`. | No |
| `diameter` | [`number`](/docs/kcl-std/types/std-types-number) | Diameter of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `radius`. | No |
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Offset of the arc in degrees. `radius` must be given. Incompatible with `end` and `endAbsolute`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this arc | No |
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `diameter`. | No |
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Diameter of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `radius`. | No |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Offset of the arc. `radius` must be given. Incompatible with `end` and `endAbsolute`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this arc. | No |
### Returns
@ -43,7 +47,10 @@ When using radius and angle, draw a curved line segment along part of an imagina
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> angledLine(angle = 45, length = 10)
|> angledLine(
angle = 45,
length = 10,
)
|> tangentialArc(end = [0, -10])
|> line(end = [-10, 0])
|> close()
@ -56,7 +63,10 @@ example = extrude(exampleSketch, length = 10)
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> angledLine(angle = 60, length = 10)
|> angledLine(
angle = 60,
length = 10,
)
|> tangentialArc(endAbsolute = [15, 15])
|> line(end = [10, -15])
|> close()
@ -69,9 +79,15 @@ example = extrude(exampleSketch, length = 10)
```kcl
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> angledLine(angle = 60, length = 10)
|> angledLine(
angle = 60,
length = 10,
)
|> tangentialArc(radius = 10, angle = -120)
|> angledLine(angle = -60, length = 10)
|> angledLine(
angle = -60,
length = 10,
)
|> close()
example = extrude(exampleSketch, length = 10)

View File

@ -10,9 +10,9 @@ Draw a line relative to the current origin to a specified distance away from the
```kcl
xLine(
@sketch: Sketch,
length?: number,
endAbsolute?: number,
tag?: TagDeclarator,
length?: number(Length),
endAbsolute?: number(Length),
tag?: tag,
): Sketch
```
@ -23,9 +23,9 @@ xLine(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far away along the X axis should this line go? Incompatible with `endAbsolute`. | No |
| `endAbsolute` | [`number`](/docs/kcl-std/types/std-types-number) | Which absolute X value should this line go to? Incompatible with `length`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How far away along the X axis should this line go? Incompatible with `endAbsolute`. | No |
| `endAbsolute` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Which absolute X value should this line go to? Incompatible with `length`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
### Returns
@ -38,10 +38,16 @@ xLine(
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> xLine(length = 15)
|> angledLine(angle = 80, length = 15)
|> angledLine(
angle = 80,
length = 15,
)
|> line(end = [8, -10])
|> xLine(length = 10)
|> angledLine(angle = 120, length = 30)
|> angledLine(
angle = 120,
length = 30,
)
|> xLine(length = -15)
|> close()

View File

@ -10,9 +10,9 @@ Draw a line relative to the current origin to a specified distance away from the
```kcl
yLine(
@sketch: Sketch,
length?: number,
endAbsolute?: number,
tag?: TagDeclarator,
length?: number(Length),
endAbsolute?: number(Length),
tag?: tag,
): Sketch
```
@ -23,9 +23,9 @@ yLine(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far away along the Y axis should this line go? Incompatible with `endAbsolute`. | No |
| `endAbsolute` | [`number`](/docs/kcl-std/types/std-types-number) | Which absolute Y value should this line go to? Incompatible with `length`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How far away along the Y axis should this line go? Incompatible with `endAbsolute`. | No |
| `endAbsolute` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Which absolute Y value should this line go to? Incompatible with `length`. | No |
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
### Returns
@ -38,7 +38,10 @@ yLine(
exampleSketch = startSketchOn(XZ)
|> startProfile(at = [0, 0])
|> yLine(length = 15)
|> angledLine(angle = 30, length = 15)
|> angledLine(
angle = 30,
length = 15,
)
|> line(end = [8, -10])
|> yLine(length = -5)
|> close()

View File

@ -1,11 +1,11 @@
---
title: "intersect"
subtitle: "Function in std::solid"
excerpt: ""
excerpt: "Intersect returns the shared volume between multiple solids, preserving only overlapping regions."
layout: manual
---
Intersect returns the shared volume between multiple solids, preserving only overlapping regions.
```kcl
intersect(
@ -14,8 +14,6 @@ intersect(
): [Solid; 1+]
```
Intersect returns the shared volume between multiple solids, preserving only
overlapping regions.
Intersect computes the geometric intersection of multiple solid bodies,
returning a new solid representing the volume that is common to all input
solids. This operation is useful for determining shared material regions,

View File

@ -1,11 +1,11 @@
---
title: "patternCircular3d"
subtitle: "Function in std::solid"
excerpt: ""
excerpt: "Repeat a 3-dimensional solid some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained."
layout: manual
---
Repeat a 3-dimensional solid some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained.
```kcl
patternCircular3d(
@ -19,9 +19,7 @@ patternCircular3d(
): [Solid; 1+]
```
Repeat a 3-dimensional solid some number of times along a partial or
complete circle some specified number of times. Each object mayadditionally be rotated along the circle, ensuring orientation of the
solid with respect to the center of the circle is maintained.
### Arguments

View File

@ -1,11 +1,11 @@
---
title: "patternLinear3d"
subtitle: "Function in std::solid"
excerpt: ""
excerpt: "Repeat a 3-dimensional solid along a linear path, with a dynamic amount of distance between each repetition, some specified number of times."
layout: manual
---
Repeat a 3-dimensional solid along a linear path, with a dynamic amount of distance between each repetition, some specified number of times.
```kcl
patternLinear3d(
@ -17,8 +17,7 @@ patternLinear3d(
): [Solid; 1+]
```
Repeat a 3-dimensional solid along a linear path, with a dynamic amount
of distance between each repetition, some specified number of times.
### Arguments

View File

@ -1,11 +1,11 @@
---
title: "shell"
subtitle: "Function in std::solid"
excerpt: ""
excerpt: "Remove volume from a 3-dimensional shape such that a wall of the provided thickness remains, taking volume starting at the provided face, leaving it open in that direction."
layout: manual
---
Remove volume from a 3-dimensional shape such that a wall of the provided thickness remains, taking volume starting at the provided face, leaving it open in that direction.
```kcl
shell(
@ -15,8 +15,7 @@ shell(
): [Solid]
```
Remove volume from a 3-dimensional shape such that a wall of the
provided thickness remains, taking volume starting at the providedface, leaving it open in that direction.
### Arguments

View File

@ -47,30 +47,30 @@ layout: manual
* [`sqrt`](/docs/kcl-std/functions/std-math-sqrt)
* [`tan`](/docs/kcl-std/functions/std-math-tan)
* [**std::sketch**](/docs/kcl-std/modules/std-sketch)
* [`angledLine`](/docs/kcl-std/angledLine)
* [`angledLineThatIntersects`](/docs/kcl-std/angledLineThatIntersects)
* [`arc`](/docs/kcl-std/arc)
* [`bezierCurve`](/docs/kcl-std/bezierCurve)
* [`angledLine`](/docs/kcl-std/functions/std-sketch-angledLine)
* [`angledLineThatIntersects`](/docs/kcl-std/functions/std-sketch-angledLineThatIntersects)
* [`arc`](/docs/kcl-std/functions/std-sketch-arc)
* [`bezierCurve`](/docs/kcl-std/functions/std-sketch-bezierCurve)
* [`circle`](/docs/kcl-std/functions/std-sketch-circle)
* [`circleThreePoint`](/docs/kcl-std/functions/std-sketch-circleThreePoint)
* [`close`](/docs/kcl-std/close)
* [`close`](/docs/kcl-std/functions/std-sketch-close)
* [`extrude`](/docs/kcl-std/functions/std-sketch-extrude)
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
* [`getPreviousAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getPreviousAdjacentEdge)
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
* [`involuteCircular`](/docs/kcl-std/functions/std-sketch-involuteCircular)
* [`lastSegX`](/docs/kcl-std/functions/std-sketch-lastSegX)
* [`lastSegY`](/docs/kcl-std/functions/std-sketch-lastSegY)
* [`line`](/docs/kcl-std/line)
* [`line`](/docs/kcl-std/functions/std-sketch-line)
* [`loft`](/docs/kcl-std/functions/std-sketch-loft)
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
* [`profileStart`](/docs/kcl-std/profileStart)
* [`profileStartX`](/docs/kcl-std/profileStartX)
* [`profileStartY`](/docs/kcl-std/profileStartY)
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)
@ -80,14 +80,14 @@ layout: manual
* [`segStart`](/docs/kcl-std/functions/std-sketch-segStart)
* [`segStartX`](/docs/kcl-std/functions/std-sketch-segStartX)
* [`segStartY`](/docs/kcl-std/functions/std-sketch-segStartY)
* [`startProfile`](/docs/kcl-std/startProfile)
* [`startSketchOn`](/docs/kcl-std/startSketchOn)
* [`subtract2d`](/docs/kcl-std/subtract2d)
* [`startProfile`](/docs/kcl-std/functions/std-sketch-startProfile)
* [`startSketchOn`](/docs/kcl-std/functions/std-sketch-startSketchOn)
* [`subtract2d`](/docs/kcl-std/functions/std-sketch-subtract2d)
* [`sweep`](/docs/kcl-std/functions/std-sketch-sweep)
* [`tangentToEnd`](/docs/kcl-std/functions/std-sketch-tangentToEnd)
* [`tangentialArc`](/docs/kcl-std/tangentialArc)
* [`xLine`](/docs/kcl-std/xLine)
* [`yLine`](/docs/kcl-std/yLine)
* [`tangentialArc`](/docs/kcl-std/functions/std-sketch-tangentialArc)
* [`xLine`](/docs/kcl-std/functions/std-sketch-xLine)
* [`yLine`](/docs/kcl-std/functions/std-sketch-yLine)
* [**std::solid**](/docs/kcl-std/modules/std-solid)
* [`appearance`](/docs/kcl-std/functions/std-solid-appearance)
* [`chamfer`](/docs/kcl-std/functions/std-solid-chamfer)
@ -144,11 +144,7 @@ layout: manual
See also the [types overview](/docs/kcl-lang/types)
* [**Primitive types**](/docs/kcl-lang/types)
* [`End`](/docs/kcl-lang/types#End)
* [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry)
* [`Start`](/docs/kcl-lang/types#Start)
* [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator)
* [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier)
* [`any`](/docs/kcl-std/types/std-types-any)
* [`bool`](/docs/kcl-std/types/std-types-bool)
* [`fn`](/docs/kcl-std/types/std-types-fn)

View File

@ -12,30 +12,30 @@ This module contains functions for creating and manipulating sketches, and makin
## Functions and constants
* [`angledLine`](/docs/kcl-std/angledLine)
* [`angledLineThatIntersects`](/docs/kcl-std/angledLineThatIntersects)
* [`arc`](/docs/kcl-std/arc)
* [`bezierCurve`](/docs/kcl-std/bezierCurve)
* [`angledLine`](/docs/kcl-std/functions/std-sketch-angledLine)
* [`angledLineThatIntersects`](/docs/kcl-std/functions/std-sketch-angledLineThatIntersects)
* [`arc`](/docs/kcl-std/functions/std-sketch-arc)
* [`bezierCurve`](/docs/kcl-std/functions/std-sketch-bezierCurve)
* [`circle`](/docs/kcl-std/functions/std-sketch-circle)
* [`circleThreePoint`](/docs/kcl-std/functions/std-sketch-circleThreePoint)
* [`close`](/docs/kcl-std/close)
* [`close`](/docs/kcl-std/functions/std-sketch-close)
* [`extrude`](/docs/kcl-std/functions/std-sketch-extrude)
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
* [`getPreviousAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getPreviousAdjacentEdge)
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
* [`involuteCircular`](/docs/kcl-std/functions/std-sketch-involuteCircular)
* [`lastSegX`](/docs/kcl-std/functions/std-sketch-lastSegX)
* [`lastSegY`](/docs/kcl-std/functions/std-sketch-lastSegY)
* [`line`](/docs/kcl-std/line)
* [`line`](/docs/kcl-std/functions/std-sketch-line)
* [`loft`](/docs/kcl-std/functions/std-sketch-loft)
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
* [`profileStart`](/docs/kcl-std/profileStart)
* [`profileStartX`](/docs/kcl-std/profileStartX)
* [`profileStartY`](/docs/kcl-std/profileStartY)
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)
@ -45,12 +45,12 @@ This module contains functions for creating and manipulating sketches, and makin
* [`segStart`](/docs/kcl-std/functions/std-sketch-segStart)
* [`segStartX`](/docs/kcl-std/functions/std-sketch-segStartX)
* [`segStartY`](/docs/kcl-std/functions/std-sketch-segStartY)
* [`startProfile`](/docs/kcl-std/startProfile)
* [`startSketchOn`](/docs/kcl-std/startSketchOn)
* [`subtract2d`](/docs/kcl-std/subtract2d)
* [`startProfile`](/docs/kcl-std/functions/std-sketch-startProfile)
* [`startSketchOn`](/docs/kcl-std/functions/std-sketch-startSketchOn)
* [`subtract2d`](/docs/kcl-std/functions/std-sketch-subtract2d)
* [`sweep`](/docs/kcl-std/functions/std-sketch-sweep)
* [`tangentToEnd`](/docs/kcl-std/functions/std-sketch-tangentToEnd)
* [`tangentialArc`](/docs/kcl-std/tangentialArc)
* [`xLine`](/docs/kcl-std/xLine)
* [`yLine`](/docs/kcl-std/yLine)
* [`tangentialArc`](/docs/kcl-std/functions/std-sketch-tangentialArc)
* [`xLine`](/docs/kcl-std/functions/std-sketch-xLine)
* [`yLine`](/docs/kcl-std/functions/std-sketch-yLine)

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,13 @@
---
title: "any"
subtitle: "Type in std::types"
excerpt: ""
excerpt: "The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value."
layout: manual
---
The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value.
The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument
with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value.
### Examples

View File

@ -964,8 +964,6 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
await page.waitForTimeout(100)
await page.keyboard.press('Enter') // accepting the auto complete, not a new line
await page.keyboard.press('Tab')
await page.waitForTimeout(100)
await page.keyboard.press('Tab')
await page.waitForTimeout(100)
await page.keyboard.type('12')
@ -984,8 +982,6 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
await page.keyboard.press('ArrowDown')
await page.keyboard.press('Enter')
// finish line with comment
await page.keyboard.press('Tab')
await page.waitForTimeout(100)
await page.keyboard.type('5')
await page.waitForTimeout(100)
await page.keyboard.press('Tab')
@ -1001,8 +997,8 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfile(%, at = [0, 12])
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|> startProfile(at = [0, 12])
|> xLine(length = 5) // lin`.replaceAll('\n', '')
)
// expect there to be no KCL errors
@ -1040,8 +1036,6 @@ sketch001 = startSketchOn(XZ)
await page.waitForTimeout(100)
await page.keyboard.press('Tab') // accepting the auto complete, not a new line
await page.keyboard.press('Tab')
await page.waitForTimeout(100)
await page.keyboard.press('Tab')
await page.keyboard.type('12')
await page.waitForTimeout(100)
@ -1057,7 +1051,6 @@ sketch001 = startSketchOn(XZ)
await page.waitForTimeout(100)
// press arrow down then tab to accept xLine
await page.keyboard.press('ArrowDown')
await page.keyboard.press('Tab')
// finish line with comment
await page.keyboard.press('Tab')
await page.waitForTimeout(100)
@ -1076,8 +1069,8 @@ sketch001 = startSketchOn(XZ)
await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfile(%, at = [0, 12])
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|> startProfile(at = [0, 12])
|> xLine(length = 5) // lin`.replaceAll('\n', '')
)
})
})

View File

@ -169,7 +169,7 @@ test(
// error text on hover
await page.hover('.cm-lint-marker-error')
const crypticErrorText = `The arg tag was given, but it was the wrong type`
const crypticErrorText = 'tag requires a value with type `tag`, but found string'
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
// black pixel means the scene has been cleared.
@ -367,7 +367,7 @@ test(
// error text on hover
await page.hover('.cm-lint-marker-error')
const crypticErrorText = `The arg tag was given, but it was the wrong type`
const crypticErrorText = 'tag requires a value with type `tag`, but found string'
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
// black pixel means the scene has been cleared.
@ -405,7 +405,7 @@ test(
// error text on hover
await page.hover('.cm-lint-marker-error')
const crypticErrorText = `The arg tag was given, but it was the wrong type`
const crypticErrorText = 'tag requires a value with type `tag`, but found string'
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
}
)

67
rust/Cargo.lock generated
View File

@ -2,16 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
dependencies = [
"lazy_static",
"regex",
]
[[package]]
name = "addr2line"
version = "0.24.2"
@ -1307,15 +1297,6 @@ dependencies = [
"digest",
]
[[package]]
name = "home"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "http"
version = "0.2.12"
@ -1824,18 +1805,8 @@ dependencies = [
name = "kcl-derive-docs"
version = "0.1.79"
dependencies = [
"Inflector",
"anyhow",
"convert_case",
"expectorate",
"once_cell",
"pretty_assertions",
"proc-macro2",
"quote",
"regex",
"rustfmt-wrapper",
"serde",
"serde_tokenstream",
"syn 2.0.100",
]
@ -3350,19 +3321,6 @@ version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustfmt-wrapper"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1adc9dfed5cc999077978cc7163b9282c5751c8d39827c4ea8c8c220ca5a440"
dependencies = [
"serde",
"tempfile",
"thiserror 1.0.69",
"toml",
"toolchain_find",
]
[[package]]
name = "rustix"
version = "1.0.2"
@ -3609,18 +3567,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_tokenstream"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1"
dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.100",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@ -4257,19 +4203,6 @@ dependencies = [
"winnow",
]
[[package]]
name = "toolchain_find"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc8c9a7f0a2966e1acdaf0461023d0b01471eeead645370cf4c3f5cff153f2a"
dependencies = [
"home",
"once_cell",
"regex",
"semver",
"walkdir",
]
[[package]]
name = "tower"
version = "0.4.13"

View File

@ -12,21 +12,9 @@ proc-macro = true
bench = false
[dependencies]
Inflector = "0.11.4"
convert_case = "0.8.0"
once_cell = "1.21.3"
proc-macro2 = "1"
quote = "1"
regex = "1.11"
serde = { workspace = true }
serde_tokenstream = "0.2"
syn = { version = "2.0.96", features = ["full"] }
[dev-dependencies]
anyhow = { workspace = true }
expectorate = "1.1.0"
pretty_assertions = "1.4.1"
rustfmt-wrapper = "0.2.1"
[lints]
workspace = true

View File

@ -149,6 +149,35 @@ pub const TEST_NAMES: &[&str] = &[
"std-sketch-tangentToEnd-2",
"std-sketch-tangentToEnd-3",
"std-sketch-tangentToEnd-4",
"std-sketch-profileStart-0",
"std-sketch-profileStartX-0",
"std-sketch-profileStartY-0",
"std-sketch-startProfile-0",
"std-sketch-startProfile-1",
"std-sketch-startProfile-2",
"std-sketch-startSketchOn-0",
"std-sketch-startSketchOn-1",
"std-sketch-startSketchOn-2",
"std-sketch-startSketchOn-3",
"std-sketch-startSketchOn-4",
"std-sketch-startSketchOn-5",
"std-sketch-angledLineThatIntersects-0",
"std-sketch-angledLine-0",
"std-sketch-arc-0",
"std-sketch-arc-1",
"std-sketch-bezierCurve-0",
"std-sketch-bezierCurve-1",
"std-sketch-close-0",
"std-sketch-close-1",
"std-sketch-involuteCircular-0",
"std-sketch-line-0",
"std-sketch-subtract2d-0",
"std-sketch-subtract2d-1",
"std-sketch-tangentialArc-0",
"std-sketch-tangentialArc-1",
"std-sketch-tangentialArc-2",
"std-sketch-xLine-0",
"std-sketch-yLine-0",
"std-solid-appearance-0",
"std-solid-appearance-1",
"std-solid-appearance-2",

View File

@ -3,29 +3,6 @@
#![allow(clippy::style)]
mod example_tests;
#[cfg(test)]
mod tests;
mod unbox;
use std::collections::HashMap;
use convert_case::Casing;
use inflector::{cases::camelcase::to_camel_case, Inflector};
use once_cell::sync::Lazy;
use quote::{format_ident, quote, quote_spanned, ToTokens};
use regex::Regex;
use serde::Deserialize;
use serde_tokenstream::{from_tokenstream, Error};
use syn::{
parse::{Parse, ParseStream},
Attribute, Signature, Visibility,
};
use unbox::unbox;
#[proc_macro_attribute]
pub fn stdlib(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
do_output(do_stdlib(attr.into(), item.into()))
}
#[proc_macro_attribute]
pub fn for_each_example_test(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
@ -36,845 +13,3 @@ pub fn for_each_example_test(_attr: proc_macro::TokenStream, item: proc_macro::T
pub fn for_all_example_test(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
example_tests::do_for_all_example_test(item.into()).into()
}
/// Describes an argument of a stdlib function.
#[derive(Deserialize, Debug)]
struct ArgMetadata {
/// Docs for the argument.
docs: String,
/// If this argument is optional, it should still be included in completion snippets.
/// Does not do anything if the argument is already required.
#[serde(default)]
include_in_snippet: bool,
/// The snippet should suggest this value for the arg.
#[serde(default)]
snippet_value: Option<String>,
/// The snippet should suggest this value for the arg.
#[serde(default)]
snippet_value_array: Option<Vec<String>>,
}
#[derive(Deserialize, Debug)]
struct StdlibMetadata {
/// The name of the function in the API.
name: String,
/// Tags for the function.
#[serde(default)]
tags: Vec<String>,
/// Whether the function is unpublished.
/// Then docs will not be generated.
#[serde(default)]
unpublished: bool,
/// Whether the function is deprecated.
/// Then specific docs detailing that this is deprecated will be generated.
#[serde(default)]
deprecated: bool,
/// Whether the function is displayed in the feature tree.
/// If true, calls to the function will be available for display.
/// If false, calls to the function will never be displayed.
#[serde(default)]
feature_tree_operation: bool,
/// If true, the first argument is unlabeled.
/// If false, all arguments require labels.
#[serde(default)]
unlabeled_first: bool,
/// Key = argument name, value = argument doc.
#[serde(default)]
args: HashMap<String, ArgMetadata>,
}
fn do_stdlib(
attr: proc_macro2::TokenStream,
item: proc_macro2::TokenStream,
) -> Result<(proc_macro2::TokenStream, Vec<Error>), Error> {
let metadata = from_tokenstream(&attr)?;
do_stdlib_inner(metadata, attr, item)
}
fn do_output(res: Result<(proc_macro2::TokenStream, Vec<Error>), Error>) -> proc_macro::TokenStream {
match res {
Err(err) => err.to_compile_error().into(),
Ok((stdlib_docs, errors)) => {
let compiler_errors = errors.iter().map(|err| err.to_compile_error());
let output = quote! {
#stdlib_docs
#( #compiler_errors )*
};
output.into()
}
}
}
fn do_stdlib_inner(
metadata: StdlibMetadata,
_attr: proc_macro2::TokenStream,
item: proc_macro2::TokenStream,
) -> Result<(proc_macro2::TokenStream, Vec<Error>), Error> {
let ast: ItemFnForSignature = syn::parse2(item.clone())?;
let mut errors = Vec::new();
if ast.sig.constness.is_some() {
errors.push(Error::new_spanned(
&ast.sig.constness,
"stdlib functions may not be const functions",
));
}
if ast.sig.unsafety.is_some() {
errors.push(Error::new_spanned(
&ast.sig.unsafety,
"stdlib functions may not be unsafe",
));
}
if ast.sig.abi.is_some() {
errors.push(Error::new_spanned(
&ast.sig.abi,
"stdlib functions may not use an alternate ABI",
));
}
if !ast.sig.generics.params.is_empty() {
if ast.sig.generics.params.iter().any(|generic_type| match generic_type {
syn::GenericParam::Lifetime(_) => false,
syn::GenericParam::Type(_) => true,
syn::GenericParam::Const(_) => true,
}) {
errors.push(Error::new_spanned(
&ast.sig.generics,
"Stdlib functions may not be generic over types or constants, only lifetimes.",
));
}
}
if ast.sig.variadic.is_some() {
errors.push(Error::new_spanned(&ast.sig.variadic, "no language C here"));
}
let name = metadata.name;
// Fail if the name is not camel case.
// Remove some known suffix exceptions first.
let name_cleaned = name.strip_suffix("2d").unwrap_or(name.as_str());
let name_cleaned = name.strip_suffix("3d").unwrap_or(name_cleaned);
if !name_cleaned.is_camel_case() {
errors.push(Error::new_spanned(
&ast.sig.ident,
format!("stdlib function names must be in camel case: `{}`", name),
));
}
let name_ident = format_ident!("{}", name.to_case(convert_case::Case::UpperCamel));
let name_str = name.to_string();
let fn_name = &ast.sig.ident;
let fn_name_str = fn_name.to_string().replace("inner_", "");
let fn_name_ident = format_ident!("{}", fn_name_str);
let boxed_fn_name_ident = format_ident!("boxed_{}", fn_name_str);
let _visibility = &ast.vis;
let doc_info = extract_doc_from_attrs(&ast.attrs);
let comment_text = {
let mut buf = String::new();
buf.push_str("Std lib function: ");
buf.push_str(&name_str);
if let Some(s) = &doc_info.summary {
buf.push_str("\n");
buf.push_str(&s);
}
if let Some(s) = &doc_info.description {
buf.push_str("\n");
buf.push_str(&s);
}
buf
};
let description_doc_comment = quote! {
#[doc = #comment_text]
};
let summary = if let Some(summary) = doc_info.summary {
quote! { #summary }
} else {
quote! { "" }
};
let description = if let Some(description) = doc_info.description {
quote! { #description }
} else {
quote! { "" }
};
if doc_info.code_blocks.is_empty() {
errors.push(Error::new_spanned(
&ast.sig,
"stdlib functions must have at least one code block",
));
}
// Make sure the function name is in all the code blocks.
for code_block in doc_info.code_blocks.iter() {
if !code_block.0.contains(&name) {
errors.push(Error::new_spanned(
&ast.sig,
format!(
"stdlib functions must have the function name `{}` in the code block",
name
),
));
}
}
let test_code_blocks = doc_info
.code_blocks
.iter()
.enumerate()
.map(|(index, (code_block, norun))| {
if !norun {
generate_code_block_test(&fn_name_str, code_block, index)
} else {
quote! {}
}
})
.collect::<Vec<_>>();
let (cb, norun): (Vec<_>, Vec<_>) = doc_info.code_blocks.into_iter().unzip();
let code_blocks = quote! {
let code_blocks = vec![#(#cb),*];
let norun = vec![#(#norun),*];
code_blocks.iter().zip(norun).map(|(cb, norun)| {
let program = crate::Program::parse_no_errs(cb).unwrap();
let mut options: crate::parsing::ast::types::FormatOptions = Default::default();
options.insert_final_newline = false;
(program.ast.recast(&options, 0), norun)
}).collect::<Vec<(String, bool)>>()
};
let tags = metadata
.tags
.iter()
.map(|tag| {
quote! { #tag.to_string() }
})
.collect::<Vec<_>>();
let deprecated = if metadata.deprecated {
quote! { true }
} else {
quote! { false }
};
let unpublished = if metadata.unpublished {
quote! { true }
} else {
quote! { false }
};
let feature_tree_operation = if metadata.feature_tree_operation {
quote! { true }
} else {
quote! { false }
};
let docs_crate = get_crate(None);
// When the user attaches this proc macro to a function with the wrong type
// signature, the resulting errors can be deeply inscrutable. To attempt to
// make failures easier to understand, we inject code that asserts the types
// of the various parameters. We do this by calling dummy functions that
// require a type that satisfies SharedExtractor or ExclusiveExtractor.
let mut arg_types = Vec::new();
for (i, arg) in ast.sig.inputs.iter().enumerate() {
// Get the name of the argument.
let arg_name = match arg {
syn::FnArg::Receiver(pat) => {
let span = pat.self_token.span.unwrap();
span.source_text().unwrap().to_string()
}
syn::FnArg::Typed(pat) => match &*pat.pat {
syn::Pat::Ident(ident) => ident.ident.to_string(),
_ => {
errors.push(Error::new_spanned(
&pat.pat,
"stdlib functions may not use destructuring patterns",
));
continue;
}
},
}
.trim_start_matches('_')
.to_string();
// These aren't really KCL args, they're just state that each stdlib function's impl needs.
if arg_name == "exec_state" || arg_name == "args" {
continue;
}
let ty = match arg {
syn::FnArg::Receiver(pat) => pat.ty.as_ref().into_token_stream(),
syn::FnArg::Typed(pat) => pat.ty.as_ref().into_token_stream(),
};
let (ty_string, ty_ident) = clean_ty_string(ty.to_string().as_str());
let ty_string = rust_type_to_openapi_type(&ty_string);
let required = !ty_ident.to_string().starts_with("Option <");
let Some(arg_meta) = metadata.args.get(&arg_name) else {
errors.push(Error::new_spanned(arg, format!("arg {arg_name} not found")));
continue;
};
let description = arg_meta.docs.clone();
let include_in_snippet = required || arg_meta.include_in_snippet;
let snippet_value = arg_meta.snippet_value.clone();
let snippet_value_array = arg_meta.snippet_value_array.clone();
if snippet_value.is_some() && snippet_value_array.is_some() {
errors.push(Error::new_spanned(arg, format!("arg {arg_name} has set both snippet_value and snippet_value array, but at most one of these may be set. Please delete one of them.")));
}
let label_required = !(i == 0 && metadata.unlabeled_first);
let camel_case_arg_name = to_camel_case(&arg_name);
if ty_string != "ExecState" && ty_string != "Args" {
let schema = quote! {
generator.root_schema_for::<#ty_ident>()
};
let q0 = quote! {
name: #camel_case_arg_name.to_string(),
type_: #ty_string.to_string(),
schema: #schema,
required: #required,
label_required: #label_required,
description: #description.to_string(),
include_in_snippet: #include_in_snippet,
};
let q1 = if let Some(snippet_value) = snippet_value {
quote! {
snippet_value: Some(#snippet_value.to_owned()),
}
} else {
quote! {
snippet_value: None,
}
};
let q2 = if let Some(snippet_value_array) = snippet_value_array {
quote! {
snippet_value_array: Some(vec![
#(#snippet_value_array.to_owned()),*
]),
}
} else {
quote! {
snippet_value_array: None,
}
};
arg_types.push(quote! {
#docs_crate::StdLibFnArg {
#q0
#q1
#q2
}
});
}
}
let return_type_inner = match &ast.sig.output {
syn::ReturnType::Default => quote! { () },
syn::ReturnType::Type(_, ty) => {
// Get the inside of the result.
match &**ty {
syn::Type::Path(syn::TypePath { path, .. }) => {
let path = &path.segments;
if path.len() == 1 {
let seg = &path[0];
if seg.ident == "Result" {
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
args,
..
}) = &seg.arguments
{
if args.len() == 2 || args.len() == 1 {
let mut args = args.iter();
let ok = args.next().unwrap();
if let syn::GenericArgument::Type(ty) = ok {
let ty = unbox(ty.clone());
quote! { #ty }
} else {
quote! { () }
}
} else {
quote! { () }
}
} else {
quote! { () }
}
} else {
let ty = unbox(*ty.clone());
quote! { #ty }
}
} else {
quote! { () }
}
}
_ => {
quote! { () }
}
}
}
};
let ret_ty_string = return_type_inner.to_string().replace(' ', "");
let return_type = if !ret_ty_string.is_empty() || ret_ty_string != "()" {
let ret_ty_string = rust_type_to_openapi_type(&ret_ty_string);
quote! {
let schema = generator.root_schema_for::<#return_type_inner>();
Some(#docs_crate::StdLibFnArg {
name: "".to_string(),
type_: #ret_ty_string.to_string(),
schema,
required: true,
label_required: true,
description: String::new(),
include_in_snippet: true,
snippet_value: None,
snippet_value_array: None,
})
}
} else {
quote! {
None
}
};
// For reasons that are not well understood unused constants that use the
// (default) call_site() Span do not trigger the dead_code lint. Because
// defining but not using an endpoint is likely a programming error, we
// want to be sure to have the compiler flag this. We force this by using
// the span from the name of the function to which this macro was applied.
let span = ast.sig.ident.span();
let const_struct = quote_spanned! {span=>
pub(crate) const #name_ident: #name_ident = #name_ident {};
};
let test_mod_name = format_ident!("test_examples_{}", fn_name_str);
// The final TokenStream returned will have a few components that reference
// `#name_ident`, the name of the function to which this macro was applied...
let stream = quote! {
#[cfg(test)]
mod #test_mod_name {
#(#test_code_blocks)*
}
// ... a struct type called `#name_ident` that has no members
#[allow(non_camel_case_types, missing_docs)]
#description_doc_comment
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars::JsonSchema, ts_rs::TS)]
#[ts(export)]
pub(crate) struct #name_ident {}
// ... a constant of type `#name` whose identifier is also #name_ident
#[allow(non_upper_case_globals, missing_docs)]
#description_doc_comment
#const_struct
fn #boxed_fn_name_ident(
exec_state: &mut crate::execution::ExecState,
args: crate::std::Args,
) -> std::pin::Pin<
Box<dyn std::future::Future<Output = anyhow::Result<crate::execution::KclValue, crate::errors::KclError>> + Send + '_>,
> {
Box::pin(#fn_name_ident(exec_state, args))
}
impl #docs_crate::StdLibFn for #name_ident
{
fn name(&self) -> String {
#name_str.to_string()
}
fn summary(&self) -> String {
#summary.to_string()
}
fn description(&self) -> String {
#description.to_string()
}
fn tags(&self) -> Vec<String> {
vec![#(#tags),*]
}
fn args(&self, inline_subschemas: bool) -> Vec<#docs_crate::StdLibFnArg> {
let mut settings = schemars::gen::SchemaSettings::openapi3();
// We set this to false so we can recurse them later.
settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings);
vec![#(#arg_types),*]
}
fn return_value(&self, inline_subschemas: bool) -> Option<#docs_crate::StdLibFnArg> {
let mut settings = schemars::gen::SchemaSettings::openapi3();
// We set this to false so we can recurse them later.
settings.inline_subschemas = inline_subschemas;
let mut generator = schemars::gen::SchemaGenerator::new(settings);
#return_type
}
fn unpublished(&self) -> bool {
#unpublished
}
fn deprecated(&self) -> bool {
#deprecated
}
fn feature_tree_operation(&self) -> bool {
#feature_tree_operation
}
fn examples(&self) -> Vec<(String, bool)> {
#code_blocks
}
fn std_lib_fn(&self) -> crate::std::StdFn {
#boxed_fn_name_ident
}
fn clone_box(&self) -> Box<dyn #docs_crate::StdLibFn> {
Box::new(self.clone())
}
}
#item
};
// Prepend the usage message if any errors were detected.
if !errors.is_empty() {
errors.insert(0, Error::new_spanned(&ast.sig, ""));
}
Ok((stream, errors))
}
#[allow(dead_code)]
fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
let compile_errors = errors.iter().map(syn::Error::to_compile_error);
quote!(#(#compile_errors)*)
}
fn get_crate(var: Option<String>) -> proc_macro2::TokenStream {
if let Some(s) = var {
if let Ok(ts) = syn::parse_str(s.as_str()) {
return ts;
}
}
quote!(crate::docs)
}
#[derive(Debug)]
struct DocInfo {
pub summary: Option<String>,
pub description: Option<String>,
pub code_blocks: Vec<(String, bool)>,
}
fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> DocInfo {
let doc = syn::Ident::new("doc", proc_macro2::Span::call_site());
let raw_lines = attrs.iter().flat_map(|attr| {
if let syn::Meta::NameValue(nv) = &attr.meta {
if nv.path.is_ident(&doc) {
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(s), ..
}) = &nv.value
{
return normalize_comment_string(s.value());
}
}
}
Vec::new()
});
// Parse any code blocks from the doc string.
let mut code_blocks: Vec<(String, bool)> = Vec::new();
let mut code_block: Option<(String, bool)> = None;
let mut parsed_lines = Vec::new();
for line in raw_lines {
if line.starts_with("```") {
if let Some((inner_code_block, norun)) = code_block {
code_blocks.push((inner_code_block.trim().to_owned(), norun));
code_block = None;
} else {
let norun = line.contains("kcl,norun") || line.contains("kcl,no_run");
code_block = Some((String::new(), norun));
}
continue;
}
if let Some((code_block, _)) = &mut code_block {
code_block.push_str(&line);
code_block.push('\n');
} else {
parsed_lines.push(line);
}
}
if let Some((code_block, norun)) = code_block {
code_blocks.push((code_block.trim().to_string(), norun));
}
let mut summary = None;
let mut description: Option<String> = None;
for line in parsed_lines {
if line.is_empty() {
if let Some(desc) = &mut description {
// Handle fully blank comments as newlines we keep.
if !desc.is_empty() && !desc.ends_with('\n') {
if desc.ends_with(' ') {
desc.pop().unwrap();
}
desc.push_str("\n\n");
}
} else if summary.is_some() {
description = Some(String::new());
}
continue;
}
if let Some(desc) = &mut description {
desc.push_str(&line);
// Default to space-separating comment fragments.
desc.push(' ');
continue;
}
if summary.is_none() {
summary = Some(String::new());
}
match &mut summary {
Some(summary) => {
summary.push_str(&line);
// Default to space-separating comment fragments.
summary.push(' ');
}
None => unreachable!(),
}
}
// Trim the summary and description.
if let Some(s) = &mut summary {
while s.ends_with(' ') || s.ends_with('\n') {
s.pop().unwrap();
}
if s.is_empty() {
summary = None;
}
}
if let Some(d) = &mut description {
while d.ends_with(' ') || d.ends_with('\n') {
d.pop().unwrap();
}
if d.is_empty() {
description = None;
}
}
DocInfo {
summary,
description,
code_blocks,
}
}
fn normalize_comment_string(s: String) -> Vec<String> {
s.split('\n')
.map(|s| {
// Rust-style comments are intrinsically single-line.
// We only want to trim a single space character from the start of
// a line, and only if it's the first character.
s.strip_prefix(' ').unwrap_or(s).trim_end().to_owned()
})
.collect()
}
/// Represent an item without concern for its body which may (or may not)
/// contain syntax errors.
#[derive(Clone)]
struct ItemFnForSignature {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub sig: Signature,
pub _block: proc_macro2::TokenStream,
}
impl Parse for ItemFnForSignature {
fn parse(input: ParseStream) -> syn::parse::Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let sig: Signature = input.parse()?;
let block = input.parse()?;
Ok(ItemFnForSignature {
attrs,
vis,
sig,
_block: block,
})
}
}
fn clean_ty_string(t: &str) -> (String, proc_macro2::TokenStream) {
let mut ty_string = t
.replace("& 'a", "")
.replace('&', "")
.replace("mut", "")
.replace("< 'a >", "")
.replace(' ', "");
if ty_string.starts_with("ExecState") {
ty_string = "ExecState".to_string();
}
if ty_string.starts_with("Args") {
ty_string = "Args".to_string();
}
let ty_string = ty_string.trim().to_string();
let ty_ident = if ty_string.starts_with("Vec<") {
let ty_string = ty_string.trim_start_matches("Vec<").trim_end_matches('>');
let (_, ty_ident) = clean_ty_string(&ty_string);
quote! {
Vec<#ty_ident>
}
} else if ty_string.starts_with("kittycad::types::") {
let ty_string = ty_string.trim_start_matches("kittycad::types::").trim_end_matches('>');
let ty_ident = format_ident!("{}", ty_string);
quote! {
kittycad::types::#ty_ident
}
} else if ty_string.starts_with("Option<") {
let ty_string = ty_string.trim_start_matches("Option<").trim_end_matches('>');
let (_, ty_ident) = clean_ty_string(&ty_string);
quote! {
Option<#ty_ident>
}
} else if let Some((inner_array_type, num)) = parse_array_type(&ty_string) {
let ty_string = inner_array_type.to_owned();
let (_, ty_ident) = clean_ty_string(&ty_string);
quote! {
[#ty_ident; #num]
}
} else if ty_string.starts_with("Box<") {
let ty_string = ty_string.trim_start_matches("Box<").trim_end_matches('>');
let (_, ty_ident) = clean_ty_string(&ty_string);
quote! {
#ty_ident
}
} else {
let ty_ident = format_ident!("{}", ty_string);
quote! {
#ty_ident
}
};
(ty_string, ty_ident)
}
fn rust_type_to_openapi_type(t: &str) -> String {
let mut t = t.to_string();
// Turn vecs into arrays.
// TODO: handle nested types
if t.starts_with("Vec<") {
t = t.replace("Vec<", "[").replace('>', "]");
}
if t.starts_with("Box<") {
t = t.replace("Box<", "").replace('>', "");
}
if t.starts_with("Option<") {
t = t.replace("Option<", "").replace('>', "");
}
if t == "[TyF64;2]" {
return "Point2d".to_owned();
}
if t == "[TyF64;3]" {
return "Point3d".to_owned();
}
if let Some((inner_type, _length)) = parse_array_type(&t) {
t = format!("[{inner_type}]")
}
if t == "f64" || t == "TyF64" || t == "u32" || t == "NonZeroU32" {
return "number".to_string();
} else if t == "str" || t == "String" {
return "string".to_string();
} else {
return t.replace("f64", "number").replace("TyF64", "number").to_string();
}
}
fn parse_array_type(type_name: &str) -> Option<(&str, usize)> {
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"\[([a-zA-Z0-9<>]+); ?(\d+)\]").unwrap());
let cap = RE.captures(type_name)?;
let inner_type = cap.get(1)?;
let length = cap.get(2)?.as_str().parse().ok()?;
Some((inner_type.as_str(), length))
}
// For each kcl code block, we want to generate a test that checks that the
// code block is valid kcl code and compiles and executes.
fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> proc_macro2::TokenStream {
let test_name = format_ident!("kcl_test_example_{}{}", fn_name, index);
let test_name_mock = format_ident!("test_mock_example_{}{}", fn_name, index);
let output_test_name_str = format!("serial_test_example_{}{}", fn_name, index);
quote! {
#[tokio::test(flavor = "multi_thread")]
async fn #test_name_mock() -> miette::Result<()> {
let program = crate::Program::parse_no_errs(#code_block).unwrap();
let ctx = crate::ExecutorContext {
engine: std::sync::Arc::new(Box::new(crate::engine::conn_mock::EngineConnection::new().await.unwrap())),
fs: std::sync::Arc::new(crate::fs::FileManager::new()),
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
settings: Default::default(),
context_type: crate::execution::ContextType::Mock,
};
if let Err(e) = ctx.run(&program, &mut crate::execution::ExecState::new(&ctx)).await {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,
filename: format!("{}{}", #fn_name, #index),
kcl_source: #code_block.to_string(),
}));
}
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn #test_name() -> miette::Result<()> {
let code = #code_block;
// Note, `crate` must be kcl_lib
let result = match crate::test_server::execute_and_snapshot(code, None).await {
Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,
filename: format!("{}{}", #fn_name, #index),
kcl_source: #code_block.to_string(),
}));
}
Err(other_err)=> panic!("{}", other_err),
Ok(img) => img,
};
twenty_twenty::assert_image(&format!("tests/outputs/{}.png", #output_test_name_str), &result, 0.99);
Ok(())
}
}
}

View File

@ -1,508 +0,0 @@
use anyhow::Result;
use quote::quote;
use crate::{do_stdlib, parse_array_type};
fn clean_text(s: &str) -> String {
// Add newlines after end-braces at <= two levels of indentation.
if cfg!(not(windows)) {
let regex = regex::Regex::new(r"(})(\n\s{0,8}[^} ])").unwrap();
regex.replace_all(s, "$1\n$2").to_string()
} else {
let regex = regex::Regex::new(r"(})(\r\n\s{0,8}[^} ])").unwrap();
regex.replace_all(s, "$1\r\n$2").to_string()
}
}
/// Format a TokenStream as a string and run `rustfmt` on the result.
fn get_text_fmt(output: &proc_macro2::TokenStream) -> Result<String> {
// Format the file with rustfmt.
let content = rustfmt_wrapper::rustfmt(output).unwrap();
Ok(clean_text(&content))
}
#[test]
fn test_get_inner_array_type() {
for (expected, input) in [
(Some(("f64", 2)), "[f64;2]"),
(Some(("String", 2)), "[String; 2]"),
(Some(("Option<String>", 12)), "[Option<String>;12]"),
(Some(("Option<String>", 12)), "[Option<String>; 12]"),
] {
let actual = parse_array_type(input);
assert_eq!(actual, expected);
}
}
#[test]
fn test_args_with_refs() {
let (item, mut errors) = do_stdlib(
quote! {
name = "someFn",
args = {
data = { docs = "The data for this function"},
},
},
quote! {
/// Docs
/// ```
/// someFn()
/// ```
fn someFn(
data: &'a str,
) -> i32 {
3
}
},
)
.unwrap();
if let Some(e) = errors.pop() {
panic!("{e}");
}
expectorate::assert_contents("tests/args_with_refs.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_args_with_lifetime() {
let (item, mut errors) = do_stdlib(
quote! {
name = "someFn",
args = {
data = { docs = "Arg for the function" },
}
},
quote! {
/// Docs
/// ```
/// someFn()
/// ```
fn someFn<'a>(
data: Foo<'a>,
) -> i32 {
3
}
},
)
.unwrap();
if let Some(e) = errors.pop() {
panic!("{e}");
}
expectorate::assert_contents("tests/args_with_lifetime.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_args_with_exec_state() {
let (item, mut errors) = do_stdlib(
quote! {
name = "someFunction",
},
quote! {
/// Docs
/// ```
/// someFunction()
/// ```
fn inner_some_function<'a>(
exec_state: &mut ExecState,
args: &Args,
) -> i32 {
3
}
},
)
.unwrap();
if let Some(e) = errors.pop() {
panic!("{e}");
}
expectorate::assert_contents("tests/test_args_with_exec_state.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_line_to() {
let (item, errors) = do_stdlib(
quote! {
name = "lineTo",
args = {
data = { docs = "the sketch you're adding the line to" },
sketch = { docs = "the sketch you're adding the line to" },
}
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is another code block.
/// yes sirrr.
/// lineTo
/// ```
fn inner_line_to(
data: LineToData,
sketch: Sketch,
args: &Args,
) -> Result<Sketch, KclError> {
Ok(())
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/lineTo.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_min() {
let (item, errors) = do_stdlib(
quote! {
name = "min",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is another code block.
/// yes sirrr.
/// min
/// ```
fn inner_min(
/// The args to do shit to.
args: Vec<f64>
) -> f64 {
let mut min = std::f64::MAX;
for arg in args.iter() {
if *arg < min {
min = *arg;
}
}
min
}
},
)
.unwrap();
let _expected = quote! {};
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/min.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_show() {
let (item, errors) = do_stdlib(
quote! {
name = "show",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is code.
/// It does other shit.
/// show
/// ```
fn inner_show(
/// The args to do shit to.
_args: Vec<f64>
) {
}
},
)
.unwrap();
let _expected = quote! {};
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/show.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_box() {
let (item, errors) = do_stdlib(
quote! {
name = "show",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is code.
/// It does other shit.
/// show
/// ```
fn inner_show(
/// The args to do shit to.
args: Box<f64>
) -> Box<f64> {
args
}
},
)
.unwrap();
let _expected = quote! {};
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/box.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_option() {
let (item, errors) = do_stdlib(
quote! {
name = "show",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is code.
/// It does other shit.
/// show
/// ```
fn inner_show(
/// The args to do shit to.
args: Option<f64>
) -> Result<Box<f64>> {
args
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/option.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_array() {
let (item, errors) = do_stdlib(
quote! {
name = "show",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is another code block.
/// yes sirrr.
/// show
/// ```
fn inner_show(
/// The args to do shit to.
args: [f64; 2]
) -> Result<Box<f64>> {
args
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/array.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_option_input_format() {
let (item, errors) = do_stdlib(
quote! {
name = "import",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is code.
/// It does other shit.
/// import
/// ```
fn inner_import(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Box<f64>> {
args
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/option_input_format.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_return_vec_sketch() {
let (item, errors) = do_stdlib(
quote! {
name = "import",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is code.
/// It does other shit.
/// import
/// ```
fn inner_import(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Vec<Sketch>> {
args
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/return_vec_sketch.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_return_vec_box_sketch() {
let (item, errors) = do_stdlib(
quote! {
name = "import",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is code.
/// It does other shit.
/// import
/// ```
fn inner_import(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Vec<Box<Sketch>>> {
args
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/return_vec_box_sketch.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_doc_comment_with_code() {
let (item, errors) = do_stdlib(
quote! {
name = "myFunc",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is another code block.
/// yes sirrr.
/// myFunc
/// ```
fn inner_my_func(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Vec<Box<Sketch>>> {
args
}
},
)
.unwrap();
assert!(errors.is_empty(), "{errors:?}");
expectorate::assert_contents("tests/doc_comment_with_code.gen", &get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_fail_non_camel_case() {
let (_, errors) = do_stdlib(
quote! {
name = "import_thing",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is another code block.
/// yes sirrr.
/// ```
fn inner_import_thing(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Vec<Box<Sketch>>> {
args
}
},
)
.unwrap();
assert!(!errors.is_empty());
assert_eq!(
errors[1].to_string(),
"stdlib function names must be in camel case: `import_thing`"
);
}
#[test]
fn test_stdlib_fail_no_code_block() {
let (_, errors) = do_stdlib(
quote! {
name = "import",
},
quote! {
fn inner_import(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Vec<Box<Sketch>>> {
args
}
},
)
.unwrap();
assert!(!errors.is_empty());
assert_eq!(
errors[1].to_string(),
"stdlib functions must have at least one code block"
);
}
#[test]
fn test_stdlib_fail_name_not_in_code_block() {
let (_, errors) = do_stdlib(
quote! {
name = "import",
},
quote! {
/// This is some function.
/// It does shit.
///
/// ```
/// This is another code block.
/// yes sirrr.
/// ```
fn inner_import(
/// The args to do shit to.
args: Option<kittycad::types::InputFormat>
) -> Result<Vec<Box<Sketch>>> {
args
}
},
)
.unwrap();
assert!(!errors.is_empty());
assert_eq!(
errors[1].to_string(),
"stdlib functions must have the function name `import` in the code block"
);
}

View File

@ -1,91 +0,0 @@
// Unbox a Vec<Box<T>> to Vec<T>.
// Unbox a Box<T> to T.
pub(crate) fn unbox(t: syn::Type) -> syn::Type {
unbox_inner(unbox_vec(t))
}
// Unbox a syn::Type that is boxed to the inner object.
fn unbox_inner(t: syn::Type) -> syn::Type {
match t {
syn::Type::Path(syn::TypePath { ref path, .. }) => {
let path = &path.segments;
if path.len() == 1 {
let seg = &path[0];
if seg.ident == "Box" {
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
&seg.arguments
{
if args.len() == 1 {
let mut args = args.iter();
let ok = args.next().unwrap();
if let syn::GenericArgument::Type(ty) = ok {
return ty.clone();
}
}
}
}
}
}
_ => {
return t;
}
}
t
}
// For a Vec<Box<T>> return Vec<T>.
// For a Vec<T> return Vec<T>.
fn unbox_vec(t: syn::Type) -> syn::Type {
match t {
syn::Type::Path(syn::TypePath { ref path, .. }) => {
let path = &path.segments;
if path.len() == 1 {
let seg = &path[0];
if seg.ident == "Vec" {
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
&seg.arguments
{
if args.len() == 1 {
let mut args = args.iter();
let ok = args.next().unwrap();
if let syn::GenericArgument::Type(ty) = ok {
let unboxed = unbox(ty.clone());
// Wrap it back in a vec.
let wrapped = syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: {
let mut segments = syn::punctuated::Punctuated::new();
segments.push_value(syn::PathSegment {
ident: syn::Ident::new("Vec", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: syn::token::Lt::default(),
args: {
let mut args = syn::punctuated::Punctuated::new();
args.push_value(syn::GenericArgument::Type(unboxed));
args
},
gt_token: syn::token::Gt::default(),
},
),
});
segments
},
},
});
return wrapped;
}
}
}
}
}
}
_ => {
return t;
}
}
t
}

View File

@ -762,7 +762,7 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
};
assert_eq!(
err.error.message(),
"This function requires a keyword argument 'center'"
"This function requires a keyword argument `center`"
);
}
@ -1230,10 +1230,7 @@ secondSketch = startSketchOn(part001, face = '')
let result = execute_and_snapshot(code, None).await;
let err = result.unwrap_err();
let err = err.as_kcl_error().unwrap();
assert_eq!(
err.message(),
"This function expected the input argument to be tag but it's actually of type string"
);
assert_eq!(err.message(), "face requires a value with type `tag`, but found string");
}
#[tokio::test(flavor = "multi_thread")]
@ -1684,10 +1681,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have an x constrained angle of 90 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(70, 111, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(70, 111, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(70, 111, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1709,10 +1712,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have an x constrained angle of 270 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(70, 112, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(70, 112, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(70, 112, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1734,10 +1743,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have a y constrained angle of 0 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(70, 110, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(70, 110, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(70, 110, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1759,10 +1774,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have a y constrained angle of 180 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(70, 112, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(70, 112, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(70, 112, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1784,10 +1805,16 @@ extrusion = extrude(sketch001, length = 10)
assert_eq!(err.message(), "Cannot have an x constrained angle of 90 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(66, 116, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(66, 116, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(66, 116, ModuleId::default()),
fn_name: None,
}
]
);
}
@ -1809,10 +1836,16 @@ extrusion = extrude(sketch001, length = 10)
assert_eq!(err.message(), "Cannot have an x constrained angle of 270 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(66, 117, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(66, 117, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(66, 117, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1836,10 +1869,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have a y constrained angle of 0 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(95, 130, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(95, 130, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(95, 130, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1863,10 +1902,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have a y constrained angle of 180 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(95, 132, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(95, 132, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(95, 132, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1890,10 +1935,16 @@ example = extrude(exampleSketch, length = 10)
assert_eq!(err.message(), "Cannot have a y constrained angle of 180 degrees");
assert_eq!(
err.backtrace(),
vec![BacktraceItem {
source_range: SourceRange::new(95, 133, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
}]
vec![
BacktraceItem {
source_range: SourceRange::new(95, 133, ModuleId::default()),
fn_name: Some("angledLine".to_owned())
},
BacktraceItem {
source_range: SourceRange::new(95, 133, ModuleId::default()),
fn_name: None
}
]
);
}
@ -1911,12 +1962,13 @@ someFunction('INVALID')
let err = err.as_kcl_error().unwrap();
assert_eq!(
err.message(),
"This function expected the input argument to be Solid or Plane but it's actually of type string"
"The input argument of `startSketchOn` requires a value with type `Solid | Plane`, but found string"
);
assert_eq!(
err.source_ranges(),
vec![
SourceRange::new(46, 55, ModuleId::default()),
SourceRange::new(32, 56, ModuleId::default()),
SourceRange::new(60, 83, ModuleId::default()),
]
);
@ -1925,6 +1977,10 @@ someFunction('INVALID')
vec![
BacktraceItem {
source_range: SourceRange::new(46, 55, ModuleId::default()),
fn_name: Some("startSketchOn".to_owned()),
},
BacktraceItem {
source_range: SourceRange::new(32, 56, ModuleId::default()),
fn_name: Some("someFunction".to_owned()),
},
BacktraceItem {

View File

@ -2,48 +2,11 @@ use std::{collections::HashMap, fs, path::Path};
use anyhow::Result;
use base64::Engine;
use convert_case::Casing;
use indexmap::IndexMap;
use itertools::Itertools;
use serde_json::json;
use tokio::task::JoinSet;
use super::kcl_doc::{ConstData, DocData, ExampleProperties, FnData, ModData, TyData};
use crate::{
docs::{StdLibFn, DECLARED_TYPES},
std::StdLib,
ExecutorContext,
};
// Types with special handling.
const SPECIAL_TYPES: [&str; 4] = ["TagDeclarator", "TagIdentifier", "Start", "End"];
const TYPE_REWRITES: [(&str, &str); 11] = [
("TagNode", "TagDeclarator"),
("SketchData", "Plane | Solid"),
("SketchOrSurface", "Sketch | Plane | Face"),
("SketchSurface", "Plane | Face"),
("SolidOrImportedGeometry", "[Solid] | ImportedGeometry"),
(
"SolidOrSketchOrImportedGeometry",
"[Solid] | [Sketch] | ImportedGeometry",
),
("KclValue", "any"),
("[KclValue]", "[any]"),
("FaceTag", "TagIdentifier | Start | End"),
("GeometryWithImportedGeometry", "Solid | Sketch | ImportedGeometry"),
("SweepPath", "Sketch | Helix"),
];
fn rename_type(input: &str) -> &str {
for (i, o) in TYPE_REWRITES {
if input == i {
return o;
}
}
input
}
use crate::ExecutorContext;
fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
let mut hbs = handlebars::Handlebars::new();
@ -104,7 +67,7 @@ fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
Ok(hbs)
}
fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &ModData) -> Result<()> {
fn generate_index(kcl_lib: &ModData) -> Result<()> {
let hbs = init_handlebars()?;
let mut functions = HashMap::new();
@ -115,31 +78,6 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &ModD
let mut types = HashMap::new();
types.insert("Primitive types".to_owned(), Vec::new());
for key in combined.keys() {
let internal_fn = combined
.get(key)
.ok_or_else(|| anyhow::anyhow!("Failed to get internal function: {}", key))?;
if internal_fn.unpublished() || internal_fn.deprecated() {
continue;
}
let tags = internal_fn.tags();
let module = tags.first().map(|s| format!("std::{s}")).unwrap_or("std".to_owned());
functions
.entry(module.to_owned())
.or_default()
.push((internal_fn.name(), format!("/docs/kcl-std/{}", internal_fn.name())));
}
for name in SPECIAL_TYPES {
types
.get_mut("Primitive types")
.unwrap()
.push((name.to_owned(), format!("/docs/kcl-lang/types#{name}")));
}
for d in kcl_lib.all_docs() {
if d.hide() {
continue;
@ -257,8 +195,8 @@ fn generate_example(index: usize, src: &str, props: &ExampleProperties, file_nam
}))
}
fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String) -> Result<()> {
if ty.properties.doc_hidden || !DECLARED_TYPES.contains(&&*ty.name) {
fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String, kcl_std: &ModData) -> Result<()> {
if ty.properties.doc_hidden {
return Ok(());
}
@ -282,18 +220,14 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String)
});
let output = hbs.render("kclType", &data)?;
let output = cleanup_types(&output);
let output = cleanup_types(&output, kcl_std);
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
Ok(())
}
fn generate_mod_from_kcl(m: &ModData, file_name: String, combined: &IndexMap<String, Box<dyn StdLibFn>>) -> Result<()> {
fn list_items(
m: &ModData,
namespace: &str,
combined: &IndexMap<String, Box<dyn StdLibFn>>,
) -> Vec<gltf_json::Value> {
fn generate_mod_from_kcl(m: &ModData, file_name: String) -> Result<()> {
fn list_items(m: &ModData, namespace: &str) -> Vec<gltf_json::Value> {
let mut items: Vec<_> = m
.children
.iter()
@ -301,25 +235,6 @@ fn generate_mod_from_kcl(m: &ModData, file_name: String, combined: &IndexMap<Str
.map(|(_, v)| (v.preferred_name().to_owned(), v.file_name()))
.collect();
if namespace == "I:" {
// Add in functions declared in Rust
items.extend(
combined
.values()
.filter(|f| {
if f.unpublished() || f.deprecated() {
return false;
}
let tags = f.tags();
let module = tags.first().map(|s| format!("std::{s}")).unwrap_or("std".to_owned());
module == m.qual_name
})
.map(|f| (f.name(), f.name())),
)
}
items.sort();
items
.into_iter()
@ -333,9 +248,9 @@ fn generate_mod_from_kcl(m: &ModData, file_name: String, combined: &IndexMap<Str
}
let hbs = init_handlebars()?;
let functions = list_items(m, "I:", combined);
let modules = list_items(m, "M:", combined);
let types = list_items(m, "T:", combined);
let functions = list_items(m, "I:");
let modules = list_items(m, "M:");
let types = list_items(m, "T:");
let data = json!({
"name": m.name,
@ -391,7 +306,7 @@ fn generate_function_from_kcl(
json!({
"name": arg.name,
"type_": arg.ty,
"description": docs.or_else(|| arg.ty.as_ref().and_then(|t| super::docs_for_type(t, kcl_std))).unwrap_or_default(),
"description": docs.or_else(|| arg.ty.as_ref().and_then(|t| docs_for_type(t, kcl_std))).unwrap_or_default(),
"required": arg.kind.required(),
})
}).collect::<Vec<_>>();
@ -408,18 +323,30 @@ fn generate_function_from_kcl(
"return_value": function.return_type.as_ref().map(|t| {
json!({
"type_": t,
"description": super::docs_for_type(t, kcl_std).unwrap_or_default(),
"description": docs_for_type(t, kcl_std).unwrap_or_default(),
})
}),
});
let output = hbs.render("function", &data)?;
let output = &cleanup_types(&output);
let output = &cleanup_types(&output, kcl_std);
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), output);
Ok(())
}
fn docs_for_type(ty: &str, kcl_std: &ModData) -> Option<String> {
let key = if ty.starts_with("number") { "number" } else { ty };
if !key.contains('|') && !key.contains('[') {
if let Some(data) = kcl_std.find_by_name(key) {
return data.summary().cloned();
}
}
None
}
fn generate_const_from_kcl(cnst: &ConstData, file_name: String, example_name: String) -> Result<()> {
if cnst.properties.doc_hidden {
return Ok(());
@ -450,83 +377,7 @@ fn generate_const_from_kcl(cnst: &ConstData, file_name: String, example_name: St
Ok(())
}
fn generate_function(internal_fn: Box<dyn StdLibFn>, kcl_std: &ModData) -> Result<()> {
let hbs = init_handlebars()?;
if internal_fn.unpublished() {
return Ok(());
}
let fn_name = internal_fn.name();
let snake_case_name = clean_function_name(&fn_name);
let examples: Vec<serde_json::Value> = internal_fn
.examples()
.iter()
.enumerate()
.map(|(index, (example, norun))| {
let image_base64 = if !norun {
let image_path = format!(
"{}/tests/outputs/serial_test_example_{}{}.png",
env!("CARGO_MANIFEST_DIR"),
snake_case_name,
index
);
let image_data =
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {}", image_path));
base64::engine::general_purpose::STANDARD.encode(&image_data)
} else {
String::new()
};
json!({
"content": example,
"image_base64": image_base64,
})
})
.collect();
let tags = internal_fn.tags();
let module = tags
.first()
.map(|s| &**s)
.map(|m| format!("std::{m}"))
.unwrap_or("std".to_owned());
let data = json!({
"name": fn_name,
"module": module,
"summary": internal_fn.summary(),
"description": internal_fn.description(),
"deprecated": internal_fn.deprecated(),
"fn_signature": internal_fn.fn_signature(true),
"examples": examples,
"args": internal_fn.args(false).iter().map(|arg| {
json!({
"name": arg.name,
"type_": rename_type(&arg.type_),
"description": arg.description(Some(kcl_std)),
"required": arg.required,
})
}).collect::<Vec<_>>(),
"return_value": internal_fn.return_value(false).map(|ret| {
json!({
"type_": rename_type(&ret.type_),
"description": ret.description(Some(kcl_std)),
})
}),
});
let mut output = hbs.render("function", &data)?;
// Fix the links to the types.
output = cleanup_types(&output);
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", fn_name), &output);
Ok(())
}
fn cleanup_types(input: &str) -> String {
fn cleanup_types(input: &str, kcl_std: &ModData) -> String {
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum State {
Text,
@ -550,7 +401,7 @@ fn cleanup_types(input: &str) -> String {
if code_type.starts_with(' ') {
code.push(' ');
}
code.push_str(&cleanup_type_string(code_type.trim(), false));
code.push_str(&cleanup_type_string(code_type.trim(), false, kcl_std));
if code_type.ends_with(' ') {
code.push(' ');
}
@ -586,7 +437,7 @@ fn cleanup_types(input: &str) -> String {
}
ticks = 0;
} else if state == State::Text && ticks == 2 && !code.is_empty() {
output.push_str(&cleanup_type_string(&code, true));
output.push_str(&cleanup_type_string(&code, true, kcl_std));
code = String::new();
ticks = 0;
} else if state == State::CodeBlock {
@ -631,14 +482,12 @@ fn cleanup_types(input: &str) -> String {
output
}
fn cleanup_type_string(input: &str, fmt_for_text: bool) -> String {
fn cleanup_type_string(input: &str, fmt_for_text: bool, kcl_std: &ModData) -> String {
assert!(
!(input.starts_with('[') && input.ends_with(']') && input.contains('|')),
"Arrays of unions are not supported"
);
let input = rename_type(input);
let tys: Vec<_> = input
.split('|')
.map(|ty| {
@ -676,9 +525,7 @@ fn cleanup_type_string(input: &str, fmt_for_text: bool) -> String {
format!("[{prefix}{ty}{suffix}](/docs/kcl-std/types/std-types-number)")
} else if fmt_for_text && ty.starts_with("fn") {
format!("[{prefix}{ty}{suffix}](/docs/kcl-std/types/std-types-fn)")
} else if fmt_for_text && SPECIAL_TYPES.contains(&ty) {
format!("[{prefix}{ty}{suffix}](/docs/kcl-lang/types#{ty})")
} else if fmt_for_text && DECLARED_TYPES.contains(&ty) {
} else if fmt_for_text && matches!(kcl_std.find_by_name(ty), Some(DocData::Ty(_))) {
format!("[{prefix}{ty}{suffix}](/docs/kcl-std/types/std-types-{ty})")
} else {
format!("{prefix}{ty}{suffix}")
@ -689,73 +536,22 @@ fn cleanup_type_string(input: &str, fmt_for_text: bool) -> String {
tys.join(if fmt_for_text { " or " } else { " | " })
}
fn clean_function_name(name: &str) -> String {
// Convert from camel case to snake case.
let mut fn_name = name.to_case(convert_case::Case::Snake);
// Clean the fn name.
if fn_name.starts_with("last_seg_") {
fn_name = fn_name.replace("last_seg_", "last_segment_");
} else if fn_name.contains("_2_d") {
fn_name = fn_name.replace("_2_d", "_2d");
} else if fn_name.contains("_3_d") {
fn_name = fn_name.replace("_3_d", "_3d");
} else if fn_name == "seg_ang" {
fn_name = "segment_angle".to_string();
} else if fn_name == "seg_len" {
fn_name = "segment_length".to_string();
} else if fn_name.starts_with("seg_") {
fn_name = fn_name.replace("seg_", "segment_");
}
fn_name
}
#[test]
fn test_generate_stdlib_markdown_docs() {
let stdlib = StdLib::new();
let combined = stdlib.combined();
let kcl_std = crate::docs::kcl_doc::walk_prelude();
// Generate the index which is the table of contents.
generate_index(&combined, &kcl_std).unwrap();
for key in combined.keys().sorted() {
let internal_fn = combined.get(key).unwrap();
generate_function(internal_fn.clone(), &kcl_std).unwrap();
}
generate_index(&kcl_std).unwrap();
for d in kcl_std.all_docs() {
match d {
DocData::Fn(f) => generate_function_from_kcl(f, d.file_name(), d.example_name(), &kcl_std).unwrap(),
DocData::Const(c) => generate_const_from_kcl(c, d.file_name(), d.example_name()).unwrap(),
DocData::Ty(t) => generate_type_from_kcl(t, d.file_name(), d.example_name()).unwrap(),
DocData::Mod(m) => generate_mod_from_kcl(m, d.file_name(), &combined).unwrap(),
DocData::Ty(t) => generate_type_from_kcl(t, d.file_name(), d.example_name(), &kcl_std).unwrap(),
DocData::Mod(m) => generate_mod_from_kcl(m, d.file_name()).unwrap(),
}
}
generate_mod_from_kcl(&kcl_std, "modules/std".to_owned(), &combined).unwrap();
}
#[test]
fn test_generate_stdlib_json_schema() {
// If this test fails and you've modified the AST or something else which affects the json repr
// of stdlib functions, you should rerun the test with `EXPECTORATE=overwrite` to create new
// test data, then check `/docs/kcl-std/std.json` to ensure the changes are expected.
// Alternatively, run `just redo-kcl-stdlib-docs` (make sure to have just installed).
let stdlib = StdLib::new();
let combined = stdlib.combined();
let json_data: Vec<_> = combined
.keys()
.sorted()
.map(|key| {
let internal_fn = combined.get(key).unwrap();
internal_fn.to_json().unwrap()
})
.collect();
expectorate::assert_contents(
"../../docs/kcl-std/std.json",
&serde_json::to_string_pretty(&json_data).unwrap(),
);
generate_mod_from_kcl(&kcl_std, "modules/std".to_owned()).unwrap();
}
#[tokio::test(flavor = "multi_thread")]

View File

@ -302,6 +302,7 @@ impl DocData {
}
}
#[allow(dead_code)]
pub(super) fn summary(&self) -> Option<&String> {
match self {
DocData::Fn(f) => f.summary.as_ref(),
@ -462,6 +463,7 @@ impl ModData {
}
}
#[allow(dead_code)]
pub fn find_by_name(&self, name: &str) -> Option<&DocData> {
if let Some(result) = self
.children
@ -812,6 +814,7 @@ impl ArgData {
return Some((index + n - 1, snippet));
}
match self.ty.as_deref() {
Some("Sketch") if self.kind == ArgKind::Special => None,
Some(s) if s.starts_with("number") => Some((index, format!(r#"{label}${{{}:10}}"#, index))),
Some("Point2d") => Some((index + 1, format!(r#"{label}[${{{}:0}}, ${{{}:0}}]"#, index, index + 1))),
Some("Point3d") => Some((
@ -827,7 +830,7 @@ impl ArgData {
Some("Sketch") | Some("Sketch | Helix") => Some((index, format!(r#"{label}${{{index}:sketch000}}"#))),
Some("Edge") => Some((index, format!(r#"{label}${{{index}:tag_or_edge_fn}}"#))),
Some("[Edge; 1+]") => Some((index, format!(r#"{label}[${{{index}:tag_or_edge_fn}}]"#))),
Some("Plane") => Some((index, format!(r#"{label}${{{}:XY}}"#, index))),
Some("Plane") | Some("Solid | Plane") => Some((index, format!(r#"{label}${{{}:XY}}"#, index))),
Some("[tag; 2]") => Some((
index + 1,
format!(r#"{label}[${{{}:tag}}, ${{{}:tag}}]"#, index, index + 1),
@ -989,7 +992,7 @@ trait ApplyMeta {
}
let mut summary = None;
let mut description = None;
let mut description: Option<String> = None;
let mut example: Option<(String, ExampleProperties)> = None;
let mut examples = Vec::new();
for l in comments.iter().filter(|l| l.starts_with("///")).map(|l| {
@ -999,22 +1002,6 @@ trait ApplyMeta {
&l[3..]
}
}) {
if description.is_none() && summary.is_none() {
summary = Some(l.to_owned());
continue;
}
if description.is_none() {
if l.is_empty() {
description = Some(String::new());
} else {
description = summary;
summary = None;
let d = description.as_mut().unwrap();
d.push('\n');
d.push_str(l);
}
continue;
}
#[allow(clippy::manual_strip)]
if l.starts_with("```") {
if let Some((e, p)) = example {
@ -1050,12 +1037,36 @@ trait ApplyMeta {
continue;
}
}
// An empty line outside of an example. This either starts the description (with or
// without a summary) or adds a blank line to the description.
if l.is_empty() {
match &mut description {
Some(d) => {
d.push('\n');
}
None => description = Some(String::new()),
}
continue;
}
// Our first line, start the summary.
if description.is_none() && summary.is_none() {
summary = Some(l.to_owned());
continue;
}
// Append the line to either the description or summary.
match &mut description {
Some(d) => {
d.push_str(l);
d.push('\n');
}
None => unreachable!(),
None => {
let s = summary.as_mut().unwrap();
s.push(' ');
s.push_str(l);
}
}
}
assert!(example.is_none());

File diff suppressed because it is too large Load Diff

View File

@ -565,30 +565,6 @@ impl KclError {
new
}
pub(crate) fn set_last_backtrace_fn_name(&self, last_fn_name: Option<String>) -> Self {
let mut new = self.clone();
match &mut new {
KclError::Lexical { details: e }
| KclError::Syntax { details: e }
| KclError::Semantic { details: e }
| KclError::ImportCycle { details: e }
| KclError::Type { details: e }
| KclError::Io { details: e }
| KclError::Unexpected { details: e }
| KclError::ValueAlreadyDefined { details: e }
| KclError::UndefinedValue { details: e, .. }
| KclError::InvalidExpression { details: e }
| KclError::Engine { details: e }
| KclError::Internal { details: e } => {
if let Some(item) = e.backtrace.last_mut() {
item.fn_name = last_fn_name;
}
}
}
new
}
pub(crate) fn add_unwind_location(&self, last_fn_name: Option<String>, source_range: SourceRange) -> Self {
let mut new = self.clone();
match &mut new {

View File

@ -1901,7 +1901,6 @@ d = b + c
project_directory: Some(crate::TypedPath(tmpdir.path().into())),
..Default::default()
},
stdlib: Arc::new(crate::std::StdLib::new()),
context_type: ContextType::Mock,
};
let mut exec_state = ExecState::new(&exec_ctxt);

View File

@ -2,7 +2,6 @@ use async_recursion::async_recursion;
use indexmap::IndexMap;
use crate::{
docs::StdLibFn,
errors::{KclError, KclErrorDetails},
execution::{
cad_op::{Group, OpArg, OpKclValue, Operation},
@ -184,40 +183,6 @@ impl<'a> From<&'a FunctionSource> for FunctionDefinition<'a> {
}
}
impl From<&dyn StdLibFn> for FunctionDefinition<'static> {
fn from(value: &dyn StdLibFn) -> Self {
let mut input_arg = None;
let mut named_args = IndexMap::new();
for a in value.args(false) {
if !a.label_required {
input_arg = Some((a.name.clone(), None));
continue;
}
named_args.insert(
a.name.clone(),
(
if a.required {
None
} else {
Some(DefaultParamVal::none())
},
None,
),
);
}
FunctionDefinition {
input_arg,
named_args,
return_type: None,
deprecated: value.deprecated(),
include_in_feature_tree: value.feature_tree_operation(),
is_std: true,
body: FunctionBody::Rust(value.std_lib_fn()),
}
}
}
impl Node<CallExpressionKw> {
#[async_recursion]
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
@ -274,62 +239,44 @@ impl Node<CallExpressionKw> {
exec_state.pipe_value().map(|v| Arg::new(v.clone(), callsite)),
);
match ctx.stdlib.get_rust_function(fn_name) {
Some(func) => {
let def: FunctionDefinition = (&*func).into();
// All std lib functions return a value, so the unwrap is safe.
def.call_kw(Some(func.name()), exec_state, ctx, args, callsite)
.await
.map(Option::unwrap)
.map_err(|e| {
// This is used for the backtrace display. We don't add
// another location the way we do for user-defined
// functions because the error uses the Args, which
// already points here.
e.set_last_backtrace_fn_name(Some(func.name()))
})
}
None => {
// Clone the function so that we can use a mutable reference to
// exec_state.
let func = fn_name.get_result(exec_state, ctx).await?.clone();
// Clone the function so that we can use a mutable reference to
// exec_state.
let func = fn_name.get_result(exec_state, ctx).await?.clone();
let Some(fn_src) = func.as_function() else {
return Err(KclError::new_semantic(KclErrorDetails::new(
"cannot call this because it isn't a function".to_string(),
vec![callsite],
)));
};
let Some(fn_src) = func.as_function() else {
return Err(KclError::new_semantic(KclErrorDetails::new(
"cannot call this because it isn't a function".to_string(),
vec![callsite],
)));
};
let return_value = fn_src
.call_kw(Some(fn_name.to_string()), exec_state, ctx, args, callsite)
.await
.map_err(|e| {
// Add the call expression to the source ranges.
//
// TODO: Use the name that the function was defined
// with, not the identifier it was used with.
e.add_unwind_location(Some(fn_name.name.name.clone()), callsite)
})?;
let return_value = fn_src
.call_kw(Some(fn_name.to_string()), exec_state, ctx, args, callsite)
.await
.map_err(|e| {
// Add the call expression to the source ranges.
//
// TODO: Use the name that the function was defined
// with, not the identifier it was used with.
e.add_unwind_location(Some(fn_name.name.name.clone()), callsite)
})?;
let result = return_value.ok_or_else(move || {
let mut source_ranges: Vec<SourceRange> = vec![callsite];
// We want to send the source range of the original function.
if let KclValue::Function { meta, .. } = func {
source_ranges = meta.iter().map(|m| m.source_range).collect();
};
KclError::new_undefined_value(
KclErrorDetails::new(
format!("Result of user-defined function {} is undefined", fn_name),
source_ranges,
),
None,
)
})?;
let result = return_value.ok_or_else(move || {
let mut source_ranges: Vec<SourceRange> = vec![callsite];
// We want to send the source range of the original function.
if let KclValue::Function { meta, .. } = func {
source_ranges = meta.iter().map(|m| m.source_range).collect();
};
KclError::new_undefined_value(
KclErrorDetails::new(
format!("Result of user-defined function {} is undefined", fn_name),
source_ranges,
),
None,
)
})?;
Ok(result)
}
}
Ok(result)
}
}
@ -603,30 +550,33 @@ fn type_check_params_kw(
for (label, arg) in &mut args.labeled {
match fn_def.named_args.get(label) {
Some((_, ty)) => {
if let Some(ty) = ty {
arg.value = arg
.value
.coerce(
&RuntimeType::from_parsed(ty.clone(), exec_state, arg.source_range).map_err(|e| KclError::new_semantic(e.into()))?,
true,
exec_state,
)
.map_err(|e| {
let mut message = format!(
"{label} requires a value with type `{}`, but found {}",
ty,
arg.value.human_friendly_type(),
);
if let Some(ty) = e.explicit_coercion {
// TODO if we have access to the AST for the argument we could choose which example to suggest.
message = format!("{message}\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`");
}
KclError::new_semantic(KclErrorDetails::new(
message,
vec![arg.source_range],
))
})?;
Some((def, ty)) => {
// For optional args, passing None should be the same as not passing an arg.
if !(def.is_some() && matches!(arg.value, KclValue::KclNone { .. })) {
if let Some(ty) = ty {
arg.value = arg
.value
.coerce(
&RuntimeType::from_parsed(ty.clone(), exec_state, arg.source_range).map_err(|e| KclError::new_semantic(e.into()))?,
true,
exec_state,
)
.map_err(|e| {
let mut message = format!(
"{label} requires a value with type `{}`, but found {}",
ty,
arg.value.human_friendly_type(),
);
if let Some(ty) = e.explicit_coercion {
// TODO if we have access to the AST for the argument we could choose which example to suggest.
message = format!("{message}\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`");
}
KclError::new_semantic(KclErrorDetails::new(
message,
vec![arg.source_range],
))
})?;
}
}
}
None => {
@ -706,7 +656,7 @@ fn type_check_params_kw(
exec_state.err(CompilationError::err(
arg.source_range,
format!(
"{} expects an unlabeled first parameter (`@{name}`), but it is labelled in the call",
"{} expects an unlabeled first argument (`@{name}`), but it is labelled in the call",
fn_name
.map(|n| format!("The function `{}`", n))
.unwrap_or_else(|| "This function".to_owned()),
@ -940,7 +890,6 @@ mod test {
crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
)),
fs: Arc::new(crate::fs::FileManager::new()),
stdlib: Arc::new(crate::std::StdLib::new()),
settings: Default::default(),
context_type: ContextType::Mock,
};

View File

@ -41,7 +41,6 @@ use crate::{
modules::{ModuleId, ModulePath, ModuleRepr},
parsing::ast::types::{Expr, ImportPath, NodeRef},
source_range::SourceRange,
std::StdLib,
walk::{Universe, UniverseMap},
CompilationError, ExecError, KclErrorWithOutputs,
};
@ -273,7 +272,6 @@ pub enum ContextType {
pub struct ExecutorContext {
pub engine: Arc<Box<dyn EngineManager>>,
pub fs: Arc<FileManager>,
pub stdlib: Arc<StdLib>,
pub settings: ExecutorSettings,
pub context_type: ContextType,
}
@ -412,7 +410,6 @@ impl ExecutorContext {
Ok(Self {
engine,
fs: Arc::new(FileManager::new()),
stdlib: Arc::new(StdLib::new()),
settings,
context_type: ContextType::Live,
})
@ -423,7 +420,6 @@ impl ExecutorContext {
ExecutorContext {
engine,
fs,
stdlib: Arc::new(StdLib::new()),
settings,
context_type: ContextType::Live,
}
@ -436,7 +432,6 @@ impl ExecutorContext {
crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
)),
fs: Arc::new(FileManager::new()),
stdlib: Arc::new(StdLib::new()),
settings: settings.unwrap_or_default(),
context_type: ContextType::Mock,
}
@ -447,7 +442,6 @@ impl ExecutorContext {
ExecutorContext {
engine,
fs,
stdlib: Arc::new(StdLib::new()),
settings,
context_type: ContextType::Mock,
}
@ -458,7 +452,6 @@ impl ExecutorContext {
ExecutorContext {
engine,
fs: Arc::new(FileManager::new()),
stdlib: Arc::new(StdLib::new()),
settings: Default::default(),
context_type: ContextType::MockCustomForwarded,
}
@ -1390,7 +1383,6 @@ pub(crate) async fn parse_execute_with_project_dir(
})?,
)),
fs: Arc::new(crate::fs::FileManager::new()),
stdlib: Arc::new(crate::std::StdLib::new()),
settings: ExecutorSettings {
project_directory,
..Default::default()

View File

@ -175,11 +175,10 @@ impl Backend {
zoo_client: kittycad::Client,
can_send_telemetry: bool,
) -> Result<Self, String> {
let stdlib = crate::std::StdLib::new();
let kcl_std = crate::docs::kcl_doc::walk_prelude();
let stdlib_completions = get_completions_from_stdlib(&stdlib, &kcl_std).map_err(|e| e.to_string())?;
let stdlib_signatures = get_signatures_from_stdlib(&stdlib, &kcl_std);
let stdlib_args = get_arg_maps_from_stdlib(&stdlib, &kcl_std);
let stdlib_completions = get_completions_from_stdlib(&kcl_std).map_err(|e| e.to_string())?;
let stdlib_signatures = get_signatures_from_stdlib(&kcl_std);
let stdlib_args = get_arg_maps_from_stdlib(&kcl_std);
Ok(Self {
client,
@ -1634,16 +1633,8 @@ impl LanguageServer for Backend {
}
/// Get completions from our stdlib.
pub fn get_completions_from_stdlib(
stdlib: &crate::std::StdLib,
kcl_std: &ModData,
) -> Result<HashMap<String, CompletionItem>> {
pub fn get_completions_from_stdlib(kcl_std: &ModData) -> Result<HashMap<String, CompletionItem>> {
let mut completions = HashMap::new();
let combined = stdlib.combined();
for internal_fn in combined.values() {
completions.insert(internal_fn.name(), internal_fn.to_completion_item()?);
}
for d in kcl_std.all_docs() {
if let Some(ci) = d.to_completion_item() {
@ -1660,13 +1651,8 @@ pub fn get_completions_from_stdlib(
}
/// Get signatures from our stdlib.
pub fn get_signatures_from_stdlib(stdlib: &crate::std::StdLib, kcl_std: &ModData) -> HashMap<String, SignatureHelp> {
pub fn get_signatures_from_stdlib(kcl_std: &ModData) -> HashMap<String, SignatureHelp> {
let mut signatures = HashMap::new();
let combined = stdlib.combined();
for internal_fn in combined.values() {
signatures.insert(internal_fn.name(), internal_fn.to_signature_help());
}
for d in kcl_std.all_docs() {
if let Some(sig) = d.to_signature_help() {
@ -1678,44 +1664,32 @@ pub fn get_signatures_from_stdlib(stdlib: &crate::std::StdLib, kcl_std: &ModData
}
/// Get signatures from our stdlib.
pub fn get_arg_maps_from_stdlib(
stdlib: &crate::std::StdLib,
kcl_std: &ModData,
) -> HashMap<String, HashMap<String, String>> {
pub fn get_arg_maps_from_stdlib(kcl_std: &ModData) -> HashMap<String, HashMap<String, String>> {
let mut result = HashMap::new();
let combined = stdlib.combined();
for internal_fn in combined.values() {
let arg_map: HashMap<String, String> = internal_fn
.args(false)
.into_iter()
for d in kcl_std.all_docs() {
let crate::docs::kcl_doc::DocData::Fn(f) = d else {
continue;
};
let arg_map: HashMap<String, String> = f
.args
.iter()
.map(|data| {
let mut tip = "```\n".to_owned();
tip.push_str(&data.name.clone());
if !data.required {
tip.push('?');
}
if !data.type_.is_empty() {
tip.push_str(": ");
tip.push_str(&data.type_);
}
tip.push_str(&data.to_string());
tip.push_str("\n```");
if !data.description.is_empty() {
if let Some(docs) = &data.docs {
tip.push_str("\n\n");
tip.push_str(&data.description);
tip.push_str(docs);
}
(data.name, tip)
(data.name.clone(), tip)
})
.collect();
if !arg_map.is_empty() {
result.insert(internal_fn.name(), arg_map);
result.insert(f.name.clone(), arg_map);
}
}
for _d in kcl_std.all_docs() {
// TODO add KCL std fns
}
result
}

View File

@ -5,11 +5,10 @@ use tower_lsp::LanguageServer;
// Create a fake kcl lsp server for testing.
pub async fn kcl_lsp_server(execute: bool) -> Result<crate::lsp::kcl::Backend> {
let stdlib = crate::std::StdLib::new();
let kcl_std = crate::docs::kcl_doc::walk_prelude();
let stdlib_completions = crate::lsp::kcl::get_completions_from_stdlib(&stdlib, &kcl_std)?;
let stdlib_signatures = crate::lsp::kcl::get_signatures_from_stdlib(&stdlib, &kcl_std);
let stdlib_args = crate::lsp::kcl::get_arg_maps_from_stdlib(&stdlib, &kcl_std);
let stdlib_completions = crate::lsp::kcl::get_completions_from_stdlib(&kcl_std)?;
let stdlib_signatures = crate::lsp::kcl::get_signatures_from_stdlib(&kcl_std);
let stdlib_args = crate::lsp::kcl::get_arg_maps_from_stdlib(&kcl_std);
let zoo_client = crate::engine::new_zoo_client(None, None)?;

View File

@ -928,7 +928,7 @@ startSketchOn(XY)
match hover.unwrap().contents {
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
assert!(value.contains("startSketchOn"));
assert!(value.contains(": SketchSurface"));
assert!(value.contains(": Plane | Face"));
assert!(value.contains("Start a new 2-dimensional sketch on a specific"));
}
_ => unreachable!(),
@ -1113,13 +1113,7 @@ async fn test_kcl_lsp_signature_help() {
"Expected one signature, got {:?}",
signature_help.signatures
);
assert_eq!(
signature_help.signatures[0].label,
r#"startSketchOn(
@planeOrSolid: SketchData,
face?: FaceTag,
): SketchSurface"#
);
assert!(signature_help.signatures[0].label.starts_with("startSketchOn"));
} else {
panic!("Expected signature help");
}
@ -3884,7 +3878,7 @@ startSketchOn(XY)
match hover.unwrap().contents {
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
assert!(value.contains("startSketchOn"));
assert!(value.contains(": SketchSurface"));
assert!(value.contains(": Plane | Face"));
assert!(value.contains("Start a new 2-dimensional sketch on a specific"));
}
_ => unreachable!(),

View File

@ -25,7 +25,6 @@ pub use crate::parsing::ast::types::{
none::KclNone,
};
use crate::{
docs::StdLibFn,
errors::KclError,
execution::{
annotations,
@ -1973,31 +1972,6 @@ impl CallExpressionKw {
}
}
/// A function declaration.
#[derive(Debug, Clone, Default, Serialize, Deserialize, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum Function {
/// A stdlib function written in Rust (aka core lib).
StdLib {
/// The function.
func: Box<dyn StdLibFn>,
},
/// A function that is defined in memory.
#[default]
InMemory,
}
impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Function::StdLib { func: func1 }, Function::StdLib { func: func2 }) => func1.name() == func2.name(),
(Function::InMemory, Function::InMemory) => true,
_ => false,
}
}
}
#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
#[ts(export)]
#[serde(rename_all = "snake_case")]

View File

@ -2480,32 +2480,13 @@ impl TryFrom<Token> for Node<TagDeclarator> {
}
}
impl Node<TagDeclarator> {
fn into_valid_binding_name(self) -> Result<Self, CompilationError> {
// Make sure they are not assigning a variable to a stdlib function.
if crate::std::name_in_stdlib(&self.name) {
return Err(CompilationError::fatal(
SourceRange::from(&self),
format!("Cannot assign a tag to a reserved keyword: {}", self.name),
));
}
Ok(self)
}
}
/// Parse a Kcl tag that starts with a `$`.
fn tag(i: &mut TokenSlice) -> ModalResult<Node<TagDeclarator>> {
dollar.parse_next(i)?;
let tag_declarator = any
.try_map(Node::<TagDeclarator>::try_from)
any.try_map(Node::<TagDeclarator>::try_from)
.context(expected("a tag, e.g. '$seg01' or '$line01'"))
.parse_next(i)
.map_err(|e: ErrMode<ContextError>| e.cut())?;
// Now that we've parsed a tag declarator, verify that it's not a stdlib
// name. If it is, stop backtracking.
tag_declarator
.into_valid_binding_name()
.map_err(|e| ErrMode::Cut(ContextError::from(e)))
.map_err(|e: ErrMode<ContextError>| e.cut())
}
/// Helper function. Matches any number of whitespace tokens and ignores them.
@ -4898,19 +4879,6 @@ let myBox = box(p=[0,0], h=-3, l=-16, w=-10)
}
}
#[test]
fn test_parse_tag_named_std_lib() {
let some_program_string = r#"startSketchOn(XY)
|> startProfile(at = [0, 0])
|> line(%, end = [5, 5], tag = $xLine)
"#;
assert_err(
some_program_string,
"Cannot assign a tag to a reserved keyword: xLine",
[86, 92],
);
}
#[test]
fn test_parse_empty_tag_brace() {
let some_program_string = r#"startSketchOn(XY)

View File

@ -143,9 +143,14 @@ impl Args {
where
T: for<'a> FromKclValue<'a>,
{
if self.kw_args.labeled.get(label).is_none() {
return Ok(None);
};
match self.kw_args.labeled.get(label) {
None => return Ok(None),
Some(a) => {
if let KclValue::KclNone { .. } = &a.value {
return Ok(None);
}
}
}
self.get_kw_arg_typed(label, ty, exec_state).map(Some)
}
@ -174,7 +179,7 @@ impl Args {
{
let Some(arg) = self.kw_args.labeled.get(label) else {
return Err(KclError::new_semantic(KclErrorDetails::new(
format!("This function requires a keyword argument '{label}'"),
format!("This function requires a keyword argument `{label}`"),
vec![self.source_range],
)));
};
@ -186,7 +191,7 @@ impl Args {
.map(|t| t.to_string())
.unwrap_or_else(|| arg.value.human_friendly_type().to_owned());
let msg_base = format!(
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
"This function expected its `{label}` argument to be {} but it's actually of type {actual_type_name}",
ty.human_friendly_type(),
);
let suggestion = match (ty, actual_type) {

View File

@ -28,14 +28,10 @@ pub mod utils;
use anyhow::Result;
pub use args::Args;
use indexmap::IndexMap;
use lazy_static::lazy_static;
use crate::{
docs::StdLibFn,
errors::KclError,
execution::{types::PrimitiveType, ExecState, KclValue},
parsing::ast::types::Name,
};
pub type StdFn = fn(
@ -43,35 +39,6 @@ pub type StdFn = fn(
Args,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<KclValue, KclError>> + Send + '_>>;
lazy_static! {
static ref CORE_FNS: Vec<Box<dyn StdLibFn>> = vec![
Box::new(crate::std::sketch::InvoluteCircular),
Box::new(crate::std::sketch::Line),
Box::new(crate::std::sketch::XLine),
Box::new(crate::std::sketch::YLine),
Box::new(crate::std::sketch::AngledLine),
Box::new(crate::std::sketch::AngledLineThatIntersects),
Box::new(crate::std::sketch::StartSketchOn),
Box::new(crate::std::sketch::StartProfile),
Box::new(crate::std::sketch::ProfileStartX),
Box::new(crate::std::sketch::ProfileStartY),
Box::new(crate::std::sketch::ProfileStart),
Box::new(crate::std::sketch::Close),
Box::new(crate::std::sketch::Arc),
Box::new(crate::std::sketch::TangentialArc),
Box::new(crate::std::sketch::BezierCurve),
Box::new(crate::std::sketch::Subtract2D),
];
}
pub fn name_in_stdlib(name: &str) -> bool {
CORE_FNS.iter().any(|f| f.name() == name)
}
pub fn get_stdlib_fn(name: &str) -> Option<Box<dyn StdLibFn>> {
CORE_FNS.iter().find(|f| f.name() == name).cloned()
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StdFnProps {
pub name: String,
@ -385,6 +352,70 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|e, a| Box::pin(crate::std::segment::tangent_to_end(e, a)),
StdFnProps::default("std::sketch::tangentToEnd"),
),
("sketch", "profileStart") => (
|e, a| Box::pin(crate::std::sketch::profile_start(e, a)),
StdFnProps::default("std::sketch::profileStart"),
),
("sketch", "profileStartX") => (
|e, a| Box::pin(crate::std::sketch::profile_start_x(e, a)),
StdFnProps::default("std::sketch::profileStartX"),
),
("sketch", "profileStartY") => (
|e, a| Box::pin(crate::std::sketch::profile_start_y(e, a)),
StdFnProps::default("std::sketch::profileStartY"),
),
("sketch", "startSketchOn") => (
|e, a| Box::pin(crate::std::sketch::start_sketch_on(e, a)),
StdFnProps::default("std::sketch::startSketchOn").include_in_feature_tree(),
),
("sketch", "startProfile") => (
|e, a| Box::pin(crate::std::sketch::start_profile(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "involuteCircular") => (
|e, a| Box::pin(crate::std::sketch::involute_circular(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "line") => (
|e, a| Box::pin(crate::std::sketch::line(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "xLine") => (
|e, a| Box::pin(crate::std::sketch::x_line(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "yLine") => (
|e, a| Box::pin(crate::std::sketch::y_line(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "angledLine") => (
|e, a| Box::pin(crate::std::sketch::angled_line(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "angledLineThatIntersects") => (
|e, a| Box::pin(crate::std::sketch::angled_line_that_intersects(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "close") => (
|e, a| Box::pin(crate::std::sketch::close(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "arc") => (
|e, a| Box::pin(crate::std::sketch::arc(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "tangentialArc") => (
|e, a| Box::pin(crate::std::sketch::tangential_arc(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "bezierCurve") => (
|e, a| Box::pin(crate::std::sketch::bezier_curve(e, a)),
StdFnProps::default("std::sketch::startProfile"),
),
("sketch", "subtract2d") => (
|e, a| Box::pin(crate::std::sketch::subtract_2d(e, a)),
StdFnProps::default("std::sketch::startProfile").include_in_feature_tree(),
),
("appearance", "hexString") => (
|e, a| Box::pin(crate::std::appearance::hex_string(e, a)),
StdFnProps::default("std::appearance::hexString"),
@ -409,56 +440,5 @@ pub(crate) fn std_ty(path: &str, fn_name: &str) -> (PrimitiveType, StdFnProps) {
}
}
pub struct StdLib {
pub fns: IndexMap<String, Box<dyn StdLibFn>>,
}
impl std::fmt::Debug for StdLib {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StdLib").field("fns.len()", &self.fns.len()).finish()
}
}
impl StdLib {
pub fn new() -> Self {
let fns = CORE_FNS
.clone()
.into_iter()
.map(|internal_fn| (internal_fn.name(), internal_fn))
.collect();
Self { fns }
}
// Get the combined hashmaps.
pub fn combined(&self) -> IndexMap<String, Box<dyn StdLibFn>> {
self.fns.clone()
}
pub fn get(&self, name: &str) -> Option<Box<dyn StdLibFn>> {
self.fns.get(name).cloned()
}
pub fn get_rust_function(&self, name: &Name) -> Option<Box<dyn StdLibFn>> {
if let Some(name) = name.local_ident() {
if let Some(f) = self.get(name.inner) {
return Some(f);
}
}
None
}
pub fn contains_key(&self, key: &str) -> bool {
self.fns.contains_key(key)
}
}
impl Default for StdLib {
fn default() -> Self {
Self::new()
}
}
/// The default tolerance for modeling commands in [`kittycad_modeling_cmds::length_unit::LengthUnit`].
const DEFAULT_TOLERANCE: f64 = 0.0000001;

View File

@ -2,7 +2,6 @@
use anyhow::Result;
use indexmap::IndexMap;
use kcl_derive_docs::stdlib;
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
use kcmc::shared::Point3d as KPoint3d; // Point3d is already defined in this pkg, to impl ts_rs traits.
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, websocket::ModelingCmdReq, ModelingCmd};
@ -100,8 +99,7 @@ pub enum StartOrEnd {
pub const NEW_TAG_KW: &str = "tag";
pub async fn involute_circular(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch =
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
let start_radius: TyF64 = args.get_kw_arg_typed("startRadius", &RuntimeType::length(), exec_state)?;
let end_radius: TyF64 = args.get_kw_arg_typed("endRadius", &RuntimeType::length(), exec_state)?;
@ -122,29 +120,6 @@ fn involute_curve(radius: f64, angle: f64) -> (f64, f64) {
)
}
/// Extend the current sketch with a new involute circular curve.
///
/// ```no_run
/// a = 10
/// b = 14
/// startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> involuteCircular(startRadius = a, endRadius = b, angle = 60)
/// |> involuteCircular(startRadius = a, endRadius = b, angle = 60, reverse = true)
/// ```
#[stdlib {
name = "involuteCircular",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
start_radius = { docs = "The involute is described between two circles, start_radius is the radius of the inner circle."},
end_radius = { docs = "The involute is described between two circles, end_radius is the radius of the outer circle."},
angle = { docs = "The angle to rotate the involute by. A value of zero will produce a curve with a tangent along the x-axis at the start point of the curve."},
reverse = { docs = "If reverse is true, the segment will start from the end of the involute, otherwise it will start from that start. Defaults to false."},
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_involute_circular(
sketch: Sketch,
@ -228,41 +203,6 @@ pub async fn line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
})
}
/// Extend the current sketch with a new straight line.
///
/// ```no_run
/// triangle = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// // The END argument means it ends at exactly [10, 0].
/// // This is an absolute measurement, it is NOT relative to
/// // the start of the sketch.
/// |> line(endAbsolute = [10, 0])
/// |> line(endAbsolute = [0, 10])
/// |> line(endAbsolute = [-10, 0], tag = $thirdLineOfTriangle)
/// |> close()
/// |> extrude(length = 5)
///
/// box = startSketchOn(XZ)
/// |> startProfile(at = [10, 10])
/// // The 'to' argument means move the pen this much.
/// // So, [10, 0] is a relative distance away from the current point.
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0], tag = $thirdLineOfBox)
/// |> close()
/// |> extrude(length = 5)
/// ```
#[stdlib {
name = "line",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
end_absolute = { docs = "Which absolute point should this line go to? Incompatible with `end`."},
end = { docs = "How far away (along the X and Y axes) should this line go? Incompatible with `endAbsolute`.", include_in_snippet = true},
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
async fn inner_line(
sketch: Sketch,
end_absolute: Option<[TyF64; 2]>,
@ -401,39 +341,6 @@ pub async fn x_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
})
}
/// Draw a line relative to the current origin to a specified distance away
/// from the current position along the 'x' axis.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> xLine(length = 15)
/// |> angledLine(
/// angle = 80,
/// length = 15,
/// )
/// |> line(end = [8, -10])
/// |> xLine(length = 10)
/// |> angledLine(
/// angle = 120,
/// length = 30,
/// )
/// |> xLine(length = -15)
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "xLine",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
length = { docs = "How far away along the X axis should this line go? Incompatible with `endAbsolute`.", include_in_snippet = true},
end_absolute = { docs = "Which absolute X value should this line go to? Incompatible with `length`."},
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
async fn inner_x_line(
sketch: Sketch,
length: Option<TyF64>,
@ -471,34 +378,6 @@ pub async fn y_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
})
}
/// Draw a line relative to the current origin to a specified distance away
/// from the current position along the 'y' axis.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> yLine(length = 15)
/// |> angledLine(
/// angle = 30,
/// length = 15,
/// )
/// |> line(end = [8, -10])
/// |> yLine(length = -5)
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "yLine",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
length = { docs = "How far away along the Y axis should this line go? Incompatible with `endAbsolute`.", include_in_snippet = true},
end_absolute = { docs = "Which absolute Y value should this line go to? Incompatible with `length`."},
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
async fn inner_y_line(
sketch: Sketch,
length: Option<TyF64>,
@ -553,38 +432,6 @@ pub async fn angled_line(exec_state: &mut ExecState, args: Args) -> Result<KclVa
})
}
/// Draw a line segment relative to the current origin using the polar
/// measure of some angle and distance.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> yLine(endAbsolute = 15)
/// |> angledLine(
/// angle = 30,
/// length = 15,
/// )
/// |> line(end = [8, -10])
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "angledLine",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
angle = { docs = "Which angle should the line be drawn at?" },
length = { docs = "Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
length_x = { docs = "Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
length_y = { docs = "Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
end_absolute_x = { docs = "Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
end_absolute_y = { docs = "Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_angled_line(
sketch: Sketch,
@ -850,37 +697,6 @@ pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args)
})
}
/// Draw an angled line from the current origin, constructing a line segment
/// such that the newly created line intersects the desired target line
/// segment.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(endAbsolute = [5, 10])
/// |> line(endAbsolute = [-10, 10], tag = $lineToIntersect)
/// |> line(endAbsolute = [0, 20])
/// |> angledLineThatIntersects(
/// angle = 80,
/// intersectTag = lineToIntersect,
/// offset = 10,
/// )
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "angledLineThatIntersects",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
angle = { docs = "Which angle should the line be drawn at?" },
intersect_tag = { docs = "The tag of the line to intersect with" },
offset = { docs = "The offset from the intersecting line. Defaults to 0." },
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
pub async fn inner_angled_line_that_intersects(
sketch: Sketch,
angle: TyF64,
@ -971,190 +787,6 @@ pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<K
}
}
/// Start a new 2-dimensional sketch on a specific plane or face.
///
/// ### Sketch on Face Behavior
///
/// There are some important behaviors to understand when sketching on a face:
///
/// The resulting sketch will _include_ the face and thus Solid
/// that was sketched on. So say you were to export the resulting Sketch / Solid
/// from a sketch on a face, you would get both the artifact of the sketch
/// on the face and the parent face / Solid itself.
///
/// This is important to understand because if you were to then sketch on the
/// resulting Solid, it would again include the face and parent Solid that was
/// sketched on. This could go on indefinitely.
///
/// The point is if you want to export the result of a sketch on a face, you
/// only need to export the final Solid that was created from the sketch on the
/// face, since it will include all the parent faces and Solids.
///
///
/// ```no_run
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
///
/// exampleSketch002 = startSketchOn(example, face = END)
/// |> startProfile(at = [1, 1])
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5)
///
/// exampleSketch003 = startSketchOn(example002, face = END)
/// |> startProfile(at = [2, 2])
/// |> line(end = [6, 0])
/// |> line(end = [0, 6])
/// |> line(end = [-6, 0])
/// |> close()
///
/// example003 = extrude(exampleSketch003, length = 5)
/// ```
///
/// ```no_run
/// // Sketch on the end of an extruded face by tagging the end face.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5, tagEnd = $end01)
///
/// exampleSketch002 = startSketchOn(example, face = end01)
/// |> startProfile(at = [1, 1])
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5, tagEnd = $end02)
///
/// exampleSketch003 = startSketchOn(example002, face = end02)
/// |> startProfile(at = [2, 2])
/// |> line(end = [6, 0])
/// |> line(end = [0, 6])
/// |> line(end = [-6, 0])
/// |> close()
///
/// example003 = extrude(exampleSketch003, length = 5)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10], tag = $sketchingFace)
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
///
/// exampleSketch002 = startSketchOn(example, face = sketchingFace)
/// |> startProfile(at = [1, 1])
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close(tag = $sketchingFace002)
///
/// example002 = extrude(exampleSketch002, length = 10)
///
/// exampleSketch003 = startSketchOn(example002, face = sketchingFace002)
/// |> startProfile(at = [-8, 12])
/// |> line(end = [0, 6])
/// |> line(end = [6, 0])
/// |> line(end = [0, -6])
/// |> close()
///
/// example003 = extrude(exampleSketch003, length = 5)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
/// |> line(end = [0, -6])
/// |> line(end = [4, -6])
/// |> line(end = [0, -6])
/// |> line(end = [-3.75, -4.5])
/// |> line(end = [0, -5.5])
/// |> line(end = [-2, 0])
/// |> close()
///
/// example = revolve(exampleSketch, axis = Y, angle = 180)
///
/// exampleSketch002 = startSketchOn(example, face = END)
/// |> startProfile(at = [4.5, -5])
/// |> line(end = [0, 5])
/// |> line(end = [5, 0])
/// |> line(end = [0, -5])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5)
/// ```
///
/// ```no_run
/// // Sketch on the end of a revolved face by tagging the end face.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
/// |> line(end = [0, -6])
/// |> line(end = [4, -6])
/// |> line(end = [0, -6])
/// |> line(end = [-3.75, -4.5])
/// |> line(end = [0, -5.5])
/// |> line(end = [-2, 0])
/// |> close()
///
/// example = revolve(exampleSketch, axis = Y, angle = 180, tagEnd = $end01)
///
/// exampleSketch002 = startSketchOn(example, face = end01)
/// |> startProfile(at = [4.5, -5])
/// |> line(end = [0, 5])
/// |> line(end = [5, 0])
/// |> line(end = [0, -5])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5)
/// ```
///
/// ```no_run
/// a1 = startSketchOn({
/// origin = { x = 0, y = 0, z = 0 },
/// xAxis = { x = 1, y = 0, z = 0 },
/// yAxis = { x = 0, y = 1, z = 0 },
/// zAxis = { x = 0, y = 0, z = 1 }
/// })
/// |> startProfile(at = [0, 0])
/// |> line(end = [100.0, 0])
/// |> yLine(length = -100.0)
/// |> xLine(length = -100.0)
/// |> yLine(length = 100.0)
/// |> close()
/// |> extrude(length = 3.14)
/// ```
#[stdlib {
name = "startSketchOn",
feature_tree_operation = true,
unlabeled_first = true,
args = {
plane_or_solid = { docs = "The plane or solid to sketch on"},
face = { docs = "Identify a face of a solid if a solid is specified as the input argument (`plane_or_solid`)"},
},
tags = ["sketch"]
}]
async fn inner_start_sketch_on(
plane_or_solid: SketchData,
face: Option<FaceTag>,
@ -1280,50 +912,6 @@ pub async fn start_profile(exec_state: &mut ExecState, args: Args) -> Result<Kcl
})
}
/// Start a new profile at a given point.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(-XZ)
/// |> startProfile(at = [10, 10])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(-XZ)
/// |> startProfile(at = [-10, 23])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
#[stdlib {
name = "startProfile",
unlabeled_first = true,
args = {
sketch_surface = { docs = "What to start the profile on" },
at = { docs = "Where to start the profile. An absolute point.", snippet_value_array = ["0", "0"] },
tag = { docs = "Tag this first starting point" },
},
tags = ["sketch"]
}]
pub(crate) async fn inner_start_profile(
sketch_surface: SketchSurface,
at: [TyF64; 2],
@ -1440,91 +1028,36 @@ pub(crate) async fn inner_start_profile(
/// Returns the X component of the sketch profile start point.
pub async fn profile_start_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("profile", &RuntimeType::sketch(), exec_state)?;
let ty = sketch.units.into();
let x = inner_profile_start_x(sketch)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(x, ty)))
}
/// Extract the provided 2-dimensional sketch's profile's origin's 'x'
/// value.
///
/// ```no_run
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [5, 2])
/// |> angledLine(angle = -26.6, length = 50)
/// |> angledLine(angle = 90, length = 50)
/// |> angledLine(angle = 30, endAbsoluteX = profileStartX(%))
/// ```
#[stdlib {
name = "profileStartX",
unlabeled_first = true,
args = {
profile = {docs = "Profile whose start is being used"},
},
tags = ["sketch"]
}]
pub(crate) fn inner_profile_start_x(profile: Sketch) -> Result<f64, KclError> {
Ok(profile.start.to[0])
}
/// Returns the Y component of the sketch profile start point.
pub async fn profile_start_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("profile", &RuntimeType::sketch(), exec_state)?;
let ty = sketch.units.into();
let x = inner_profile_start_y(sketch)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(x, ty)))
}
/// Extract the provided 2-dimensional sketch's profile's origin's 'y'
/// value.
///
/// ```no_run
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [5, 2])
/// |> angledLine(angle = -60, length = 14 )
/// |> angledLine(angle = 30, endAbsoluteY = profileStartY(%))
/// ```
#[stdlib {
name = "profileStartY",
unlabeled_first = true,
args = {
profile = {docs = "Profile whose start is being used"},
},
tags = ["sketch"]
}]
pub(crate) fn inner_profile_start_y(profile: Sketch) -> Result<f64, KclError> {
Ok(profile.start.to[1])
}
/// Returns the sketch profile start point.
pub async fn profile_start(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("profile", &RuntimeType::sketch(), exec_state)?;
let ty = sketch.units.into();
let point = inner_profile_start(sketch)?;
Ok(KclValue::from_point2d(point, ty, args.into()))
}
/// Extract the provided 2-dimensional sketch's profile's origin
/// value.
///
/// ```no_run
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [5, 2])
/// |> angledLine(angle = 120, length = 50 , tag = $seg01)
/// |> angledLine(angle = segAng(seg01) + 120, length = 50 )
/// |> line(end = profileStart(%))
/// |> close()
/// |> extrude(length = 20)
/// ```
#[stdlib {
name = "profileStart",
unlabeled_first = true,
args = {
profile = {docs = "Profile whose start is being used"},
},
tags = ["sketch"]
}]
pub(crate) fn inner_profile_start(profile: Sketch) -> Result<[f64; 2], KclError> {
Ok(profile.start.to)
}
@ -1540,41 +1073,6 @@ pub async fn close(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
})
}
/// Construct a line segment from the current origin back to the profile's
/// origin, ensuring the resulting 2-dimensional sketch is not open-ended.
///
/// If you want to perform some 3-dimensional operation on a sketch, like
/// extrude or sweep, you must `close` it first. `close` must be called even
/// if the end point of the last segment is coincident with the sketch
/// starting point.
///
/// ```no_run
/// startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 10])
/// |> line(end = [10, 0])
/// |> close()
/// |> extrude(length = 10)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(-XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "close",
unlabeled_first = true,
args = {
sketch = { docs = "The sketch you want to close"},
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
pub(crate) async fn inner_close(
sketch: Sketch,
tag: Option<TagNode>,
@ -1644,54 +1142,6 @@ pub async fn arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
})
}
/// Draw a curved line segment along an imaginary circle.
///
/// The arc is constructed such that the current position of the sketch is
/// placed along an imaginary circle of the specified radius, at angleStart
/// degrees. The resulting arc is the segment of the imaginary circle from
/// that origin point to angleEnd, radius away from the center of the imaginary
/// circle.
///
/// Unless this makes a lot of sense and feels like what you're looking
/// for to construct your shape, you're likely looking for tangentialArc.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> arc(
/// angleStart = 0,
/// angleEnd = 280,
/// radius = 16
/// )
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> arc(
/// endAbsolute = [10,0],
/// interiorAbsolute = [5,5]
/// )
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "arc",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?" },
angle_start = { docs = "Where along the circle should this arc start?", include_in_snippet = true },
angle_end = { docs = "Where along the circle should this arc end?", include_in_snippet = true },
radius = { docs = "How large should the circle be? Incompatible with `diameter`." },
diameter = { docs = "How large should the circle be? Incompatible with `radius`.", include_in_snippet = true },
interior_absolute = { docs = "Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`" },
end_absolute = { docs = "Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd`" },
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
pub(crate) async fn inner_arc(
sketch: Sketch,
@ -1880,74 +1330,6 @@ pub async fn tangential_arc(exec_state: &mut ExecState, args: Args) -> Result<Kc
})
}
/// Starting at the current sketch's origin, draw a curved line segment along
/// some part of an imaginary circle until it reaches the desired (x, y)
/// coordinates.
///
/// When using radius and angle, draw a curved line segment along part of an
/// imaginary circle. The arc is constructed such that the last line segment is
/// placed tangent to the imaginary circle of the specified radius. The
/// resulting arc is the segment of the imaginary circle from that tangent point
/// for 'angle' degrees along the imaginary circle.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 45,
/// length = 10,
/// )
/// |> tangentialArc(end = [0, -10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 60,
/// length = 10,
/// )
/// |> tangentialArc(endAbsolute = [15, 15])
/// |> line(end = [10, -15])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 60,
/// length = 10,
/// )
/// |> tangentialArc(radius = 10, angle = -120)
/// |> angledLine(
/// angle = -60,
/// length = 10,
/// )
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "tangentialArc",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
end_absolute = { docs = "Which absolute point should this arc go to? Incompatible with `end`, `radius`, and `offset`."},
end = { docs = "How far away (along the X and Y axes) should this arc go? Incompatible with `endAbsolute`, `radius`, and `offset`.", include_in_snippet = true },
radius = { docs = "Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `diameter`."},
diameter = { docs = "Diameter of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `radius`."},
angle = { docs = "Offset of the arc in degrees. `radius` must be given. Incompatible with `end` and `endAbsolute`."},
tag = { docs = "Create a new tag which refers to this arc"},
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_tangential_arc(
sketch: Sketch,
@ -2206,48 +1588,6 @@ pub async fn bezier_curve(exec_state: &mut ExecState, args: Args) -> Result<KclV
})
}
/// Draw a smooth, continuous, curved line segment from the current origin to
/// the desired (x, y), using a number of control points to shape the curve's
/// shape.
///
/// ```no_run
/// // Example using relative control points.
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 10])
/// |> bezierCurve(
/// control1 = [5, 0],
/// control2 = [5, 10],
/// end = [10, 10],
/// )
/// |> line(endAbsolute = [10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
/// ```no_run
/// // Example using absolute control points.
/// startSketchOn(XY)
/// |> startProfile(at = [300, 300])
/// |> bezierCurve(control1Absolute = [600, 300], control2Absolute = [-300, -100], endAbsolute = [600, 600])
/// |> close()
/// |> extrude(length = 10)
/// ```
#[stdlib {
name = "bezierCurve",
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
control1 = { docs = "First control point for the cubic" },
control2 = { docs = "Second control point for the cubic" },
end = { docs = "How far away (along the X and Y axes) should this line go?" },
control1_absolute = { docs = "First control point for the cubic. Absolute point." },
control2_absolute = { docs = "Second control point for the cubic. Absolute point." },
end_absolute = { docs = "Coordinate on the plane at which this line should end." },
tag = { docs = "Create a new tag which refers to this line"},
},
tags = ["sketch"]
}]
#[allow(clippy::too_many_arguments)]
async fn inner_bezier_curve(
sketch: Sketch,
@ -2364,47 +1704,6 @@ pub async fn subtract_2d(exec_state: &mut ExecState, args: Args) -> Result<KclVa
})
}
/// Use a 2-dimensional sketch to cut a hole in another 2-dimensional sketch.
///
/// ```no_run
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 5])
/// |> line(end = [5, 0])
/// |> line(end = [0, -5])
/// |> close()
/// |> subtract2d(tool =circle( center = [1, 1], radius = .25 ))
/// |> subtract2d(tool =circle( center = [1, 4], radius = .25 ))
///
/// example = extrude(exampleSketch, length = 1)
/// ```
///
/// ```no_run
/// fn squareHoleSketch() {
/// squareSketch = startSketchOn(-XZ)
/// |> startProfile(at = [-1, -1])
/// |> line(end = [2, 0])
/// |> line(end = [0, 2])
/// |> line(end = [-2, 0])
/// |> close()
/// return squareSketch
/// }
///
/// exampleSketch = startSketchOn(-XZ)
/// |> circle( center = [0, 0], radius = 3 )
/// |> subtract2d(tool = squareHoleSketch())
/// example = extrude(exampleSketch, length = 1)
/// ```
#[stdlib {
name = "subtract2d",
feature_tree_operation = true,
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?" },
tool = { docs = "The shape(s) which should be cut out of the sketch." },
},
tags = ["sketch"]
}]
async fn inner_subtract_2d(
sketch: Sketch,
tool: Vec<Sketch>,

View File

@ -7,6 +7,233 @@
@no_std
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
/// Start a new 2-dimensional sketch on a specific plane or face.
///
/// ### Sketch on Face Behavior
///
/// There are some important behaviors to understand when sketching on a face:
///
/// The resulting sketch will _include_ the face and thus Solid
/// that was sketched on. So say you were to export the resulting Sketch / Solid
/// from a sketch on a face, you would get both the artifact of the sketch
/// on the face and the parent face / Solid itself.
///
/// This is important to understand because if you were to then sketch on the
/// resulting Solid, it would again include the face and parent Solid that was
/// sketched on. This could go on indefinitely.
///
/// The point is if you want to export the result of a sketch on a face, you
/// only need to export the final Solid that was created from the sketch on the
/// face, since it will include all the parent faces and Solids.
///
///
/// ```kcl
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
///
/// exampleSketch002 = startSketchOn(example, face = END)
/// |> startProfile(at = [1, 1])
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5)
///
/// exampleSketch003 = startSketchOn(example002, face = END)
/// |> startProfile(at = [2, 2])
/// |> line(end = [6, 0])
/// |> line(end = [0, 6])
/// |> line(end = [-6, 0])
/// |> close()
///
/// example003 = extrude(exampleSketch003, length = 5)
/// ```
///
/// ```kcl
/// // Sketch on the end of an extruded face by tagging the end face.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5, tagEnd = $end01)
///
/// exampleSketch002 = startSketchOn(example, face = end01)
/// |> startProfile(at = [1, 1])
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5, tagEnd = $end02)
///
/// exampleSketch003 = startSketchOn(example002, face = end02)
/// |> startProfile(at = [2, 2])
/// |> line(end = [6, 0])
/// |> line(end = [0, 6])
/// |> line(end = [-6, 0])
/// |> close()
///
/// example003 = extrude(exampleSketch003, length = 5)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10], tag = $sketchingFace)
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
///
/// exampleSketch002 = startSketchOn(example, face = sketchingFace)
/// |> startProfile(at = [1, 1])
/// |> line(end = [8, 0])
/// |> line(end = [0, 8])
/// |> line(end = [-8, 0])
/// |> close(tag = $sketchingFace002)
///
/// example002 = extrude(exampleSketch002, length = 10)
///
/// exampleSketch003 = startSketchOn(example002, face = sketchingFace002)
/// |> startProfile(at = [-8, 12])
/// |> line(end = [0, 6])
/// |> line(end = [6, 0])
/// |> line(end = [0, -6])
/// |> close()
///
/// example003 = extrude(exampleSketch003, length = 5)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
/// |> line(end = [0, -6])
/// |> line(end = [4, -6])
/// |> line(end = [0, -6])
/// |> line(end = [-3.75, -4.5])
/// |> line(end = [0, -5.5])
/// |> line(end = [-2, 0])
/// |> close()
///
/// example = revolve(exampleSketch, axis = Y, angle = 180)
///
/// exampleSketch002 = startSketchOn(example, face = END)
/// |> startProfile(at = [4.5, -5])
/// |> line(end = [0, 5])
/// |> line(end = [5, 0])
/// |> line(end = [0, -5])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5)
/// ```
///
/// ```kcl
/// // Sketch on the end of a revolved face by tagging the end face.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [4, 12])
/// |> line(end = [2, 0])
/// |> line(end = [0, -6])
/// |> line(end = [4, -6])
/// |> line(end = [0, -6])
/// |> line(end = [-3.75, -4.5])
/// |> line(end = [0, -5.5])
/// |> line(end = [-2, 0])
/// |> close()
///
/// example = revolve(exampleSketch, axis = Y, angle = 180, tagEnd = $end01)
///
/// exampleSketch002 = startSketchOn(example, face = end01)
/// |> startProfile(at = [4.5, -5])
/// |> line(end = [0, 5])
/// |> line(end = [5, 0])
/// |> line(end = [0, -5])
/// |> close()
///
/// example002 = extrude(exampleSketch002, length = 5)
/// ```
///
/// ```kcl
/// a1 = startSketchOn({
/// origin = { x = 0, y = 0, z = 0 },
/// xAxis = { x = 1, y = 0, z = 0 },
/// yAxis = { x = 0, y = 1, z = 0 },
/// zAxis = { x = 0, y = 0, z = 1 }
/// })
/// |> startProfile(at = [0, 0])
/// |> line(end = [100.0, 0])
/// |> yLine(length = -100.0)
/// |> xLine(length = -100.0)
/// |> yLine(length = 100.0)
/// |> close()
/// |> extrude(length = 3.14)
/// ```
@(impl = std_rust)
export fn startSketchOn(
/// Profile whose start is being used.
@planeOrSolid: Solid | Plane,
/// Identify a face of a solid if a solid is specified as the input argument (`planeOrSolid`).
face?: tag,
): Plane | Face {}
/// Start a new profile at a given point.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(-XZ)
/// |> startProfile(at = [10, 10])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(-XZ)
/// |> startProfile(at = [-10, 23])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
@(impl = std_rust)
export fn startProfile(
/// What to start the profile on.
@startProfileOn: Plane | Face,
/// Where to start the profile. An absolute point.
@(snippetArray = ["0", "0"])
at: Point2d,
/// Tag this first starting point.
tag?: tag,
): Sketch {}
/// Construct a 2-dimensional circle, of the specified radius, centered at
/// the provided (x, y) origin point.
///
@ -1196,3 +1423,498 @@ export fn tangentToEnd(
/// The line segment being queried by its tag.
@tag: tag,
): number(Angle) {}
/// Extract the provided 2-dimensional sketch's profile's origin value.
///
/// ```kcl
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [5, 2])
/// |> angledLine(angle = 120, length = 50 , tag = $seg01)
/// |> angledLine(angle = segAng(seg01) + 120, length = 50 )
/// |> line(end = profileStart(%))
/// |> close()
/// |> extrude(length = 20)
/// ```
@(impl = std_rust)
export fn profileStart(
/// Profile whose start is being used.
@profile: Sketch,
): Point2d {}
/// Extract the provided 2-dimensional sketch's profile's origin's 'x' value.
///
/// ```kcl
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [5, 2])
/// |> angledLine(angle = -26.6, length = 50)
/// |> angledLine(angle = 90, length = 50)
/// |> angledLine(angle = 30, endAbsoluteX = profileStartX(%))
/// ```
@(impl = std_rust)
export fn profileStartX(
/// Profile whose start is being used.
@profile: Sketch,
): number(Length) {}
/// Extract the provided 2-dimensional sketch's profile's origin's 'y' value.
///
/// ```kcl
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [5, 2])
/// |> angledLine(angle = -60, length = 14 )
/// |> angledLine(angle = 30, endAbsoluteY = profileStartY(%))
/// ```
@(impl = std_rust)
export fn profileStartY(
/// Profile whose start is being used.
@profile: Sketch,
): number(Length) {}
/// Extend the current sketch with a new involute circular curve.
///
/// ```kcl
/// a = 10
/// b = 14
/// startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> involuteCircular(startRadius = a, endRadius = b, angle = 60)
/// |> involuteCircular(startRadius = a, endRadius = b, angle = 60, reverse = true)
/// ```
@(impl = std_rust)
export fn involuteCircular(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// The involute is described between two circles, start_radius is the radius of the inner circle.
startRadius: number(Length),
/// The involute is described between two circles, end_radius is the radius of the outer circle.
endRadius: number(Length),
/// The angle to rotate the involute by. A value of zero will produce a curve with a tangent along the x-axis at the start point of the curve.
angle: number(Angle),
/// If reverse is true, the segment will start from the end of the involute, otherwise it will start from that start.
reverse?: bool = false,
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Extend the current sketch with a new straight line.
///
/// ```kcl
/// triangle = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// // The END argument means it ends at exactly [10, 0].
/// // This is an absolute measurement, it is NOT relative to
/// // the start of the sketch.
/// |> line(endAbsolute = [10, 0])
/// |> line(endAbsolute = [0, 10])
/// |> line(endAbsolute = [-10, 0], tag = $thirdLineOfTriangle)
/// |> close()
/// |> extrude(length = 5)
///
/// box = startSketchOn(XZ)
/// |> startProfile(at = [10, 10])
/// // The 'to' argument means move the pen this much.
/// // So, [10, 0] is a relative distance away from the current point.
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0], tag = $thirdLineOfBox)
/// |> close()
/// |> extrude(length = 5)
/// ```
@(impl = std_rust)
export fn line(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// Which absolute point should this line go to? Incompatible with `end`.
endAbsolute?: Point2d,
/// How far away (along the X and Y axes) should this line go? Incompatible with `endAbsolute`.
@(includeInSnippet = true)
end?: Point2d,
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Draw a line relative to the current origin to a specified distance away
/// from the current position along the 'x' axis.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> xLine(length = 15)
/// |> angledLine(
/// angle = 80,
/// length = 15,
/// )
/// |> line(end = [8, -10])
/// |> xLine(length = 10)
/// |> angledLine(
/// angle = 120,
/// length = 30,
/// )
/// |> xLine(length = -15)
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn xLine(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// How far away along the X axis should this line go? Incompatible with `endAbsolute`.
@(includeInSnippet = true)
length?: number(Length),
/// Which absolute X value should this line go to? Incompatible with `length`.
endAbsolute?: number(Length),
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Draw a line relative to the current origin to a specified distance away
/// from the current position along the 'y' axis.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> yLine(length = 15)
/// |> angledLine(
/// angle = 30,
/// length = 15,
/// )
/// |> line(end = [8, -10])
/// |> yLine(length = -5)
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn yLine(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// How far away along the Y axis should this line go? Incompatible with `endAbsolute`.
@(includeInSnippet = true)
length?: number(Length),
/// Which absolute Y value should this line go to? Incompatible with `length`.
endAbsolute?: number(Length),
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Draw a line segment relative to the current origin using the polar
/// measure of some angle and distance.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> yLine(endAbsolute = 15)
/// |> angledLine(
/// angle = 30,
/// length = 15,
/// )
/// |> line(end = [8, -10])
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn angledLine(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// Which angle should the line be drawn at?
angle: number(Angle),
/// Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given.
length?: number(Length),
/// Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given.
lengthX?: number(Length),
/// Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given.
lengthY?: number(Length),
/// Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given.
endAbsoluteX?: number(Length),
/// Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given.
endAbsoluteY?: number(Length),
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Draw an angled line from the current origin, constructing a line segment
/// such that the newly created line intersects the desired target line
/// segment.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(endAbsolute = [5, 10])
/// |> line(endAbsolute = [-10, 10], tag = $lineToIntersect)
/// |> line(endAbsolute = [0, 20])
/// |> angledLineThatIntersects(
/// angle = 80,
/// intersectTag = lineToIntersect,
/// offset = 10,
/// )
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn angledLineThatIntersects(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// Which angle should the line be drawn at?
angle: number(Angle),
/// The tag of the line to intersect with.
intersectTag: tag,
/// The offset from the intersecting line.
offset?: number(Length) = 0mm,
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Construct a line segment from the current origin back to the profile's
/// origin, ensuring the resulting 2-dimensional sketch is not open-ended.
///
/// If you want to perform some 3-dimensional operation on a sketch, like
/// extrude or sweep, you must `close` it first. `close` must be called even
/// if the end point of the last segment is coincident with the sketch
/// starting point.
///
/// ```kcl
/// startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 10])
/// |> line(end = [10, 0])
/// |> close()
/// |> extrude(length = 10)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(-XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn close(
/// The sketch you want to close.
@sketch: Sketch,
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Draw a curved line segment along an imaginary circle.
///
/// The arc is constructed such that the current position of the sketch is
/// placed along an imaginary circle of the specified radius, at angleStart
/// degrees. The resulting arc is the segment of the imaginary circle from
/// that origin point to angleEnd, radius away from the center of the imaginary
/// circle.
///
/// Unless this makes a lot of sense and feels like what you're looking
/// for to construct your shape, you're likely looking for tangentialArc.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> arc(
/// angleStart = 0,
/// angleEnd = 280,
/// radius = 16
/// )
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> arc(
/// endAbsolute = [10,0],
/// interiorAbsolute = [5,5]
/// )
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn arc(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// Where along the circle should this arc start?
@(includeInSnippet = true)
angleStart?: number(Angle),
/// Where along the circle should this arc end?
@(includeInSnippet = true)
angleEnd?: number(Angle),
/// How large should the circle be? Incompatible with `diameter`.
radius?: number(Length),
/// How large should the circle be? Incompatible with `radius`.
@(includeInSnippet = true)
diameter?: number(Length),
/// Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`.
interiorAbsolute?: Point2d,
/// Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd`.
endAbsolute?: Point2d,
/// Create a new tag which refers to this arc.
tag?: tag,
): Sketch {}
/// Starting at the current sketch's origin, draw a curved line segment along
/// some part of an imaginary circle until it reaches the desired (x, y)
/// coordinates.
///
/// When using radius and angle, draw a curved line segment along part of an
/// imaginary circle. The arc is constructed such that the last line segment is
/// placed tangent to the imaginary circle of the specified radius. The
/// resulting arc is the segment of the imaginary circle from that tangent point
/// for 'angle' degrees along the imaginary circle.
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 45,
/// length = 10,
/// )
/// |> tangentialArc(end = [0, -10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 60,
/// length = 10,
/// )
/// |> tangentialArc(endAbsolute = [15, 15])
/// |> line(end = [10, -15])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 60,
/// length = 10,
/// )
/// |> tangentialArc(radius = 10, angle = -120)
/// |> angledLine(
/// angle = -60,
/// length = 10,
/// )
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
@(impl = std_rust)
export fn tangentialArc(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// Which absolute point should this arc go to? Incompatible with `end`, `radius`, and `offset`.
endAbsolute?: Point2d,
/// How far away (along the X and Y axes) should this arc go? Incompatible with `endAbsolute`, `radius`, and `offset`.
@(includeInSnippet = true)
end?: Point2d,
/// Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `diameter`.
radius?: number(Length),
/// Diameter of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `radius`.
diameter?: number(Length),
/// Offset of the arc. `radius` must be given. Incompatible with `end` and `endAbsolute`.
angle?: number(Angle),
/// Create a new tag which refers to this arc.
tag?: tag,
): Sketch {}
/// Draw a smooth, continuous, curved line segment from the current origin to
/// the desired (x, y), using a number of control points to shape the curve's
/// shape.
///
/// ```kcl
/// // Example using relative control points.
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 10])
/// |> bezierCurve(
/// control1 = [5, 0],
/// control2 = [5, 10],
/// end = [10, 10],
/// )
/// |> line(endAbsolute = [10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
///
/// ```kcl
/// // Example using absolute control points.
/// startSketchOn(XY)
/// |> startProfile(at = [300, 300])
/// |> bezierCurve(control1Absolute = [600, 300], control2Absolute = [-300, -100], endAbsolute = [600, 600])
/// |> close()
/// |> extrude(length = 10)
/// ```
@(impl = std_rust)
export fn bezierCurve(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// First control point for the cubic.
control1?: Point2d,
/// Second control point for the cubic.
control2?: Point2d,
/// How far away (along the X and Y axes) should this line go?
end?: Point2d,
/// First control point for the cubic. Absolute point.
control1Absolute?: Point2d,
/// Second control point for the cubic. Absolute point.
control2Absolute?: Point2d,
/// Coordinate on the plane at which this line should end.
endAbsolute?: Point2d,
/// Create a new tag which refers to this line.
tag?: tag,
): Sketch {}
/// Use a 2-dimensional sketch to cut a hole in another 2-dimensional sketch.
///
/// ```kcl
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 5])
/// |> line(end = [5, 0])
/// |> line(end = [0, -5])
/// |> close()
/// |> subtract2d(tool =circle( center = [1, 1], radius = .25 ))
/// |> subtract2d(tool =circle( center = [1, 4], radius = .25 ))
///
/// example = extrude(exampleSketch, length = 1)
/// ```
///
/// ```kcl
/// fn squareHoleSketch() {
/// squareSketch = startSketchOn(-XZ)
/// |> startProfile(at = [-1, -1])
/// |> line(end = [2, 0])
/// |> line(end = [0, 2])
/// |> line(end = [-2, 0])
/// |> close()
/// return squareSketch
/// }
///
/// exampleSketch = startSketchOn(-XZ)
/// |> circle( center = [0, 0], radius = 3 )
/// |> subtract2d(tool = squareHoleSketch())
/// example = extrude(exampleSketch, length = 1)
/// ```
@(impl = std_rust)
export fn subtract2d(
/// Which sketch should this path be added to?
@sketch: Sketch,
/// The shape(s) which should be cut out of the sketch.
tool: [Sketch; 1+],
): Sketch {}

View File

@ -4,13 +4,14 @@ description: Error from executing error_inside_fn_also_has_source_range_of_call_
---
KCL Semantic error
× semantic: This function expected the input argument to be Solid or Plane
but it's actually of type string
╭─[3:23]
× semantic: The input argument of `startSketchOn` requires a value with type
`Solid | Plane`, but found string
╭─[3:9]
2 │ fn someNestedFunction(@something2) {
3 │ startSketchOn(something2)
· ─────┬────
· ╰── tests/error_inside_fn_also_has_source_range_of_call_site_recursive/input.kcl
· ────────────┬────────────┬
· ╰── tests/error_inside_fn_also_has_source_range_of_call_site_recursive/input.kcl
· ╰── tests/error_inside_fn_also_has_source_range_of_call_site_recursive/input.kcl
4 │ }
5 │
6 │ someNestedFunction(something)
@ -24,8 +25,8 @@ KCL Semantic error
╰────
├─▶ KCL Semantic error
× semantic: This function expected the input argument to be Solid or
│ │ Plane but it's actually of type string
× semantic: The input argument of `startSketchOn` requires a value
│ │ with type `Solid | Plane`, but found string
│ ╭─[3:23]
│ 2 │ fn someNestedFunction(@something2) {
│ 3 │ startSketchOn(something2)
@ -34,10 +35,22 @@ KCL Semantic error
│ error_inside_fn_also_has_source_range_of_call_site_recursive/input.kcl
│ 4 │ }
│ ╰────
├─▶ KCL Semantic error
× semantic: The input argument of `startSketchOn` requires a value
│ │ with type `Solid | Plane`, but found string
│ ╭─[3:9]
│ 2 │ fn someNestedFunction(@something2) {
│ 3 │ startSketchOn(something2)
│ · ────────────┬────────────
│ · ╰── tests/
│ error_inside_fn_also_has_source_range_of_call_site_recursive/input.kcl
│ 4 │ }
│ ╰────
╰─▶ KCL Semantic error
× semantic: This function expected the input argument to be Solid or
│ Plane but it's actually of type string
× semantic: The input argument of `startSketchOn` requires a value
with type `Solid | Plane`, but found string
╭─[6:5]
5 │
6 │ someNestedFunction(something)

View File

@ -3,20 +3,6 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed error_inside_fn_also_has_source_range_of_call_site_recursive.kcl
---
[
{
"type": "StdLibCall",
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "String",
"value": "INVALID"
},
"sourceRange": []
},
"labeledArgs": {},
"sourceRange": [],
"isError": true
},
{
"type": "GroupBegin",
"group": {

View File

@ -1105,141 +1105,8 @@ description: Operations executed counterdrilled-weldment.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 2.5,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.5,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -1251,141 +1118,8 @@ description: Operations executed counterdrilled-weldment.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -2.5,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.5,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

@ -153,185 +153,8 @@ description: Operations executed enclosure.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 3.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -343,185 +166,8 @@ description: Operations executed enclosure.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 3.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -533,185 +179,8 @@ description: Operations executed enclosure.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 3.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -723,185 +192,8 @@ description: Operations executed enclosure.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 3.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

@ -8,175 +8,8 @@ description: Operations executed exhaust-manifold.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -0.0,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -188,175 +21,8 @@ description: Operations executed exhaust-manifold.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 2.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -0.01745240643728351,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.9998476951563913,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -368,175 +34,8 @@ description: Operations executed exhaust-manifold.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 4.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -0.4115143586051088,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.9114032766354453,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -548,175 +47,8 @@ description: Operations executed exhaust-manifold.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 6.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -0.4257792915650726,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.9048270524660196,
"ty": {
"type": "Known",
"type": "Count"
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

@ -8,185 +8,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 44.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"zAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": -1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -346,185 +169,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 49.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"zAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -731,185 +377,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 49.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"zAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -1116,185 +585,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": -52.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"zAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -1338,185 +630,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": -52.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"zAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

@ -674,185 +674,8 @@ description: Operations executed food-service-spatula.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 208.593833,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 75.921946,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.34202,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": -0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": -0.939693,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.939693,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": -0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.34202,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

@ -123,185 +123,8 @@ description: Operations executed french-press.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": -0.26,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.26,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"zAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

@ -1587,141 +1587,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 3.75,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 11.75,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -1733,141 +1600,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 122.25,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 11.75,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -1879,141 +1613,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 3.75,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 11.75,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -2025,141 +1626,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 80.25,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 11.75,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"xAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"yAxis": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

File diff suppressed because it is too large Load Diff

View File

@ -168,141 +168,8 @@ description: Operations executed poopy-shoe.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": -1.4375,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -401,141 +268,8 @@ description: Operations executed poopy-shoe.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": -3.875,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},
@ -690,141 +424,8 @@ description: Operations executed poopy-shoe.kcl
"name": "startSketchOn",
"unlabeledArg": {
"value": {
"type": "Object",
"value": {
"origin": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": -3.875,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.125,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"xAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": -1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
},
"yAxis": {
"type": "Object",
"value": {
"x": {
"type": "Number",
"value": 1.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"y": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
},
"z": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
}
}
}
}
}
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
},

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

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