Skip to content

Commit

Permalink
Spec test cases for array assignment.
Browse files Browse the repository at this point in the history
Get rid of a call to LooksLikeAssignment().  This will make putting the
array-detection logic in easier.
  • Loading branch information
Andy Chu committed Sep 15, 2018
1 parent e90eb65 commit 3812c98
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
36 changes: 19 additions & 17 deletions osh/cmd_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,20 +229,15 @@ def _SplitSimpleCommandPrefix(words):
def _MakeSimpleCommand(prefix_bindings, suffix_words, redirects):
"""Create an ast.SimpleCommand node."""

# FOO=(1 2 3) ls is not allowed
# FOO=(1 2 3) ls is not allowed.
for k, _, v, _ in prefix_bindings:
if word.HasArrayPart(v):
p_die("Environment bindings can't contain array literals", word=v)

# echo FOO=(1 2 3) is not allowed
# NOTE: Other checks can be inserted here. Can resolve builtins,
# functions, aliases, static PATH, etc.
# echo FOO=(1 2 3) is not allowed (but we should NOT fail on echo FOO[x]=1).
for w in suffix_words:
kov = word.LooksLikeAssignment(w)
if kov:
_, _, v = kov
if word.HasArrayPart(v):
p_die("Commands can't contain array literals", word=w)
if word.HasArrayPart(w):
p_die("Commands can't contain array literals", word=w)

# NOTE: # In bash, {~bob,~jane}/src works, even though ~ isn't the leading
# character of the initial word.
Expand Down Expand Up @@ -699,7 +694,7 @@ def ParseSimpleCommand(self, cur_aliases):

prefix_bindings, suffix_words = _SplitSimpleCommandPrefix(words)

if not suffix_words: # ONE=1 TWO=2 (with no other words)
if not suffix_words: # ONE=1 a[x]=1 TWO=2 (with no other words)
if redirects:
binding1 = prefix_bindings[0]
_, _, _, spid = binding1
Expand All @@ -711,6 +706,9 @@ def ParseSimpleCommand(self, cur_aliases):
p.spids.append(spid)
pairs.append(p)

# TODO: Invoke ArithParser, but not before, because the presence of
# a[...] could still lead to an error (when it's an environment binding.

node = ast.Assignment(Id.Assign_None, [], pairs)
left_spid = word.LeftMostSpanForWord(words[0])
node.spids.append(left_spid) # no keyword spid to skip past
Expand All @@ -719,20 +717,21 @@ def ParseSimpleCommand(self, cur_aliases):
kind, kw_token = word.KeywordToken(suffix_words[0])

if kind == Kind.Assign:
# Here we StaticEval suffix_words[1] to see if it's a command like
# 'typeset -p'. Then it becomes a SimpleCommand node instead of an
# Assignment. Note we're not handling duplicate flags like 'typeset
# -pf'. I see this in bashdb (bash debugger) but it can just be changed
# to 'typeset -p -f'.
# Here we StaticEval suffix_words[1] to see if we have an ASSIGNMENT COMMAND
# like 'typeset -p', which lists variables -- a SimpleCommand rather than
# an Assignment.
#
# Note we're not handling duplicate flags like 'typeset -pf'. I see this
# in bashdb (bash debugger) but it can just be changed to 'typeset -p
# -f'.
is_command = False
if len(suffix_words) > 1:
ok, val, _ = word.StaticEval(suffix_words[1])
if ok and (kw_token.id, val) in self._ASSIGN_COMMANDS:
is_command = True

if is_command: # declare -f, declare -p, typeset -p, etc.
node = _MakeSimpleCommand(prefix_bindings, suffix_words,
redirects)
node = _MakeSimpleCommand(prefix_bindings, suffix_words, redirects)
return node

if redirects:
Expand Down Expand Up @@ -779,6 +778,9 @@ def ParseSimpleCommand(self, cur_aliases):
_AppendMoreEnv(prefix_bindings, node.more_env)
return node

# TODO check that we don't have env1=x x[1]=y env2=z here.

# FOO=bar printenv.py FOO
node = _MakeSimpleCommand(prefix_bindings, suffix_words, redirects)
return node

Expand Down
34 changes: 34 additions & 0 deletions spec/assign.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -375,3 +375,37 @@ lib/
## END
## N-I dash stdout: None

#### Multiple assignments / array assignments on a line
a=1 b[0+0]=2 c=3
echo $a $b $c
## stdout: 1 2 3
## N-I dash stdout:

#### assignments / array assignments not interpreted after 'echo'
a=1 echo b[0]=2 c=3
## stdout: b[0]=2 c=3

#### Env bindings shouldn't contain array assignments
a=1 b[0]=2 c=3 printenv.py a b c
## STDOUT:
1
None
3
## END
## BUG mksh STDOUT:
1
2
3
## END
## N-I dash stdout-json: ""
## N-I dash status: 127

#### syntax error in array assignment
a=x b[0+]=y c=z
echo $a $b $c
# status: 2
## BUG bash stdout: x
## BUG bash status: 0
## OK mksh stdout-json: ""
## OK mksh status: 1

0 comments on commit 3812c98

Please sign in to comment.