diff --git a/core/bash_impl.py b/core/bash_impl.py index 48d552109a..83fa2604be 100644 --- a/core/bash_impl.py +++ b/core/bash_impl.py @@ -322,6 +322,27 @@ def SparseArray_SetElement(sparse_val, index, s): return 0 +def SparseArray_UnsetElement(sparse_val, index): + # type: (value.SparseArray, mops.BigInt) -> int + """A non-zero return value represents an error code. If this + function returns 1, the specified index is out of range. + + """ + + index, ok = _SparseArray_CanonicalizeIndex(sparse_val, index) + if not ok: + return 1 # error_code: out-of-range index + mylib.dict_erase(sparse_val.d, index) + + # update max_index + if mops.Equal(index, sparse_val.max_index): + sparse_val.max_index = mops.MINUS_ONE + for index in sparse_val.d: + if mops.Greater(index, sparse_val.max_index): + sparse_val.max_index = index + return 0 + + def SparseArray_ToStrForShellPrint(sparse_val): # type: (value.SparseArray) -> str diff --git a/core/state.py b/core/state.py index 0ece2292ac..c7f87dbe6c 100644 --- a/core/state.py +++ b/core/state.py @@ -2288,6 +2288,15 @@ def Unset(self, lval, which_scopes): raise error.Runtime( "%s[%d]: Index is out of bounds for array of length %d" % (var_name, lval.index, n)) + elif val.tag() == value_e.SparseArray: + val = cast(value.SparseArray, UP_val) + error_code = bash_impl.SparseArray_UnsetElement( + val, mops.IntWiden(lval.index)) + if error_code == 1: + big_length = bash_impl.SparseArray_Length(val) + raise error.Runtime( + "%s[%d]: Index is out of bounds for array of length %s" + % (var_name, lval.index, mops.ToStr(big_length))) else: raise error.Runtime("%r isn't an array" % var_name) diff --git a/spec/ble-idioms.test.sh b/spec/ble-idioms.test.sh index f568b8b1a5..9d6dd6de1b 100644 --- a/spec/ble-idioms.test.sh +++ b/spec/ble-idioms.test.sh @@ -534,5 +534,77 @@ sp1+=(2) ## STDERR: + sp1+=(2) ## END + ## N-I bash/zsh/mksh/ash STDERR: ## END + + +#### SparseArray: unset -v a[i] +case $SH in bash|zsh|mksh|ash) exit ;; esac + +a=({1..9}) +var a = _a2sp(a) + +declare -p a +unset -v "a[1]" +declare -p a +unset -v "a[9]" +declare -p a +unset -v "a[0]" +declare -p a + +## STDOUT: +declare -a a=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9) +declare -a a=([0]=1 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9) +declare -a a=([0]=1 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9) +declare -a a=([2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9) +## END + +## N-I bash/zsh/mksh/ash STDOUT: +## END + + +#### SparseArray: unset -v a[i] with out-of-bound negative index +case $SH in bash|zsh|mksh|ash) exit ;; esac + +a=(1) +var a = _a2sp(a) + +unset -v "a[-2]" +unset -v "a[-3]" + +## status: 1 +## STDOUT: +## END +## STDERR: + unset -v "a[-2]" + ^ +[ stdin ]:6: a[-2]: Index is out of bounds for array of length 1 + unset -v "a[-3]" + ^ +[ stdin ]:7: a[-3]: Index is out of bounds for array of length 1 +## END + +## N-I bash/zsh/mksh/ash status: 0 +## N-I bash/zsh/mksh/ash STDERR: +## END + + +#### SparseArray: unset -v a[i] for max index +case $SH in bash|zsh|mksh|ash) exit ;; esac + +a=({1..9}) +unset -v 'a[-1]' +a[-1]=x +declare -p a +unset -v 'a[-1]' +a[-1]=x +declare -p a + +## STDOUT: +declare -a a=(1 2 3 4 5 6 7 x) +declare -a a=(1 2 3 4 5 6 x) +## END + +## N-I bash/zsh/mksh/ash STDOUT: +## END