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
def EvalToInt(self, node): # type: (arith_expr_t) -> int """Used externally by ${a[i+1]} and ${a:start:len}. Also used internally. """ val = self.Eval(node) # BASH_LINENO, arr (array name with shopt -s compat_array), etc. if val.tag_() in (value_e.MaybeStrArray, value_e.AssocArray) and node.tag_() == arith_expr_e.VarRef: tok = cast(Token, node) if word_eval.CheckCompatArray(tok.val, self.exec_opts): val = word_eval.ResolveCompatArray(val) # TODO: Can we avoid the runtime cost of adding location info? span_id = location.SpanForArithExpr(node) i = self._ValToIntOrError(val, span_id=span_id) return i