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.
This commit is contained in:
Michael Schimmel
2026-02-24 10:10:47 +01:00
parent 6810d5fa9f
commit 683d0f4dbe
5 changed files with 45 additions and 10 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
;; Benchmark: 969ns
;; Benchmark-Repeat: 2078
;; Benchmark: 969ns
;; Benchmark-Repeat: 2078
;; Comprehensive Destructuring Test
;; Covers: Nested tuples, mixed params, dynamic passing
+12
View File
@@ -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"]])
)
+1 -7
View File
@@ -308,13 +308,7 @@ impl Specializer {
fn flatten_tuple(&self, node: AnalyzedNode) -> Vec<AnalyzedNode> {
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],
}
}
+9 -1
View File
@@ -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();
+21
View File
@@ -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\"]"
);
}
}