Compare commits

..

2 Commits

Author SHA1 Message Date
538f3a322f Format code 2025-07-01 23:27:21 -04:00
ab4ebbe78a Fix to show backtraces of errors in other files 2025-07-01 23:27:00 -04:00
8 changed files with 53 additions and 417 deletions

View File

@ -1086,32 +1086,6 @@ 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> { impl Node<BinaryExpression> {
#[async_recursion] #[async_recursion]
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> { pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
@ -1130,50 +1104,6 @@ impl Node<BinaryExpression> {
meta, 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. // Then check if we have solids.

View File

@ -246,7 +246,7 @@ impl RuntimeType {
} }
// Subtype with no coercion, including refining numeric types. // Subtype with no coercion, including refining numeric types.
pub(super) fn subtype(&self, sup: &RuntimeType) -> bool { fn subtype(&self, sup: &RuntimeType) -> bool {
use RuntimeType::*; use RuntimeType::*;
match (self, sup) { match (self, sup) {

View File

@ -14,7 +14,7 @@ description: Result of parsing add_arrays.kcl
"commentStart": 0, "commentStart": 0,
"end": 0, "end": 0,
"moduleId": 0, "moduleId": 0,
"name": "a", "name": "answer",
"start": 0, "start": 0,
"type": "Identifier" "type": "Identifier"
}, },
@ -96,170 +96,6 @@ description: Result of parsing add_arrays.kcl
"start": 0, "start": 0,
"type": "VariableDeclaration", "type": "VariableDeclaration",
"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, "commentStart": 0,

View File

@ -0,0 +1,12 @@
---
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
╰────

View File

@ -1,3 +1 @@
a = [0, 1] + [2] answer = [0, 1] + [2]
b = [0, 1] + 2
c = 0 + [1, 2]

View File

@ -1,138 +0,0 @@
---
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"
}
}
}
]
}
}

View File

@ -2,6 +2,4 @@
source: kcl-lib/src/simulation_tests.rs source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing add_arrays.kcl description: Result of unparsing add_arrays.kcl
--- ---
a = [0, 1] + [2] answer = [0, 1] + [2]
b = [0, 1] + 2
c = 0 + [1, 2]

View File

@ -371,53 +371,53 @@ export function kclErrorsToDiagnostics(
sourceCode: string sourceCode: string
): CodeMirrorDiagnostic[] { ): CodeMirrorDiagnostic[] {
let nonFatal: CodeMirrorDiagnostic[] = [] let nonFatal: CodeMirrorDiagnostic[] = []
const errs = errors const errs = errors.flatMap((err) => {
?.filter((err) => isTopLevelModule(err.sourceRange)) const diagnostics: CodeMirrorDiagnostic[] = []
.flatMap((err) => { let message = err.msg
const diagnostics: CodeMirrorDiagnostic[] = [] if (err.kclBacktrace.length > 0) {
let message = err.msg // Show the backtrace in the error message.
if (err.kclBacktrace.length > 0) { const backtraceLines: Array<string> = []
// Show the backtrace in the error message. for (let i = 0; i < err.kclBacktrace.length; i++) {
const backtraceLines: Array<string> = [] const item = err.kclBacktrace[i]
for (let i = 0; i < err.kclBacktrace.length; i++) { if (
const item = err.kclBacktrace[i] i > 0 &&
if ( isTopLevelModule(item.sourceRange) &&
i > 0 && !sourceRangeContains(item.sourceRange, err.sourceRange)
isTopLevelModule(item.sourceRange) && ) {
!sourceRangeContains(item.sourceRange, err.sourceRange) diagnostics.push({
) { from: toUtf16(item.sourceRange[0], sourceCode),
diagnostics.push({ to: toUtf16(item.sourceRange[1], sourceCode),
from: toUtf16(item.sourceRange[0], sourceCode), message: 'Part of the error backtrace',
to: toUtf16(item.sourceRange[1], sourceCode), severity: 'hint',
message: 'Part of the error backtrace', })
severity: 'hint',
})
}
if (i === err.kclBacktrace.length - 1 && !item.fnName) {
// The top-level doesn't have a name.
break
}
const name = item.fnName ? `${item.fnName}()` : '(anonymous)'
backtraceLines.push(name)
} }
// If the backtrace is only one line, it's not helpful to show. if (i === err.kclBacktrace.length - 1 && !item.fnName) {
if (backtraceLines.length > 1) { // The top-level doesn't have a name.
message += `\n\nBacktrace:\n${backtraceLines.join('\n')}` break
} }
const name = item.fnName ? `${item.fnName}()` : '(anonymous)'
backtraceLines.push(name)
} }
if (err.nonFatal.length > 0) { // If the backtrace is only one line, it's not helpful to show.
nonFatal = nonFatal.concat( if (backtraceLines.length > 1) {
compilationErrorsToDiagnostics(err.nonFatal, sourceCode) message += `\n\nBacktrace:\n${backtraceLines.join('\n')}`
)
} }
}
if (err.nonFatal.length > 0) {
nonFatal = nonFatal.concat(
compilationErrorsToDiagnostics(err.nonFatal, sourceCode)
)
}
if (isTopLevelModule(err.sourceRange)) {
diagnostics.push({ diagnostics.push({
from: toUtf16(err.sourceRange[0], sourceCode), from: toUtf16(err.sourceRange[0], sourceCode),
to: toUtf16(err.sourceRange[1], sourceCode), to: toUtf16(err.sourceRange[1], sourceCode),
message, message,
severity: 'error', severity: 'error',
}) })
return diagnostics }
}) return diagnostics
})
return errs.concat(nonFatal) return errs.concat(nonFatal)
} }