コード例 #1
0
ファイル: sh_expr_eval.py プロジェクト: shamrin/oil
def _EvalLhsArith(node, mem, arith_ev):
    # type: (sh_lhs_expr_t, Mem, ArithEvaluator) -> lvalue_t
    """sh_lhs_expr -> lvalue.
  
  Very similar to EvalLhs above in core/cmd_exec.
  """
    assert isinstance(node, sh_lhs_expr_t), node

    UP_node = node
    with tagswitch(node) as case:
        if case(sh_lhs_expr_e.Name):  # (( i = 42 ))
            node = cast(sh_lhs_expr__Name, UP_node)

            lval = lvalue.Named(node.name)  # type: lvalue_t
            # TODO: location info.  Use the = token?
            #lval.spids.append(spid)

        elif case(sh_lhs_expr_e.IndexedName):  # (( a[42] = 42 ))
            node = cast(sh_lhs_expr__IndexedName, UP_node)

            # The index of MaybeStrArray needs to be coerced to int, but not the
            # index of an AssocArray.
            if mem.IsAssocArray(node.name, scope_e.Dynamic):
                key = arith_ev.EvalWordToString(node.index)
                lval = lvalue.Keyed(node.name, key)
            else:
                index = arith_ev.EvalToInt(node.index)
                lval = lvalue.Indexed(node.name, index)
                # TODO: location info.  Use the = token?
                #lval.spids.append(node.spids[0])

        else:
            raise AssertionError(node.tag_())

    return lval
コード例 #2
0
ファイル: sh_expr_eval.py プロジェクト: drwilly/oil
  def EvalArithLhs(self, anode, span_id):
    # type: (arith_expr_t, int) -> lvalue_t
    """
    For (( a[x] = 1 )) etc.
    """
    UP_anode = anode
    if anode.tag_() == arith_expr_e.Binary:
      anode = cast(arith_expr__Binary, UP_anode)
      if anode.op_id == Id.Arith_LBracket:
        var_name, span_id = self._VarRefOrWord(anode.left)
        if var_name is not None:
          if self.mem.IsAssocArray(var_name, scope_e.Dynamic):
            key = self.EvalWordToString(anode.right)
            lval2 = lvalue.Keyed(var_name, key)
            lval2.spids.append(span_id)
            lval = lval2  # type: lvalue_t
            return lval
          else:
            index = self.EvalToInt(anode.right)
            lval3 = lvalue.Indexed(var_name, index)
            lval3.spids.append(span_id)
            lval = lval3
            return lval

    var_name, span_id = self._VarRefOrWord(anode)
    if var_name is not None:
      lval1 = lvalue.Named(var_name)
      lval1.spids.append(span_id)
      lval = lval1
      return lval

    # e.g. unset 'x-y'.  status 2 for runtime parse error
    e_die('Invalid place to modify', span_id=span_id, status=2)
コード例 #3
0
def _EvalLhsArith(node, mem, arith_ev):
  """sh_lhs_expr -> lvalue.
  
  Very similar to EvalLhs above in core/cmd_exec.
  """
  assert isinstance(node, sh_lhs_expr_t), node

  if node.tag == sh_lhs_expr_e.Name:  # (( i = 42 ))
    lval = lvalue.Named(node.name)
    # TODO: location info.  Use the = token?
    #lval.spids.append(spid)
    return lval

  elif node.tag == sh_lhs_expr_e.IndexedName:  # (( a[42] = 42 ))
    # The index of MaybeStrArray needs to be coerced to int, but not the index of
    # an AssocArray.
    if mem.IsAssocArray(node.name, scope_e.Dynamic):
      key = arith_ev.EvalWordToString(node.index)
      lval = lvalue.Keyed(node.name, key)
    else:
      index = arith_ev.EvalToIndex(node.index)
      lval = lvalue.Indexed(node.name, index)
      # TODO: location info.  Use the = token?
      #lval.spids.append(node.spids[0])

  else:
    raise AssertionError(node.tag)

  return lval
コード例 #4
0
def EvalLhs(node, arith_ev, mem, spid, lookup_mode):
  """sh_lhs_expr -> lvalue.

  Used for a=b and a[x]=b
  """
  assert isinstance(node, sh_lhs_expr_t), node

  if node.tag == sh_lhs_expr_e.Name:  # a=x
    lval = lvalue.Named(node.name)
    lval.spids.append(spid)

  elif node.tag == sh_lhs_expr_e.IndexedName:  # a[1+2]=x

    if mem.IsAssocArray(node.name, lookup_mode):
      key = arith_ev.EvalWordToString(node.index)
      lval = lvalue.Keyed(node.name, key)
      lval.spids.append(node.spids[0])  # copy left-most token over
    else:
      index = arith_ev.EvalToIndex(node.index)
      lval = lvalue.Indexed(node.name, index)
      lval.spids.append(node.spids[0])  # copy left-most token over

  else:
    raise AssertionError(node.tag)

  return lval
