Compare commits

..

6 Commits

Author SHA1 Message Date
09dc17f994 Fix the test 2024-01-25 10:00:17 +11:00
4fa9eb4a0e Refactor: simplify bad code 2024-01-25 10:00:17 +11:00
c2d3808f7c Refactor: plan_to_bind_one returns EvalPlan not tuple 2024-01-25 10:00:17 +11:00
e77c83a7b8 Feature: Grackle stores array length in KCEP
When Grackle compiles a KCL array into KCEP memory, it will write the array length as the first element in memory.
2024-01-25 10:00:17 +11:00
189099bce5 Refactor: EpBinding::Sequence variant is now structlike, not tuplelike 2024-01-25 10:00:17 +11:00
628310952f Failing TDD test 2024-01-25 10:00:17 +11:00
8 changed files with 202 additions and 146 deletions

View File

@ -1864,7 +1864,6 @@ dependencies = [
"dashmap", "dashmap",
"databake", "databake",
"derive-docs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "derive-docs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"either",
"expectorate", "expectorate",
"futures", "futures",
"insta", "insta",

View File

@ -17,7 +17,12 @@ pub enum EpBinding {
/// A KCL value which gets stored in a particular address in KCEP memory. /// A KCL value which gets stored in a particular address in KCEP memory.
Single(Address), Single(Address),
/// A sequence of KCL values, indexed by their position in the sequence. /// A sequence of KCL values, indexed by their position in the sequence.
Sequence(Vec<EpBinding>), Sequence {
/// Address where the length of the array is stored.
length_at: Address,
/// Where is each element in the array bound?
elements: Vec<EpBinding>,
},
/// A sequence of KCL values, indexed by their identifier. /// A sequence of KCL values, indexed by their identifier.
Map(HashMap<String, EpBinding>), Map(HashMap<String, EpBinding>),
/// Not associated with a KCEP address. /// Not associated with a KCEP address.
@ -38,9 +43,11 @@ impl EpBinding {
LiteralIdentifier::Literal(litval) => match litval.value { LiteralIdentifier::Literal(litval) => match litval.value {
// Arrays can be indexed by integers. // Arrays can be indexed by integers.
LiteralValue::IInteger(i) => match self { LiteralValue::IInteger(i) => match self {
EpBinding::Sequence(seq) => { EpBinding::Sequence { length_at: _, elements } => {
let i = usize::try_from(i).map_err(|_| CompileError::InvalidIndex(i.to_string()))?; let i = usize::try_from(i).map_err(|_| CompileError::InvalidIndex(i.to_string()))?;
seq.get(i).ok_or(CompileError::IndexOutOfBounds { i, len: seq.len() }) elements
.get(i)
.ok_or(CompileError::IndexOutOfBounds { i, len: elements.len() })
} }
EpBinding::Map(_) => Err(CompileError::CannotIndex), EpBinding::Map(_) => Err(CompileError::CannotIndex),
EpBinding::Single(_) => Err(CompileError::CannotIndex), EpBinding::Single(_) => Err(CompileError::CannotIndex),
@ -50,7 +57,7 @@ impl EpBinding {
LiteralValue::String(property) => match self { LiteralValue::String(property) => match self {
EpBinding::Single(_) => Err(CompileError::NoProperties), EpBinding::Single(_) => Err(CompileError::NoProperties),
EpBinding::Function(_) => Err(CompileError::NoProperties), EpBinding::Function(_) => Err(CompileError::NoProperties),
EpBinding::Sequence(_) => Err(CompileError::ArrayDoesNotHaveProperties), EpBinding::Sequence { .. } => Err(CompileError::ArrayDoesNotHaveProperties),
EpBinding::Map(map) => map.get(&property).ok_or(CompileError::UndefinedProperty { property }), EpBinding::Map(map) => map.get(&property).ok_or(CompileError::UndefinedProperty { property }),
}, },
// It's never valid to index by a fractional number. // It's never valid to index by a fractional number.

View File

@ -231,7 +231,7 @@ impl Planner {
binding: arg, binding: arg,
} = match KclValueGroup::from(argument) { } = match KclValueGroup::from(argument) {
KclValueGroup::Single(value) => self.plan_to_compute_single(ctx, value)?, KclValueGroup::Single(value) => self.plan_to_compute_single(ctx, value)?,
KclValueGroup::ArrayExpression(_) => todo!(), KclValueGroup::ArrayExpression(expr) => self.plan_to_bind_array(ctx, *expr)?,
KclValueGroup::ObjectExpression(_) => todo!(), KclValueGroup::ObjectExpression(_) => todo!(),
}; };
acc_instrs.extend(new_instructions); acc_instrs.extend(new_instructions);
@ -411,9 +411,9 @@ impl Planner {
.declarations .declarations
.into_iter() .into_iter()
.try_fold(Vec::new(), |mut acc, declaration| { .try_fold(Vec::new(), |mut acc, declaration| {
let (instrs, binding) = self.plan_to_bind_one(&mut ctx, declaration.init)?; let EvalPlan { instructions, binding } = self.plan_to_bind_one(&mut ctx, declaration.init)?;
self.binding_scope.bind(declaration.id.name, binding); self.binding_scope.bind(declaration.id.name, binding);
acc.extend(instrs); acc.extend(instructions);
Ok(acc) Ok(acc)
}) })
} }
@ -422,69 +422,14 @@ impl Planner {
&mut self, &mut self,
ctx: &mut Context, ctx: &mut Context,
value_being_bound: ast::types::Value, value_being_bound: ast::types::Value,
) -> Result<(Vec<Instruction>, EpBinding), CompileError> { ) -> Result<EvalPlan, CompileError> {
match KclValueGroup::from(value_being_bound) { match KclValueGroup::from(value_being_bound) {
KclValueGroup::Single(init_value) => { KclValueGroup::Single(init_value) => {
// Simple! Just evaluate it, note where the final value will be stored in KCEP memory, // Simple! Just evaluate it, note where the final value will be stored in KCEP memory,
// and bind it to the KCL identifier. // and bind it to the KCL identifier.
let EvalPlan { instructions, binding } = self.plan_to_compute_single(ctx, init_value)?; self.plan_to_compute_single(ctx, init_value)
Ok((instructions, binding))
}
KclValueGroup::ArrayExpression(expr) => {
// First, emit a plan to compute each element of the array.
// Collect all the bindings from each element too.
let (instructions, bindings) = expr.elements.into_iter().try_fold(
(Vec::new(), Vec::new()),
|(mut acc_instrs, mut acc_bindings), element| {
match KclValueGroup::from(element) {
KclValueGroup::Single(value) => {
// If this element of the array is a single value, then binding it is
// straightforward -- you got a single binding, no need to change anything.
let EvalPlan { instructions, binding } = self.plan_to_compute_single(ctx, value)?;
acc_instrs.extend(instructions);
acc_bindings.push(binding);
}
KclValueGroup::ArrayExpression(expr) => {
// If this element of the array is _itself_ an array, then we need to
// emit a plan to calculate each element of this child array.
// Then we collect the child array's bindings, and bind them to one
// element of the parent array.
let binding = expr
.elements
.into_iter()
.try_fold(Vec::new(), |mut seq, child_element| {
let (instructions, binding) = self.plan_to_bind_one(ctx, child_element)?;
acc_instrs.extend(instructions);
seq.push(binding);
Ok(seq)
})
.map(EpBinding::Sequence)?;
acc_bindings.push(binding);
}
KclValueGroup::ObjectExpression(expr) => {
// If this element of the array is an object, then we need to
// emit a plan to calculate each value of each property of the object.
// Then we collect the bindings for each child value, and bind them to one
// element of the parent array.
let map = HashMap::with_capacity(expr.properties.len());
let binding = expr
.properties
.into_iter()
.try_fold(map, |mut map, property| {
let (instructions, binding) = self.plan_to_bind_one(ctx, property.value)?;
map.insert(property.key.name, binding);
acc_instrs.extend(instructions);
Ok(map)
})
.map(EpBinding::Map)?;
acc_bindings.push(binding);
}
};
Ok((acc_instrs, acc_bindings))
},
)?;
Ok((instructions, EpBinding::Sequence(bindings)))
} }
KclValueGroup::ArrayExpression(expr) => self.plan_to_bind_array(ctx, *expr),
KclValueGroup::ObjectExpression(expr) => { KclValueGroup::ObjectExpression(expr) => {
// Convert the object to a sequence of key-value pairs. // Convert the object to a sequence of key-value pairs.
let mut kvs = expr.properties.into_iter().map(|prop| (prop.key, prop.value)); let mut kvs = expr.properties.into_iter().map(|prop| (prop.key, prop.value));
@ -502,16 +447,22 @@ impl Planner {
// each element of that array. Collect their bindings, and bind them all // each element of that array. Collect their bindings, and bind them all
// under one property of the parent object. // under one property of the parent object.
let n = expr.elements.len(); let n = expr.elements.len();
let length_at = self.next_addr.offset_by(1);
acc_instrs.push(Instruction::SetPrimitive {
address: length_at,
value: n.into(),
});
let binding = expr let binding = expr
.elements .elements
.into_iter() .into_iter()
.try_fold(Vec::with_capacity(n), |mut seq, child_element| { .try_fold(Vec::with_capacity(n), |mut seq, child_element| {
let (instructions, binding) = self.plan_to_bind_one(ctx, child_element)?; let EvalPlan { instructions, binding } =
self.plan_to_bind_one(ctx, child_element)?;
seq.push(binding); seq.push(binding);
acc_instrs.extend(instructions); acc_instrs.extend(instructions);
Ok(seq) Ok(seq)
}) })
.map(EpBinding::Sequence)?; .map(|elements| EpBinding::Sequence { length_at, elements })?;
acc_bindings.insert(key.name, binding); acc_bindings.insert(key.name, binding);
} }
KclValueGroup::ObjectExpression(expr) => { KclValueGroup::ObjectExpression(expr) => {
@ -524,7 +475,8 @@ impl Planner {
.properties .properties
.into_iter() .into_iter()
.try_fold(HashMap::with_capacity(n), |mut map, property| { .try_fold(HashMap::with_capacity(n), |mut map, property| {
let (instructions, binding) = self.plan_to_bind_one(ctx, property.value)?; let EvalPlan { instructions, binding } =
self.plan_to_bind_one(ctx, property.value)?;
map.insert(property.key.name, binding); map.insert(property.key.name, binding);
acc_instrs.extend(instructions); acc_instrs.extend(instructions);
Ok(map) Ok(map)
@ -536,10 +488,90 @@ impl Planner {
Ok((acc_instrs, acc_bindings)) Ok((acc_instrs, acc_bindings))
}, },
)?; )?;
Ok((instructions, EpBinding::Map(each_property_binding))) Ok(EvalPlan {
instructions,
binding: EpBinding::Map(each_property_binding),
})
} }
} }
} }
fn plan_to_bind_array(
&mut self,
ctx: &mut Context,
expr: ast::types::ArrayExpression,
) -> Result<EvalPlan, CompileError> {
let length_at = self.next_addr.offset_by(1);
let mut instructions = vec![Instruction::SetPrimitive {
address: length_at,
value: expr.elements.len().into(),
}];
// First, emit a plan to compute each element of the array.
// Collect all the bindings from each element too.
let (instrs, bindings) = expr.elements.into_iter().try_fold(
(Vec::new(), Vec::new()),
|(mut acc_instrs, mut acc_bindings), element| {
match KclValueGroup::from(element) {
KclValueGroup::Single(value) => {
// If this element of the array is a single value, then binding it is
// straightforward -- you got a single binding, no need to change anything.
let EvalPlan { instructions, binding } = self.plan_to_compute_single(ctx, value)?;
acc_instrs.extend(instructions);
acc_bindings.push(binding);
}
KclValueGroup::ArrayExpression(expr) => {
// If this element of the array is _itself_ an array, then we need to
// emit a plan to calculate each element of this child array.
// Then we collect the child array's bindings, and bind them to one
// element of the parent array.
let length_at = self.next_addr.offset_by(1);
acc_instrs.push(Instruction::SetPrimitive {
address: length_at,
value: expr.elements.len().into(),
});
let binding = expr
.elements
.into_iter()
.try_fold(Vec::new(), |mut seq, child_element| {
let EvalPlan { instructions, binding } = self.plan_to_bind_one(ctx, child_element)?;
acc_instrs.extend(instructions);
seq.push(binding);
Ok(seq)
})
.map(|elements| EpBinding::Sequence { length_at, elements })?;
acc_bindings.push(binding);
}
KclValueGroup::ObjectExpression(expr) => {
// If this element of the array is an object, then we need to
// emit a plan to calculate each value of each property of the object.
// Then we collect the bindings for each child value, and bind them to one
// element of the parent array.
let map = HashMap::with_capacity(expr.properties.len());
let binding = expr
.properties
.into_iter()
.try_fold(map, |mut map, property| {
let EvalPlan { instructions, binding } = self.plan_to_bind_one(ctx, property.value)?;
map.insert(property.key.name, binding);
acc_instrs.extend(instructions);
Ok(map)
})
.map(EpBinding::Map)?;
acc_bindings.push(binding);
}
};
Ok((acc_instrs, acc_bindings))
},
)?;
instructions.extend(instrs);
Ok(EvalPlan {
instructions,
binding: EpBinding::Sequence {
length_at,
elements: bindings,
},
})
}
} }
/// Every KCL literal value is equivalent to an Execution Plan value, and therefore can be /// Every KCL literal value is equivalent to an Execution Plan value, and therefore can be

View File

@ -48,16 +48,22 @@ fn bind_array() {
assert_eq!( assert_eq!(
plan, plan,
vec![ vec![
// Arrays start with the length.
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO, address: Address::ZERO,
value: 3usize.into(),
},
// Then the elements follow.
Instruction::SetPrimitive {
address: Address::ZERO + 1,
value: 44i64.into(), value: 44i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(1), address: Address::ZERO + 2,
value: 55i64.into(), value: 55i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(2), address: Address::ZERO + 3,
value: "sixty-six".to_owned().into(), value: "sixty-six".to_owned().into(),
} }
] ]
@ -73,14 +79,22 @@ fn bind_nested_array() {
vec![ vec![
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO, address: Address::ZERO,
value: 2usize.into(),
},
Instruction::SetPrimitive {
address: Address::ZERO + 1,
value: 44i64.into(), value: 44i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(1), address: Address::ZERO + 2,
value: 2usize.into(),
},
Instruction::SetPrimitive {
address: Address::ZERO + 3,
value: 55i64.into(), value: 55i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(2), address: Address::ZERO + 4,
value: "sixty-six".to_owned().into(), value: "sixty-six".to_owned().into(),
} }
] ]
@ -96,14 +110,18 @@ fn bind_arrays_with_objects_elements() {
vec![ vec![
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO, address: Address::ZERO,
value: 2usize.into()
},
Instruction::SetPrimitive {
address: Address::ZERO + 1,
value: 44i64.into(), value: 44i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(1), address: Address::ZERO + 2,
value: 55i64.into(), value: 55i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(2), address: Address::ZERO + 3,
value: "sixty-six".to_owned().into(), value: "sixty-six".to_owned().into(),
} }
] ]
@ -187,6 +205,45 @@ fn use_native_function_add() {
); );
} }
#[test]
fn arrays_as_parameters() {
let program = "fn identity = (x) => { return x }
let array = identity([1,2,3])";
let (plan, scope) = must_plan(program);
let expected_plan = vec![
// Array length
Instruction::SetPrimitive {
address: Address::ZERO,
value: 3usize.into(),
},
// Array contents
Instruction::SetPrimitive {
address: Address::ZERO + 1,
value: 1i64.into(),
},
Instruction::SetPrimitive {
address: Address::ZERO + 2,
value: 2i64.into(),
},
Instruction::SetPrimitive {
address: Address::ZERO + 3,
value: 3i64.into(),
},
];
assert_eq!(plan, expected_plan);
assert_eq!(
scope.get("array").unwrap(),
&EpBinding::Sequence {
length_at: Address::ZERO,
elements: vec![
EpBinding::Single(Address::ZERO + 1),
EpBinding::Single(Address::ZERO + 2),
EpBinding::Single(Address::ZERO + 3),
]
}
)
}
#[test] #[test]
fn use_native_function_id() { fn use_native_function_id() {
let program = "let x = id(2)"; let program = "let x = id(2)";
@ -265,7 +322,7 @@ fn member_expressions_array() {
let (_plan, scope) = must_plan(program); let (_plan, scope) = must_plan(program);
match scope.get("first").unwrap() { match scope.get("first").unwrap() {
EpBinding::Single(addr) => { EpBinding::Single(addr) => {
assert_eq!(*addr, Address::ZERO); assert_eq!(*addr, Address::ZERO + 2);
} }
other => { other => {
panic!("expected 'number' bound to 0x0 but it was bound to {other:?}"); panic!("expected 'number' bound to 0x0 but it was bound to {other:?}");
@ -273,7 +330,7 @@ fn member_expressions_array() {
} }
match scope.get("last").unwrap() { match scope.get("last").unwrap() {
EpBinding::Single(addr) => { EpBinding::Single(addr) => {
assert_eq!(*addr, Address::ZERO + 3); assert_eq!(*addr, Address::ZERO + 6);
} }
other => { other => {
panic!("expected 'number' bound to 0x3 but it was bound to {other:?}"); panic!("expected 'number' bound to 0x3 but it was bound to {other:?}");
@ -682,14 +739,11 @@ fn store_object() {
assert_eq!( assert_eq!(
bindings.get("x0").unwrap(), bindings.get("x0").unwrap(),
&EpBinding::Map(HashMap::from([ &EpBinding::Map(HashMap::from([
("a".to_owned(), EpBinding::Single(Address::ZERO),), ("a".to_owned(), EpBinding::Single(Address::ZERO)),
("b".to_owned(), EpBinding::Single(Address::ZERO.offset(1))), ("b".to_owned(), EpBinding::Single(Address::ZERO + 1)),
( (
"c".to_owned(), "c".to_owned(),
EpBinding::Map(HashMap::from([( EpBinding::Map(HashMap::from([("d".to_owned(), EpBinding::Single(Address::ZERO + 2))]))
"d".to_owned(),
EpBinding::Single(Address::ZERO.offset(2))
)]))
), ),
])) ]))
) )
@ -697,7 +751,7 @@ fn store_object() {
#[test] #[test]
fn store_object_with_array_property() { fn store_object_with_array_property() {
let program = "const x0 = {a: 1, b: [2, 3]}"; let program = "const x0 = {a: 1, b: [22, 33]}";
let (actual, bindings) = must_plan(program); let (actual, bindings) = must_plan(program);
let expected = vec![ let expected = vec![
Instruction::SetPrimitive { Instruction::SetPrimitive {
@ -705,12 +759,16 @@ fn store_object_with_array_property() {
value: 1i64.into(), value: 1i64.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(1), address: Address::ZERO + 1,
value: 2i64.into(), value: 2usize.into(),
}, },
Instruction::SetPrimitive { Instruction::SetPrimitive {
address: Address::ZERO.offset(2), address: Address::ZERO + 2,
value: 3i64.into(), value: 22i64.into(),
},
Instruction::SetPrimitive {
address: Address::ZERO + 3,
value: 33i64.into(),
}, },
]; ];
assert_eq!(actual, expected); assert_eq!(actual, expected);
@ -721,10 +779,13 @@ fn store_object_with_array_property() {
("a".to_owned(), EpBinding::Single(Address::ZERO),), ("a".to_owned(), EpBinding::Single(Address::ZERO),),
( (
"b".to_owned(), "b".to_owned(),
EpBinding::Sequence(vec![ EpBinding::Sequence {
EpBinding::Single(Address::ZERO.offset(1)), length_at: Address::ZERO.offset(1),
EpBinding::Single(Address::ZERO.offset(2)), elements: vec![
]) EpBinding::Single(Address::ZERO.offset(2)),
EpBinding::Single(Address::ZERO.offset(3)),
]
}
), ),
])) ]))
) )

View File

@ -32,7 +32,6 @@ thiserror = "1.0.50"
ts-rs = { version = "7", features = ["uuid-impl"] } ts-rs = { version = "7", features = ["uuid-impl"] }
uuid = { version = "1.6.1", features = ["v4", "js", "serde"] } uuid = { version = "1.6.1", features = ["v4", "js", "serde"] }
winnow = "0.5.18" winnow = "0.5.18"
either = "1.6.1"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = { version = "0.3.65" } js-sys = { version = "0.3.65" }

View File

@ -19,7 +19,6 @@ use crate::{
parser::PIPE_OPERATOR, parser::PIPE_OPERATOR,
std::{kcl_stdlib::KclStdLibFn, FunctionKind}, std::{kcl_stdlib::KclStdLibFn, FunctionKind},
}; };
use crate::executor::PathToNode;
mod literal_value; mod literal_value;
mod none; mod none;
@ -1434,7 +1433,6 @@ impl From<Literal> for MemoryItem {
value: JValue::from(literal.value.clone()), value: JValue::from(literal.value.clone()),
meta: vec![Metadata { meta: vec![Metadata {
source_range: literal.into(), source_range: literal.into(),
path_to_node: vec![],
}], }],
}) })
} }
@ -1446,7 +1444,6 @@ impl From<&Box<Literal>> for MemoryItem {
value: JValue::from(literal.value.clone()), value: JValue::from(literal.value.clone()),
meta: vec![Metadata { meta: vec![Metadata {
source_range: literal.into(), source_range: literal.into(),
path_to_node: vec![],
}], }],
}) })
} }
@ -1644,7 +1641,7 @@ impl ArrayExpression {
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await?, 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::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, ctx).await?,
Value::ArrayExpression(array_expression) => array_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, vec![]).await?, Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx).await?,
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
@ -1668,7 +1665,6 @@ impl ArrayExpression {
value: results.into(), value: results.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})) }))
} }
@ -1798,7 +1794,7 @@ impl ObjectExpression {
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await?, 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::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, ctx).await?,
Value::ArrayExpression(array_expression) => array_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, vec![]).await?, Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx).await?,
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
@ -1826,7 +1822,6 @@ impl ObjectExpression {
value: object.into(), value: object.into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})) }))
} }
@ -2036,7 +2031,6 @@ impl MemberExpression {
value: value.clone(), value: value.clone(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})) }))
} else { } else {
@ -2093,7 +2087,6 @@ impl MemberExpression {
value: value.clone(), value: value.clone(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})) }))
} else { } else {
@ -2258,7 +2251,6 @@ impl BinaryExpression {
value, value,
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})); }));
} }
@ -2280,7 +2272,6 @@ impl BinaryExpression {
value, value,
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})) }))
} }
@ -2444,7 +2435,6 @@ impl UnaryExpression {
value: (-(num)).into(), value: (-(num)).into(),
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.into(), source_range: self.into(),
path_to_node: vec![],
}], }],
})) }))
} }
@ -2574,12 +2564,11 @@ impl PipeExpression {
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
path_to_node: PathToNode,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
// Reset the previous results. // Reset the previous results.
pipe_info.previous_results = vec![]; pipe_info.previous_results = vec![];
pipe_info.index = 0; pipe_info.index = 0;
execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx, path_to_node).await execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx).await
} }
/// Rename all identifiers that have the old name to the new given name. /// Rename all identifiers that have the old name to the new given name.
@ -2597,8 +2586,6 @@ async fn execute_pipe_body(
pipe_info: &mut PipeInfo, pipe_info: &mut PipeInfo,
source_range: SourceRange, source_range: SourceRange,
ctx: &ExecutorContext, ctx: &ExecutorContext,
path_to_node: PathToNode,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
if pipe_info.index == body.len() { if pipe_info.index == body.len() {
pipe_info.is_in_pipe = false; pipe_info.is_in_pipe = false;

View File

@ -11,7 +11,6 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value as JValue; use serde_json::Value as JValue;
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
// use either::Either;
use crate::{ use crate::{
ast::types::{BodyItem, FunctionExpression, KclNone, Value}, ast::types::{BodyItem, FunctionExpression, KclNone, Value},
@ -633,18 +632,6 @@ impl From<Point3d> 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. /// Metadata.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
@ -652,16 +639,11 @@ pub type PathToNode = Vec<(NumberOrString, String)>;
pub struct Metadata { pub struct Metadata {
/// The source range. /// The source range.
pub source_range: SourceRange, pub source_range: SourceRange,
/// The path to node for this memory Item
pub path_to_node: PathToNode,
} }
impl From<SourceRange> for Metadata { impl From<SourceRange> for Metadata {
fn from(source_range: SourceRange) -> Self { fn from(source_range: SourceRange) -> Self {
Self { Self { source_range }
source_range,
path_to_node: Vec::new()
}
} }
} }
@ -847,17 +829,12 @@ pub async fn execute(
) -> Result<ProgramMemory, KclError> { ) -> Result<ProgramMemory, KclError> {
let mut pipe_info = PipeInfo::default(); 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. // Iterate over the body of the program.
for (index, statement) in program.body.iter().enumerate() { for statement in &program.body {
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 { match statement {
BodyItem::ExpressionStatement(expression_statement) => { BodyItem::ExpressionStatement(expression_statement) => {
if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { if let Value::PipeExpression(pipe_expr) = &expression_statement.expression {
pipe_expr.get_result(memory, &mut pipe_info, ctx, with_body_path_to_node).await?; pipe_expr.get_result(memory, &mut pipe_info, ctx).await?;
} else if let Value::CallExpression(call_expr) = &expression_statement.expression { } else if let Value::CallExpression(call_expr) = &expression_statement.expression {
let fn_name = call_expr.callee.name.to_string(); let fn_name = call_expr.callee.name.to_string();
let mut args: Vec<MemoryItem> = Vec::new(); let mut args: Vec<MemoryItem> = Vec::new();
@ -928,15 +905,10 @@ pub async fn execute(
} }
} }
BodyItem::VariableDeclaration(variable_declaration) => { 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 var_name = declaration.id.name.to_string();
let source_range: SourceRange = declaration.init.clone().into(); let source_range: SourceRange = declaration.init.clone().into();
let mut with_dec_path_to_node = with_body_path_to_node.clone(); let metadata = Metadata { source_range };
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 { match &declaration.init {
Value::None(none) => { Value::None(none) => {
@ -991,7 +963,7 @@ pub async fn execute(
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::PipeExpression(pipe_expression) => { Value::PipeExpression(pipe_expression) => {
let result = pipe_expression.get_result(memory, &mut pipe_info, ctx, with_dec_path_to_node).await?; let result = pipe_expression.get_result(memory, &mut pipe_info, ctx).await?;
memory.add(&var_name, result, source_range)?; memory.add(&var_name, result, source_range)?;
} }
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
@ -1055,7 +1027,7 @@ pub async fn execute(
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeExpression(pipe_expr) => { Value::PipeExpression(pipe_expr) => {
let result = pipe_expr.get_result(memory, &mut pipe_info, ctx, with_body_path_to_node).await?; let result = pipe_expr.get_result(memory, &mut pipe_info, ctx).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeSubstitution(_) => {} Value::PipeSubstitution(_) => {}

View File

@ -190,7 +190,6 @@ impl Args {
value: j, value: j,
meta: vec![Metadata { meta: vec![Metadata {
source_range: self.source_range, source_range: self.source_range,
path_to_node: Vec::new()
}], }],
})) }))
} }