From 7bf6bc3048f1f3fa770b8c1ae0552dcea1a2250c Mon Sep 17 00:00:00 2001 From: Adam Chalmers Date: Sat, 3 Aug 2024 00:24:00 -0500 Subject: [PATCH] Fix computed properties of KCL objects (#3246) * Fix computed properties of KCL objects Fixes https://github.com/KittyCAD/modeling-app/issues/3201 * Incorporate Jon's feedback --- src/wasm-lib/kcl/src/ast/types.rs | 155 ++++++++++++++---- .../tests/executor/inputs/computed_var.kcl | 18 ++ src/wasm-lib/tests/executor/main.rs | 7 + .../tests/executor/outputs/computed_var.png | Bin 0 -> 71525 bytes 4 files changed, 150 insertions(+), 30 deletions(-) create mode 100644 src/wasm-lib/tests/executor/inputs/computed_var.kcl create mode 100644 src/wasm-lib/tests/executor/outputs/computed_var.png diff --git a/src/wasm-lib/kcl/src/ast/types.rs b/src/wasm-lib/kcl/src/ast/types.rs index 99373a235..aaaff9971 100644 --- a/src/wasm-lib/kcl/src/ast/types.rs +++ b/src/wasm-lib/kcl/src/ast/types.rs @@ -2834,31 +2834,94 @@ impl MemberExpression { } pub fn get_result(&self, memory: &mut ProgramMemory) -> Result { - let property_name = match &self.property { - LiteralIdentifier::Identifier(identifier) => identifier.name.to_string(), + #[derive(Debug)] + enum Property { + Number(usize), + String(String), + } + + impl Property { + fn type_name(&self) -> &'static str { + match self { + Property::Number(_) => "number", + Property::String(_) => "string", + } + } + } + + let property_src: SourceRange = self.property.clone().into(); + let property_sr = vec![property_src]; + + let property: Property = match self.property.clone() { + LiteralIdentifier::Identifier(identifier) => { + let name = identifier.name; + if !self.computed { + // Treat the property as a literal + Property::String(name.to_string()) + } else { + // Actually evaluate memory to compute the property. + let prop = memory.get(&name, property_src)?; + let MemoryItem::UserVal(prop) = prop else { + return Err(KclError::Syntax(KclErrorDetails { + source_ranges: property_sr, + message: format!( + "{name} is not a valid property/index, you can only use a string or int (>= 0) here", + ), + })); + }; + match prop.value { + JValue::Number(ref num) => { + num + .as_u64() + .and_then(|x| usize::try_from(x).ok()) + .map(Property::Number) + .ok_or_else(|| { + KclError::Syntax(KclErrorDetails { + source_ranges: property_sr, + message: format!( + "{name} is not a valid property/index, you can only use a string or int (>= 0) here", + ), + }) + })? + } + JValue::String(ref x) => Property::String(x.to_owned()), + _ => { + return Err(KclError::Syntax(KclErrorDetails { + source_ranges: property_sr, + message: format!( + "{name} is not a valid property/index, you can only use a string to get the property of an object, or an int (>= 0) to get an item in an array", + ), + })); + } + } + } + } LiteralIdentifier::Literal(literal) => { let value = literal.value.clone(); match value { - LiteralValue::IInteger(x) if x >= 0 => return self.get_result_array(memory, x as usize), LiteralValue::IInteger(x) => { + if let Ok(x) = u64::try_from(x) { + Property::Number(x.try_into().unwrap()) + } else { + return Err(KclError::Syntax(KclErrorDetails { + source_ranges: property_sr, + message: format!("{x} is not a valid index, indices must be whole numbers >= 0"), + })); + } + } + LiteralValue::String(s) => Property::String(s), + _ => { return Err(KclError::Syntax(KclErrorDetails { source_ranges: vec![self.into()], - message: format!("invalid index: {x}"), - })) + message: "Only strings or ints (>= 0) can be properties/indexes".to_owned(), + })); } - LiteralValue::Fractional(x) => { - return Err(KclError::Syntax(KclErrorDetails { - source_ranges: vec![self.into()], - message: format!("invalid index: {x}"), - })) - } - LiteralValue::String(s) => s, - LiteralValue::Bool(b) => b.to_string(), } } }; let object = match &self.object { + // TODO: Don't use recursion here, use a loop. MemberObject::MemberExpression(member_expr) => member_expr.get_result(memory)?, MemberObject::Identifier(identifier) => { let value = memory.get(&identifier.name, identifier.into())?; @@ -2868,25 +2931,57 @@ impl MemberExpression { let object_json = object.get_json_value()?; - if let serde_json::Value::Object(map) = object_json { - if let Some(value) = map.get(&property_name) { - Ok(MemoryItem::UserVal(UserVal { - value: value.clone(), - meta: vec![Metadata { - source_range: self.into(), - }], - })) - } else { - Err(KclError::UndefinedValue(KclErrorDetails { - message: format!("Property {} not found in object", property_name), - source_ranges: vec![self.clone().into()], - })) + // Check the property and object match -- e.g. ints for arrays, strs for objects. + match (object_json, property) { + (JValue::Object(map), Property::String(property)) => { + if let Some(value) = map.get(&property) { + Ok(MemoryItem::UserVal(UserVal { + value: value.clone(), + meta: vec![Metadata { + source_range: self.into(), + }], + })) + } else { + Err(KclError::UndefinedValue(KclErrorDetails { + message: format!("Property {property} not found in object"), + source_ranges: vec![self.clone().into()], + })) + } } - } else { - Err(KclError::Semantic(KclErrorDetails { - message: format!("MemberExpression object is not an object: {:?}", object), + (JValue::Object(_), p) => Err(KclError::Semantic(KclErrorDetails { + message: format!( + "Only strings can be used as the property of an object, but you're using a {}", + p.type_name() + ), source_ranges: vec![self.clone().into()], - })) + })), + (JValue::Array(arr), Property::Number(index)) => { + let value_of_arr: Option<&JValue> = arr.get(index); + if let Some(value) = value_of_arr { + Ok(MemoryItem::UserVal(UserVal { + value: value.clone(), + meta: vec![Metadata { + source_range: self.into(), + }], + })) + } else { + Err(KclError::UndefinedValue(KclErrorDetails { + message: format!("The array doesn't have any item at index {index}"), + source_ranges: vec![self.clone().into()], + })) + } + } + (JValue::Array(_), p) => Err(KclError::Semantic(KclErrorDetails { + message: format!( + "Only integers >= 0 can be used as the index of an array, but you're using a {}", + p.type_name() + ), + source_ranges: vec![self.clone().into()], + })), + (_, _) => Err(KclError::Semantic(KclErrorDetails { + message: "Only arrays and objects can be indexed".to_owned(), + source_ranges: vec![self.clone().into()], + })), } } diff --git a/src/wasm-lib/tests/executor/inputs/computed_var.kcl b/src/wasm-lib/tests/executor/inputs/computed_var.kcl new file mode 100644 index 000000000..3797c808e --- /dev/null +++ b/src/wasm-lib/tests/executor/inputs/computed_var.kcl @@ -0,0 +1,18 @@ +// This tests computed properties. + +const arr = [0, 0, 0, 10] +const i = 3 +const ten = arr[i] + +assertLessThanOrEq(ten, 10, "oops") +assertGreaterThanOrEq(ten, 10, "oops2") + +const p = "foo" +const obj = { + foo: 1, + bar: 0, +} +const one = obj[p] + +assertLessThanOrEq(one, 1, "oops") +assertGreaterThanOrEq(one, 1, "oops2") diff --git a/src/wasm-lib/tests/executor/main.rs b/src/wasm-lib/tests/executor/main.rs index 7eb27622b..d88a92e03 100644 --- a/src/wasm-lib/tests/executor/main.rs +++ b/src/wasm-lib/tests/executor/main.rs @@ -38,6 +38,13 @@ async fn kcl_test_lego() { assert_out("lego", &result); } +#[tokio::test(flavor = "multi_thread")] +async fn kcl_test_computed_var() { + let code = kcl_input!("computed_var"); + let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap(); + assert_out("computed_var", &result); +} + #[tokio::test(flavor = "multi_thread")] async fn kcl_test_pipe_as_arg() { let code = kcl_input!("pipe_as_arg"); diff --git a/src/wasm-lib/tests/executor/outputs/computed_var.png b/src/wasm-lib/tests/executor/outputs/computed_var.png new file mode 100644 index 0000000000000000000000000000000000000000..2f91fcf9b2986174d8945ff0f3bd15a3406e725c GIT binary patch literal 71525 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�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 A>;M1& literal 0 HcmV?d00001