コード例 #5
0
    def _EvalLhsAndLookupArith(self, node):
        # type: (arith_expr_t) -> Tuple[int, lvalue_t]
        """ For x = y  and   x += y  and  ++x """

        lval = self.EvalArithLhs(node, runtime.NO_SPID)
        val = OldValue(lval, self.mem, self.exec_opts)

        # BASH_LINENO, arr (array name with shopt -s compat_array), etc.
        if val.tag_() in (value_e.MaybeStrArray, value_e.AssocArray
                          ) and lval.tag_() == lvalue_e.Named:
            named_lval = cast(lvalue__Named, lval)
            if word_eval.CheckCompatArray(named_lval.name, self.exec_opts):
                if val.tag_() == value_e.MaybeStrArray:
                    lval = lvalue.Indexed(named_lval.name, 0)
                elif val.tag_() == value_e.AssocArray:
                    lval = lvalue.Keyed(named_lval.name, '0')
                val = word_eval.ResolveCompatArray(val)

        # This error message could be better, but we already have one
        #if val.tag_() == value_e.MaybeStrArray:
        #  e_die("Can't use assignment like ++ or += on arrays")

        span_id = location.SpanForArithExpr(node)
        i = self._ValToIntOrError(val, span_id=span_id)
        return i, lval
コード例 #6
0
ファイル: sh_expr_eval.py プロジェクト: shamrin/oil
def EvalLhs(node, arith_ev, mem, spid, lookup_mode):
    # type: (sh_lhs_expr_t, ArithEvaluator, Mem, int, scope_t) -> lvalue_t
    """sh_lhs_expr -> lvalue.

  Used for a=b and a[x]=b
  """
    assert isinstance(node, sh_lhs_expr_t), node

    UP_node = node
    lval = None  # type: lvalue_t
    with tagswitch(node) as case:
        if case(sh_lhs_expr_e.Name):  # a=x
            node = cast(sh_lhs_expr__Name, UP_node)

            # Note: C++ constructor doesn't take spids directly.  Should we add that?
            lval1 = lvalue.Named(node.name)
            lval1.spids.append(spid)
            lval = lval1

        elif case(sh_lhs_expr_e.IndexedName):  # a[1+2]=x
            node = cast(sh_lhs_expr__IndexedName, UP_node)

            if mem.IsAssocArray(node.name, lookup_mode):
                key = arith_ev.EvalWordToString(node.index)
                # copy left-mode spid
                lval2 = lvalue.Keyed(node.name, key)
                lval2.spids.append(node.spids[0])
                lval = lval2
            else:
                index = arith_ev.EvalToInt(node.index)
                # copy left-mode spid
                lval3 = lvalue.Indexed(node.name, index)
                lval3.spids.append(node.spids[0])
                lval = lval3

        else:
            raise AssertionError(node.tag_())

    return lval
コード例 #7
0
ファイル: sh_expr_eval.py プロジェクト: drwilly/oil
  def EvalShellLhs(self, node, spid, lookup_mode):
    # type: (sh_lhs_expr_t, int, scope_t) -> lvalue_t
    """Evaluate a shell LHS expression, i.e. place expression.

    For  a=b  and  a[x]=b  etc.
    """
    assert isinstance(node, sh_lhs_expr_t), node

    UP_node = node
    lval = None  # type: lvalue_t
    with tagswitch(node) as case:
      if case(sh_lhs_expr_e.Name):  # a=x
        node = cast(sh_lhs_expr__Name, UP_node)

        # Note: C++ constructor doesn't take spids directly.  Should we add that?
        lval1 = lvalue.Named(node.name)
        lval1.spids.append(spid)
        lval = lval1

      elif case(sh_lhs_expr_e.IndexedName):  # a[1+2]=x
        node = cast(sh_lhs_expr__IndexedName, UP_node)

        if self.mem.IsAssocArray(node.name, lookup_mode):
          key = self.EvalWordToString(node.index)
          lval2 = lvalue.Keyed(node.name, key)
          lval2.spids.append(node.spids[0])
          lval = lval2
        else:
          index = self.EvalToInt(node.index)
          lval3 = lvalue.Indexed(node.name, index)
          lval3.spids.append(node.spids[0])
          lval = lval3

      else:
        raise AssertionError(node.tag_())

    return lval
