Permalink
Browse files

More word_eval and splitter cleanup.

- Remove WordPartEvaluator.  We just use WordEvaluator for everything,
  which is a lot cleaner.

- Rename RootSplitter to SplitContext.
- Remove CompletionSplitter; use SplitContext everywhere.
- Make GetJoinChar() a method on the SplitContext
  • Loading branch information...
Andy Chu
Andy Chu committed Jan 6, 2018
1 parent 7dc753e commit c35d3e1a0cdbad9b7130a92fd7a994a494c15d4f
Showing with 72 additions and 120 deletions.
  1. +1 −1 bin/oil.py
  2. +1 −1 core/cmd_exec.py
  3. +5 −5 core/cmd_exec_test.py
  4. +1 −1 core/completion_test.py
  5. +24 −14 core/legacy.py
  6. +1 −1 core/runtime.asdl
  7. +39 −97 core/word_eval.py
View
@@ -326,7 +326,7 @@ def OshMain(argv, login_shell):
# NOTE: We're using a different evaluator here. The completion system can
# also run functions... it gets the Executor through Executor._Complete.
if HAVE_READLINE:
splitter = legacy.CompletionSplitter()
splitter = legacy.SplitContext(mem)
ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter)
status_out = completion.StatusOutput(status_lines, exec_opts)
completion.Init(pool, builtin.BUILTIN_DEF, mem, funcs, comp_lookup,
View
@@ -125,7 +125,7 @@ def __init__(self, mem, status_lines, funcs, completion, comp_lookup,
self.exec_opts = exec_opts
self.arena = arena
self.splitter = legacy.RootSplitter(self.mem)
self.splitter = legacy.SplitContext(self.mem)
self.word_ev = word_eval.NormalWordEvaluator(
mem, exec_opts, self.splitter, self)
self.arith_ev = expr_eval.ArithEvaluator(mem, exec_opts, self.word_ev)
View
@@ -60,7 +60,7 @@ def InitEvaluator():
exec_opts = state.ExecOpts(mem)
# Don't need side effects for most things
splitter = legacy.CompletionSplitter()
splitter = legacy.SplitContext(mem)
return word_eval.CompletionWordEvaluator(mem, exec_opts, splitter)
@@ -85,12 +85,12 @@ def testVarOps(self):
ev = InitEvaluator() # initializes x=xxx and y=yyy
unset_sub = ast.BracedVarSub(ast.token(Id.VSub_Name, 'unset'))
part_vals = []
ev.part_ev.EvalWordPart(unset_sub, part_vals)
ev._EvalWordPart(unset_sub, part_vals)
print(part_vals)
set_sub = ast.BracedVarSub(ast.token(Id.VSub_Name, 'x'))
part_vals = []
ev.part_ev.EvalWordPart(set_sub, part_vals)
ev._EvalWordPart(set_sub, part_vals)
print(part_vals)
# Now add some ops
@@ -101,11 +101,11 @@ def testVarOps(self):
set_sub.suffix_op = test_op
part_vals = []
ev.part_ev.EvalWordPart(unset_sub, part_vals)
ev._EvalWordPart(unset_sub, part_vals)
print(part_vals)
part_vals = []
ev.part_ev.EvalWordPart(set_sub, part_vals)
ev._EvalWordPart(set_sub, part_vals)
print(part_vals)
View
@@ -147,7 +147,7 @@ def testRootCompleter(self):
def _MakeTestEvaluator():
mem = state.Mem('', [], {}, None)
exec_opts = state.ExecOpts(mem)
splitter = legacy.CompletionSplitter()
splitter = legacy.SplitContext(mem)
ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter)
return ev
View
@@ -27,18 +27,6 @@
DEFAULT_IFS = ' \t\n'
class CompletionSplitter:
def __init__(self):
pass
def SplitForWordEval(self, s):
# Return a span that is the whole thing?
# Honestly do I even need this?
return (False, len(s))
# NOTE: Doesn't need to implement SplitForRead
# TODO:
#
# Do we have different splitters? Awk splitter might be useful. Regex
@@ -89,7 +77,7 @@ def _SpansToParts(s, spans):
return parts
class RootSplitter(object):
class SplitContext(object):
""" A polymorphic interface to field splitting.
It respects a STACK of IFS values, for example:
@@ -137,6 +125,28 @@ def _GetSplitter(self):
return sp
def GetJoinChar(self):
"""
For decaying arrays by joining, eg. "$@" -> $@.
array
"""
# https://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters
# http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02
# "When the expansion occurs within a double-quoted string (see
# Double-Quotes), it shall expand to a single field with the value of
# each parameter separated by the first character of the IFS variable, or
# by a <space> if IFS is unset. If IFS is set to a null string, this is
# not equivalent to unsetting it; its first character does not exist, so
# the parameter values are concatenated."
val = self.mem.GetVar('IFS')
if val.tag == value_e.Undef:
return ''
elif val.tag == value_e.Str:
return val.s[0]
else:
# TODO: Raise proper error
raise AssertionError("IFS shouldn't be an array")
def Escape(self, s):
"""Escape IFS chars."""
sp = self._GetSplitter()
@@ -362,7 +372,7 @@ def Split(self, s, allow_escape):
return spans
# self.splitter = RootSplitter()
# self.splitter = SplitContext()
# SplitManager
# Has the cache from IFS -> splitter
# Split(s, allow_escape)
View
@@ -1,6 +1,6 @@
-- Data types for evaluating an AST (or LST at the moment.)
-- TODO: add ASDL option to put constructors under the vraitn namespace:
-- TODO: add ASDL option to put constructors under the variant namespace:
-- part_value.String, part_value.Array
-- fragment
-- arg.Const, arg.Glob
Oops, something went wrong.

0 comments on commit c35d3e1

Please sign in to comment.