Skip to content

Commit

Permalink
[word_eval] Implement enough of ${var@a} for ble/is-array.
Browse files Browse the repository at this point in the history
Addresses issue #690.
  • Loading branch information
Andy Chu committed Apr 6, 2020
1 parent 7746dd2 commit fbf7b79
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 12 deletions.
2 changes: 1 addition & 1 deletion frontend/syntax.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ module syntax
| ArrayIndex(arith_expr expr)

suffix_op =
Nullary(id op_id) -- ${x@Q} or ${!prefix@} (which also has prefix_op)
Nullary %Token -- ${x@Q} or ${!prefix@} (which also has prefix_op)
| Unary(id op_id, word arg_word) -- e.g. ${v:-default}
-- TODO: token for / to attribute errors
| PatSub(word pat, word? replace, id replace_mode)
Expand Down
25 changes: 18 additions & 7 deletions osh/word_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
braced_var_sub, Token,
word, word_e, word_t, compound_word,
bracket_op_e, bracket_op__ArrayIndex, bracket_op__WholeArray,
suffix_op_e, suffix_op__Nullary, suffix_op__PatSub, suffix_op__Slice,
suffix_op_e, suffix_op__PatSub, suffix_op__Slice,
suffix_op__Unary,
sh_array_literal, single_quoted, double_quoted, simple_var_sub,
command_sub,
Expand Down Expand Up @@ -862,9 +862,9 @@ def _EvalBracedVarSub(self, part, part_vals, quoted):
names.sort()
val = value.MaybeStrArray(names) # type: value_t

suffix_op = cast(suffix_op__Nullary, part.suffix_op)
suffix_op = cast(Token, part.suffix_op)
# "${!prefix@}" is the only one that doesn't decay
maybe_decay_array = not (quoted and suffix_op.op_id == Id.VOp3_At)
maybe_decay_array = not (quoted and suffix_op.id == Id.VOp3_At)
name_query = True
else:
var_name = part.token.val
Expand Down Expand Up @@ -995,18 +995,29 @@ def _EvalBracedVarSub(self, part, part_vals, quoted):
UP_op = op
with tagswitch(op) as case:
if case(suffix_op_e.Nullary):
op = cast(suffix_op__Nullary, UP_op)
if op.op_id == Id.VOp0_P:
op = cast(Token, UP_op)
op_id = op.id
if op_id == Id.VOp0_P:
prompt = self.prompt_ev.EvalPrompt(val)
# readline gets rid of these, so we should too.
p = prompt.replace('\x01', '').replace('\x02', '')
val = value.Str(p)
elif op.op_id == Id.VOp0_Q:
elif op_id == Id.VOp0_Q:
assert val.tag_() == value_e.Str, val
val = cast(value__Str, val)
val = value.Str(string_ops.ShellQuote(val.s))
elif op_id == Id.VOp0_a:
# We're ONLY simluating -a and -A, not -r -x -n for now. See
# spec/ble-idioms.test.sh.
s = ''
with tagswitch(val) as case:
if case(value_e.MaybeStrArray):
s += 'a'
elif case(value_e.AssocArray):
s += 'A'
val = value.Str(s)
else:
raise NotImplementedError(op.op_id)
e_die('Var op %r not implemented', op.val, token=op)

elif case(suffix_op_e.Unary):
op = cast(suffix_op__Unary, UP_op)
Expand Down
6 changes: 2 additions & 4 deletions osh/word_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,7 @@ def _ParseVarExpr(self, arg_lex_mode, allow_query=False):
part.suffix_op = suffix_op.Unary(op_id, arg_word)

elif op_kind == Kind.VOp0:
op_id = self.token_type
part.suffix_op = suffix_op.Nullary(op_id)
part.suffix_op = self.cur_token # Nullary
self._Next(lex_mode_e.VSub_2) # Expecting }
self._Peek()

Expand Down Expand Up @@ -373,8 +372,7 @@ def _ParseVarExpr(self, arg_lex_mode, allow_query=False):

elif op_kind == Kind.VOp3:
if allow_query:
op_id = self.token_type
part.suffix_op = suffix_op.Nullary(op_id)
part.suffix_op = self.cur_token # Nullary
self._Next(lex_mode_e.VSub_2) # Expecting }
self._Peek()
else:
Expand Down
23 changes: 23 additions & 0 deletions spec/ble-idioms.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,26 @@ echo c_x=$c_x c_y=$c_y
c_x=3 c_y=4
c_x=7 c_y=24
## END

#### is-array with ${var@a}
case $SH in (mksh|ash) exit 1 ;; esac

function ble/is-array { [[ ${!1@a} == *a* ]]; }

ble/is-array undef
echo undef $?

string=''
ble/is-array string
echo string $?

array=(one two three)
ble/is-array array
echo array $?
## STDOUT:
undef 1
string 1
array 0
## END
## N-I zsh/mksh/ash status: 1
## N-I zsh/mksh/ash stdout-json: ""

0 comments on commit fbf7b79

Please sign in to comment.