Ejemplo n.º 1
0
Archivo: args.py Proyecto: dotmpe/oil
def _SetToArg(action, suffix, arg_r, out):
    # type: (SetToArgAction, Optional[str], Reader, _Attributes) -> bool
    """
  Perform the action.
  """
    if suffix:  # for the ',' in -d,
        arg = suffix
    else:
        arg_r.Next()
        arg = arg_r.Peek()
        if arg is None:
            e_usage('expected argument to %r' % ('-' + action.name),
                    span_id=arg_r.SpanId())

    # e.g. spec.LongFlag('--format', ['text', 'html'])
    # Should change to arg.Enum([...])
    with tagswitch(action.flag_type) as case:
        if case(flag_type_e.Enum):
            alts = cast(flag_type__Enum, action.flag_type).alts
            if arg not in alts:
                e_usage('got invalid argument %r to %r, expected one of: %s' %
                        (arg, ('-' + action.name), ', '.join(alts)),
                        span_id=arg_r.SpanId())
            val = value.Str(arg)  # type: value_t

        elif case(flag_type_e.Str):
            val = value.Str(arg)

        elif case(flag_type_e.Int):
            try:
                i = int(arg)
            except ValueError:
                e_usage('expected integer after %s, got %r' %
                        ('-' + action.name, arg),
                        span_id=arg_r.SpanId())

            # So far all our int values are > 0, so use -1 as the 'unset' value
            if i < 0:
                e_usage('got invalid integer for %s: %s' %
                        ('-' + action.name, arg),
                        span_id=arg_r.SpanId())
            val = value.Int(i)

        elif case(flag_type_e.Float):
            try:
                val = value.Float(float(arg))
            except ValueError:
                e_usage('expected number after %r, got %r' %
                        ('-' + action.name, arg),
                        span_id=arg_r.SpanId())
        else:
            raise AssertionError()

    out.Set(action.name, val)
    return action.quit_parsing_flags
Ejemplo n.º 2
0
Archivo: args.py Proyecto: grahamc/oil
    def _Value(self, arg, span_id):
        # type: (str, int) -> value_t
        try:
            i = int(arg)
        except ValueError:
            e_usage('expected integer after %s, got %r' %
                    ('-' + self.name, arg),
                    span_id=span_id)

        # So far all our int values are > 0, so use -1 as the 'unset' value
        # corner case: this treats -0 as 0!
        if i < 0:
            e_usage('got invalid integer for %s: %s' % ('-' + self.name, arg),
                    span_id=span_id)
        return value.Int(i)
    def OnMatch(self, prefix, suffix, arg_r, out):
        # type: (Optional[str], Optional[str], Reader, _Attributes) -> bool
        """Called when the flag matches."""

        if suffix:  # for the ',' in -d,
            arg = suffix
        else:
            arg_r.Next()
            arg = arg_r.Peek()
            if arg is None:
                e_usage('expected argument to %r' % ('-' + self.name),
                        span_id=arg_r.SpanId())

        # e.g. spec.LongFlag('--format', ['text', 'html'])
        # Should change to arg.Enum([...])
        with tagswitch(self.flag_type) as case:
            if case(flag_type_e.Enum):
                alts = cast(flag_type__Enum, self.flag_type).alts
                if arg not in alts:
                    e_usage(
                        'got invalid argument %r to %r, expected one of: %s' %
                        (arg, ('-' + self.name), ', '.join(alts)),
                        span_id=arg_r.SpanId())
                val = value.Str(arg)  # type: value_t

            elif case(flag_type_e.Str):
                val = value.Str(arg)

            elif case(flag_type_e.Int):
                try:
                    val = value.Int(int(arg))
                except ValueError:
                    e_usage('expected integer after %r, got %r' %
                            ('-' + self.name, arg),
                            span_id=arg_r.SpanId())

            elif case(flag_type_e.Float):
                try:
                    val = value.Float(float(arg))
                except ValueError:
                    e_usage('expected number after %r, got %r' %
                            ('-' + self.name, arg),
                            span_id=arg_r.SpanId())
            else:
                raise AssertionError()

        out.Set(self.name, val)
        return self.quit_parsing_flags
