Whole module imports (#4767)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -9,7 +9,7 @@ Create a 3D surface or solid by interpolating between two or more sketches.
|
|||||||
The sketches need to closed and on the same plane.
|
The sketches need to closed and on the same plane.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
loft(sketches: [Sketch], v_degree: NonZeroU32, bez_approximate_rational: bool, base_curve_index?: u32, tolerance?: number) -> Solid
|
loft(sketches: [Sketch], v_degree: NonZeroU32, bez_approximate_rational: bool, base_curve_index?: integer, tolerance?: number) -> Solid
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ loft(sketches: [Sketch], v_degree: NonZeroU32, bez_approximate_rational: bool, b
|
|||||||
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | Which sketches to loft. Must include at least 2 sketches. | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | Which sketches to loft. Must include at least 2 sketches. | Yes |
|
||||||
| `v_degree` | `NonZeroU32` | Degree of the interpolation. Must be greater than zero. For example, use 2 for quadratic, or 3 for cubic interpolation in the V direction. This defaults to 2, if not specified. | Yes |
|
| `v_degree` | `NonZeroU32` | Degree of the interpolation. Must be greater than zero. For example, use 2 for quadratic, or 3 for cubic interpolation in the V direction. This defaults to 2, if not specified. | Yes |
|
||||||
| `bez_approximate_rational` | `bool` | Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios Over time, this field won't be necessary. | Yes |
|
| `bez_approximate_rational` | `bool` | Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios Over time, this field won't be necessary. | Yes |
|
||||||
| `base_curve_index` | `u32` | This can be set to override the automatically determined topological base curve, which is usually the first section encountered. | No |
|
| `base_curve_index` | `integer` | This can be set to override the automatically determined topological base curve, which is usually the first section encountered. | No |
|
||||||
| `tolerance` | `number` | Tolerance for the loft operation. | No |
|
| `tolerance` | `number` | Tolerance for the loft operation. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
@ -35,7 +35,7 @@ The transform function returns a transform object. All properties of the object
|
|||||||
- `rotation.origin` (either "local" i.e. rotate around its own center, "global" i.e. rotate around the scene's center, or a 3D point, defaults to "local")
|
- `rotation.origin` (either "local" i.e. rotate around its own center, "global" i.e. rotate around the scene's center, or a 3D point, defaults to "local")
|
||||||
|
|
||||||
```js
|
```js
|
||||||
patternTransform(total_instances: u32, transform_function: FunctionParam, solid_set: SolidSet) -> [Solid]
|
patternTransform(total_instances: integer, transform_function: FunctionParam, solid_set: SolidSet) -> [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ patternTransform(total_instances: u32, transform_function: FunctionParam, solid_
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `total_instances` | `u32` | | Yes |
|
| `total_instances` | `integer` | | Yes |
|
||||||
| `transform_function` | `FunctionParam` | | Yes |
|
| `transform_function` | `FunctionParam` | | Yes |
|
||||||
| `solid_set` | [`SolidSet`](/docs/kcl/types/SolidSet) | A solid or a group of solids. | Yes |
|
| `solid_set` | [`SolidSet`](/docs/kcl/types/SolidSet) | A solid or a group of solids. | Yes |
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ Just like patternTransform, but works on 2D sketches not 3D solids.
|
|||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
patternTransform2d(total_instances: u32, transform_function: FunctionParam, solid_set: SketchSet) -> [Sketch]
|
patternTransform2d(total_instances: integer, transform_function: FunctionParam, solid_set: SketchSet) -> [Sketch]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ patternTransform2d(total_instances: u32, transform_function: FunctionParam, soli
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `total_instances` | `u32` | | Yes |
|
| `total_instances` | `integer` | | Yes |
|
||||||
| `transform_function` | `FunctionParam` | | Yes |
|
| `transform_function` | `FunctionParam` | | Yes |
|
||||||
| `solid_set` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes |
|
| `solid_set` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes |
|
||||||
|
|
||||||
|
@ -97135,7 +97135,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "base_curve_index",
|
"name": "base_curve_index",
|
||||||
"type": "u32",
|
"type": "integer",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "Nullable_uint32",
|
"title": "Nullable_uint32",
|
||||||
@ -101932,6 +101932,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -103313,6 +103338,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -103931,6 +103962,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -105312,6 +105368,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -105934,6 +105996,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -107315,6 +107402,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -122705,7 +122798,7 @@
|
|||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "total_instances",
|
"name": "total_instances",
|
||||||
"type": "u32",
|
"type": "integer",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "uint32",
|
"title": "uint32",
|
||||||
@ -125482,7 +125575,7 @@
|
|||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "total_instances",
|
"name": "total_instances",
|
||||||
"type": "u32",
|
"type": "integer",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "uint32",
|
"title": "uint32",
|
||||||
@ -137258,6 +137351,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -138639,6 +138757,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -139254,6 +139378,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -139869,6 +140018,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -141250,6 +141424,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -141866,6 +142046,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -142508,6 +142713,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -143862,6 +144092,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -144496,6 +144732,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -145877,6 +146138,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -146492,6 +146759,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -147107,6 +147399,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -148488,6 +148805,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -149106,6 +149429,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -150487,6 +150835,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -151103,6 +151457,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -151745,6 +152124,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"__meta",
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Module"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/components/schemas/ModuleId"
|
||||||
|
},
|
||||||
|
"__meta": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -153099,6 +153503,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModuleId": {
|
||||||
|
"description": "Identifier of a source file. Uses a u32 to keep the size small.",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
"KclNone": {
|
"KclNone": {
|
||||||
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
"description": "KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application).",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -13,13 +13,18 @@ Data to draw an angled line.
|
|||||||
|
|
||||||
An angle and length with explicitly named parameters
|
An angle and length with explicitly named parameters
|
||||||
|
|
||||||
[`PolarCoordsData`](/docs/kcl/types/PolarCoordsData)
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `angle` |`number`| The angle of the line (in degrees). | No |
|
||||||
|
| `length` |`number`| The length of the line. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -329,6 +329,23 @@ Data for an imported geometry.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `Module`| | No |
|
||||||
|
| `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Any KCL value. | No |
|
||||||
|
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|
16
docs/kcl/types/ModuleId.md
Normal file
16
docs/kcl/types/ModuleId.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "ModuleId"
|
||||||
|
excerpt: "Identifier of a source file. Uses a u32 to keep the size small."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Identifier of a source file. Uses a u32 to keep the size small.
|
||||||
|
|
||||||
|
**Type:** `integer` (`uint32`)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -397,6 +397,7 @@ function moreNodePathFromSourceRange(
|
|||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error('not implemented: ' + node.type)
|
console.error('not implemented: ' + node.type)
|
||||||
|
@ -259,7 +259,7 @@ export function emptyExecState(): ExecState {
|
|||||||
|
|
||||||
function execStateFromRaw(raw: RawExecState): ExecState {
|
function execStateFromRaw(raw: RawExecState): ExecState {
|
||||||
return {
|
return {
|
||||||
memory: ProgramMemory.fromRaw(raw.memory),
|
memory: ProgramMemory.fromRaw(raw.modLocal.memory),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,6 +779,8 @@ fn rust_type_to_openapi_type(t: &str) -> String {
|
|||||||
|
|
||||||
if t == "f64" {
|
if t == "f64" {
|
||||||
return "number".to_string();
|
return "number".to_string();
|
||||||
|
} else if t == "u32" {
|
||||||
|
return "integer".to_string();
|
||||||
} else if t == "str" {
|
} else if t == "str" {
|
||||||
return "string".to_string();
|
return "string".to_string();
|
||||||
} else {
|
} else {
|
||||||
@ -813,7 +815,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
|||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default()).await.unwrap();
|
ctx.run(program.into(), &mut crate::ExecState::new()).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||||
|
@ -14,7 +14,7 @@ mod test_examples_someFn {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ mod test_examples_someFn {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_my_func {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ mod test_examples_my_func {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ mod test_examples_line_to {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ mod test_examples_line_to {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_min {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ mod test_examples_min {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_import {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_import {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_import {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ mod test_examples_show {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ mod test_examples_some_function {
|
|||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
context_type: crate::execution::ContextType::Mock,
|
context_type: crate::execution::ContextType::Mock,
|
||||||
};
|
};
|
||||||
ctx.run(program.into(), &mut crate::ExecState::default())
|
ctx.run(program.into(), &mut crate::ExecState::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ async fn snapshot_endpoint(body: Bytes, state: ExecutorContext) -> Response<Body
|
|||||||
};
|
};
|
||||||
|
|
||||||
eprintln!("Executing {test_name}");
|
eprintln!("Executing {test_name}");
|
||||||
let mut exec_state = ExecState::default();
|
let mut exec_state = ExecState::new();
|
||||||
// This is a shitty source range, I don't know what else to use for it though.
|
// This is a shitty source range, I don't know what else to use for it though.
|
||||||
// There's no actual KCL associated with this reset_scene call.
|
// There's no actual KCL associated with this reset_scene call.
|
||||||
if let Err(e) = state
|
if let Err(e) = state
|
||||||
|
@ -16,7 +16,7 @@ pub async fn kcl_to_engine_core(code: &str) -> Result<String> {
|
|||||||
let ctx = ExecutorContext::new_forwarded_mock(Arc::new(Box::new(
|
let ctx = ExecutorContext::new_forwarded_mock(Arc::new(Box::new(
|
||||||
crate::conn_mock_core::EngineConnection::new(ref_result).await?,
|
crate::conn_mock_core::EngineConnection::new(ref_result).await?,
|
||||||
)));
|
)));
|
||||||
ctx.run(program.into(), &mut ExecState::default()).await?;
|
ctx.run(program.into(), &mut ExecState::new()).await?;
|
||||||
|
|
||||||
let result = result.lock().expect("mutex lock").clone();
|
let result = result.lock().expect("mutex lock").clone();
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
@ -604,24 +604,6 @@ fn clean_function_name(name: &str) -> String {
|
|||||||
fn_name
|
fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a schema is the same as another schema, but don't check the description.
|
|
||||||
fn is_same_schema(sa: &schemars::schema::Schema, sb: &schemars::schema::Schema) -> bool {
|
|
||||||
let schemars::schema::Schema::Object(a) = sa else {
|
|
||||||
return sa == sb;
|
|
||||||
};
|
|
||||||
|
|
||||||
let schemars::schema::Schema::Object(b) = sb else {
|
|
||||||
return sa == sb;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut a = a.clone();
|
|
||||||
a.metadata = None;
|
|
||||||
let mut b = b.clone();
|
|
||||||
b.metadata = None;
|
|
||||||
|
|
||||||
a == b
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Recursively create references for types we already know about.
|
/// Recursively create references for types we already know about.
|
||||||
fn recurse_and_create_references(
|
fn recurse_and_create_references(
|
||||||
name: &str,
|
name: &str,
|
||||||
@ -655,24 +637,6 @@ fn recurse_and_create_references(
|
|||||||
return Ok(schemars::schema::Schema::Object(obj));
|
return Ok(schemars::schema::Schema::Object(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is the type we already know about.
|
|
||||||
for (n, s) in types {
|
|
||||||
if is_same_schema(schema, s) && name != n && !n.starts_with("[") {
|
|
||||||
// Return a reference to the type.
|
|
||||||
let sref = schemars::schema::Schema::new_ref(n.to_string());
|
|
||||||
// Add the existing metadata to the reference.
|
|
||||||
let schemars::schema::Schema::Object(ro) = sref else {
|
|
||||||
return Err(anyhow::anyhow!(
|
|
||||||
"Failed to get object schema, should have not been a primitive"
|
|
||||||
));
|
|
||||||
};
|
|
||||||
let mut ro = ro.clone();
|
|
||||||
ro.metadata = o.metadata.clone();
|
|
||||||
|
|
||||||
return Ok(schemars::schema::Schema::Object(ro));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut obj = o.clone();
|
let mut obj = o.clone();
|
||||||
|
|
||||||
// If we have an object iterate over the properties and recursively create references.
|
// If we have an object iterate over the properties and recursively create references.
|
||||||
|
@ -29,7 +29,7 @@ impl BinaryPart {
|
|||||||
match self {
|
match self {
|
||||||
BinaryPart::Literal(literal) => Ok(literal.into()),
|
BinaryPart::Literal(literal) => Ok(literal.into()),
|
||||||
BinaryPart::Identifier(identifier) => {
|
BinaryPart::Identifier(identifier) => {
|
||||||
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory().get(&identifier.name, identifier.into())?;
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
}
|
}
|
||||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
||||||
@ -47,7 +47,7 @@ impl Node<MemberExpression> {
|
|||||||
let array = match &self.object {
|
let array = match &self.object {
|
||||||
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
||||||
MemberObject::Identifier(identifier) => {
|
MemberObject::Identifier(identifier) => {
|
||||||
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory().get(&identifier.name, identifier.into())?;
|
||||||
value.clone()
|
value.clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -75,7 +75,7 @@ impl Node<MemberExpression> {
|
|||||||
// TODO: Don't use recursion here, use a loop.
|
// TODO: Don't use recursion here, use a loop.
|
||||||
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
||||||
MemberObject::Identifier(identifier) => {
|
MemberObject::Identifier(identifier) => {
|
||||||
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory().get(&identifier.name, identifier.into())?;
|
||||||
value.clone()
|
value.clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -310,11 +310,11 @@ pub(crate) async fn execute_pipe_body(
|
|||||||
// Now that we've evaluated the first child expression in the pipeline, following child expressions
|
// Now that we've evaluated the first child expression in the pipeline, following child expressions
|
||||||
// should use the previous child expression for %.
|
// should use the previous child expression for %.
|
||||||
// This means there's no more need for the previous pipe_value from the parent AST node above this one.
|
// This means there's no more need for the previous pipe_value from the parent AST node above this one.
|
||||||
let previous_pipe_value = std::mem::replace(&mut exec_state.pipe_value, Some(output));
|
let previous_pipe_value = std::mem::replace(&mut exec_state.mod_local.pipe_value, Some(output));
|
||||||
// Evaluate remaining elements.
|
// Evaluate remaining elements.
|
||||||
let result = inner_execute_pipe_body(exec_state, body, ctx).await;
|
let result = inner_execute_pipe_body(exec_state, body, ctx).await;
|
||||||
// Restore the previous pipe value.
|
// Restore the previous pipe value.
|
||||||
exec_state.pipe_value = previous_pipe_value;
|
exec_state.mod_local.pipe_value = previous_pipe_value;
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -340,10 +340,10 @@ async fn inner_execute_pipe_body(
|
|||||||
let output = ctx
|
let output = ctx
|
||||||
.execute_expr(expression, exec_state, &metadata, StatementKind::Expression)
|
.execute_expr(expression, exec_state, &metadata, StatementKind::Expression)
|
||||||
.await?;
|
.await?;
|
||||||
exec_state.pipe_value = Some(output);
|
exec_state.mod_local.pipe_value = Some(output);
|
||||||
}
|
}
|
||||||
// Safe to unwrap here, because pipe_value always has something pushed in when the `match first` executes.
|
// Safe to unwrap here, because pipe_value always has something pushed in when the `match first` executes.
|
||||||
let final_output = exec_state.pipe_value.take().unwrap();
|
let final_output = exec_state.mod_local.pipe_value.take().unwrap();
|
||||||
Ok(final_output)
|
Ok(final_output)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ impl Node<CallExpressionKw> {
|
|||||||
// before running, and we will likely want to use the
|
// before running, and we will likely want to use the
|
||||||
// return value. The call takes ownership of the args,
|
// return value. The call takes ownership of the args,
|
||||||
// so we need to build the op before the call.
|
// so we need to build the op before the call.
|
||||||
exec_state.operations.push(op);
|
exec_state.mod_local.operations.push(op);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
@ -431,8 +431,8 @@ impl Node<CallExpressionKw> {
|
|||||||
let source_range = SourceRange::from(self);
|
let source_range = SourceRange::from(self);
|
||||||
// Clone the function so that we can use a mutable reference to
|
// Clone the function so that we can use a mutable reference to
|
||||||
// exec_state.
|
// exec_state.
|
||||||
let func = exec_state.memory.get(fn_name, source_range)?.clone();
|
let func = exec_state.memory().get(fn_name, source_range)?.clone();
|
||||||
let fn_dynamic_state = exec_state.dynamic_state.merge(&exec_state.memory);
|
let fn_dynamic_state = exec_state.mod_local.dynamic_state.merge(exec_state.memory());
|
||||||
|
|
||||||
// Track call operation.
|
// Track call operation.
|
||||||
let op_labeled_args = args
|
let op_labeled_args = args
|
||||||
@ -441,16 +441,20 @@ impl Node<CallExpressionKw> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| (k.clone(), OpArg::new(v.source_range)))
|
.map(|(k, v)| (k.clone(), OpArg::new(v.source_range)))
|
||||||
.collect();
|
.collect();
|
||||||
exec_state.operations.push(Operation::UserDefinedFunctionCall {
|
exec_state
|
||||||
name: Some(fn_name.clone()),
|
.mod_local
|
||||||
function_source_range: func.function_def_source_range().unwrap_or_default(),
|
.operations
|
||||||
unlabeled_arg: args.kw_args.unlabeled.as_ref().map(|arg| OpArg::new(arg.source_range)),
|
.push(Operation::UserDefinedFunctionCall {
|
||||||
labeled_args: op_labeled_args,
|
name: Some(fn_name.clone()),
|
||||||
source_range: callsite,
|
function_source_range: func.function_def_source_range().unwrap_or_default(),
|
||||||
});
|
unlabeled_arg: args.kw_args.unlabeled.as_ref().map(|arg| OpArg::new(arg.source_range)),
|
||||||
|
labeled_args: op_labeled_args,
|
||||||
|
source_range: callsite,
|
||||||
|
});
|
||||||
|
|
||||||
let return_value = {
|
let return_value = {
|
||||||
let previous_dynamic_state = std::mem::replace(&mut exec_state.dynamic_state, fn_dynamic_state);
|
let previous_dynamic_state =
|
||||||
|
std::mem::replace(&mut exec_state.mod_local.dynamic_state, fn_dynamic_state);
|
||||||
let result = func
|
let result = func
|
||||||
.call_fn_kw(args, exec_state, ctx.clone(), callsite)
|
.call_fn_kw(args, exec_state, ctx.clone(), callsite)
|
||||||
.await
|
.await
|
||||||
@ -459,7 +463,7 @@ impl Node<CallExpressionKw> {
|
|||||||
// TODO currently ignored by the frontend
|
// TODO currently ignored by the frontend
|
||||||
e.add_source_ranges(vec![source_range])
|
e.add_source_ranges(vec![source_range])
|
||||||
});
|
});
|
||||||
exec_state.dynamic_state = previous_dynamic_state;
|
exec_state.mod_local.dynamic_state = previous_dynamic_state;
|
||||||
result?
|
result?
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -476,7 +480,10 @@ impl Node<CallExpressionKw> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Track return operation.
|
// Track return operation.
|
||||||
exec_state.operations.push(Operation::UserDefinedFunctionReturn);
|
exec_state
|
||||||
|
.mod_local
|
||||||
|
.operations
|
||||||
|
.push(Operation::UserDefinedFunctionReturn);
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@ -537,7 +544,7 @@ impl Node<CallExpression> {
|
|||||||
// before running, and we will likely want to use the
|
// before running, and we will likely want to use the
|
||||||
// return value. The call takes ownership of the args,
|
// return value. The call takes ownership of the args,
|
||||||
// so we need to build the op before the call.
|
// so we need to build the op before the call.
|
||||||
exec_state.operations.push(op);
|
exec_state.mod_local.operations.push(op);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
@ -551,27 +558,31 @@ impl Node<CallExpression> {
|
|||||||
let source_range = SourceRange::from(self);
|
let source_range = SourceRange::from(self);
|
||||||
// Clone the function so that we can use a mutable reference to
|
// Clone the function so that we can use a mutable reference to
|
||||||
// exec_state.
|
// exec_state.
|
||||||
let func = exec_state.memory.get(fn_name, source_range)?.clone();
|
let func = exec_state.memory().get(fn_name, source_range)?.clone();
|
||||||
let fn_dynamic_state = exec_state.dynamic_state.merge(&exec_state.memory);
|
let fn_dynamic_state = exec_state.mod_local.dynamic_state.merge(exec_state.memory());
|
||||||
|
|
||||||
// Track call operation.
|
// Track call operation.
|
||||||
exec_state.operations.push(Operation::UserDefinedFunctionCall {
|
exec_state
|
||||||
name: Some(fn_name.clone()),
|
.mod_local
|
||||||
function_source_range: func.function_def_source_range().unwrap_or_default(),
|
.operations
|
||||||
unlabeled_arg: None,
|
.push(Operation::UserDefinedFunctionCall {
|
||||||
// TODO: Add the arguments for legacy positional parameters.
|
name: Some(fn_name.clone()),
|
||||||
labeled_args: Default::default(),
|
function_source_range: func.function_def_source_range().unwrap_or_default(),
|
||||||
source_range: callsite,
|
unlabeled_arg: None,
|
||||||
});
|
// TODO: Add the arguments for legacy positional parameters.
|
||||||
|
labeled_args: Default::default(),
|
||||||
|
source_range: callsite,
|
||||||
|
});
|
||||||
|
|
||||||
let return_value = {
|
let return_value = {
|
||||||
let previous_dynamic_state = std::mem::replace(&mut exec_state.dynamic_state, fn_dynamic_state);
|
let previous_dynamic_state =
|
||||||
|
std::mem::replace(&mut exec_state.mod_local.dynamic_state, fn_dynamic_state);
|
||||||
let result = func.call_fn(fn_args, exec_state, ctx.clone()).await.map_err(|e| {
|
let result = func.call_fn(fn_args, exec_state, ctx.clone()).await.map_err(|e| {
|
||||||
// Add the call expression to the source ranges.
|
// Add the call expression to the source ranges.
|
||||||
// TODO currently ignored by the frontend
|
// TODO currently ignored by the frontend
|
||||||
e.add_source_ranges(vec![source_range])
|
e.add_source_ranges(vec![source_range])
|
||||||
});
|
});
|
||||||
exec_state.dynamic_state = previous_dynamic_state;
|
exec_state.mod_local.dynamic_state = previous_dynamic_state;
|
||||||
result?
|
result?
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -588,7 +599,10 @@ impl Node<CallExpression> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Track return operation.
|
// Track return operation.
|
||||||
exec_state.operations.push(Operation::UserDefinedFunctionReturn);
|
exec_state
|
||||||
|
.mod_local
|
||||||
|
.operations
|
||||||
|
.push(Operation::UserDefinedFunctionReturn);
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@ -604,7 +618,7 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
|||||||
match result {
|
match result {
|
||||||
KclValue::Sketch { value: ref mut sketch } => {
|
KclValue::Sketch { value: ref mut sketch } => {
|
||||||
for (_, tag) in sketch.tags.iter() {
|
for (_, tag) in sketch.tags.iter() {
|
||||||
exec_state.memory.update_tag(&tag.value, tag.clone())?;
|
exec_state.mut_memory().update_tag(&tag.value, tag.clone())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KclValue::Solid(ref mut solid) => {
|
KclValue::Solid(ref mut solid) => {
|
||||||
@ -642,7 +656,7 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
|||||||
info.sketch = solid.id;
|
info.sketch = solid.id;
|
||||||
t.info = Some(info);
|
t.info = Some(info);
|
||||||
|
|
||||||
exec_state.memory.update_tag(&tag.name, t.clone())?;
|
exec_state.mut_memory().update_tag(&tag.name, t.clone())?;
|
||||||
|
|
||||||
// update the sketch tags.
|
// update the sketch tags.
|
||||||
solid.sketch.tags.insert(tag.name.clone(), t);
|
solid.sketch.tags.insert(tag.name.clone(), t);
|
||||||
@ -650,11 +664,8 @@ fn update_memory_for_tags_of_geometry(result: &mut KclValue, exec_state: &mut Ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the stale sketch in memory and update it.
|
// Find the stale sketch in memory and update it.
|
||||||
if let Some(current_env) = exec_state
|
let cur_env_index = exec_state.memory().current_env.index();
|
||||||
.memory
|
if let Some(current_env) = exec_state.mut_memory().environments.get_mut(cur_env_index) {
|
||||||
.environments
|
|
||||||
.get_mut(exec_state.memory.current_env.index())
|
|
||||||
{
|
|
||||||
current_env.update_sketch_tags(&solid.sketch);
|
current_env.update_sketch_tags(&solid.sketch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -673,7 +684,9 @@ impl Node<TagDeclarator> {
|
|||||||
}],
|
}],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
exec_state.memory.add(&self.name, memory_item.clone(), self.into())?;
|
exec_state
|
||||||
|
.mut_memory()
|
||||||
|
.add(&self.name, memory_item.clone(), self.into())?;
|
||||||
|
|
||||||
Ok(self.into())
|
Ok(self.into())
|
||||||
}
|
}
|
||||||
@ -868,7 +881,7 @@ impl Property {
|
|||||||
Ok(Property::String(name.to_string()))
|
Ok(Property::String(name.to_string()))
|
||||||
} else {
|
} else {
|
||||||
// Actually evaluate memory to compute the property.
|
// Actually evaluate memory to compute the property.
|
||||||
let prop = exec_state.memory.get(name, property_src)?;
|
let prop = exec_state.memory().get(name, property_src)?;
|
||||||
jvalue_to_prop(prop, property_sr, name)
|
jvalue_to_prop(prop, property_sr, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||||||
execution::{Face, ImportedGeometry, MemoryFunction, Metadata, Plane, SketchSet, Solid, SolidSet, TagIdentifier},
|
execution::{Face, ImportedGeometry, MemoryFunction, Metadata, Plane, SketchSet, Solid, SolidSet, TagIdentifier},
|
||||||
parsing::ast::types::{FunctionExpression, KclNone, LiteralValue, TagDeclarator, TagNode},
|
parsing::ast::types::{FunctionExpression, KclNone, LiteralValue, TagDeclarator, TagNode},
|
||||||
std::{args::Arg, FnAsArg},
|
std::{args::Arg, FnAsArg},
|
||||||
ExecState, ExecutorContext, KclError, SourceRange,
|
ExecState, ExecutorContext, KclError, ModuleId, SourceRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type KclObjectFields = HashMap<String, KclValue>;
|
pub type KclObjectFields = HashMap<String, KclValue>;
|
||||||
@ -84,6 +84,11 @@ pub enum KclValue {
|
|||||||
#[serde(rename = "__meta")]
|
#[serde(rename = "__meta")]
|
||||||
meta: Vec<Metadata>,
|
meta: Vec<Metadata>,
|
||||||
},
|
},
|
||||||
|
Module {
|
||||||
|
value: ModuleId,
|
||||||
|
#[serde(rename = "__meta")]
|
||||||
|
meta: Vec<Metadata>,
|
||||||
|
},
|
||||||
KclNone {
|
KclNone {
|
||||||
value: KclNone,
|
value: KclNone,
|
||||||
#[serde(rename = "__meta")]
|
#[serde(rename = "__meta")]
|
||||||
@ -143,6 +148,7 @@ impl From<KclValue> for Vec<SourceRange> {
|
|||||||
KclValue::String { meta, .. } => to_vec_sr(&meta),
|
KclValue::String { meta, .. } => to_vec_sr(&meta),
|
||||||
KclValue::Array { meta, .. } => to_vec_sr(&meta),
|
KclValue::Array { meta, .. } => to_vec_sr(&meta),
|
||||||
KclValue::Object { meta, .. } => to_vec_sr(&meta),
|
KclValue::Object { meta, .. } => to_vec_sr(&meta),
|
||||||
|
KclValue::Module { meta, .. } => to_vec_sr(&meta),
|
||||||
KclValue::Uuid { meta, .. } => to_vec_sr(&meta),
|
KclValue::Uuid { meta, .. } => to_vec_sr(&meta),
|
||||||
KclValue::KclNone { meta, .. } => to_vec_sr(&meta),
|
KclValue::KclNone { meta, .. } => to_vec_sr(&meta),
|
||||||
}
|
}
|
||||||
@ -173,6 +179,7 @@ impl From<&KclValue> for Vec<SourceRange> {
|
|||||||
KclValue::Uuid { meta, .. } => to_vec_sr(meta),
|
KclValue::Uuid { meta, .. } => to_vec_sr(meta),
|
||||||
KclValue::Array { meta, .. } => to_vec_sr(meta),
|
KclValue::Array { meta, .. } => to_vec_sr(meta),
|
||||||
KclValue::Object { meta, .. } => to_vec_sr(meta),
|
KclValue::Object { meta, .. } => to_vec_sr(meta),
|
||||||
|
KclValue::Module { meta, .. } => to_vec_sr(meta),
|
||||||
KclValue::KclNone { meta, .. } => to_vec_sr(meta),
|
KclValue::KclNone { meta, .. } => to_vec_sr(meta),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,6 +205,7 @@ impl KclValue {
|
|||||||
KclValue::Solids { value } => value.iter().flat_map(|sketch| &sketch.meta).copied().collect(),
|
KclValue::Solids { value } => value.iter().flat_map(|sketch| &sketch.meta).copied().collect(),
|
||||||
KclValue::ImportedGeometry(x) => x.meta.clone(),
|
KclValue::ImportedGeometry(x) => x.meta.clone(),
|
||||||
KclValue::Function { meta, .. } => meta.clone(),
|
KclValue::Function { meta, .. } => meta.clone(),
|
||||||
|
KclValue::Module { meta, .. } => meta.clone(),
|
||||||
KclValue::KclNone { meta, .. } => meta.clone(),
|
KclValue::KclNone { meta, .. } => meta.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,6 +271,7 @@ impl KclValue {
|
|||||||
KclValue::String { .. } => "string (text)",
|
KclValue::String { .. } => "string (text)",
|
||||||
KclValue::Array { .. } => "array (list)",
|
KclValue::Array { .. } => "array (list)",
|
||||||
KclValue::Object { .. } => "object",
|
KclValue::Object { .. } => "object",
|
||||||
|
KclValue::Module { .. } => "module",
|
||||||
KclValue::KclNone { .. } => "None",
|
KclValue::KclNone { .. } => "None",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ type Point3D = kcmc::shared::Point3d<f64>;
|
|||||||
|
|
||||||
pub use function_param::FunctionParam;
|
pub use function_param::FunctionParam;
|
||||||
pub use kcl_value::{KclObjectFields, KclValue};
|
pub use kcl_value::{KclObjectFields, KclValue};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub(crate) mod cache;
|
pub(crate) mod cache;
|
||||||
mod cad_op;
|
mod cad_op;
|
||||||
@ -35,7 +36,8 @@ use crate::{
|
|||||||
execution::cache::{CacheInformation, CacheResult},
|
execution::cache::{CacheInformation, CacheResult},
|
||||||
fs::{FileManager, FileSystem},
|
fs::{FileManager, FileSystem},
|
||||||
parsing::ast::types::{
|
parsing::ast::types::{
|
||||||
BodyItem, Expr, FunctionExpression, ImportSelector, ItemVisibility, Node, NodeRef, TagDeclarator, TagNode,
|
BodyItem, Expr, FunctionExpression, ImportSelector, ItemVisibility, Node, NodeRef, Program as AstProgram,
|
||||||
|
TagDeclarator, TagNode,
|
||||||
},
|
},
|
||||||
settings::types::UnitLength,
|
settings::types::UnitLength,
|
||||||
source_range::{ModuleId, SourceRange},
|
source_range::{ModuleId, SourceRange},
|
||||||
@ -47,14 +49,32 @@ use crate::{
|
|||||||
pub use cad_op::Operation;
|
pub use cad_op::Operation;
|
||||||
|
|
||||||
/// State for executing a program.
|
/// State for executing a program.
|
||||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ExecState {
|
pub struct ExecState {
|
||||||
/// Program variable bindings.
|
pub global: GlobalState,
|
||||||
pub memory: ProgramMemory,
|
pub mod_local: ModuleState,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GlobalState {
|
||||||
/// The stable artifact ID generator.
|
/// The stable artifact ID generator.
|
||||||
pub id_generator: IdGenerator,
|
pub id_generator: IdGenerator,
|
||||||
|
/// Map from source file absolute path to module ID.
|
||||||
|
pub path_to_source_id: IndexMap<std::path::PathBuf, ModuleId>,
|
||||||
|
/// Map from module ID to module info.
|
||||||
|
pub module_infos: IndexMap<ModuleId, ModuleInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ModuleState {
|
||||||
|
/// Program variable bindings.
|
||||||
|
pub memory: ProgramMemory,
|
||||||
/// Dynamic state that follows dynamic flow of the program.
|
/// Dynamic state that follows dynamic flow of the program.
|
||||||
pub dynamic_state: DynamicState,
|
pub dynamic_state: DynamicState,
|
||||||
/// The current value of the pipe operator returned from the previous
|
/// The current value of the pipe operator returned from the previous
|
||||||
@ -65,29 +85,104 @@ pub struct ExecState {
|
|||||||
/// The stack of import statements for detecting circular module imports.
|
/// The stack of import statements for detecting circular module imports.
|
||||||
/// If this is empty, we're not currently executing an import statement.
|
/// If this is empty, we're not currently executing an import statement.
|
||||||
pub import_stack: Vec<std::path::PathBuf>,
|
pub import_stack: Vec<std::path::PathBuf>,
|
||||||
/// Map from source file absolute path to module ID.
|
|
||||||
pub path_to_source_id: IndexMap<std::path::PathBuf, ModuleId>,
|
|
||||||
/// Map from module ID to module info.
|
|
||||||
pub module_infos: IndexMap<ModuleId, ModuleInfo>,
|
|
||||||
/// Operations that have been performed in execution order, for display in
|
/// Operations that have been performed in execution order, for display in
|
||||||
/// the Feature Tree.
|
/// the Feature Tree.
|
||||||
pub operations: Vec<Operation>,
|
pub operations: Vec<Operation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ExecState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ExecState {
|
impl ExecState {
|
||||||
fn add_module(&mut self, path: std::path::PathBuf) -> ModuleId {
|
pub fn new() -> Self {
|
||||||
|
ExecState {
|
||||||
|
global: GlobalState::new(),
|
||||||
|
mod_local: ModuleState::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
let mut id_generator = self.global.id_generator.clone();
|
||||||
|
// We do not pop the ids, since we want to keep the same id generator.
|
||||||
|
// This is for the front end to keep track of the ids.
|
||||||
|
id_generator.next_id = 0;
|
||||||
|
|
||||||
|
let mut global = GlobalState::new();
|
||||||
|
global.id_generator = id_generator;
|
||||||
|
|
||||||
|
*self = ExecState {
|
||||||
|
global,
|
||||||
|
mod_local: ModuleState::default(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn memory(&self) -> &ProgramMemory {
|
||||||
|
&self.mod_local.memory
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mut_memory(&mut self) -> &mut ProgramMemory {
|
||||||
|
&mut self.mod_local.memory
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_uuid(&mut self) -> Uuid {
|
||||||
|
self.global.id_generator.next_uuid()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add_module(
|
||||||
|
&mut self,
|
||||||
|
path: std::path::PathBuf,
|
||||||
|
ctxt: &ExecutorContext,
|
||||||
|
source_range: SourceRange,
|
||||||
|
) -> Result<ModuleId, KclError> {
|
||||||
// Need to avoid borrowing self in the closure.
|
// Need to avoid borrowing self in the closure.
|
||||||
let new_module_id = ModuleId::from_usize(self.path_to_source_id.len());
|
let new_module_id = ModuleId::from_usize(self.global.path_to_source_id.len());
|
||||||
let mut is_new = false;
|
let mut is_new = false;
|
||||||
let id = *self.path_to_source_id.entry(path.clone()).or_insert_with(|| {
|
let id = *self.global.path_to_source_id.entry(path.clone()).or_insert_with(|| {
|
||||||
is_new = true;
|
is_new = true;
|
||||||
new_module_id
|
new_module_id
|
||||||
});
|
});
|
||||||
|
|
||||||
if is_new {
|
if is_new {
|
||||||
let module_info = ModuleInfo { id, path };
|
let source = ctxt.fs.read_to_string(&path, source_range).await?;
|
||||||
self.module_infos.insert(id, module_info);
|
// TODO handle parsing errors properly
|
||||||
|
let parsed = crate::parsing::parse_str(&source, id).parse_errs_as_err()?;
|
||||||
|
|
||||||
|
let module_info = ModuleInfo {
|
||||||
|
id,
|
||||||
|
path,
|
||||||
|
parsed: Some(parsed),
|
||||||
|
};
|
||||||
|
self.global.module_infos.insert(id, module_info);
|
||||||
}
|
}
|
||||||
id
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalState {
|
||||||
|
fn new() -> Self {
|
||||||
|
let mut global = GlobalState {
|
||||||
|
id_generator: Default::default(),
|
||||||
|
path_to_source_id: Default::default(),
|
||||||
|
module_infos: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(#4434): Use the top-level file's path.
|
||||||
|
let root_path = PathBuf::new();
|
||||||
|
let root_id = ModuleId::default();
|
||||||
|
global.module_infos.insert(
|
||||||
|
root_id,
|
||||||
|
ModuleInfo {
|
||||||
|
id: root_id,
|
||||||
|
path: root_path.clone(),
|
||||||
|
parsed: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
global.path_to_source_id.insert(root_path, root_id);
|
||||||
|
global
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +254,13 @@ impl ProgramMemory {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all bindings in the current scope.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn get_all_cur_scope(&self) -> IndexMap<String, KclValue> {
|
||||||
|
let env = &self.environments[self.current_env.index()];
|
||||||
|
env.bindings.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Find all solids in the memory that are on a specific sketch id.
|
/// Find all solids in the memory that are on a specific sketch id.
|
||||||
/// This does not look inside closures. But as long as we do not allow
|
/// This does not look inside closures. But as long as we do not allow
|
||||||
/// mutation of variables in KCL, closure memory should be a subset of this.
|
/// mutation of variables in KCL, closure memory should be a subset of this.
|
||||||
@ -274,18 +376,14 @@ pub struct DynamicState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicState {
|
impl DynamicState {
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn merge(&self, memory: &ProgramMemory) -> Self {
|
fn merge(&self, memory: &ProgramMemory) -> Self {
|
||||||
let mut merged = self.clone();
|
let mut merged = self.clone();
|
||||||
merged.append(memory);
|
merged.append(memory);
|
||||||
merged
|
merged
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, memory: &ProgramMemory) {
|
fn append(&mut self, memory: &ProgramMemory) {
|
||||||
for env in &memory.environments {
|
for env in &memory.environments {
|
||||||
for item in env.bindings.values() {
|
for item in env.bindings.values() {
|
||||||
if let KclValue::Solid(eg) = item {
|
if let KclValue::Solid(eg) = item {
|
||||||
@ -295,7 +393,7 @@ impl DynamicState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edge_cut_ids_on_sketch(&self, sketch_id: uuid::Uuid) -> Vec<uuid::Uuid> {
|
pub(crate) fn edge_cut_ids_on_sketch(&self, sketch_id: uuid::Uuid) -> Vec<uuid::Uuid> {
|
||||||
self.solid_ids
|
self.solid_ids
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|eg| {
|
.flat_map(|eg| {
|
||||||
@ -553,7 +651,7 @@ pub struct Plane {
|
|||||||
|
|
||||||
impl Plane {
|
impl Plane {
|
||||||
pub(crate) fn from_plane_data(value: crate::std::sketch::PlaneData, exec_state: &mut ExecState) -> Self {
|
pub(crate) fn from_plane_data(value: crate::std::sketch::PlaneData, exec_state: &mut ExecState) -> Self {
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.global.id_generator.next_uuid();
|
||||||
match value {
|
match value {
|
||||||
crate::std::sketch::PlaneData::XY => Plane {
|
crate::std::sketch::PlaneData::XY => Plane {
|
||||||
id,
|
id,
|
||||||
@ -1001,13 +1099,14 @@ pub enum BodyType {
|
|||||||
|
|
||||||
/// Info about a module. Right now, this is pretty minimal. We hope to cache
|
/// Info about a module. Right now, this is pretty minimal. We hope to cache
|
||||||
/// modules here in the future.
|
/// modules here in the future.
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct ModuleInfo {
|
pub struct ModuleInfo {
|
||||||
/// The ID of the module.
|
/// The ID of the module.
|
||||||
id: ModuleId,
|
id: ModuleId,
|
||||||
/// Absolute path of the module's source file.
|
/// Absolute path of the module's source file.
|
||||||
path: std::path::PathBuf,
|
path: std::path::PathBuf,
|
||||||
|
parsed: Option<Node<AstProgram>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy, ts_rs::TS, JsonSchema)]
|
||||||
@ -1796,7 +1895,7 @@ impl ExecutorContext {
|
|||||||
source_range: crate::execution::SourceRange,
|
source_range: crate::execution::SourceRange,
|
||||||
) -> Result<(), KclError> {
|
) -> Result<(), KclError> {
|
||||||
self.engine
|
self.engine
|
||||||
.clear_scene(&mut exec_state.id_generator, source_range)
|
.clear_scene(&mut exec_state.global.id_generator, source_range)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// We do not create the planes here as the post hook in wasm will do that
|
// We do not create the planes here as the post hook in wasm will do that
|
||||||
@ -1897,23 +1996,13 @@ impl ExecutorContext {
|
|||||||
|
|
||||||
if cache_result.clear_scene && !self.is_mock() {
|
if cache_result.clear_scene && !self.is_mock() {
|
||||||
// Pop the execution state, since we are starting fresh.
|
// Pop the execution state, since we are starting fresh.
|
||||||
let mut id_generator = exec_state.id_generator.clone();
|
exec_state.reset();
|
||||||
// We do not pop the ids, since we want to keep the same id generator.
|
|
||||||
// This is for the front end to keep track of the ids.
|
|
||||||
id_generator.next_id = 0;
|
|
||||||
*exec_state = ExecState {
|
|
||||||
id_generator,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// We don't do this in mock mode since there is no engine connection
|
// We don't do this in mock mode since there is no engine connection
|
||||||
// anyways and from the TS side we override memory and don't want to clear it.
|
// anyways and from the TS side we override memory and don't want to clear it.
|
||||||
self.reset_scene(exec_state, Default::default()).await?;
|
self.reset_scene(exec_state, Default::default()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use the top-level file's path.
|
|
||||||
exec_state.add_module(std::path::PathBuf::from(""));
|
|
||||||
|
|
||||||
// Re-apply the settings, in case the cache was busted.
|
// Re-apply the settings, in case the cache was busted.
|
||||||
self.engine.reapply_settings(&self.settings, Default::default()).await?;
|
self.engine.reapply_settings(&self.settings, Default::default()).await?;
|
||||||
|
|
||||||
@ -1937,11 +2026,13 @@ impl ExecutorContext {
|
|||||||
match statement {
|
match statement {
|
||||||
BodyItem::ImportStatement(import_stmt) => {
|
BodyItem::ImportStatement(import_stmt) => {
|
||||||
let source_range = SourceRange::from(import_stmt);
|
let source_range = SourceRange::from(import_stmt);
|
||||||
let (module_memory, module_exports) =
|
let module_id = self.open_module(&import_stmt.path, exec_state, source_range).await?;
|
||||||
self.open_module(&import_stmt.path, exec_state, source_range).await?;
|
|
||||||
|
|
||||||
match &import_stmt.selector {
|
match &import_stmt.selector {
|
||||||
ImportSelector::List { items } => {
|
ImportSelector::List { items } => {
|
||||||
|
let (_, module_memory, module_exports) = self
|
||||||
|
.exec_module(module_id, exec_state, ExecutionKind::Isolated, source_range)
|
||||||
|
.await?;
|
||||||
for import_item in items {
|
for import_item in items {
|
||||||
// Extract the item from the module.
|
// Extract the item from the module.
|
||||||
let item =
|
let item =
|
||||||
@ -1965,18 +2056,24 @@ impl ExecutorContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the item to the current module.
|
// Add the item to the current module.
|
||||||
exec_state.memory.add(
|
exec_state.mut_memory().add(
|
||||||
import_item.identifier(),
|
import_item.identifier(),
|
||||||
item.clone(),
|
item.clone(),
|
||||||
SourceRange::from(&import_item.name),
|
SourceRange::from(&import_item.name),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let ItemVisibility::Export = import_stmt.visibility {
|
if let ItemVisibility::Export = import_stmt.visibility {
|
||||||
exec_state.module_exports.push(import_item.identifier().to_owned());
|
exec_state
|
||||||
|
.mod_local
|
||||||
|
.module_exports
|
||||||
|
.push(import_item.identifier().to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => {
|
ImportSelector::Glob(_) => {
|
||||||
|
let (_, module_memory, module_exports) = self
|
||||||
|
.exec_module(module_id, exec_state, ExecutionKind::Isolated, source_range)
|
||||||
|
.await?;
|
||||||
for name in module_exports.iter() {
|
for name in module_exports.iter() {
|
||||||
let item = module_memory.get(name, source_range).map_err(|_err| {
|
let item = module_memory.get(name, source_range).map_err(|_err| {
|
||||||
KclError::Internal(KclErrorDetails {
|
KclError::Internal(KclErrorDetails {
|
||||||
@ -1984,18 +2081,20 @@ impl ExecutorContext {
|
|||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
exec_state.memory.add(name, item.clone(), source_range)?;
|
exec_state.mut_memory().add(name, item.clone(), source_range)?;
|
||||||
|
|
||||||
if let ItemVisibility::Export = import_stmt.visibility {
|
if let ItemVisibility::Export = import_stmt.visibility {
|
||||||
exec_state.module_exports.push(name.clone());
|
exec_state.mod_local.module_exports.push(name.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportSelector::None(_) => {
|
ImportSelector::None { .. } => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
let name = import_stmt.module_name().unwrap();
|
||||||
message: "Importing whole module is not yet implemented, sorry.".to_owned(),
|
let item = KclValue::Module {
|
||||||
source_ranges: vec![source_range],
|
value: module_id,
|
||||||
}));
|
meta: vec![source_range.into()],
|
||||||
|
};
|
||||||
|
exec_state.mut_memory().add(&name, item, source_range)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_expr = None;
|
last_expr = None;
|
||||||
@ -2025,11 +2124,11 @@ impl ExecutorContext {
|
|||||||
StatementKind::Declaration { name: &var_name },
|
StatementKind::Declaration { name: &var_name },
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
exec_state.memory.add(&var_name, memory_item, source_range)?;
|
exec_state.mut_memory().add(&var_name, memory_item, source_range)?;
|
||||||
|
|
||||||
// Track exports.
|
// Track exports.
|
||||||
if let ItemVisibility::Export = variable_declaration.visibility {
|
if let ItemVisibility::Export = variable_declaration.visibility {
|
||||||
exec_state.module_exports.push(var_name);
|
exec_state.mod_local.module_exports.push(var_name);
|
||||||
}
|
}
|
||||||
last_expr = None;
|
last_expr = None;
|
||||||
}
|
}
|
||||||
@ -2043,7 +2142,7 @@ impl ExecutorContext {
|
|||||||
StatementKind::Expression,
|
StatementKind::Expression,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
exec_state.memory.return_ = Some(value);
|
exec_state.mut_memory().return_ = Some(value);
|
||||||
last_expr = None;
|
last_expr = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2069,18 +2168,19 @@ impl ExecutorContext {
|
|||||||
path: &str,
|
path: &str,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<(ProgramMemory, Vec<String>), KclError> {
|
) -> Result<ModuleId, KclError> {
|
||||||
let resolved_path = if let Some(project_dir) = &self.settings.project_directory {
|
let resolved_path = if let Some(project_dir) = &self.settings.project_directory {
|
||||||
project_dir.join(path)
|
project_dir.join(path)
|
||||||
} else {
|
} else {
|
||||||
std::path::PathBuf::from(&path)
|
std::path::PathBuf::from(&path)
|
||||||
};
|
};
|
||||||
|
|
||||||
if exec_state.import_stack.contains(&resolved_path) {
|
if exec_state.mod_local.import_stack.contains(&resolved_path) {
|
||||||
return Err(KclError::ImportCycle(KclErrorDetails {
|
return Err(KclError::ImportCycle(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
"circular import of modules is not allowed: {} -> {}",
|
"circular import of modules is not allowed: {} -> {}",
|
||||||
exec_state
|
exec_state
|
||||||
|
.mod_local
|
||||||
.import_stack
|
.import_stack
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.as_path().to_string_lossy())
|
.map(|p| p.as_path().to_string_lossy())
|
||||||
@ -2091,31 +2191,44 @@ impl ExecutorContext {
|
|||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
let module_id = exec_state.add_module(resolved_path.clone());
|
exec_state.add_module(resolved_path.clone(), self, source_range).await
|
||||||
let source = self.fs.read_to_string(&resolved_path, source_range).await?;
|
}
|
||||||
// TODO handle parsing errors properly
|
|
||||||
let program = crate::parsing::parse_str(&source, module_id).parse_errs_as_err()?;
|
|
||||||
|
|
||||||
exec_state.import_stack.push(resolved_path.clone());
|
async fn exec_module(
|
||||||
let original_execution = self.engine.replace_execution_kind(ExecutionKind::Isolated);
|
&self,
|
||||||
let original_memory = std::mem::take(&mut exec_state.memory);
|
module_id: ModuleId,
|
||||||
let original_exports = std::mem::take(&mut exec_state.module_exports);
|
exec_state: &mut ExecState,
|
||||||
|
exec_kind: ExecutionKind,
|
||||||
|
source_range: SourceRange,
|
||||||
|
) -> Result<(Option<KclValue>, ProgramMemory, Vec<String>), KclError> {
|
||||||
|
// TODO It sucks that we have to clone the whole module AST here
|
||||||
|
let info = exec_state.global.module_infos[&module_id].clone();
|
||||||
|
|
||||||
|
let mut local_state = ModuleState {
|
||||||
|
import_stack: exec_state.mod_local.import_stack.clone(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
local_state.import_stack.push(info.path.clone());
|
||||||
|
std::mem::swap(&mut exec_state.mod_local, &mut local_state);
|
||||||
|
let original_execution = self.engine.replace_execution_kind(exec_kind);
|
||||||
|
|
||||||
|
// The unwrap here is safe since we only elide the AST for the top module.
|
||||||
let result = self
|
let result = self
|
||||||
.inner_execute(&program, exec_state, crate::execution::BodyType::Root)
|
.inner_execute(&info.parsed.unwrap(), exec_state, crate::execution::BodyType::Root)
|
||||||
.await;
|
.await;
|
||||||
let module_exports = std::mem::replace(&mut exec_state.module_exports, original_exports);
|
|
||||||
let module_memory = std::mem::replace(&mut exec_state.memory, original_memory);
|
|
||||||
self.engine.replace_execution_kind(original_execution);
|
|
||||||
exec_state.import_stack.pop();
|
|
||||||
|
|
||||||
result.map_err(|err| {
|
std::mem::swap(&mut exec_state.mod_local, &mut local_state);
|
||||||
|
self.engine.replace_execution_kind(original_execution);
|
||||||
|
|
||||||
|
let result = result.map_err(|err| {
|
||||||
if let KclError::ImportCycle(_) = err {
|
if let KclError::ImportCycle(_) = err {
|
||||||
// It was an import cycle. Keep the original message.
|
// It was an import cycle. Keep the original message.
|
||||||
err.override_source_ranges(vec![source_range])
|
err.override_source_ranges(vec![source_range])
|
||||||
} else {
|
} else {
|
||||||
KclError::Semantic(KclErrorDetails {
|
KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
"Error loading imported file. Open it to view more details. {path}: {}",
|
"Error loading imported file. Open it to view more details. {}: {}",
|
||||||
|
info.path.display(),
|
||||||
err.message()
|
err.message()
|
||||||
),
|
),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
@ -2123,7 +2236,7 @@ impl ExecutorContext {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok((module_memory, module_exports))
|
Ok((result, local_state.memory, local_state.module_exports))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
@ -2139,8 +2252,23 @@ impl ExecutorContext {
|
|||||||
Expr::Literal(literal) => KclValue::from(literal),
|
Expr::Literal(literal) => KclValue::from(literal),
|
||||||
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
|
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
|
||||||
Expr::Identifier(identifier) => {
|
Expr::Identifier(identifier) => {
|
||||||
let value = exec_state.memory.get(&identifier.name, identifier.into())?;
|
let value = exec_state.memory().get(&identifier.name, identifier.into())?.clone();
|
||||||
value.clone()
|
if let KclValue::Module { value: module_id, meta } = value {
|
||||||
|
let (result, _, _) = self
|
||||||
|
.exec_module(module_id, exec_state, ExecutionKind::Normal, metadata.source_range)
|
||||||
|
.await?;
|
||||||
|
result.ok_or_else(|| {
|
||||||
|
KclError::Semantic(KclErrorDetails {
|
||||||
|
message: format!(
|
||||||
|
"Evaluating module `{}` as part of an assembly did not produce a result",
|
||||||
|
identifier.name
|
||||||
|
),
|
||||||
|
source_ranges: vec![metadata.source_range, meta[0].source_range],
|
||||||
|
})
|
||||||
|
})?
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, self).await?,
|
Expr::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, self).await?,
|
||||||
Expr::FunctionExpression(function_expression) => {
|
Expr::FunctionExpression(function_expression) => {
|
||||||
@ -2151,7 +2279,7 @@ impl ExecutorContext {
|
|||||||
expression: function_expression.clone(),
|
expression: function_expression.clone(),
|
||||||
meta: vec![metadata.to_owned()],
|
meta: vec![metadata.to_owned()],
|
||||||
func: None,
|
func: None,
|
||||||
memory: Box::new(exec_state.memory.clone()),
|
memory: Box::new(exec_state.memory().clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::CallExpression(call_expression) => call_expression.execute(exec_state, self).await?,
|
Expr::CallExpression(call_expression) => call_expression.execute(exec_state, self).await?,
|
||||||
@ -2168,7 +2296,7 @@ impl ExecutorContext {
|
|||||||
source_ranges: vec![pipe_substitution.into()],
|
source_ranges: vec![pipe_substitution.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
StatementKind::Expression => match exec_state.pipe_value.clone() {
|
StatementKind::Expression => match exec_state.mod_local.pipe_value.clone() {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => {
|
None => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
@ -2188,7 +2316,9 @@ impl ExecutorContext {
|
|||||||
let result = self
|
let result = self
|
||||||
.execute_expr(&expr.expr, exec_state, metadata, statement_kind)
|
.execute_expr(&expr.expr, exec_state, metadata, statement_kind)
|
||||||
.await?;
|
.await?;
|
||||||
exec_state.memory.add(&expr.label.name, result.clone(), init.into())?;
|
exec_state
|
||||||
|
.mut_memory()
|
||||||
|
.add(&expr.label.name, result.clone(), init.into())?;
|
||||||
// TODO this lets us use the label as a variable name, but not as a tag in most cases
|
// TODO this lets us use the label as a variable name, but not as a tag in most cases
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -2373,12 +2503,12 @@ pub(crate) async fn call_user_defined_function(
|
|||||||
|
|
||||||
// Execute the function body using the memory we just created.
|
// Execute the function body using the memory we just created.
|
||||||
let (result, fn_memory) = {
|
let (result, fn_memory) = {
|
||||||
let previous_memory = std::mem::replace(&mut exec_state.memory, fn_memory);
|
let previous_memory = std::mem::replace(&mut exec_state.mod_local.memory, fn_memory);
|
||||||
let result = ctx
|
let result = ctx
|
||||||
.inner_execute(&function_expression.body, exec_state, BodyType::Block)
|
.inner_execute(&function_expression.body, exec_state, BodyType::Block)
|
||||||
.await;
|
.await;
|
||||||
// Restore the previous memory.
|
// Restore the previous memory.
|
||||||
let fn_memory = std::mem::replace(&mut exec_state.memory, previous_memory);
|
let fn_memory = std::mem::replace(&mut exec_state.mod_local.memory, previous_memory);
|
||||||
|
|
||||||
(result, fn_memory)
|
(result, fn_memory)
|
||||||
};
|
};
|
||||||
@ -2403,12 +2533,12 @@ pub(crate) async fn call_user_defined_function_kw(
|
|||||||
|
|
||||||
// Execute the function body using the memory we just created.
|
// Execute the function body using the memory we just created.
|
||||||
let (result, fn_memory) = {
|
let (result, fn_memory) = {
|
||||||
let previous_memory = std::mem::replace(&mut exec_state.memory, fn_memory);
|
let previous_memory = std::mem::replace(&mut exec_state.mod_local.memory, fn_memory);
|
||||||
let result = ctx
|
let result = ctx
|
||||||
.inner_execute(&function_expression.body, exec_state, BodyType::Block)
|
.inner_execute(&function_expression.body, exec_state, BodyType::Block)
|
||||||
.await;
|
.await;
|
||||||
// Restore the previous memory.
|
// Restore the previous memory.
|
||||||
let fn_memory = std::mem::replace(&mut exec_state.memory, previous_memory);
|
let fn_memory = std::mem::replace(&mut exec_state.mod_local.memory, previous_memory);
|
||||||
|
|
||||||
(result, fn_memory)
|
(result, fn_memory)
|
||||||
};
|
};
|
||||||
@ -2433,7 +2563,7 @@ mod tests {
|
|||||||
OldAstState,
|
OldAstState,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn parse_execute(code: &str) -> Result<(Program, ExecutorContext, ExecState)> {
|
async fn parse_execute(code: &str) -> Result<(Program, ExecutorContext, ExecState)> {
|
||||||
let program = Program::parse_no_errs(code)?;
|
let program = Program::parse_no_errs(code)?;
|
||||||
|
|
||||||
let ctx = ExecutorContext {
|
let ctx = ExecutorContext {
|
||||||
@ -2450,6 +2580,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to get a JSON value from memory and unwrap.
|
/// Convenience function to get a JSON value from memory and unwrap.
|
||||||
|
#[track_caller]
|
||||||
fn mem_get_json(memory: &ProgramMemory, name: &str) -> KclValue {
|
fn mem_get_json(memory: &ProgramMemory, name: &str) -> KclValue {
|
||||||
memory.get(name, SourceRange::default()).unwrap().to_owned()
|
memory.get(name, SourceRange::default()).unwrap().to_owned()
|
||||||
}
|
}
|
||||||
@ -2880,21 +3011,21 @@ let shape = layer() |> patternTransform(10, transform, %)
|
|||||||
async fn test_math_execute_with_functions() {
|
async fn test_math_execute_with_functions() {
|
||||||
let ast = r#"const myVar = 2 + min(100, -1 + legLen(5, 3))"#;
|
let ast = r#"const myVar = 2 + min(100, -1 + legLen(5, 3))"#;
|
||||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(5.0, mem_get_json(&exec_state.memory, "myVar").as_f64().unwrap());
|
assert_eq!(5.0, mem_get_json(exec_state.memory(), "myVar").as_f64().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_math_execute() {
|
async fn test_math_execute() {
|
||||||
let ast = r#"const myVar = 1 + 2 * (3 - 4) / -5 + 6"#;
|
let ast = r#"const myVar = 1 + 2 * (3 - 4) / -5 + 6"#;
|
||||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(7.4, mem_get_json(&exec_state.memory, "myVar").as_f64().unwrap());
|
assert_eq!(7.4, mem_get_json(exec_state.memory(), "myVar").as_f64().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_math_execute_start_negative() {
|
async fn test_math_execute_start_negative() {
|
||||||
let ast = r#"const myVar = -5 + 6"#;
|
let ast = r#"const myVar = -5 + 6"#;
|
||||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(1.0, mem_get_json(&exec_state.memory, "myVar").as_f64().unwrap());
|
assert_eq!(1.0, mem_get_json(exec_state.memory(), "myVar").as_f64().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -2903,7 +3034,7 @@ let shape = layer() |> patternTransform(10, transform, %)
|
|||||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
std::f64::consts::TAU,
|
std::f64::consts::TAU,
|
||||||
mem_get_json(&exec_state.memory, "myVar").as_f64().unwrap()
|
mem_get_json(exec_state.memory(), "myVar").as_f64().unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2911,7 +3042,7 @@ let shape = layer() |> patternTransform(10, transform, %)
|
|||||||
async fn test_math_define_decimal_without_leading_zero() {
|
async fn test_math_define_decimal_without_leading_zero() {
|
||||||
let ast = r#"let thing = .4 + 7"#;
|
let ast = r#"let thing = .4 + 7"#;
|
||||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(7.4, mem_get_json(&exec_state.memory, "thing").as_f64().unwrap());
|
assert_eq!(7.4, mem_get_json(exec_state.memory(), "thing").as_f64().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -2951,10 +3082,10 @@ fn check = (x) => {
|
|||||||
check(false)
|
check(false)
|
||||||
"#;
|
"#;
|
||||||
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
let (_, _, exec_state) = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(false, mem_get_json(&exec_state.memory, "notTrue").as_bool().unwrap());
|
assert_eq!(false, mem_get_json(exec_state.memory(), "notTrue").as_bool().unwrap());
|
||||||
assert_eq!(true, mem_get_json(&exec_state.memory, "notFalse").as_bool().unwrap());
|
assert_eq!(true, mem_get_json(exec_state.memory(), "notFalse").as_bool().unwrap());
|
||||||
assert_eq!(true, mem_get_json(&exec_state.memory, "c").as_bool().unwrap());
|
assert_eq!(true, mem_get_json(exec_state.memory(), "c").as_bool().unwrap());
|
||||||
assert_eq!(false, mem_get_json(&exec_state.memory, "d").as_bool().unwrap());
|
assert_eq!(false, mem_get_json(exec_state.memory(), "d").as_bool().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -3635,4 +3766,65 @@ shell({ faces = ['end'], thickness = 0.25 }, firstSketch)"#;
|
|||||||
|
|
||||||
assert_eq!(result, None);
|
assert_eq!(result, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_ids_stable_between_executions() {
|
||||||
|
let code = r#"sketch001 = startSketchOn('XZ')
|
||||||
|
|> startProfileAt([61.74, 206.13], %)
|
||||||
|
|> xLine(305.11, %, $seg01)
|
||||||
|
|> yLine(-291.85, %)
|
||||||
|
|> xLine(-segLen(seg01), %)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(40.14, %)
|
||||||
|
|> shell({
|
||||||
|
faces: [seg01],
|
||||||
|
thickness: 3.14,
|
||||||
|
}, %)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let ctx = crate::test_server::new_context(UnitLength::Mm, true, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let old_program = crate::Program::parse_no_errs(code).unwrap();
|
||||||
|
// Execute the program.
|
||||||
|
let mut exec_state = Default::default();
|
||||||
|
let cache_info = crate::CacheInformation {
|
||||||
|
old: None,
|
||||||
|
new_ast: old_program.ast.clone(),
|
||||||
|
};
|
||||||
|
ctx.run(cache_info, &mut exec_state).await.unwrap();
|
||||||
|
|
||||||
|
// Get the id_generator from the first execution.
|
||||||
|
let id_generator = exec_state.global.id_generator.clone();
|
||||||
|
|
||||||
|
let code = r#"sketch001 = startSketchOn('XZ')
|
||||||
|
|> startProfileAt([62.74, 206.13], %)
|
||||||
|
|> xLine(305.11, %, $seg01)
|
||||||
|
|> yLine(-291.85, %)
|
||||||
|
|> xLine(-segLen(seg01), %)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(40.14, %)
|
||||||
|
|> shell({
|
||||||
|
faces: [seg01],
|
||||||
|
thickness: 3.14,
|
||||||
|
}, %)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
// Execute a slightly different program again.
|
||||||
|
let program: Program = crate::Program::parse_no_errs(code).unwrap();
|
||||||
|
let cache_info = crate::CacheInformation {
|
||||||
|
old: Some(crate::OldAstState {
|
||||||
|
ast: old_program.ast.clone(),
|
||||||
|
exec_state: exec_state.clone(),
|
||||||
|
settings: ctx.settings.clone(),
|
||||||
|
}),
|
||||||
|
new_ast: program.ast.clone(),
|
||||||
|
};
|
||||||
|
// Execute the program.
|
||||||
|
ctx.run(cache_info, &mut exec_state).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(id_generator, exec_state.global.id_generator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -726,11 +726,11 @@ impl Backend {
|
|||||||
drop(last_successful_ast_state);
|
drop(last_successful_ast_state);
|
||||||
|
|
||||||
self.memory_map
|
self.memory_map
|
||||||
.insert(params.uri.to_string(), exec_state.memory.clone());
|
.insert(params.uri.to_string(), exec_state.memory().clone());
|
||||||
|
|
||||||
// Send the notification to the client that the memory was updated.
|
// Send the notification to the client that the memory was updated.
|
||||||
self.client
|
self.client
|
||||||
.send_notification::<custom_notifications::MemoryUpdated>(exec_state.memory)
|
.send_notification::<custom_notifications::MemoryUpdated>(exec_state.mod_local.memory)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2344,6 +2344,7 @@ async fn kcl_test_kcl_lsp_diagnostics_on_execution_error() {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Get the diagnostics.
|
// Get the diagnostics.
|
||||||
|
// TODO warnings being stomped by execution errors?
|
||||||
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 1);
|
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 1);
|
||||||
|
|
||||||
// Update the text.
|
// Update the text.
|
||||||
|
@ -59,8 +59,8 @@ impl ImportStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => hasher.update(b"ImportSelector::Glob"),
|
ImportSelector::Glob(_) => hasher.update(b"ImportSelector::Glob"),
|
||||||
ImportSelector::None(None) => hasher.update(b"ImportSelector::None"),
|
ImportSelector::None { alias: None } => hasher.update(b"ImportSelector::None"),
|
||||||
ImportSelector::None(Some(alias)) => {
|
ImportSelector::None { alias: Some(alias) } => {
|
||||||
hasher.update(b"ImportSelector::None");
|
hasher.update(b"ImportSelector::None");
|
||||||
hasher.update(alias.compute_digest());
|
hasher.update(alias.compute_digest());
|
||||||
}
|
}
|
||||||
|
@ -1225,7 +1225,7 @@ pub enum ImportSelector {
|
|||||||
Glob(Node<()>),
|
Glob(Node<()>),
|
||||||
/// Import the module itself (the param is an optional alias).
|
/// Import the module itself (the param is an optional alias).
|
||||||
/// E.g., `import "foo.kcl" as bar`
|
/// E.g., `import "foo.kcl" as bar`
|
||||||
None(Option<Node<Identifier>>),
|
None { alias: Option<Node<Identifier>> },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportSelector {
|
impl ImportSelector {
|
||||||
@ -1244,8 +1244,8 @@ impl ImportSelector {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => None,
|
ImportSelector::Glob(_) => None,
|
||||||
ImportSelector::None(None) => None,
|
ImportSelector::None { alias: None } => None,
|
||||||
ImportSelector::None(Some(alias)) => {
|
ImportSelector::None { alias: Some(alias) } => {
|
||||||
let alias_source_range = SourceRange::from(&*alias);
|
let alias_source_range = SourceRange::from(&*alias);
|
||||||
if !alias_source_range.contains(pos) {
|
if !alias_source_range.contains(pos) {
|
||||||
return None;
|
return None;
|
||||||
@ -1264,8 +1264,8 @@ impl ImportSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => {}
|
ImportSelector::Glob(_) => {}
|
||||||
ImportSelector::None(None) => {}
|
ImportSelector::None { alias: None } => {}
|
||||||
ImportSelector::None(Some(alias)) => alias.rename(old_name, new_name),
|
ImportSelector::None { alias: Some(alias) } => alias.rename(old_name, new_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1296,7 +1296,7 @@ impl Node<ImportStatement> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => false,
|
ImportSelector::Glob(_) => false,
|
||||||
ImportSelector::None(_) => name == self.module_name().unwrap(),
|
ImportSelector::None { .. } => name == self.module_name().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1304,7 +1304,7 @@ impl Node<ImportStatement> {
|
|||||||
/// Validated during parsing and guaranteed to return `Some` if the statement imports
|
/// Validated during parsing and guaranteed to return `Some` if the statement imports
|
||||||
/// the module itself (i.e., self.selector is ImportSelector::None).
|
/// the module itself (i.e., self.selector is ImportSelector::None).
|
||||||
pub fn module_name(&self) -> Option<String> {
|
pub fn module_name(&self) -> Option<String> {
|
||||||
if let ImportSelector::None(Some(alias)) = &self.selector {
|
if let ImportSelector::None { alias: Some(alias) } = &self.selector {
|
||||||
return Some(alias.name.clone());
|
return Some(alias.name.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,7 +1447,7 @@ fn import_stmt(i: &mut TokenSlice) -> PResult<BoxNode<ImportStatement>> {
|
|||||||
require_whitespace(i)?;
|
require_whitespace(i)?;
|
||||||
|
|
||||||
let (mut selector, path) = alt((
|
let (mut selector, path) = alt((
|
||||||
string_literal.map(|s| (ImportSelector::None(None), Some(s))),
|
string_literal.map(|s| (ImportSelector::None { alias: None }, Some(s))),
|
||||||
glob.map(|t| {
|
glob.map(|t| {
|
||||||
let s = t.as_source_range();
|
let s = t.as_source_range();
|
||||||
(
|
(
|
||||||
@ -1510,7 +1510,7 @@ fn import_stmt(i: &mut TokenSlice) -> PResult<BoxNode<ImportStatement>> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ImportSelector::None(ref mut a) = selector {
|
if let ImportSelector::None { alias: ref mut a } = selector {
|
||||||
if let Some(alias) = opt(preceded(
|
if let Some(alias) = opt(preceded(
|
||||||
(whitespace, import_as_keyword, whitespace),
|
(whitespace, import_as_keyword, whitespace),
|
||||||
identifier.context(expected("an identifier to alias the import")),
|
identifier.context(expected("an identifier to alias the import")),
|
||||||
|
@ -365,6 +365,7 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parsing::token::TokenSlice;
|
use crate::parsing::token::TokenSlice;
|
||||||
|
|
||||||
fn assert_parse_err<'i, P, O, E>(mut p: P, s: &'i str)
|
fn assert_parse_err<'i, P, O, E>(mut p: P, s: &'i str)
|
||||||
where
|
where
|
||||||
O: std::fmt::Debug,
|
O: std::fmt::Debug,
|
||||||
|
@ -127,7 +127,7 @@ async fn execute(test_name: &str, render_to_png: bool) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert_snapshot(test_name, "Operations executed", || {
|
assert_snapshot(test_name, "Operations executed", || {
|
||||||
insta::assert_json_snapshot!("ops", e.exec_state.operations);
|
insta::assert_json_snapshot!("ops", e.exec_state.mod_local.operations);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
e => {
|
e => {
|
||||||
@ -711,6 +711,27 @@ mod import_glob {
|
|||||||
super::execute(TEST_NAME, false).await
|
super::execute(TEST_NAME, false).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mod import_whole {
|
||||||
|
const TEST_NAME: &str = "import_whole";
|
||||||
|
|
||||||
|
/// Test parsing KCL.
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
super::parse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||||
|
#[test]
|
||||||
|
fn unparse() {
|
||||||
|
super::unparse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that KCL is executed correctly.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute() {
|
||||||
|
super::execute(TEST_NAME, false).await
|
||||||
|
}
|
||||||
|
}
|
||||||
mod import_side_effect {
|
mod import_side_effect {
|
||||||
const TEST_NAME: &str = "import_side_effect";
|
const TEST_NAME: &str = "import_side_effect";
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ impl Args {
|
|||||||
exec_state: &'e mut ExecState,
|
exec_state: &'e mut ExecState,
|
||||||
tag: &'a TagIdentifier,
|
tag: &'a TagIdentifier,
|
||||||
) -> Result<&'e crate::execution::TagEngineInfo, KclError> {
|
) -> Result<&'e crate::execution::TagEngineInfo, KclError> {
|
||||||
if let KclValue::TagIdentifier(t) = exec_state.memory.get(&tag.value, self.source_range)? {
|
if let KclValue::TagIdentifier(t) = exec_state.memory().get(&tag.value, self.source_range)? {
|
||||||
Ok(t.info.as_ref().ok_or_else(|| {
|
Ok(t.info.as_ref().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Tag `{}` does not have engine info", tag.value),
|
message: format!("Tag `{}` does not have engine info", tag.value),
|
||||||
@ -251,12 +251,12 @@ impl Args {
|
|||||||
// Find all the solids on the same shared sketch.
|
// Find all the solids on the same shared sketch.
|
||||||
ids.extend(
|
ids.extend(
|
||||||
exec_state
|
exec_state
|
||||||
.memory
|
.memory()
|
||||||
.find_solids_on_sketch(solid.sketch.id)
|
.find_solids_on_sketch(solid.sketch.id)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|eg| eg.get_all_edge_cut_ids()),
|
.flat_map(|eg| eg.get_all_edge_cut_ids()),
|
||||||
);
|
);
|
||||||
ids.extend(exec_state.dynamic_state.edge_cut_ids_on_sketch(sketch_id));
|
ids.extend(exec_state.mod_local.dynamic_state.edge_cut_ids_on_sketch(sketch_id));
|
||||||
traversed_sketches.push(sketch_id);
|
traversed_sketches.push(sketch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ async fn inner_chamfer(
|
|||||||
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
|
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.global.id_generator.next_uuid();
|
||||||
args.batch_end_cmd(
|
args.batch_end_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::Solid3dFilletEdge {
|
ModelingCmd::from(mcmd::Solid3dFilletEdge {
|
||||||
|
@ -84,7 +84,7 @@ async fn inner_extrude(
|
|||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<SolidSet, KclError> {
|
) -> Result<SolidSet, KclError> {
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
// Extrude the element(s).
|
// Extrude the element(s).
|
||||||
let sketches: Vec<Sketch> = sketch_set.into();
|
let sketches: Vec<Sketch> = sketch_set.into();
|
||||||
@ -93,7 +93,7 @@ async fn inner_extrude(
|
|||||||
// Before we extrude, we need to enable the sketch mode.
|
// Before we extrude, we need to enable the sketch mode.
|
||||||
// We do this here in case extrude is called out of order.
|
// We do this here in case extrude is called out of order.
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::EnableSketchMode {
|
ModelingCmd::from(mcmd::EnableSketchMode {
|
||||||
animated: false,
|
animated: false,
|
||||||
ortho: false,
|
ortho: false,
|
||||||
@ -121,7 +121,7 @@ async fn inner_extrude(
|
|||||||
|
|
||||||
// Disable the sketch mode.
|
// Disable the sketch mode.
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@ -140,7 +140,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
// Bring the object to the front of the scene.
|
// Bring the object to the front of the scene.
|
||||||
// See: https://github.com/KittyCAD/modeling-app/issues/806
|
// See: https://github.com/KittyCAD/modeling-app/issues/806
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::ObjectBringToFront { object_id: sketch.id }),
|
ModelingCmd::from(mcmd::ObjectBringToFront { object_id: sketch.id }),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@ -163,7 +163,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
|
|
||||||
let solid3d_info = args
|
let solid3d_info = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::Solid3dGetExtrusionFaceInfo {
|
ModelingCmd::from(mcmd::Solid3dGetExtrusionFaceInfo {
|
||||||
edge_id: any_edge_id,
|
edge_id: any_edge_id,
|
||||||
object_id: sketch.id,
|
object_id: sketch.id,
|
||||||
@ -196,7 +196,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
// Instead, the Typescript codebases (which handles WebSocket sends when compiled via Wasm)
|
// Instead, the Typescript codebases (which handles WebSocket sends when compiled via Wasm)
|
||||||
// uses this to build the artifact graph, which the UI needs.
|
// uses this to build the artifact graph, which the UI needs.
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
|
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
|
||||||
edge_id: curve_id,
|
edge_id: curve_id,
|
||||||
object_id: sketch.id,
|
object_id: sketch.id,
|
||||||
@ -206,7 +206,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
|
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
|
||||||
edge_id: curve_id,
|
edge_id: curve_id,
|
||||||
object_id: sketch.id,
|
object_id: sketch.id,
|
||||||
@ -259,7 +259,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
|
|
||||||
let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::execution::ExtrudePlane {
|
let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::execution::ExtrudePlane {
|
||||||
// pushing this values with a fake face_id to make extrudes mock-execute safe
|
// pushing this values with a fake face_id to make extrudes mock-execute safe
|
||||||
face_id: exec_state.id_generator.next_uuid(),
|
face_id: exec_state.next_uuid(),
|
||||||
tag: path.get_base().tag.clone(),
|
tag: path.get_base().tag.clone(),
|
||||||
geo_meta: GeoMeta {
|
geo_meta: GeoMeta {
|
||||||
id: path.get_base().geo_meta.id,
|
id: path.get_base().geo_meta.id,
|
||||||
@ -305,8 +305,8 @@ fn analyze_faces(exec_state: &mut ExecState, args: &Args, face_infos: Vec<Extrus
|
|||||||
};
|
};
|
||||||
if args.ctx.is_mock() {
|
if args.ctx.is_mock() {
|
||||||
// Create fake IDs for start and end caps, to make extrudes mock-execute safe
|
// Create fake IDs for start and end caps, to make extrudes mock-execute safe
|
||||||
faces.start_cap_id = Some(exec_state.id_generator.next_uuid());
|
faces.start_cap_id = Some(exec_state.next_uuid());
|
||||||
faces.end_cap_id = Some(exec_state.id_generator.next_uuid());
|
faces.end_cap_id = Some(exec_state.next_uuid());
|
||||||
}
|
}
|
||||||
for face_info in face_infos {
|
for face_info in face_infos {
|
||||||
match face_info.cap {
|
match face_info.cap {
|
||||||
|
@ -143,7 +143,7 @@ async fn inner_fillet(
|
|||||||
for edge_tag in data.tags {
|
for edge_tag in data.tags {
|
||||||
let edge_id = edge_tag.get_engine_id(exec_state, &args)?;
|
let edge_id = edge_tag.get_engine_id(exec_state, &args)?;
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_end_cmd(
|
args.batch_end_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::Solid3dFilletEdge {
|
ModelingCmd::from(mcmd::Solid3dFilletEdge {
|
||||||
@ -225,11 +225,11 @@ pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result
|
|||||||
}]
|
}]
|
||||||
async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<Uuid, KclError> {
|
async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState, args: Args) -> Result<Uuid, KclError> {
|
||||||
if args.ctx.is_mock() {
|
if args.ctx.is_mock() {
|
||||||
return Ok(exec_state.id_generator.next_uuid());
|
return Ok(exec_state.next_uuid());
|
||||||
}
|
}
|
||||||
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
@ -302,11 +302,11 @@ async fn inner_get_next_adjacent_edge(
|
|||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Uuid, KclError> {
|
) -> Result<Uuid, KclError> {
|
||||||
if args.ctx.is_mock() {
|
if args.ctx.is_mock() {
|
||||||
return Ok(exec_state.id_generator.next_uuid());
|
return Ok(exec_state.next_uuid());
|
||||||
}
|
}
|
||||||
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
@ -387,11 +387,11 @@ async fn inner_get_previous_adjacent_edge(
|
|||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Uuid, KclError> {
|
) -> Result<Uuid, KclError> {
|
||||||
if args.ctx.is_mock() {
|
if args.ctx.is_mock() {
|
||||||
return Ok(exec_state.id_generator.next_uuid());
|
return Ok(exec_state.next_uuid());
|
||||||
}
|
}
|
||||||
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
let face_id = args.get_adjacent_face_to_tag(exec_state, &tag, false).await?;
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
let tagged_path = args.get_tag_engine_info(exec_state, &tag)?;
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
|
@ -61,7 +61,7 @@ async fn inner_helix(
|
|||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<Solid>, KclError> {
|
) -> Result<Box<Solid>, KclError> {
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::EntityMakeHelix {
|
ModelingCmd::from(mcmd::EntityMakeHelix {
|
||||||
|
@ -300,13 +300,13 @@ async fn inner_import(
|
|||||||
|
|
||||||
if args.ctx.is_mock() {
|
if args.ctx.is_mock() {
|
||||||
return Ok(ImportedGeometry {
|
return Ok(ImportedGeometry {
|
||||||
id: exec_state.id_generator.next_uuid(),
|
id: exec_state.next_uuid(),
|
||||||
value: import_files.iter().map(|f| f.path.to_string()).collect(),
|
value: import_files.iter().map(|f| f.path.to_string()).collect(),
|
||||||
meta: vec![args.source_range.into()],
|
meta: vec![args.source_range.into()],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
let resp = args
|
let resp = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
|
@ -142,7 +142,7 @@ async fn inner_loft(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::Loft {
|
ModelingCmd::from(mcmd::Loft {
|
||||||
|
@ -121,7 +121,7 @@ async fn inner_mirror_2d(
|
|||||||
let (axis, origin) = axis.axis_and_origin()?;
|
let (axis, origin) = axis.axis_and_origin()?;
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::EntityMirror {
|
ModelingCmd::from(mcmd::EntityMirror {
|
||||||
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
||||||
axis,
|
axis,
|
||||||
@ -134,7 +134,7 @@ async fn inner_mirror_2d(
|
|||||||
let edge_id = edge.get_engine_id(exec_state, &args)?;
|
let edge_id = edge.get_engine_id(exec_state, &args)?;
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
|
ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
|
||||||
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
||||||
edge_id,
|
edge_id,
|
||||||
|
@ -379,7 +379,7 @@ async fn send_pattern_transform<T: GeometryTrait>(
|
|||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: &Args,
|
args: &Args,
|
||||||
) -> Result<Vec<T>, KclError> {
|
) -> Result<Vec<T>, KclError> {
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
let resp = args
|
let resp = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
@ -1032,7 +1032,7 @@ async fn pattern_circular(
|
|||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Geometries, KclError> {
|
) -> Result<Geometries, KclError> {
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
let num_repetitions = match data.repetitions() {
|
let num_repetitions = match data.repetitions() {
|
||||||
RepetitionsNeeded::More(n) => n,
|
RepetitionsNeeded::More(n) => n,
|
||||||
RepetitionsNeeded::None => {
|
RepetitionsNeeded::None => {
|
||||||
|
@ -209,7 +209,7 @@ async fn make_offset_plane_in_engine(plane: &Plane, exec_state: &mut ExecState,
|
|||||||
|
|
||||||
// Set the color.
|
// Set the color.
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::PlaneSetColor {
|
ModelingCmd::from(mcmd::PlaneSetColor {
|
||||||
color,
|
color,
|
||||||
plane_id: plane.id,
|
plane_id: plane.id,
|
||||||
|
@ -264,7 +264,7 @@ async fn inner_revolve(
|
|||||||
|
|
||||||
let angle = Angle::from_degrees(data.angle.unwrap_or(360.0));
|
let angle = Angle::from_degrees(data.angle.unwrap_or(360.0));
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
match data.axis {
|
match data.axis {
|
||||||
AxisOrEdgeReference::Axis(axis) => {
|
AxisOrEdgeReference::Axis(axis) => {
|
||||||
let (axis, origin) = axis.axis_and_origin()?;
|
let (axis, origin) = axis.axis_and_origin()?;
|
||||||
|
@ -100,7 +100,7 @@ async fn inner_circle(
|
|||||||
let angle_start = Angle::zero();
|
let angle_start = Angle::zero();
|
||||||
let angle_end = Angle::turn();
|
let angle_end = Angle::turn();
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -269,7 +269,7 @@ async fn inner_polygon(
|
|||||||
// Draw all the lines with unique IDs and modified tags
|
// Draw all the lines with unique IDs and modified tags
|
||||||
for vertex in vertices.iter().skip(1) {
|
for vertex in vertices.iter().skip(1) {
|
||||||
let from = sketch.current_pen_position()?;
|
let from = sketch.current_pen_position()?;
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -304,7 +304,7 @@ async fn inner_polygon(
|
|||||||
|
|
||||||
// Close the polygon by connecting back to the first vertex with a new ID
|
// Close the polygon by connecting back to the first vertex with a new ID
|
||||||
let from = sketch.current_pen_position()?;
|
let from = sketch.current_pen_position()?;
|
||||||
let close_id = exec_state.id_generator.next_uuid();
|
let close_id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
close_id,
|
close_id,
|
||||||
@ -337,7 +337,7 @@ async fn inner_polygon(
|
|||||||
sketch.paths.push(current_path);
|
sketch.paths.push(current_path);
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }),
|
ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -230,7 +230,7 @@ async fn inner_shell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::Solid3dShellFace {
|
ModelingCmd::from(mcmd::Solid3dShellFace {
|
||||||
hollow: false,
|
hollow: false,
|
||||||
face_ids,
|
face_ids,
|
||||||
@ -316,7 +316,7 @@ async fn inner_hollow(
|
|||||||
args.flush_batch_for_solid_set(exec_state, solid.clone().into()).await?;
|
args.flush_batch_for_solid_set(exec_state, solid.clone().into()).await?;
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::Solid3dShellFace {
|
ModelingCmd::from(mcmd::Solid3dShellFace {
|
||||||
hollow: true,
|
hollow: true,
|
||||||
face_ids: Vec::new(), // This is empty because we want to hollow the entire object.
|
face_ids: Vec::new(), // This is empty because we want to hollow the entire object.
|
||||||
|
@ -124,7 +124,7 @@ async fn inner_line_to(
|
|||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Sketch, KclError> {
|
) -> Result<Sketch, KclError> {
|
||||||
let from = sketch.current_pen_position()?;
|
let from = sketch.current_pen_position()?;
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -299,7 +299,7 @@ async fn inner_line(
|
|||||||
let from = sketch.current_pen_position()?;
|
let from = sketch.current_pen_position()?;
|
||||||
let to = [from.x + delta[0], from.y + delta[1]];
|
let to = [from.x + delta[0], from.y + delta[1]];
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -488,7 +488,7 @@ async fn inner_angled_line(
|
|||||||
|
|
||||||
let to: [f64; 2] = [from.x + delta[0], from.y + delta[1]];
|
let to: [f64; 2] = [from.x + delta[0], from.y + delta[1]];
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -1230,7 +1230,7 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
// Hide whatever plane we are sketching on.
|
// Hide whatever plane we are sketching on.
|
||||||
// This is especially helpful for offset planes, which would be visible otherwise.
|
// This is especially helpful for offset planes, which would be visible otherwise.
|
||||||
args.batch_end_cmd(
|
args.batch_end_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::ObjectVisible {
|
ModelingCmd::from(mcmd::ObjectVisible {
|
||||||
object_id: plane.id,
|
object_id: plane.id,
|
||||||
hidden: true,
|
hidden: true,
|
||||||
@ -1243,7 +1243,7 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
|
|
||||||
// Enter sketch mode on the surface.
|
// Enter sketch mode on the surface.
|
||||||
// We call this here so you can reuse the sketch surface for multiple sketches.
|
// We call this here so you can reuse the sketch surface for multiple sketches.
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::EnableSketchMode {
|
ModelingCmd::from(mcmd::EnableSketchMode {
|
||||||
@ -1261,8 +1261,8 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
let path_id = exec_state.id_generator.next_uuid();
|
let path_id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(path_id, ModelingCmd::from(mcmd::StartPath {}))
|
args.batch_modeling_cmd(path_id, ModelingCmd::from(mcmd::StartPath {}))
|
||||||
.await?;
|
.await?;
|
||||||
@ -1427,7 +1427,7 @@ pub(crate) async fn inner_close(
|
|||||||
let from = sketch.current_pen_position()?;
|
let from = sketch.current_pen_position()?;
|
||||||
let to: Point2d = sketch.start.from.into();
|
let to: Point2d = sketch.start.from.into();
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(id, ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }))
|
args.batch_modeling_cmd(id, ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }))
|
||||||
.await?;
|
.await?;
|
||||||
@ -1436,7 +1436,7 @@ pub(crate) async fn inner_close(
|
|||||||
if let SketchSurface::Plane(_) = sketch.on {
|
if let SketchSurface::Plane(_) = sketch.on {
|
||||||
// We were on a plane, disable the sketch mode.
|
// We were on a plane, disable the sketch mode.
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@ -1573,7 +1573,7 @@ pub(crate) async fn inner_arc(
|
|||||||
}
|
}
|
||||||
let ccw = angle_start < angle_end;
|
let ccw = angle_start < angle_end;
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -1652,7 +1652,7 @@ pub(crate) async fn inner_arc_to(
|
|||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Sketch, KclError> {
|
) -> Result<Sketch, KclError> {
|
||||||
let from: Point2d = sketch.current_pen_position()?;
|
let from: Point2d = sketch.current_pen_position()?;
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
// The start point is taken from the path you are extending.
|
// The start point is taken from the path you are extending.
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
@ -1798,7 +1798,7 @@ async fn inner_tangential_arc(
|
|||||||
let tangent_info = sketch.get_tangential_info_from_paths(); //this function desperately needs some documentation
|
let tangent_info = sketch.get_tangential_info_from_paths(); //this function desperately needs some documentation
|
||||||
let tan_previous_point = tangent_info.tan_previous_point(from.into());
|
let tan_previous_point = tangent_info.tan_previous_point(from.into());
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
let (center, to, ccw) = match data {
|
let (center, to, ccw) = match data {
|
||||||
TangentialArcData::RadiusAndOffset { radius, offset } => {
|
TangentialArcData::RadiusAndOffset { radius, offset } => {
|
||||||
@ -1935,7 +1935,7 @@ async fn inner_tangential_arc_to(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let delta = [to_x - from.x, to_y - from.y];
|
let delta = [to_x - from.x, to_y - from.y];
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_modeling_cmd(id, tan_arc_to(&sketch, &delta)).await?;
|
args.batch_modeling_cmd(id, tan_arc_to(&sketch, &delta)).await?;
|
||||||
|
|
||||||
let current_path = Path::TangentialArcTo {
|
let current_path = Path::TangentialArcTo {
|
||||||
@ -2018,7 +2018,7 @@ async fn inner_tangential_arc_to_relative(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_modeling_cmd(id, tan_arc_to(&sketch, &delta)).await?;
|
args.batch_modeling_cmd(id, tan_arc_to(&sketch, &delta)).await?;
|
||||||
|
|
||||||
let current_path = Path::TangentialArcTo {
|
let current_path = Path::TangentialArcTo {
|
||||||
@ -2138,7 +2138,7 @@ async fn inner_bezier_curve(
|
|||||||
let delta = data.to;
|
let delta = data.to;
|
||||||
let to = [from.x + data.to[0], from.y + data.to[1]];
|
let to = [from.x + data.to[0], from.y + data.to[1]];
|
||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -2230,7 +2230,7 @@ async fn inner_hole(
|
|||||||
let hole_sketches: Vec<Sketch> = hole_sketch.into();
|
let hole_sketches: Vec<Sketch> = hole_sketch.into();
|
||||||
for hole_sketch in hole_sketches {
|
for hole_sketch in hole_sketches {
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::Solid2dAddHole {
|
ModelingCmd::from(mcmd::Solid2dAddHole {
|
||||||
object_id: sketch.id,
|
object_id: sketch.id,
|
||||||
hole_id: hole_sketch.id,
|
hole_id: hole_sketch.id,
|
||||||
@ -2241,7 +2241,7 @@ async fn inner_hole(
|
|||||||
// suggestion (mike)
|
// suggestion (mike)
|
||||||
// we also hide the source hole since its essentially "consumed" by this operation
|
// we also hide the source hole since its essentially "consumed" by this operation
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
exec_state.id_generator.next_uuid(),
|
exec_state.next_uuid(),
|
||||||
ModelingCmd::from(mcmd::ObjectVisible {
|
ModelingCmd::from(mcmd::ObjectVisible {
|
||||||
object_id: hole_sketch.id,
|
object_id: hole_sketch.id,
|
||||||
hidden: true,
|
hidden: true,
|
||||||
|
@ -87,7 +87,7 @@ async fn inner_sweep(
|
|||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<Solid>, KclError> {
|
) -> Result<Box<Solid>, KclError> {
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.next_uuid();
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::Sweep {
|
ModelingCmd::from(mcmd::Sweep {
|
||||||
|
@ -41,7 +41,7 @@ pub async fn execute_and_snapshot_ast(
|
|||||||
let ctx = new_context(units, true, project_directory).await?;
|
let ctx = new_context(units, true, project_directory).await?;
|
||||||
do_execute_and_snapshot(&ctx, ast)
|
do_execute_and_snapshot(&ctx, ast)
|
||||||
.await
|
.await
|
||||||
.map(|(state, snap)| (state.memory, state.operations, snap))
|
.map(|(state, snap)| (state.mod_local.memory, state.mod_local.operations, snap))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_and_snapshot_no_auth(
|
pub async fn execute_and_snapshot_no_auth(
|
||||||
|
@ -146,11 +146,11 @@ impl ImportStatement {
|
|||||||
string.push_str(" from ");
|
string.push_str(" from ");
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => string.push_str("* from "),
|
ImportSelector::Glob(_) => string.push_str("* from "),
|
||||||
ImportSelector::None(_) => {}
|
ImportSelector::None { .. } => {}
|
||||||
}
|
}
|
||||||
string.push_str(&format!("\"{}\"", self.path));
|
string.push_str(&format!("\"{}\"", self.path));
|
||||||
|
|
||||||
if let ImportSelector::None(Some(alias)) = &self.selector {
|
if let ImportSelector::None { alias: Some(alias) } = &self.selector {
|
||||||
string.push_str(" as ");
|
string.push_str(" as ");
|
||||||
string.push_str(&alias.name);
|
string.push_str(&alias.name);
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,9 @@ description: Error from executing import_side_effect.kcl
|
|||||||
KCL Semantic error
|
KCL Semantic error
|
||||||
|
|
||||||
× semantic: Error loading imported file. Open it to view more details.
|
× semantic: Error loading imported file. Open it to view more details.
|
||||||
│ export_side_effect.kcl: Cannot send modeling commands while importing.
|
│ tests/import_side_effect/export_side_effect.kcl: Cannot send modeling
|
||||||
│ Wrap your code in a function if you want to import the file.
|
│ commands while importing. Wrap your code in a function if you want to
|
||||||
|
│ import the file.
|
||||||
╭────
|
╭────
|
||||||
1 │ import foo from "export_side_effect.kcl"
|
1 │ import foo from "export_side_effect.kcl"
|
||||||
· ────────────────────────────────────────
|
· ────────────────────────────────────────
|
||||||
|
@ -1,27 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: kcl/src/simulation_tests.rs
|
source: kcl/src/simulation_tests.rs
|
||||||
description: Operations executed import_side_effect.kcl
|
description: Operations executed import_side_effect.kcl
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
[
|
[]
|
||||||
{
|
|
||||||
"isError": true,
|
|
||||||
"labeledArgs": {
|
|
||||||
"data": {
|
|
||||||
"sourceRange": [
|
|
||||||
95,
|
|
||||||
99,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "startSketchOn",
|
|
||||||
"sourceRange": [
|
|
||||||
81,
|
|
||||||
100,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"type": "StdLibCall",
|
|
||||||
"unlabeledArg": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
150
src/wasm-lib/kcl/tests/import_whole/ast.snap
Normal file
150
src/wasm-lib/kcl/tests/import_whole/ast.snap
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/simulation_tests.rs
|
||||||
|
description: Result of parsing import_whole.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"Ok": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"end": 32,
|
||||||
|
"path": "exported_mod.kcl",
|
||||||
|
"selector": {
|
||||||
|
"type": "None",
|
||||||
|
"alias": {
|
||||||
|
"end": 32,
|
||||||
|
"name": "foo",
|
||||||
|
"start": 29,
|
||||||
|
"type": "Identifier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ImportStatement",
|
||||||
|
"type": "ImportStatement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"declaration": {
|
||||||
|
"end": 96,
|
||||||
|
"id": {
|
||||||
|
"end": 37,
|
||||||
|
"name": "bar",
|
||||||
|
"start": 34,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"end": 43,
|
||||||
|
"name": "foo",
|
||||||
|
"start": 40,
|
||||||
|
"type": "Identifier",
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"end": 92,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"end": 72,
|
||||||
|
"key": {
|
||||||
|
"end": 62,
|
||||||
|
"name": "faces",
|
||||||
|
"start": 57,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"start": 57,
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"value": {
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"end": 71,
|
||||||
|
"raw": "'end'",
|
||||||
|
"start": 66,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": "end"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 72,
|
||||||
|
"start": 65,
|
||||||
|
"type": "ArrayExpression",
|
||||||
|
"type": "ArrayExpression"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"end": 90,
|
||||||
|
"key": {
|
||||||
|
"end": 83,
|
||||||
|
"name": "thickness",
|
||||||
|
"start": 74,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"start": 74,
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"value": {
|
||||||
|
"end": 90,
|
||||||
|
"raw": "0.25",
|
||||||
|
"start": 86,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": 0.25
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start": 55,
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"type": "ObjectExpression"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"end": 95,
|
||||||
|
"start": 94,
|
||||||
|
"type": "PipeSubstitution",
|
||||||
|
"type": "PipeSubstitution"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callee": {
|
||||||
|
"end": 54,
|
||||||
|
"name": "shell",
|
||||||
|
"start": 49,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"end": 96,
|
||||||
|
"start": 49,
|
||||||
|
"type": "CallExpression",
|
||||||
|
"type": "CallExpression"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 96,
|
||||||
|
"start": 40,
|
||||||
|
"type": "PipeExpression",
|
||||||
|
"type": "PipeExpression"
|
||||||
|
},
|
||||||
|
"start": 34,
|
||||||
|
"type": "VariableDeclarator"
|
||||||
|
},
|
||||||
|
"end": 96,
|
||||||
|
"kind": "const",
|
||||||
|
"start": 34,
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": 97,
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"end": 34,
|
||||||
|
"start": 32,
|
||||||
|
"type": "NonCodeNode",
|
||||||
|
"value": {
|
||||||
|
"type": "newLine"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startNodes": []
|
||||||
|
},
|
||||||
|
"start": 0
|
||||||
|
}
|
||||||
|
}
|
3
src/wasm-lib/kcl/tests/import_whole/exported_mod.kcl
Normal file
3
src/wasm-lib/kcl/tests/import_whole/exported_mod.kcl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
startSketchOn('XY')
|
||||||
|
|> circle({ center = [5, 5], radius = 10 }, %)
|
||||||
|
|> extrude(10, %)
|
4
src/wasm-lib/kcl/tests/import_whole/input.kcl
Normal file
4
src/wasm-lib/kcl/tests/import_whole/input.kcl
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import "exported_mod.kcl" as foo
|
||||||
|
|
||||||
|
bar = foo
|
||||||
|
|> shell({ faces = ['end'], thickness = 0.25 }, %)
|
32
src/wasm-lib/kcl/tests/import_whole/ops.snap
Normal file
32
src/wasm-lib/kcl/tests/import_whole/ops.snap
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/simulation_tests.rs
|
||||||
|
description: Operations executed import_whole.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"labeledArgs": {
|
||||||
|
"data": {
|
||||||
|
"sourceRange": [
|
||||||
|
55,
|
||||||
|
92,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"solid_set": {
|
||||||
|
"sourceRange": [
|
||||||
|
94,
|
||||||
|
95,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "shell",
|
||||||
|
"sourceRange": [
|
||||||
|
49,
|
||||||
|
96,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "StdLibCall",
|
||||||
|
"unlabeledArg": null
|
||||||
|
}
|
||||||
|
]
|
164
src/wasm-lib/kcl/tests/import_whole/program_memory.snap
Normal file
164
src/wasm-lib/kcl/tests/import_whole/program_memory.snap
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/simulation_tests.rs
|
||||||
|
description: Program memory after executing import_whole.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"environments": [
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"HALF_TURN": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 180.0,
|
||||||
|
"__meta": []
|
||||||
|
},
|
||||||
|
"QUARTER_TURN": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 90.0,
|
||||||
|
"__meta": []
|
||||||
|
},
|
||||||
|
"THREE_QUARTER_TURN": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 270.0,
|
||||||
|
"__meta": []
|
||||||
|
},
|
||||||
|
"ZERO": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 0.0,
|
||||||
|
"__meta": []
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"type": "Solid",
|
||||||
|
"type": "Solid",
|
||||||
|
"id": "[uuid]",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"faceId": "[uuid]",
|
||||||
|
"id": "[uuid]",
|
||||||
|
"sourceRange": [
|
||||||
|
25,
|
||||||
|
68,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"tag": null,
|
||||||
|
"type": "extrudeArc"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sketch": {
|
||||||
|
"type": "Sketch",
|
||||||
|
"id": "[uuid]",
|
||||||
|
"paths": [
|
||||||
|
{
|
||||||
|
"__geoMeta": {
|
||||||
|
"id": "[uuid]",
|
||||||
|
"sourceRange": [
|
||||||
|
25,
|
||||||
|
68,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ccw": true,
|
||||||
|
"center": [
|
||||||
|
5.0,
|
||||||
|
5.0
|
||||||
|
],
|
||||||
|
"from": [
|
||||||
|
15.0,
|
||||||
|
5.0
|
||||||
|
],
|
||||||
|
"radius": 10.0,
|
||||||
|
"tag": null,
|
||||||
|
"to": [
|
||||||
|
15.0,
|
||||||
|
5.0
|
||||||
|
],
|
||||||
|
"type": "Circle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"on": {
|
||||||
|
"type": "plane",
|
||||||
|
"id": "[uuid]",
|
||||||
|
"value": "XY",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"xAxis": {
|
||||||
|
"x": 1.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"yAxis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"zAxis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 1.0
|
||||||
|
},
|
||||||
|
"__meta": []
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"from": [
|
||||||
|
15.0,
|
||||||
|
5.0
|
||||||
|
],
|
||||||
|
"to": [
|
||||||
|
15.0,
|
||||||
|
5.0
|
||||||
|
],
|
||||||
|
"tag": null,
|
||||||
|
"__geoMeta": {
|
||||||
|
"id": "[uuid]",
|
||||||
|
"sourceRange": [
|
||||||
|
25,
|
||||||
|
68,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"__meta": [
|
||||||
|
{
|
||||||
|
"sourceRange": [
|
||||||
|
25,
|
||||||
|
68,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"height": 10.0,
|
||||||
|
"startCapId": "[uuid]",
|
||||||
|
"endCapId": "[uuid]",
|
||||||
|
"__meta": [
|
||||||
|
{
|
||||||
|
"sourceRange": [
|
||||||
|
25,
|
||||||
|
68,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"foo": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 1,
|
||||||
|
"__meta": [
|
||||||
|
{
|
||||||
|
"sourceRange": [
|
||||||
|
0,
|
||||||
|
32,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentEnv": 0,
|
||||||
|
"return": null
|
||||||
|
}
|
@ -86,7 +86,7 @@ pub async fn execute(
|
|||||||
|
|
||||||
// Populate from the old exec state if it exists.
|
// Populate from the old exec state if it exists.
|
||||||
if let Some(program_memory_override) = program_memory_override {
|
if let Some(program_memory_override) = program_memory_override {
|
||||||
exec_state.memory = program_memory_override;
|
exec_state.mod_local.memory = program_memory_override;
|
||||||
} else {
|
} else {
|
||||||
// If we are in mock mode, we don't want to use any cache.
|
// If we are in mock mode, we don't want to use any cache.
|
||||||
if let Some(old) = read_old_ast_memory().await {
|
if let Some(old) = read_old_ast_memory().await {
|
||||||
@ -110,7 +110,7 @@ pub async fn execute(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add additional outputs to the error.
|
// Add additional outputs to the error.
|
||||||
let error = KclErrorWithOutputs::new(err, exec_state.operations.clone());
|
let error = KclErrorWithOutputs::new(err, exec_state.mod_local.operations.clone());
|
||||||
|
|
||||||
// Throw the error.
|
// Throw the error.
|
||||||
return Err(serde_json::to_string(&error).map_err(|serde_err| serde_err.to_string())?);
|
return Err(serde_json::to_string(&error).map_err(|serde_err| serde_err.to_string())?);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod cache;
|
mod cache;
|
||||||
|
|
||||||
use kcl_lib::{
|
use kcl_lib::{
|
||||||
test_server::{execute_and_snapshot, execute_and_snapshot_no_auth, new_context},
|
test_server::{execute_and_snapshot, execute_and_snapshot_no_auth},
|
||||||
UnitLength,
|
UnitLength,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2001,62 +2001,3 @@ async fn kcl_test_error_no_auth_websocket() {
|
|||||||
.to_string()
|
.to_string()
|
||||||
.contains("Please send the following object over this websocket"));
|
.contains("Please send the following object over this websocket"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
|
||||||
async fn kcl_test_ids_stable_between_executions() {
|
|
||||||
let code = r#"sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([61.74, 206.13], %)
|
|
||||||
|> xLine(305.11, %, $seg01)
|
|
||||||
|> yLine(-291.85, %)
|
|
||||||
|> xLine(-segLen(seg01), %)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
|> extrude(40.14, %)
|
|
||||||
|> shell({
|
|
||||||
faces: [seg01],
|
|
||||||
thickness: 3.14,
|
|
||||||
}, %)
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let ctx = new_context(UnitLength::Mm, true, None).await.unwrap();
|
|
||||||
let old_program = kcl_lib::Program::parse_no_errs(code).unwrap();
|
|
||||||
// Execute the program.
|
|
||||||
let mut exec_state = Default::default();
|
|
||||||
let cache_info = kcl_lib::CacheInformation {
|
|
||||||
old: None,
|
|
||||||
new_ast: old_program.ast.clone(),
|
|
||||||
};
|
|
||||||
ctx.run(cache_info, &mut exec_state).await.unwrap();
|
|
||||||
|
|
||||||
// Get the id_generator from the first execution.
|
|
||||||
let id_generator = exec_state.id_generator.clone();
|
|
||||||
|
|
||||||
let code = r#"sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([62.74, 206.13], %)
|
|
||||||
|> xLine(305.11, %, $seg01)
|
|
||||||
|> yLine(-291.85, %)
|
|
||||||
|> xLine(-segLen(seg01), %)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
|> extrude(40.14, %)
|
|
||||||
|> shell({
|
|
||||||
faces: [seg01],
|
|
||||||
thickness: 3.14,
|
|
||||||
}, %)
|
|
||||||
"#;
|
|
||||||
|
|
||||||
// Execute a slightly different program again.
|
|
||||||
let program = kcl_lib::Program::parse_no_errs(code).unwrap();
|
|
||||||
let cache_info = kcl_lib::CacheInformation {
|
|
||||||
old: Some(kcl_lib::OldAstState {
|
|
||||||
ast: old_program.ast.clone(),
|
|
||||||
exec_state: exec_state.clone(),
|
|
||||||
settings: ctx.settings.clone(),
|
|
||||||
}),
|
|
||||||
new_ast: program.ast.clone(),
|
|
||||||
};
|
|
||||||
// Execute the program.
|
|
||||||
ctx.run(cache_info, &mut exec_state).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(id_generator, exec_state.id_generator);
|
|
||||||
}
|
|
||||||
|
@ -15,8 +15,8 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, Modu
|
|||||||
|
|
||||||
// We need to get the sketch ID.
|
// We need to get the sketch ID.
|
||||||
// Get the sketch ID from memory.
|
// Get the sketch ID from memory.
|
||||||
let KclValue::Sketch { value: sketch } = exec_state.memory.get(name, SourceRange::default()).unwrap() else {
|
let KclValue::Sketch { value: sketch } = exec_state.memory().get(name, SourceRange::default()).unwrap() else {
|
||||||
anyhow::bail!("part001 not found in memory: {:?}", exec_state.memory);
|
anyhow::bail!("part001 not found in memory: {:?}", exec_state.memory());
|
||||||
};
|
};
|
||||||
let sketch_id = sketch.id;
|
let sketch_id = sketch.id;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user