Skip to content

Commit

Permalink
Remove EmptyPart; replace it with EmptyWord.
Browse files Browse the repository at this point in the history
This is a tighter invariant on the representation.

All unit, spec, gold, osh-usage, and osh2oil tests pass now.
  • Loading branch information
Andy Chu committed Sep 16, 2018
1 parent 298992a commit 64b5fed
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 28 deletions.
3 changes: 2 additions & 1 deletion bin/oil.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,9 @@ def OshMain(argv0, argv, login_shell):


def OilMain(argv):
arg_r = args.Reader(argv)
try:
opts, opt_index = OIL_SPEC.Parse(argv)
opts = OIL_SPEC.Parse(arg_r)
except args.UsageError as e:
ui.usage('oil usage error: %s', e)
return 2
Expand Down
9 changes: 6 additions & 3 deletions core/word.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,6 @@ def LeftMostSpanForPart(part):
elif part.tag == word_part_e.BracedAltPart:
return const.NO_INTEGER

elif part.tag == word_part_e.EmptyPart:
return const.NO_INTEGER

else:
raise AssertionError(part.__class__.__name__)

Expand Down Expand Up @@ -229,6 +226,9 @@ def LeftMostSpanForWord(w):
elif w.tag == word_e.TokenWord:
return w.token.span_id

elif w.tag == word_e.EmptyWord:
return const.NO_INTEGER

elif w.tag == word_e.BracedWordTree:
if len(w.parts) == 0:
return const.NO_INTEGER
Expand All @@ -253,6 +253,9 @@ def RightMostSpanForWord(w):
end = w.parts[-1]
return _RightMostSpanForPart(end)

elif w.tag == word_e.EmptyWord:
return const.NO_INTEGER

# It's a TokenWord?
return w.token.span_id

Expand Down
15 changes: 8 additions & 7 deletions core/word_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,9 +708,6 @@ def _EvalWordPart(self, part, part_vals, quoted=False):
v = runtime.StringPartValue(s, False)
part_vals.append(v)

elif part.tag == word_part_e.EmptyPart:
part_vals.append(runtime.StringPartValue('', False))

elif part.tag == word_part_e.SingleQuotedPart:
if part.left.id == Id.Left_SingleQuote:
s = ''.join(t.val for t in part.tokens)
Expand Down Expand Up @@ -784,11 +781,15 @@ def _EvalWordToParts(self, word, quoted, part_vals):
List of part_value.
But note that this is a TREE.
"""
assert isinstance(word, ast.CompoundWord), \
"Expected CompoundWord, got %s" % word
if word.tag == word_e.CompoundWord:
for p in word.parts:
self._EvalWordPart(p, part_vals, quoted=quoted)

for p in word.parts:
self._EvalWordPart(p, part_vals, quoted=quoted)
elif word.tag == word_e.EmptyWord:
part_vals.append(runtime.StringPartValue('', False))

else:
raise AssertionError(word.__class__.__name__)

def EvalWordToString(self, word, do_fnmatch=False):
"""
Expand Down
13 changes: 0 additions & 13 deletions osh/osh.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ module osh
| LiteralPart(token token)
| EscapedLiteralPart(token token)
-- for 'foo=' and "${a:-}"
| EmptyPart()
| SingleQuotedPart(token left, token* tokens)
| DoubleQuotedPart(word_part* parts)
| SimpleVarSub(token token)
Expand Down Expand Up @@ -115,18 +114,6 @@ module osh
LhsName(string name)
| LhsIndexedName(string name, arith_expr index)

-- s=1 a[x]=1 a=(1 2 3)
rhs_expr =
Scalar(word w)
| Array(word items)

-- The more principled thing to do
assign_parse =
ScalarLocation(token var_like, assign_op op, rhs_expr rhs)
| ArrayLocation(token array_open, int spid1, int spid2, assign_op op,
rhs_expr rhs)
| Not

-- Need to preserve physical parens? Maybe need Parens node.
arith_expr =
-- TODO: need token
Expand Down
3 changes: 2 additions & 1 deletion osh/word_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ def _ReadVarOpArg(self, arg_lex_mode, eof_type=Id.Undefined_Tok,
# return a CompoundWord with no parts, which is explicitly checked with a
# custom error message.
if not w.parts and arg_lex_mode == lex_mode_e.VS_ARG_DQ and empty_ok:
w.parts.append(ast.EmptyPart())
return ast.EmptyWord()

return w

def _ReadSliceVarOp(self):
Expand Down
1 change: 1 addition & 0 deletions test/osh2oil.sh
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ body
'''
OIL
return
# Bug fix: the combination of an empty here doc and a redirect afterward.
osh0-oil3 << 'OSH' 3<< 'OIL'
cat <<EOF >expect
Expand Down
14 changes: 11 additions & 3 deletions tools/osh2oil.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ def _GetRhsStyle(w):

# Actually splitting NEVER HAPPENS ON ASSIGNMENT. LEAVE IT OFF.

if w.tag == word_e.EmptyWord:
return word_style_e.SQ

if len(w.parts) == 0:
raise AssertionError(w)

Expand Down Expand Up @@ -1086,6 +1089,14 @@ def DoWordInCommand(self, node, local_symbols):
# Not doing anything now
pass

elif node.tag == word_e.EmptyWord:
# Hm do I need to make it ''?
# This only happens for:
# s=
# a[x]=
# ${x:-}
pass

else:
raise AssertionError(node.__class__.__name__)

Expand Down Expand Up @@ -1269,9 +1280,6 @@ def DoWordPart(self, node, local_symbols, quoted=False):
self.f.write("')")
self.cursor.SkipUntil(right_spid + 1)

elif node.tag == word_part_e.EmptyPart:
pass

elif node.tag == word_part_e.ExtGlobPart:
# Change this into a function? It depends whether it is used as
# a glob or fnmatch.
Expand Down

0 comments on commit 64b5fed

Please sign in to comment.