From d5e2f0b1db286a0ce5f7f9ec145e36f6560910f9 Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Fri, 27 Mar 2026 23:36:45 +0000 Subject: [PATCH] fix(interpreter): initialize assoc/indexed arrays for local -A/-a without value `local -A m` followed by `m["a"]="1"` produced an indexed array instead of associative because execute_local_builtin only inserted into call_stack.locals without creating the assoc_arrays entry. Initialize the appropriate array type when local -A or -a is used without a compound assignment value, in both function and global paths. Closes #875 --- crates/bashkit/src/interpreter/mod.rs | 13 ++++++++- .../spec_cases/bash/assoc-arrays.test.sh | 29 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index aca72bdb..e39225ad 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -4505,6 +4505,11 @@ impl Interpreter { .unwrap() .locals .insert(arg.to_string(), String::new()); + if flags.assoc { + self.assoc_arrays.entry(arg.to_string()).or_default(); + } else if flags.array { + self.arrays.entry(arg.to_string()).or_default(); + } if flags.integer { self.variables .insert(format!("_INTEGER_{}", arg), "1".to_string()); @@ -4542,7 +4547,13 @@ impl Interpreter { .insert(var_name.to_string(), value.to_string()); } } else if !is_internal_variable(arg) { - self.insert_variable_checked(arg.to_string(), String::new()); + if flags.assoc { + self.assoc_arrays.entry(arg.to_string()).or_default(); + } else if flags.array { + self.arrays.entry(arg.to_string()).or_default(); + } else { + self.insert_variable_checked(arg.to_string(), String::new()); + } } } } diff --git a/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh b/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh index fc0829a9..1ed9c7bb 100644 --- a/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh @@ -173,6 +173,35 @@ b=2 c=3 ### end +### assoc_local_declare_then_assign +myfunc() { + local -A m + m["a"]="1" + m["b"]="2" + echo "count: ${#m[@]}" + for k in "${!m[@]}"; do echo "key=$k"; done | sort +} +myfunc +### expect +count: 2 +key=a +key=b +### end + +### assoc_local_keys_in_cmdsub +myfunc() { + local -A m + m["a"]="1" + m["b"]="2" + result="$(printf '%s\n' "${!m[@]}" | sort)" + echo "result: [$result]" +} +myfunc +### expect +result: [a +b] +### end + ### assoc_iteration declare -A m m[a]="1"