コード例 #8
0
ファイル: sh_expr_eval.py プロジェクト: shamrin/oil
def EvalLhsAndLookup(node,
                     arith_ev,
                     mem,
                     exec_opts,
                     lookup_mode=scope_e.Dynamic):
    # type: (sh_lhs_expr_t, ArithEvaluator, Mem, optview.Exec, scope_t) -> Tuple[value_t, lvalue_t]
    """Evaluate the operand for i++, a[0]++, i+=2, a[0]+=2 as an R-value.

  Also used by the Executor for s+='x' and a[42]+='x'.

  Args:
    node: syntax_asdl.sh_lhs_expr

  Returns:
    value_t, lvalue_t
  """
    #log('sh_lhs_expr NODE %s', node)

    assert isinstance(node, sh_lhs_expr_t), node

    UP_node = node
    with tagswitch(node) as case:
        if case(sh_lhs_expr_e.Name):  # a = b
            node = cast(sh_lhs_expr__Name, UP_node)
            # Problem: It can't be an array?
            # a=(1 2)
            # (( a++ ))
            lval = lvalue.Named(node.name)  # type: lvalue_t
            val = _LookupVar(node.name, mem, exec_opts)

        elif case(sh_lhs_expr_e.IndexedName):  # a[1] = b
            node = cast(sh_lhs_expr__IndexedName, UP_node)
            # See tdop.IsIndexable for valid values:
            # - VarRef (not Name): a[1]
            # - FuncCall: f(x), 1
            # - Binary LBracket: f[1][1] -- no semantics for this?

            val = mem.GetVar(node.name)

            UP_val = val
            with tagswitch(val) as case2:
                if case2(value_e.Str):
                    e_die("Can't assign to characters of string %r", node.name)

                elif case2(value_e.Undef):
                    # compatible behavior: Treat it like an array.
                    # TODO: Does this code ever get triggered?  It seems like the error is
                    # caught earlier.

                    index = arith_ev.EvalToInt(node.index)
                    lval = lvalue.Indexed(node.name, index)
                    if exec_opts.nounset():
                        e_die("Undefined variable can't be indexed")
                    else:
                        val = value.Str('')

                elif case2(value_e.MaybeStrArray):
                    array_val = cast(value__MaybeStrArray, UP_val)

                    #log('ARRAY %s -> %s, index %d', node.name, array, index)
                    index = arith_ev.EvalToInt(node.index)
                    lval = lvalue.Indexed(node.name, index)
                    # NOTE: Similar logic in RHS Arith_LBracket
                    try:
                        s = array_val.strs[index]
                    except IndexError:
                        s = None

                    if s is None:
                        val = value.Str(
                            '')  # NOTE: Other logic is value.Undef()?  0?
                    else:
                        assert isinstance(s, str), s
                        val = value.Str(s)

                elif case2(value_e.AssocArray):  # declare -A a; a['x']+=1
                    assoc_val = cast(value__AssocArray, UP_val)

                    key = arith_ev.EvalWordToString(node.index)
                    lval = lvalue.Keyed(node.name, key)

                    s = assoc_val.d.get(key)
                    if s is None:
                        val = value.Str('')
                    else:
                        val = value.Str(s)

                else:
                    raise AssertionError(val.tag_())

        else:
            raise AssertionError(node.tag_())

    return val, lval
コード例 #9
0
def EvalLhsAndLookup(node, arith_ev, mem, exec_opts,
                     lookup_mode=scope_e.Dynamic):
  """Evaluate the operand for i++, a[0]++, i+=2, a[0]+=2 as an R-value.

  Also used by the Executor for s+='x' and a[42]+='x'.

  Args:
    node: syntax_asdl.lhs_expr

  Returns:
    value_t, lvalue_t
  """
  #log('lhs_expr NODE %s', node)

  assert isinstance(node, lhs_expr_t), node

  if node.tag == lhs_expr_e.LhsName:  # a = b
    # Problem: It can't be an array?
    # a=(1 2)
    # (( a++ ))
    lval = lvalue.Named(node.name)
    val = _LookupVar(node.name, mem, exec_opts)

  elif node.tag == lhs_expr_e.LhsIndexedName:  # a[1] = b
    # See tdop.IsIndexable for valid values:
    # - ArithVarRef (not LhsName): a[1]
    # - FuncCall: f(x), 1
    # - ArithBinary LBracket: f[1][1] -- no semantics for this?

    val = mem.GetVar(node.name)

    if val.tag == value_e.Str:
      e_die("Can't assign to characters of string %r", node.name)

    elif val.tag == value_e.Undef:
      # compatible behavior: Treat it like an array.
      # TODO: Does this code ever get triggered?  It seems like the error is
      # caught earlier.

      index = arith_ev.Eval(node.index)
      lval = lvalue.Indexed(node.name, index)
      if exec_opts.nounset:
        e_die("Undefined variable can't be indexed")
      else:
        val = value.Str('')

    elif val.tag == value_e.StrArray:

      #log('ARRAY %s -> %s, index %d', node.name, array, index)
      array = val.strs
      index = arith_ev.Eval(node.index)
      lval = lvalue.Indexed(node.name, index)
      # NOTE: Similar logic in RHS Arith_LBracket
      try:
        s = array[index]
      except IndexError:
        s = None

      if s is None:
        val = value.Str('')  # NOTE: Other logic is value.Undef()?  0?
      else:
        assert isinstance(s, str), s
        val = value.Str(s)

    elif val.tag == value_e.AssocArray:  # declare -A a; a['x']+=1
      key = arith_ev.EvalWordToString(node.index)
      lval = lvalue.Keyed(node.name, key)

      s = val.d.get(key)
      if s is None:
        val = value.Str('')
      else:
        val = value.Str(s)

    else:
      raise AssertionError(val.tag)

  else:
    raise AssertionError(node.tag)

  return val, lval