diff --git a/src/wasm-lib/Cargo.lock b/src/wasm-lib/Cargo.lock index c985a06a4..fb6b32528 100644 --- a/src/wasm-lib/Cargo.lock +++ b/src/wasm-lib/Cargo.lock @@ -1864,6 +1864,7 @@ dependencies = [ "dashmap", "databake", "derive-docs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "either", "expectorate", "futures", "insta", diff --git a/src/wasm-lib/kcl/Cargo.toml b/src/wasm-lib/kcl/Cargo.toml index a63e3e421..76c7749b4 100644 --- a/src/wasm-lib/kcl/Cargo.toml +++ b/src/wasm-lib/kcl/Cargo.toml @@ -32,6 +32,7 @@ thiserror = "1.0.50" ts-rs = { version = "7", features = ["uuid-impl"] } uuid = { version = "1.6.1", features = ["v4", "js", "serde"] } winnow = "0.5.18" +either = "1.6.1" [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = { version = "0.3.65" } diff --git a/src/wasm-lib/kcl/src/ast/types.rs b/src/wasm-lib/kcl/src/ast/types.rs index 641404a63..c43db51a1 100644 --- a/src/wasm-lib/kcl/src/ast/types.rs +++ b/src/wasm-lib/kcl/src/ast/types.rs @@ -19,6 +19,7 @@ use crate::{ parser::PIPE_OPERATOR, std::{kcl_stdlib::KclStdLibFn, FunctionKind}, }; +use crate::executor::PathToNode; mod literal_value; mod none; @@ -1433,6 +1434,7 @@ impl From for MemoryItem { value: JValue::from(literal.value.clone()), meta: vec![Metadata { source_range: literal.into(), + path_to_node: vec![], }], }) } @@ -1444,6 +1446,7 @@ impl From<&Box> for MemoryItem { value: JValue::from(literal.value.clone()), meta: vec![Metadata { source_range: literal.into(), + path_to_node: vec![], }], }) } @@ -1641,7 +1644,7 @@ impl ArrayExpression { Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await?, Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, ctx).await?, Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, ctx).await?, - Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx).await?, + Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx, vec![]).await?, Value::PipeSubstitution(pipe_substitution) => { return Err(KclError::Semantic(KclErrorDetails { message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), @@ -1665,6 +1668,7 @@ impl ArrayExpression { value: results.into(), meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })) } @@ -1794,7 +1798,7 @@ impl ObjectExpression { Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await?, Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, ctx).await?, Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, ctx).await?, - Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx).await?, + Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx, vec![]).await?, Value::PipeSubstitution(pipe_substitution) => { return Err(KclError::Semantic(KclErrorDetails { message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), @@ -1822,6 +1826,7 @@ impl ObjectExpression { value: object.into(), meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })) } @@ -2031,6 +2036,7 @@ impl MemberExpression { value: value.clone(), meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })) } else { @@ -2087,6 +2093,7 @@ impl MemberExpression { value: value.clone(), meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })) } else { @@ -2251,6 +2258,7 @@ impl BinaryExpression { value, meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })); } @@ -2272,6 +2280,7 @@ impl BinaryExpression { value, meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })) } @@ -2435,6 +2444,7 @@ impl UnaryExpression { value: (-(num)).into(), meta: vec![Metadata { source_range: self.into(), + path_to_node: vec![], }], })) } @@ -2564,11 +2574,12 @@ impl PipeExpression { memory: &mut ProgramMemory, pipe_info: &mut PipeInfo, ctx: &ExecutorContext, + path_to_node: PathToNode, ) -> Result { // Reset the previous results. pipe_info.previous_results = vec![]; pipe_info.index = 0; - execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx).await + execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx, path_to_node).await } /// Rename all identifiers that have the old name to the new given name. @@ -2586,6 +2597,8 @@ async fn execute_pipe_body( pipe_info: &mut PipeInfo, source_range: SourceRange, ctx: &ExecutorContext, + path_to_node: PathToNode, + ) -> Result { if pipe_info.index == body.len() { pipe_info.is_in_pipe = false; diff --git a/src/wasm-lib/kcl/src/executor.rs b/src/wasm-lib/kcl/src/executor.rs index 2b3b976c8..9f5f4fca6 100644 --- a/src/wasm-lib/kcl/src/executor.rs +++ b/src/wasm-lib/kcl/src/executor.rs @@ -11,6 +11,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_json::Value as JValue; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; +// use either::Either; use crate::{ ast::types::{BodyItem, FunctionExpression, KclNone, Value}, @@ -632,6 +633,18 @@ impl From for kittycad::types::Point3D { } } +/// number or string +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] +#[ts(export)] +pub enum NumberOrString { + Num(i32), // assuming 'number' is equivalent to a 32-bit integer + Str(String), +} + +/// PathToNode +pub type PathToNode = Vec<(NumberOrString, String)>; + + /// Metadata. #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[ts(export)] @@ -639,11 +652,16 @@ impl From for kittycad::types::Point3D { pub struct Metadata { /// The source range. pub source_range: SourceRange, + /// The path to node for this memory Item + pub path_to_node: PathToNode, } impl From for Metadata { fn from(source_range: SourceRange) -> Self { - Self { source_range } + Self { + source_range, + path_to_node: Vec::new() + } } } @@ -829,12 +847,17 @@ pub async fn execute( ) -> Result { let mut pipe_info = PipeInfo::default(); + // let path_to_Node: PathToNode = vec![("body".to_string(), "".to_string())]; + let path_to_node: PathToNode = vec![(NumberOrString::Str("body".to_string()), "".to_string())]; + // Iterate over the body of the program. - for statement in &program.body { + for (index, statement) in program.body.iter().enumerate() { + let mut with_body_path_to_node = path_to_node.clone(); + with_body_path_to_node.push((NumberOrString::Num(index as i32), "index".to_string())); match statement { BodyItem::ExpressionStatement(expression_statement) => { if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { - pipe_expr.get_result(memory, &mut pipe_info, ctx).await?; + pipe_expr.get_result(memory, &mut pipe_info, ctx, with_body_path_to_node).await?; } else if let Value::CallExpression(call_expr) = &expression_statement.expression { let fn_name = call_expr.callee.name.to_string(); let mut args: Vec = Vec::new(); @@ -905,10 +928,15 @@ pub async fn execute( } } BodyItem::VariableDeclaration(variable_declaration) => { - for declaration in &variable_declaration.declarations { + + for (index, declaration) in variable_declaration.declarations.iter().enumerate() { let var_name = declaration.id.name.to_string(); let source_range: SourceRange = declaration.init.clone().into(); - let metadata = Metadata { source_range }; + let mut with_dec_path_to_node = with_body_path_to_node.clone(); + with_dec_path_to_node.push((NumberOrString::Str("declarations".to_string()), "VariableDeclaration".to_string())); + with_dec_path_to_node.push((NumberOrString::Num(index as i32), "index".to_string())); + with_dec_path_to_node.push((NumberOrString::Str("init".to_string()), "".to_string())); + let metadata = Metadata { source_range, path_to_node: with_dec_path_to_node.clone() }; match &declaration.init { Value::None(none) => { @@ -963,7 +991,7 @@ pub async fn execute( memory.add(&var_name, result, source_range)?; } Value::PipeExpression(pipe_expression) => { - let result = pipe_expression.get_result(memory, &mut pipe_info, ctx).await?; + let result = pipe_expression.get_result(memory, &mut pipe_info, ctx, with_dec_path_to_node).await?; memory.add(&var_name, result, source_range)?; } Value::PipeSubstitution(pipe_substitution) => { @@ -1027,7 +1055,7 @@ pub async fn execute( memory.return_ = Some(ProgramReturn::Value(result)); } Value::PipeExpression(pipe_expr) => { - let result = pipe_expr.get_result(memory, &mut pipe_info, ctx).await?; + let result = pipe_expr.get_result(memory, &mut pipe_info, ctx, with_body_path_to_node).await?; memory.return_ = Some(ProgramReturn::Value(result)); } Value::PipeSubstitution(_) => {} diff --git a/src/wasm-lib/kcl/src/std/mod.rs b/src/wasm-lib/kcl/src/std/mod.rs index 1dfdef8e9..0a7b21fe1 100644 --- a/src/wasm-lib/kcl/src/std/mod.rs +++ b/src/wasm-lib/kcl/src/std/mod.rs @@ -190,6 +190,7 @@ impl Args { value: j, meta: vec![Metadata { source_range: self.source_range, + path_to_node: Vec::new() }], })) }