Implement dynamic ranges (#4151)
Closes #4021 Allows array ranges (e.g., `[0..10]`) to take expression instead of just numeric literals as their start and end values. Both expressions are required (we don't support `[0..]`, etc.). I've created a new kind of expression in the AST. The alternative was to represent the internals of an array as some kind of pattern which could initially be fully explicit or ranges. I figured the chosen version was simpler and easier to extend to open ranges, whereas the latter would be easier to extend to mixed ranges or other patterns. I chose simpler, it'll be easy enough to refactor if necessary. Parsing is tested implicitly by the tests of execution and unparsing. --------- Signed-off-by: Nick Cameron <nrc@ncameron.org> Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
This commit is contained in:
File diff suppressed because one or more lines are too long
@ -32,7 +32,7 @@ reduce(array: [KclValue], start: KclValue, reduce_fn: FunctionParam) -> KclValue
|
||||
fn decagon = (radius) => {
|
||||
step = 1 / 10 * tau()
|
||||
sketch001 = startSketchAt([cos(0) * radius, sin(0) * radius])
|
||||
return reduce([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], sketch001, (i, sg) => {
|
||||
return reduce([1..10], sketch001, (i, sg) => {
|
||||
x = cos(step * i) * radius
|
||||
y = sin(step * i) * radius
|
||||
return lineTo([x, y], sg)
|
||||
|
||||
@ -83233,6 +83233,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -86831,6 +86881,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -90433,6 +90533,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -91704,8 +91854,8 @@
|
||||
"unpublished": false,
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"r = 10 // radius\nfn drawCircle = (id) => {\n return startSketchOn(\"XY\")\n |> circle({ center: [id * 2 * r, 0], radius: r }, %)\n}\n\n// Call `drawCircle`, passing in each element of the array.\n// The outputs from each `drawCircle` form a new array,\n// which is the return value from `map`.\ncircles = map([1, 2, 3], drawCircle)",
|
||||
"r = 10 // radius\n// Call `map`, using an anonymous function instead of a named one.\ncircles = map([1, 2, 3], (id) => {\n return startSketchOn(\"XY\")\n |> circle({ center: [id * 2 * r, 0], radius: r }, %)\n})"
|
||||
"r = 10 // radius\nfn drawCircle = (id) => {\n return startSketchOn(\"XY\")\n |> circle({ center: [id * 2 * r, 0], radius: r }, %)\n}\n\n// Call `drawCircle`, passing in each element of the array.\n// The outputs from each `drawCircle` form a new array,\n// which is the return value from `map`.\ncircles = map([1..3], drawCircle)",
|
||||
"r = 10 // radius\n// Call `map`, using an anonymous function instead of a named one.\ncircles = map([1..3], (id) => {\n return startSketchOn(\"XY\")\n |> circle({ center: [id * 2 * r, 0], radius: r }, %)\n})"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -114887,6 +115037,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -118878,6 +119078,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -122476,6 +122726,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -126072,6 +126372,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"end",
|
||||
"endElement",
|
||||
"endInclusive",
|
||||
"start",
|
||||
"startElement",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ArrayRangeExpression"
|
||||
]
|
||||
},
|
||||
"start": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"end": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"startElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endElement": {
|
||||
"$ref": "#/components/schemas/Expr"
|
||||
},
|
||||
"endInclusive": {
|
||||
"description": "Is the `end_element` included in the range?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"digest": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxItems": 32,
|
||||
"minItems": 32,
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -127739,7 +128089,7 @@
|
||||
"unpublished": false,
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"fn decagon = (radius) => {\n step = 1 / 10 * tau()\n sketch001 = startSketchAt([cos(0) * radius, sin(0) * radius])\n return reduce([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], sketch001, (i, sg) => {\n x = cos(step * i) * radius\n y = sin(step * i) * radius\n return lineTo([x, y], sg)\n})\n}\ndecagon(5.0)\n |> close(%)",
|
||||
"fn decagon = (radius) => {\n step = 1 / 10 * tau()\n sketch001 = startSketchAt([cos(0) * radius, sin(0) * radius])\n return reduce([1..10], sketch001, (i, sg) => {\n x = cos(step * i) * radius\n y = sin(step * i) * radius\n return lineTo([x, y], sg)\n})\n}\ndecagon(5.0)\n |> close(%)",
|
||||
"array = [1, 2, 3]\nsum = reduce(array, 0, (i, result_so_far) => {\n return i + result_so_far\n})\nassertEqual(sum, 6, 0.00001, \"1 + 2 + 3 summed is 6\")",
|
||||
"fn add = (a, b) => {\n return a + b\n}\nfn sum = (array) => {\n return reduce(array, 0, add)\n}\nassertEqual(sum([1, 2, 3]), 6, 0.00001, \"1 + 2 + 3 summed is 6\")"
|
||||
]
|
||||
|
||||
@ -197,6 +197,27 @@ An expression can be evaluated to yield a single KCL value.
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `ArrayRangeExpression`| | No |
|
||||
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
|
||||
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
|
||||
| `startElement` |[`Expr`](/docs/kcl/types/Expr)| An expression can be evaluated to yield a single KCL value. | No |
|
||||
| `endElement` |[`Expr`](/docs/kcl/types/Expr)| An expression can be evaluated to yield a single KCL value. | No |
|
||||
| `endInclusive` |`boolean`| Is the `end_element` included in the range? | No |
|
||||
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|
||||
Reference in New Issue
Block a user