Ejemplo n.º 4
0
Archivo: args.py Proyecto: grahamc/oil
    def PyToValue(py_val):
        # type: (Any) -> value_t

        if py_val is None:
            val = value.Undef()  # type: value_t
        elif isinstance(py_val, bool):
            val = value.Bool(py_val)
        elif isinstance(py_val, int):
            val = value.Int(py_val)
        elif isinstance(py_val, float):
            val = value.Float()  # TODO: ASDL needs float primitive
        elif isinstance(py_val, str):
            val = value.Str(py_val)
        else:
            raise AssertionError(py_val)

        return val
    def ShortFlag(self, short_name, arg_type=None, help=None):
        # type: (str, Optional[int], Optional[str]) -> None
        """
    This is very similar to ShortFlag for FlagSpecAndMore, except we have
    separate arity0 and arity1 dicts.
    """
        assert short_name.startswith('-'), short_name
        assert len(short_name) == 2, short_name

        char = short_name[1]
        if arg_type is None:
            self.arity0[char] = True
        else:
            self.arity1[char] = args.SetToArg(char, _FlagType(arg_type))

        # TODO: callers should pass flag_type
        if arg_type is None:
            typ = flag_type.Bool()  # type: flag_type_t
            default = value.Bool(False)  # type: value_t
        elif arg_type == args.Int:
            typ = flag_type.Int()
            default = value.Int(-1)
        elif arg_type == args.Float:
            typ = flag_type.Float()
            default = value.Float(0.0)
        elif arg_type == args.String:
            typ = flag_type.Str()
            default = value.Str('')
        elif isinstance(arg_type, list):
            typ = flag_type.Enum(arg_type)
            default = value.Str('')  # This isn't valid
        else:
            raise AssertionError(arg_type)

        if self.typed:
            self.defaults[char] = default
        else:
            # TODO: remove when all builtins converted
            self.defaults[char] = value.Undef()

        self.fields[char] = typ
Ejemplo n.º 6
0
def _Default(arg_type, arg_default=None):
    # type: (Union[None, int, List[str]], Optional[str]) -> value_t

    # for enum or string
    # note: not using this for integers yet
    if arg_default is not None:
        return value.Str(arg_default)  # early return

    if arg_type is None:
        default = value.Bool(False)  # type: value_t
    elif arg_type == args.Int:
        default = value.Int(-1)  # positive values aren't allowed now
    elif arg_type == args.Float:
        default = value.Float(0.0)
    elif arg_type == args.String:
        default = value.Undef()  # e.g. read -d '' is NOT the default
    elif isinstance(arg_type, list):
        default = value.Str('')  # This isn't valid
    else:
        raise AssertionError(arg_type)
    return default
