diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 64f8f31d4..0b21b1484 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -307,6 +307,7 @@ impl ExecutorContext { // During the evaluation of the variable's RHS, set context that this is all happening inside a variable // declaration, for the given name. This helps improve user-facing error messages. let lhs = variable_declaration.inner.name().to_owned(); + let prev_being_declared = exec_state.mod_local.being_declared.clone(); exec_state.mod_local.being_declared = Some(lhs); let rhs_result = self .execute_expr( @@ -318,7 +319,7 @@ impl ExecutorContext { ) .await; // Declaration over, so unset this context. - exec_state.mod_local.being_declared = None; + exec_state.mod_local.being_declared = prev_being_declared; let rhs = rhs_result?; exec_state @@ -836,6 +837,17 @@ impl Node { &self, exec_state: &'a mut ExecState, ctx: &ExecutorContext, + ) -> Result<&'a KclValue, KclError> { + let being_declared = exec_state.mod_local.being_declared.clone(); + self.get_result_inner(exec_state, ctx) + .await + .map_err(|e| var_in_own_ref_err(e, &being_declared)) + } + + async fn get_result_inner<'a>( + &self, + exec_state: &'a mut ExecState, + ctx: &ExecutorContext, ) -> Result<&'a KclValue, KclError> { if self.abs_path { return Err(KclError::new_semantic(KclErrorDetails::new( diff --git a/rust/kcl-lib/src/simulation_tests.rs b/rust/kcl-lib/src/simulation_tests.rs index 6b57c284c..78927417d 100644 --- a/rust/kcl-lib/src/simulation_tests.rs +++ b/rust/kcl-lib/src/simulation_tests.rs @@ -3525,3 +3525,24 @@ mod ascription_unknown_type { super::execute(TEST_NAME, true).await } } +mod var_ref_in_own_def_decl { + const TEST_NAME: &str = "var_ref_in_own_def_decl"; + + /// Test parsing KCL. + #[test] + fn parse() { + super::parse(TEST_NAME) + } + + /// Test that parsing and unparsing KCL produces the original KCL input. + #[tokio::test(flavor = "multi_thread")] + async fn unparse() { + super::unparse(TEST_NAME).await + } + + /// Test that KCL is executed correctly. + #[tokio::test(flavor = "multi_thread")] + async fn kcl_test_execute() { + super::execute(TEST_NAME, true).await + } +} diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_commands.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_commands.snap new file mode 100644 index 000000000..5756d1352 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_commands.snap @@ -0,0 +1,32 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Artifact commands var_ref_in_own_def_decl.kcl +--- +[ + { + "cmdId": "[uuid]", + "range": [], + "command": { + "type": "edge_lines_visible", + "hidden": false + } + }, + { + "cmdId": "[uuid]", + "range": [], + "command": { + "type": "object_visible", + "object_id": "[uuid]", + "hidden": true + } + }, + { + "cmdId": "[uuid]", + "range": [], + "command": { + "type": "object_visible", + "object_id": "[uuid]", + "hidden": true + } + } +] diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_graph_flowchart.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_graph_flowchart.snap new file mode 100644 index 000000000..0156e40b2 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_graph_flowchart.snap @@ -0,0 +1,6 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Artifact graph flowchart var_ref_in_own_def_decl.kcl +extension: md +snapshot_kind: binary +--- diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_graph_flowchart.snap.md new file mode 100644 index 000000000..13e533509 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/artifact_graph_flowchart.snap.md @@ -0,0 +1,3 @@ +```mermaid +flowchart LR +``` diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap new file mode 100644 index 000000000..f39f611aa --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/ast.snap @@ -0,0 +1,189 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Result of parsing var_ref_in_own_def_decl.kcl +--- +{ + "Ok": { + "body": [ + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "name": "declare", + "start": 0, + "type": "Identifier" + }, + "init": { + "body": { + "body": [ + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "init": { + "commentStart": 0, + "end": 0, + "raw": "0", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.0, + "suffix": "None" + } + }, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "const", + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + }, + { + "argument": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "name": { + "commentStart": 0, + "end": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "start": 0, + "type": "ReturnStatement", + "type": "ReturnStatement" + } + ], + "commentStart": 0, + "end": 0, + "start": 0 + }, + "commentStart": 0, + "end": 0, + "params": [], + "start": 0, + "type": "FunctionExpression", + "type": "FunctionExpression" + }, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "fn", + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + }, + { + "commentStart": 0, + "declaration": { + "commentStart": 0, + "end": 0, + "id": { + "commentStart": 0, + "end": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "init": { + "commentStart": 0, + "end": 0, + "left": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "name": { + "commentStart": 0, + "end": 0, + "name": "x", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + "operator": "+", + "right": { + "callee": { + "abs_path": false, + "commentStart": 0, + "end": 0, + "name": { + "commentStart": 0, + "end": 0, + "name": "declare", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name" + }, + "commentStart": 0, + "end": 0, + "start": 0, + "type": "CallExpressionKw", + "type": "CallExpressionKw", + "unlabeled": null + }, + "start": 0, + "type": "BinaryExpression", + "type": "BinaryExpression" + }, + "start": 0, + "type": "VariableDeclarator" + }, + "end": 0, + "kind": "const", + "start": 0, + "type": "VariableDeclaration", + "type": "VariableDeclaration" + } + ], + "commentStart": 0, + "end": 0, + "nonCodeMeta": { + "nonCodeNodes": { + "0": [ + { + "commentStart": 0, + "end": 0, + "start": 0, + "type": "NonCodeNode", + "value": { + "type": "newLine" + } + } + ] + }, + "startNodes": [] + }, + "start": 0 + } +} diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/execution_error.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/execution_error.snap new file mode 100644 index 000000000..ff5d9c375 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/execution_error.snap @@ -0,0 +1,14 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Error from executing var_ref_in_own_def_decl.kcl +--- +KCL UndefinedValue error + + × undefined value: You can't use `x` because you're currently trying to + │ define it. Use a different variable here instead. + ╭─[6:5] + 5 │ + 6 │ x = x + declare() + · ┬ + · ╰── tests/var_ref_in_own_def_decl/input.kcl + ╰──── diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/input.kcl b/rust/kcl-lib/tests/var_ref_in_own_def_decl/input.kcl new file mode 100644 index 000000000..16c8a6941 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/input.kcl @@ -0,0 +1,6 @@ +fn declare() { + x = 0 + return x +} + +x = x + declare() diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/ops.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/ops.snap new file mode 100644 index 000000000..3c633d243 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/ops.snap @@ -0,0 +1,5 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Operations executed var_ref_in_own_def_decl.kcl +--- +[] diff --git a/rust/kcl-lib/tests/var_ref_in_own_def_decl/unparsed.snap b/rust/kcl-lib/tests/var_ref_in_own_def_decl/unparsed.snap new file mode 100644 index 000000000..f9efa0351 --- /dev/null +++ b/rust/kcl-lib/tests/var_ref_in_own_def_decl/unparsed.snap @@ -0,0 +1,10 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Result of unparsing var_ref_in_own_def_decl.kcl +--- +fn declare() { + x = 0 + return x +} + +x = x + declare()