From 683d0f4dbed09673107de16ec1d382491ad97535 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Tue, 24 Feb 2026 10:10:47 +0100 Subject: [PATCH] Simplify tuple flattening and destructuring The `flatten_tuple` function was unnecessarily recursive. It can now simply return the elements of the tuple directly. The VM's destructuring logic has been updated to handle nested destructuring more efficiently. A new integration test case for multi-level destructuring has been added. --- examples/destructuring.myc | 4 ++-- examples/tuple-struct.myc | 12 ++++++++++++ src/ast/compiler/specializer.rs | 8 +------- src/ast/vm.rs | 10 +++++++++- src/integration_test.rs | 21 +++++++++++++++++++++ 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 examples/tuple-struct.myc diff --git a/examples/destructuring.myc b/examples/destructuring.myc index 23ad46e..a40a632 100644 --- a/examples/destructuring.myc +++ b/examples/destructuring.myc @@ -1,5 +1,5 @@ -;; Benchmark: 969ns -;; Benchmark-Repeat: 2078 +;; Benchmark: 969ns +;; Benchmark-Repeat: 2078 ;; Comprehensive Destructuring Test ;; Covers: Nested tuples, mixed params, dynamic passing diff --git a/examples/tuple-struct.myc b/examples/tuple-struct.myc new file mode 100644 index 0000000..567811c --- /dev/null +++ b/examples/tuple-struct.myc @@ -0,0 +1,12 @@ +(do + (def pipe (fn [conf] + (do + (def [str s] conf) + (def [f ss] s) + ["Symbol:" str "field:" f "id:" ss] + ) + ) + ) + + (pipe ["btc" [:close "cls"]]) + ) \ No newline at end of file diff --git a/src/ast/compiler/specializer.rs b/src/ast/compiler/specializer.rs index 197fe39..6d35082 100644 --- a/src/ast/compiler/specializer.rs +++ b/src/ast/compiler/specializer.rs @@ -308,13 +308,7 @@ impl Specializer { fn flatten_tuple(&self, node: AnalyzedNode) -> Vec { match node.kind { - BoundKind::Tuple { elements } => { - let mut flat = Vec::new(); - for el in elements { - flat.extend(self.flatten_tuple(el)); - } - flat - } + BoundKind::Tuple { elements } => elements, _ => vec![node], } } diff --git a/src/ast/vm.rs b/src/ast/vm.rs index a8ba6a4..ab23eb4 100644 --- a/src/ast/vm.rs +++ b/src/ast/vm.rs @@ -416,7 +416,15 @@ impl VM { { self.stack.extend(arg_vals); } else { - self.unpack(&closure.parameter_node, &arg_vals, &mut 0)?; + // Map each parameter pattern to the provided arguments + if let BoundKind::Tuple { elements } = &closure.parameter_node.kind { + let mut offset = 0; + for el in elements { + self.unpack(el, &arg_vals, &mut offset)?; + } + } else { + self.unpack(&closure.parameter_node, &arg_vals, &mut 0)?; + } } let result = self.eval_internal(obs, &closure.exec_node); self.frames.pop(); diff --git a/src/integration_test.rs b/src/integration_test.rs index 82cfc59..a817561 100644 --- a/src/integration_test.rs +++ b/src/integration_test.rs @@ -369,4 +369,25 @@ mod tests { } } } + + #[test] + fn test_multi_level_destructuring() { + let env = Environment::new(); + let source = "(do + (def pipe (fn [conf] + (do + (def [str s] conf) + (def [f ss] s) + [\"Symbol:\" str \"field:\" f \"id:\" ss] + ) + ) + ) + (pipe [\"btc\" [:close \"cls\"]]))"; + + let res = env.run_script(source).unwrap(); + assert_eq!( + format!("{}", res), + "[\"Symbol:\" \"btc\" \"field:\" :close \"id:\" \"cls\"]" + ); + } }