Ejemplo n.º 7
0
    def Eval(self, node):
        # type: (arith_expr_t) -> value_t
        """
    Args:
      node: arith_expr_t

    Returns:
      None for Undef  (e.g. empty cell)  TODO: Don't return 0!
      int for Str
      List[int] for MaybeStrArray
      Dict[str, str] for AssocArray (TODO: Should we support this?)

    NOTE: (( A['x'] = 'x' )) and (( x = A['x'] )) are syntactically valid in
    bash, but don't do what you'd think.  'x' sometimes a variable name and
    sometimes a key.
    """
        # OSH semantics: Variable NAMES cannot be formed dynamically; but INTEGERS
        # can.  ${foo:-3}4 is OK.  $? will be a compound word too, so we don't have
        # to handle that as a special case.

        UP_node = node
        with tagswitch(node) as case:
            if case(arith_expr_e.VarRef):  # $(( x ))  (can be array)
                node = cast(arith_expr__VarRef, UP_node)
                tok = node.token
                return _LookupVar(tok.val, self.mem, self.exec_opts)

            elif case(
                    arith_expr_e.ArithWord):  # $(( $x )) $(( ${x}${y} )), etc.
                node = cast(arith_expr__ArithWord, UP_node)
                return self.word_ev.EvalWordToString(node.w)

            elif case(arith_expr_e.UnaryAssign):  # a++
                node = cast(arith_expr__UnaryAssign, UP_node)

                op_id = node.op_id
                old_int, lval = self._EvalLhsAndLookupArith(node.child)

                if op_id == Id.Node_PostDPlus:  # post-increment
                    new_int = old_int + 1
                    ret = old_int

                elif op_id == Id.Node_PostDMinus:  # post-decrement
                    new_int = old_int - 1
                    ret = old_int

                elif op_id == Id.Arith_DPlus:  # pre-increment
                    new_int = old_int + 1
                    ret = new_int

                elif op_id == Id.Arith_DMinus:  # pre-decrement
                    new_int = old_int - 1
                    ret = new_int

                else:
                    raise AssertionError(op_id)

                #log('old %d new %d ret %d', old_int, new_int, ret)
                self._Store(lval, new_int)
                return value.Int(ret)

            elif case(arith_expr_e.BinaryAssign):  # a=1, a+=5, a[1]+=5
                node = cast(arith_expr__BinaryAssign, UP_node)
                op_id = node.op_id

                if op_id == Id.Arith_Equal:
                    lval = _EvalLhsArith(node.left, self.mem, self)
                    # Disallowing (( a = myarray ))
                    # It has to be an integer
                    rhs_int = self.EvalToInt(node.right)
                    self._Store(lval, rhs_int)
                    return value.Int(rhs_int)

                old_int, lval = self._EvalLhsAndLookupArith(node.left)
                rhs = self.EvalToInt(node.right)

                if op_id == Id.Arith_PlusEqual:
                    new_int = old_int + rhs
                elif op_id == Id.Arith_MinusEqual:
                    new_int = old_int - rhs
                elif op_id == Id.Arith_StarEqual:
                    new_int = old_int * rhs

                elif op_id == Id.Arith_SlashEqual:
                    if rhs == 0:
                        e_die('Divide by zero')  # TODO: location
                    new_int = old_int / rhs

                elif op_id == Id.Arith_PercentEqual:
                    if rhs == 0:
                        e_die('Divide by zero')  # TODO: location
                    new_int = old_int % rhs

                elif op_id == Id.Arith_DGreatEqual:
                    new_int = old_int >> rhs
                elif op_id == Id.Arith_DLessEqual:
                    new_int = old_int << rhs
                elif op_id == Id.Arith_AmpEqual:
                    new_int = old_int & rhs
                elif op_id == Id.Arith_PipeEqual:
                    new_int = old_int | rhs
                elif op_id == Id.Arith_CaretEqual:
                    new_int = old_int ^ rhs
                else:
                    raise AssertionError(op_id)  # shouldn't get here

                self._Store(lval, new_int)
                return value.Int(new_int)

            elif case(arith_expr_e.Unary):
                node = cast(arith_expr__Unary, UP_node)
                op_id = node.op_id

                i = self.EvalToInt(node.child)

                if op_id == Id.Node_UnaryPlus:
                    ret = i
                elif op_id == Id.Node_UnaryMinus:
                    ret = -i

                elif op_id == Id.Arith_Bang:  # logical negation
                    ret = 1 if i == 0 else 0
                elif op_id == Id.Arith_Tilde:  # bitwise complement
                    ret = ~i
                else:
                    raise AssertionError(op_id)  # shouldn't get here

                return value.Int(ret)

            elif case(arith_expr_e.Binary):
                node = cast(arith_expr__Binary, UP_node)
                op_id = node.op_id

                # Short-circuit evaluation for || and &&.
                if op_id == Id.Arith_DPipe:
                    lhs = self.EvalToInt(node.left)
                    if lhs == 0:
                        rhs = self.EvalToInt(node.right)
                        ret = int(rhs != 0)
                    else:
                        ret = 1  # true
                    return value.Int(ret)

                if op_id == Id.Arith_DAmp:
                    lhs = self.EvalToInt(node.left)
                    if lhs == 0:
                        ret = 0  # false
                    else:
                        rhs = self.EvalToInt(node.right)
                        ret = int(rhs != 0)
                    return value.Int(ret)

                if op_id == Id.Arith_LBracket:
                    # NOTE: Similar to bracket_op_e.ArrayIndex in osh/word_eval.py

                    left = self.Eval(node.left)
                    UP_left = left
                    with tagswitch(left) as case:
                        if case(value_e.MaybeStrArray):
                            left = cast(value__MaybeStrArray, UP_left)
                            rhs_int = self.EvalToInt(node.right)
                            try:
                                # could be None because representation is sparse
                                s = left.strs[rhs_int]
                            except IndexError:
                                s = None

                        elif case(value_e.AssocArray):
                            left = cast(value__AssocArray, UP_left)
                            key = self.EvalWordToString(node.right)
                            s = left.d.get(key)

                        else:
                            # TODO: Add error context
                            e_die(
                                'Expected array or assoc in index expression, got %s',
                                ui.ValType(left))

                    if s is None:
                        val = value.Undef()  # type: value_t
                    else:
                        val = value.Str(s)

                    return val

                if op_id == Id.Arith_Comma:
                    self.Eval(node.left)  # throw away result
                    return self.Eval(node.right)

                # Rest are integers
                lhs = self.EvalToInt(node.left)
                rhs = self.EvalToInt(node.right)

                if op_id == Id.Arith_Plus:
                    ret = lhs + rhs
                elif op_id == Id.Arith_Minus:
                    ret = lhs - rhs
                elif op_id == Id.Arith_Star:
                    ret = lhs * rhs
                elif op_id == Id.Arith_Slash:
                    if rhs == 0:
                        # TODO: Could also blame /
                        e_die('Divide by zero',
                              span_id=location.SpanForArithExpr(node.right))

                    ret = lhs / rhs

                elif op_id == Id.Arith_Percent:
                    if rhs == 0:
                        # TODO: Could also blame /
                        e_die('Divide by zero',
                              span_id=location.SpanForArithExpr(node.right))

                    ret = lhs % rhs

                elif op_id == Id.Arith_DStar:
                    # OVM is stripped of certain functions that are somehow necessary for
                    # exponentiation.
                    # Python/ovm_stub_pystrtod.c:21: PyOS_double_to_string: Assertion `0'
                    # failed.
                    if rhs < 0:
                        e_die("Exponent can't be less than zero"
                              )  # TODO: error location
                    ret = 1
                    for i in xrange(rhs):
                        ret *= lhs

                elif op_id == Id.Arith_DEqual:
                    ret = int(lhs == rhs)
                elif op_id == Id.Arith_NEqual:
                    ret = int(lhs != rhs)
                elif op_id == Id.Arith_Great:
                    ret = int(lhs > rhs)
                elif op_id == Id.Arith_GreatEqual:
                    ret = int(lhs >= rhs)
                elif op_id == Id.Arith_Less:
                    ret = int(lhs < rhs)
                elif op_id == Id.Arith_LessEqual:
                    ret = int(lhs <= rhs)

                elif op_id == Id.Arith_Pipe:
                    ret = lhs | rhs
                elif op_id == Id.Arith_Amp:
                    ret = lhs & rhs
                elif op_id == Id.Arith_Caret:
                    ret = lhs ^ rhs

                # Note: how to define shift of negative numbers?
                elif op_id == Id.Arith_DLess:
                    ret = lhs << rhs
                elif op_id == Id.Arith_DGreat:
                    ret = lhs >> rhs
                else:
                    raise AssertionError(op_id)

                return value.Int(ret)

            elif case(arith_expr_e.TernaryOp):
                node = cast(arith_expr__TernaryOp, UP_node)

                cond = self.EvalToInt(node.cond)
                if cond:  # nonzero
                    return self.Eval(node.true_expr)
                else:
                    return self.Eval(node.false_expr)

            else:
                raise AssertionError(node.tag_())