Add array concatenation using the plus operator
This commit is contained in:
@ -1086,6 +1086,32 @@ impl Node<MemberExpression> {
|
||||
}
|
||||
}
|
||||
|
||||
fn concat(left: &[KclValue], left_el_ty: &RuntimeType, right: &[KclValue], right_el_ty: &RuntimeType) -> KclValue {
|
||||
if left.is_empty() {
|
||||
return KclValue::HomArray {
|
||||
value: right.to_vec(),
|
||||
ty: right_el_ty.clone(),
|
||||
};
|
||||
}
|
||||
if right.is_empty() {
|
||||
return KclValue::HomArray {
|
||||
value: left.to_vec(),
|
||||
ty: left_el_ty.clone(),
|
||||
};
|
||||
}
|
||||
let mut new = left.to_vec();
|
||||
new.extend_from_slice(right);
|
||||
// Propagate the element type if we can.
|
||||
let ty = if right_el_ty.subtype(left_el_ty) {
|
||||
left_el_ty.clone()
|
||||
} else if left_el_ty.subtype(right_el_ty) {
|
||||
right_el_ty.clone()
|
||||
} else {
|
||||
RuntimeType::any()
|
||||
};
|
||||
KclValue::HomArray { value: new, ty }
|
||||
}
|
||||
|
||||
impl Node<BinaryExpression> {
|
||||
#[async_recursion]
|
||||
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||
@ -1104,6 +1130,50 @@ impl Node<BinaryExpression> {
|
||||
meta,
|
||||
});
|
||||
}
|
||||
// Array plus is concatenation.
|
||||
match (&left_value, &right_value) {
|
||||
(
|
||||
KclValue::HomArray {
|
||||
value: left,
|
||||
ty: left_el_ty,
|
||||
..
|
||||
},
|
||||
KclValue::HomArray {
|
||||
value: right,
|
||||
ty: right_el_ty,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
return Ok(concat(left, left_el_ty, right, right_el_ty));
|
||||
}
|
||||
(
|
||||
KclValue::HomArray {
|
||||
value: left,
|
||||
ty: left_el_ty,
|
||||
..
|
||||
},
|
||||
_,
|
||||
) => {
|
||||
// Any single value can be coerced to an array.
|
||||
let right = vec![right_value.clone()];
|
||||
let right_el_ty = RuntimeType::any();
|
||||
return Ok(concat(left, left_el_ty, &right, &right_el_ty));
|
||||
}
|
||||
(
|
||||
_,
|
||||
KclValue::HomArray {
|
||||
value: right,
|
||||
ty: right_el_ty,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
// Any single value can be coerced to an array.
|
||||
let left = vec![left_value.clone()];
|
||||
let left_el_ty = RuntimeType::any();
|
||||
return Ok(concat(&left, &left_el_ty, right, right_el_ty));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Then check if we have solids.
|
||||
|
@ -246,7 +246,7 @@ impl RuntimeType {
|
||||
}
|
||||
|
||||
// Subtype with no coercion, including refining numeric types.
|
||||
fn subtype(&self, sup: &RuntimeType) -> bool {
|
||||
pub(super) fn subtype(&self, sup: &RuntimeType) -> bool {
|
||||
use RuntimeType::*;
|
||||
|
||||
match (self, sup) {
|
||||
|
@ -14,7 +14,7 @@ description: Result of parsing add_arrays.kcl
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"name": "answer",
|
||||
"name": "a",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
@ -96,6 +96,170 @@ description: Result of parsing add_arrays.kcl
|
||||
"start": 0,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"declaration": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"id": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"name": "b",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"left": {
|
||||
"commentStart": 0,
|
||||
"elements": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"raw": "0",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"start": 0,
|
||||
"type": "ArrayExpression",
|
||||
"type": "ArrayExpression"
|
||||
},
|
||||
"moduleId": 0,
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"raw": "2",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
},
|
||||
"moduleId": 0,
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
},
|
||||
"end": 0,
|
||||
"kind": "const",
|
||||
"moduleId": 0,
|
||||
"start": 0,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"declaration": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"id": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"name": "c",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"left": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"raw": "0",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"moduleId": 0,
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"commentStart": 0,
|
||||
"elements": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"raw": "2",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 0,
|
||||
"moduleId": 0,
|
||||
"start": 0,
|
||||
"type": "ArrayExpression",
|
||||
"type": "ArrayExpression"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
},
|
||||
"moduleId": 0,
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
},
|
||||
"end": 0,
|
||||
"kind": "const",
|
||||
"moduleId": 0,
|
||||
"start": 0,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration"
|
||||
}
|
||||
],
|
||||
"commentStart": 0,
|
||||
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Error from executing add_arrays.kcl
|
||||
---
|
||||
KCL Semantic error
|
||||
|
||||
× semantic: Expected a number, but found an array of `number`, `number`
|
||||
╭────
|
||||
1 │ answer = [0, 1] + [2]
|
||||
· ───┬──
|
||||
· ╰── tests/add_arrays/input.kcl
|
||||
╰────
|
@ -1 +1,3 @@
|
||||
answer = [0, 1] + [2]
|
||||
a = [0, 1] + [2]
|
||||
b = [0, 1] + 2
|
||||
c = 0 + [1, 2]
|
||||
|
138
rust/kcl-lib/tests/add_arrays/program_memory.snap
Normal file
138
rust/kcl-lib/tests/add_arrays/program_memory.snap
Normal file
@ -0,0 +1,138 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Variables in memory after executing add_arrays.kcl
|
||||
---
|
||||
{
|
||||
"a": {
|
||||
"type": "HomArray",
|
||||
"value": [
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 2.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"b": {
|
||||
"type": "HomArray",
|
||||
"value": [
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 2.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"c": {
|
||||
"type": "HomArray",
|
||||
"value": [
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 0.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 1.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Number",
|
||||
"value": 2.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -2,4 +2,6 @@
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of unparsing add_arrays.kcl
|
||||
---
|
||||
answer = [0, 1] + [2]
|
||||
a = [0, 1] + [2]
|
||||
b = [0, 1] + 2
|
||||
c = 0 + [1, 2]
|
||||
|
Reference in New Issue
Block a user