예제 #1
0
 def struct_literals(expr, name, context):
     member_subs = {}
     member_typs = {}
     for key, value in zip(expr.keys, expr.values):
         if not isinstance(key, vy_ast.Name):
             raise TypeMismatch(
                 f"Invalid member variable for struct: {getattr(key, 'id', '')}",
                 key,
             )
         check_valid_varname(
             key.id,
             context.structs,
             context.constants,
             "Invalid member variable for struct",
         )
         if key.id in member_subs:
             raise TypeMismatch("Member variable duplicated: " + key.id,
                                key)
         sub = Expr(value, context).lll_node
         member_subs[key.id] = sub
         member_typs[key.id] = sub.typ
     return LLLnode.from_list(
         ["multi"] + [member_subs[key] for key in member_subs.keys()],
         typ=StructType(member_typs, name, is_literal=True),
         pos=getpos(expr),
     )
예제 #2
0
파일: core.py 프로젝트: ProGamerCode/vyper
def make_byte_array_copier(dst, src):
    assert isinstance(src.typ, ByteArrayLike)
    assert isinstance(dst.typ, ByteArrayLike)

    if src.typ.maxlen > dst.typ.maxlen:
        raise TypeMismatch(f"Cannot cast from {src.typ} to {dst.typ}")
    # stricter check for zeroing a byte array.
    if src.value == "~empty" and src.typ.maxlen != dst.typ.maxlen:
        raise TypeMismatch(
            f"Bad type for clearing bytes: expected {dst.typ} but got {src.typ}"
        )  # pragma: notest

    if src.value == "~empty":
        # set length word to 0.
        return STORE(dst, 0)

    with src.cache_when_complex("src") as (b1, src):
        with get_bytearray_length(src).cache_when_complex("len") as (b2, len_):

            max_bytes = src.typ.maxlen

            ret = ["seq"]
            # store length
            ret.append(STORE(dst, len_))

            dst = bytes_data_ptr(dst)
            src = bytes_data_ptr(src)

            ret.append(copy_bytes(dst, src, len_, max_bytes))
            return b1.resolve(b2.resolve(ret))
예제 #3
0
    def unary_operations(self):
        operand = Expr.parse_value_expr(self.expr.operand, self.context)
        if isinstance(self.expr.op, vy_ast.Not):
            if isinstance(operand.typ, BaseType) and operand.typ.typ == 'bool':
                return LLLnode.from_list(["iszero", operand],
                                         typ='bool',
                                         pos=getpos(self.expr))
            else:
                raise TypeMismatch(
                    f"Only bool is supported for not operation, {operand.typ} supplied.",
                    self.expr,
                )
        elif isinstance(self.expr.op, vy_ast.USub):
            if not is_numeric_type(operand.typ):
                raise TypeMismatch(
                    f"Unsupported type for negation: {operand.typ}",
                    self.expr,
                )

            # Clamp on minimum integer value as we cannot negate that value
            # (all other integer values are fine)
            min_int_val = get_min_val_for_type(operand.typ.typ)
            return LLLnode.from_list(
                ["sub", 0, ["clampgt", operand, min_int_val]],
                typ=operand.typ,
                pos=getpos(self.expr))
        else:
            raise StructureException(
                "Only the 'not' or 'neg' unary operators are supported")
예제 #4
0
파일: core.py 프로젝트: fubuloubu/vyper
def _check_assign_bytes(left, right):
    if right.typ.maxlen > left.typ.maxlen:
        raise TypeMismatch(
            f"Cannot cast from {right.typ} to {left.typ}")  # pragma: notest

    # stricter check for zeroing a byte array.
    if right.value == "~empty" and right.typ.maxlen != left.typ.maxlen:
        raise TypeMismatch(f"Cannot cast from empty({right.typ}) to {left.typ}"
                           )  # pragma: notest
예제 #5
0
def base_type_conversion(orig, frm, to, pos, in_function_call=False):
    orig = unwrap_location(orig)
    is_valid_int128_to_decimal = (is_base_type(frm, 'int128') and is_base_type(
        to, 'decimal')) and are_units_compatible(frm, to)

    if getattr(frm, 'is_literal', False):
        if frm.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(frm.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)
            # Special Case: Literals in function calls should always convey unit type as well.
            if in_function_call and not (frm.unit == to.unit
                                         and frm.positional == to.positional):
                raise InvalidLiteral(
                    f"Function calls require explicit unit definitions on calls, expected {to}",
                    pos)
        if to.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(to.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)

    if not isinstance(frm,
                      (BaseType, NullType)) or not isinstance(to, BaseType):
        raise TypeMismatch(
            f"Base type conversion from or to non-base type: {frm} {to}", pos)
    elif is_base_type(frm, to.typ) and are_units_compatible(frm, to):
        return LLLnode(orig.value,
                       orig.args,
                       typ=to,
                       add_gas_estimate=orig.add_gas_estimate)
    elif isinstance(frm, ContractType) and to == BaseType('address'):
        return LLLnode(orig.value,
                       orig.args,
                       typ=to,
                       add_gas_estimate=orig.add_gas_estimate)
    elif is_valid_int128_to_decimal:
        return LLLnode.from_list(
            ['mul', orig, DECIMAL_DIVISOR],
            typ=BaseType('decimal', to.unit, to.positional),
        )
    elif isinstance(frm, NullType):
        if to.typ not in ('int128', 'bool', 'uint256', 'address', 'bytes32',
                          'decimal'):
            # This is only to future proof the use of  base_type_conversion.
            raise TypeMismatch(  # pragma: no cover
                f"Cannot convert null-type object to type {to}", pos)
        return LLLnode.from_list(0, typ=to)
    # Integer literal conversion.
    elif (frm.typ, to.typ, frm.is_literal) == ('int128', 'uint256', True):
        return LLLnode(orig.value,
                       orig.args,
                       typ=to,
                       add_gas_estimate=orig.add_gas_estimate)
    else:
        raise TypeMismatch(
            f"Typecasting from base type {frm} to {to} unavailable", pos)
예제 #6
0
    def call(self):
        from vyper.functions import (
            DISPATCH_TABLE, )

        if isinstance(self.expr.func, vy_ast.Name):
            function_name = self.expr.func.id

            if function_name in DISPATCH_TABLE:
                return DISPATCH_TABLE[function_name].build_LLL(
                    self.expr, self.context)

            # Struct constructors do not need `self` prefix.
            elif function_name in self.context.structs:
                args = self.expr.args
                if len(args) != 1:
                    raise StructureException(
                        "Struct constructor is called with one argument only",
                        self.expr,
                    )

                arg = args[0]
                if not isinstance(arg, vy_ast.Dict):
                    raise TypeMismatch(
                        "Struct can only be constructed with a dict",
                        self.expr,
                    )
                return Expr.struct_literals(arg, function_name, self.context)

            # Contract assignment. Bar(<address>).
            elif function_name in self.context.sigs:
                ret, arg_lll = self._is_valid_contract_assign()
                if ret is True:
                    arg_lll.typ = ContractType(
                        function_name)  # Cast to Correct contract type.
                    return arg_lll
                else:
                    raise TypeMismatch(
                        "ContractType definition expects one address argument.",
                        self.expr,
                    )
            else:
                err_msg = f"Not a top-level function: {function_name}"
                if function_name in [
                        x.split('(')[0]
                        for x, _ in self.context.sigs['self'].items()
                ]:
                    err_msg += f". Did you mean self.{function_name}?"
                raise StructureException(err_msg, self.expr)
        elif isinstance(self.expr.func, vy_ast.Attribute) and isinstance(
                self.expr.func.value, vy_ast.Name
        ) and self.expr.func.value.id == "self":  # noqa: E501
            return self_call.make_call(self.expr, self.context)
        else:
            return external_call.make_external_call(self.expr, self.context)
예제 #7
0
def to_bytes32(expr, args, kwargs, context):
    in_arg = args[0]
    input_type, _len = get_type(in_arg)

    if input_type == "Bytes":
        if _len > 32:
            raise TypeMismatch(
                f"Unable to convert bytes[{_len}] to bytes32, max length is too "
                "large.")

        with in_arg.cache_when_complex("bytes") as (b1, in_arg):
            op = load_op(in_arg.location)
            ofst = wordsize(in_arg.location) * DYNAMIC_ARRAY_OVERHEAD
            bytes_val = [op, ["add", in_arg, ofst]]

            # zero out any dirty bytes (which can happen in the last
            # word of a bytearray)
            len_ = get_bytearray_length(in_arg)
            num_zero_bits = LLLnode.from_list(["mul", ["sub", 32, len_], 8])
            with num_zero_bits.cache_when_complex("bits") as (b2,
                                                              num_zero_bits):
                ret = shl(num_zero_bits, shr(num_zero_bits, bytes_val))
                ret = b1.resolve(b2.resolve(ret))

    else:
        # literal
        ret = in_arg

    return LLLnode.from_list(ret, typ="bytes32", pos=getpos(expr))
예제 #8
0
    def parse_List(self):
        if not len(self.expr.elements):
            return

        def get_out_type(lll_node):
            if isinstance(lll_node, ListType):
                return get_out_type(lll_node.subtype)
            return lll_node.typ

        lll_node = []
        previous_type = None
        out_type = None

        for elt in self.expr.elements:
            current_lll_node = Expr(elt, self.context).lll_node
            if not out_type:
                out_type = current_lll_node.typ

            current_type = get_out_type(current_lll_node)
            if len(lll_node) > 0 and previous_type != current_type:
                raise TypeMismatch("Lists may only contain one type",
                                   self.expr)
            else:
                lll_node.append(current_lll_node)
                previous_type = current_type

        return LLLnode.from_list(
            ["multi"] + lll_node,
            typ=ListType(out_type, len(lll_node)),
            pos=getpos(self.expr),
        )
예제 #9
0
def validate_expected_type(node, expected_type):
    """
    Validate that the given node matches the expected type(s)

    Raises if the node does not match one of the expected types.

    Arguments
    ---------
    node : VyperNode
        Vyper ast node.
    expected_type : Tuple | BaseType
        A type object, or tuple of type objects

    Returns
    -------
    None
    """
    given_types = _ExprTypeChecker().get_possible_types_from_node(node)
    if not isinstance(expected_type, tuple):
        expected_type = (expected_type, )

    if isinstance(node, (vy_ast.List, vy_ast.Tuple)):
        # special case - for literal arrays or tuples we individually validate each item
        for expected in (i for i in expected_type
                         if isinstance(i, ArrayDefinition)):
            if _validate_literal_array(node, expected):
                return
    else:
        for given, expected in itertools.product(given_types, expected_type):
            if expected.compare_type(given):
                return

    # validation failed, prepare a meaningful error message
    if len(expected_type) > 1:
        expected_str = f"one of {', '.join(str(i) for i in expected_type)}"
    else:
        expected_str = expected_type[0]

    if len(given_types) == 1 and getattr(given_types[0], "_is_callable",
                                         False):
        raise StructureException(
            f"{given_types[0]} cannot be referenced directly, it must be called",
            node)

    if not isinstance(node,
                      (vy_ast.List, vy_ast.Tuple)) and node.get_descendants(
                          vy_ast.Name, include_self=True):
        given = given_types[0]
        raise TypeMismatch(
            f"Given reference has type {given}, expected {expected_str}", node)
    else:
        if len(given_types) == 1:
            given_str = str(given_types[0])
        else:
            types_str = sorted(str(i) for i in given_types)
            given_str = f"{', '.join(types_str[:1])} or {types_str[-1]}"

        raise InvalidType(
            f"Expected {expected_str} but literal can only be cast as {given_str}",
            node)
예제 #10
0
 def types_from_Compare(self, node):
     # comparison: `x < y`
     if isinstance(node.op, vy_ast.In):
         # x in y
         left = self.get_possible_types_from_node(node.left)
         right = self.get_possible_types_from_node(node.right)
         if next((i for i in left if isinstance(i, ArrayDefinition)),
                 False):
             raise InvalidOperation(
                 "Left operand in membership comparison cannot be Array type",
                 node.left,
             )
         if next((i for i in right if not isinstance(i, ArrayDefinition)),
                 False):
             raise InvalidOperation(
                 "Right operand must be Array for membership comparison",
                 node.right)
         types_list = [
             i for i in left
             if _is_type_in_list(i, [i.value_type for i in right])
         ]
         if not types_list:
             raise TypeMismatch(
                 "Cannot perform membership comparison between dislike types",
                 node)
     else:
         types_list = get_common_types(node.left, node.right)
         _validate_op(node, types_list, "validate_comparator")
     return [BoolDefinition()]
예제 #11
0
    def list_literals(self):

        if not len(self.expr.elts):
            raise StructureException("List must have elements", self.expr)

        def get_out_type(lll_node):
            if isinstance(lll_node, ListType):
                return get_out_type(lll_node.subtype)
            return lll_node.typ

        o = []
        previous_type = None
        out_type = None

        for elt in self.expr.elts:
            current_lll_node = Expr(elt, self.context).lll_node
            if not out_type:
                out_type = current_lll_node.typ

            current_type = get_out_type(current_lll_node)
            if len(o) > 0 and previous_type != current_type:
                raise TypeMismatch("Lists may only contain one type",
                                   self.expr)
            else:
                o.append(current_lll_node)
                previous_type = current_type

        return LLLnode.from_list(
            ["multi"] + o,
            typ=ListType(out_type, len(o)),
            pos=getpos(self.expr),
        )
예제 #12
0
def raw_log(expr, args, kwargs, context):
    if not isinstance(args[0], vy_ast.List) or len(args[0].elts) > 4:
        raise StructureException(
            "Expecting a list of 0-4 topics as first argument", args[0])
    topics = []
    for elt in args[0].elts:
        arg = Expr.parse_value_expr(elt, context)
        if not is_base_type(arg.typ, 'bytes32'):
            raise TypeMismatch("Expecting a bytes32 argument as topic", elt)
        topics.append(arg)
    if args[1].typ == BaseType('bytes32'):
        placeholder = context.new_placeholder(BaseType('bytes32'))
        return LLLnode.from_list([
            'seq', ['mstore', placeholder,
                    unwrap_location(args[1])],
            [
                "log" + str(len(topics)),
                placeholder,
                32,
            ] + topics
        ],
                                 typ=None,
                                 pos=getpos(expr))
    if args[1].location == "memory":
        return LLLnode.from_list([
            "with", "_arr", args[1],
            [
                "log" + str(len(topics)),
                ["add", "_arr", 32],
                ["mload", "_arr"],
            ] + topics
        ],
                                 typ=None,
                                 pos=getpos(expr))
    placeholder = context.new_placeholder(args[1].typ)
    placeholder_node = LLLnode.from_list(placeholder,
                                         typ=args[1].typ,
                                         location='memory')
    copier = make_byte_array_copier(
        placeholder_node,
        LLLnode.from_list('_sub', typ=args[1].typ, location=args[1].location),
        pos=getpos(expr),
    )
    return LLLnode.from_list(
        [
            "with",
            "_sub",
            args[1],
            [
                "seq", copier,
                [
                    "log" + str(len(topics)),
                    ["add", placeholder_node, 32],
                    ["mload", placeholder_node],
                ] + topics
            ],
        ],
        typ=None,
        pos=getpos(expr),
    )
예제 #13
0
def get_min_val_for_type(typ: str) -> int:
    key = 'MIN_' + typ.upper()
    try:
        min_val, _ = BUILTIN_CONSTANTS[key]
    except KeyError as e:
        raise TypeMismatch(f"Not a signed type: {typ}") from e
    return min_val
예제 #14
0
    def evaluate(self) -> VyperNode:
        """
        Attempt to evaluate the comparison.

        Returns
        -------
        NameConstant
            Node representing the result of the evaluation.
        """
        left, right = self.left, self.right
        if not isinstance(left, Constant):
            raise UnfoldableNode("Node contains invalid field(s) for evaluation")

        if isinstance(self.op, In):
            if not isinstance(right, List):
                raise UnfoldableNode("Node contains invalid field(s) for evaluation")
            if next((i for i in right.elements if not isinstance(i, Constant)), None):
                raise UnfoldableNode("Node contains invalid field(s) for evaluation")
            if len(set([type(i) for i in right.elements])) > 1:
                raise UnfoldableNode("List contains multiple literal types")
            value = self.op._op(left.value, [i.value for i in right.elements])
            return NameConstant.from_node(self, value=value)

        if not isinstance(left, type(right)):
            raise UnfoldableNode("Cannot compare different literal types")

        if not isinstance(self.op, (Eq, NotEq)) and not isinstance(left, (Int, Decimal)):
            raise TypeMismatch(f"Invalid literal types for {self.op.description} comparison", self)

        value = self.op._op(left.value, right.value)
        return NameConstant.from_node(self, value=value)
예제 #15
0
    def _validate_arg_types(self, node):
        num_args = len(
            self._inputs)  # the number of args the signature indicates

        expect_num_args = num_args
        if self._has_varargs:
            # note special meaning for -1 in validate_call_args API
            expect_num_args = (num_args, -1)

        validate_call_args(node, expect_num_args, self._kwargs)

        for arg, (_, expected) in zip(node.args, self._inputs):
            self._validate_single(arg, expected)

        for kwarg in node.keywords:
            kwarg_settings = self._kwargs[kwarg.arg]
            if kwarg_settings.require_literal and not isinstance(
                    kwarg.value, vy_ast.Constant):
                raise TypeMismatch("Value for kwarg must be a literal",
                                   kwarg.value)
            self._validate_single(kwarg.value, kwarg_settings.typ)

        # typecheck varargs. we don't have type info from the signature,
        # so ensure that the types of the args can be inferred exactly.
        varargs = node.args[num_args:]
        if len(varargs) > 0:
            assert self._has_varargs  # double check validate_call_args
        for arg in varargs:
            # call get_exact_type_from_node for its side effects -
            # ensures the type can be inferred exactly.
            get_exact_type_from_node(arg)
예제 #16
0
def minmax(expr, args, kwargs, context, comparator):
    def _can_compare_with_uint256(operand):
        if operand.typ.typ == 'uint256':
            return True
        elif operand.typ.typ == 'int128' and operand.typ.is_literal and SizeLimits.in_bounds(
                'uint256', operand.value):  # noqa: E501
            return True
        return False

    left, right = args[0], args[1]
    if left.typ.typ == right.typ.typ:
        if left.typ.typ != 'uint256':
            # if comparing like types that are not uint256, use SLT or SGT
            comparator = f's{comparator}'
        o = ['if', [comparator, '_l', '_r'], '_r', '_l']
        otyp = left.typ
        otyp.is_literal = False
    elif _can_compare_with_uint256(left) and _can_compare_with_uint256(right):
        o = ['if', [comparator, '_l', '_r'], '_r', '_l']
        if right.typ.typ == 'uint256':
            otyp = right.typ
        else:
            otyp = left.typ
        otyp.is_literal = False
    else:
        raise TypeMismatch(
            f"Minmax types incompatible: {left.typ.typ} {right.typ.typ}")
    return LLLnode.from_list(
        ['with', '_l', left, ['with', '_r', right, o]],
        typ=otyp,
        pos=getpos(expr),
    )
예제 #17
0
 def _op(self, left, right):
     if isinstance(left, decimal.Decimal):
         raise TypeMismatch(
             "Cannot perform exponentiation on decimal values.",
             self._parent)
     if right < 0:
         raise InvalidOperation("Cannot calculate a negative power",
                                self._parent)
     return int(left**right)
예제 #18
0
파일: stmt.py 프로젝트: 1holeshot/vyper
 def _check_implicit_conversion(self, var_id, sub):
     target_typ = self.context.vars[var_id].typ
     assign_typ = sub.typ
     if isinstance(target_typ, BaseType) and isinstance(
             assign_typ, BaseType):
         if not assign_typ.is_literal and assign_typ.typ != target_typ.typ:
             raise TypeMismatch(
                 f'Invalid type {assign_typ.typ}, expected: {target_typ.typ}',
                 self.stmt)
예제 #19
0
파일: expr.py 프로젝트: 6pakla/vyper
 def subscript(self):
     sub = Expr.parse_variable_location(self.expr.value, self.context)
     if isinstance(sub.typ, (MappingType, ListType)):
         if not isinstance(self.expr.slice, vy_ast.Index):
             raise StructureException(
                 "Array access must access a single element, not a slice",
                 self.expr,
             )
         index = Expr.parse_value_expr(self.expr.slice.value, self.context)
     elif isinstance(sub.typ, TupleType):
         if not isinstance(self.expr.slice.value, vy_ast.Int) or self.expr.slice.value.n < 0 or self.expr.slice.value.n >= len(sub.typ.members):  # noqa: E501
             raise TypeMismatch("Tuple index invalid", self.expr.slice.value)
         index = self.expr.slice.value.n
     else:
         raise TypeMismatch("Bad subscript attempt", self.expr.value)
     o = add_variable_offset(sub, index, pos=getpos(self.expr))
     o.mutable = sub.mutable
     return o
예제 #20
0
def raw_call(expr, args, kwargs, context):
    to, data = args
    gas, value, outsize, delegate_call = (
        kwargs['gas'],
        kwargs['value'],
        kwargs['outsize'],
        kwargs['is_delegate_call'],
    )
    if delegate_call.typ.is_literal is False:
        raise TypeMismatch(
            'The delegate_call parameter has to be a static/literal boolean value.'
        )
    if context.is_constant():
        raise ConstancyViolation(
            f"Cannot make calls from {context.pp_constancy()}",
            expr,
        )
    placeholder = context.new_placeholder(data.typ)
    placeholder_node = LLLnode.from_list(placeholder,
                                         typ=data.typ,
                                         location='memory')
    copier = make_byte_array_copier(placeholder_node, data, pos=getpos(expr))
    output_placeholder = context.new_placeholder(ByteArrayType(outsize))
    output_node = LLLnode.from_list(
        output_placeholder,
        typ=ByteArrayType(outsize),
        location='memory',
    )

    # build LLL for call or delegatecall
    common_call_lll = [
        ['add', placeholder_node, 32],
        ['mload', placeholder_node],
        # if there is no return value, the return offset can be 0
        ['add', output_node, 32] if outsize else 0,
        outsize
    ]

    if delegate_call.value == 1:
        call_lll = ['delegatecall', gas, to] + common_call_lll
    else:
        call_lll = ['call', gas, to, value] + common_call_lll

    # build sequence LLL
    if outsize:
        # only copy the return value to memory if outsize > 0
        seq = [
            'seq', copier, ['assert', call_lll],
            ['mstore', output_node, outsize], output_node
        ]
        typ = ByteArrayType(outsize)
    else:
        seq = ['seq', copier, ['assert', call_lll]]
        typ = None

    return LLLnode.from_list(seq, typ=typ, location="memory", pos=getpos(expr))
예제 #21
0
파일: stmt.py 프로젝트: 6pakla/vyper
    def assign(self):
        # Assignment (e.g. x[4] = y)

        with self.context.assignment_scope():
            sub = Expr(self.stmt.value, self.context).lll_node

            is_valid_rlp_list_assign = (
                isinstance(self.stmt.value, vy_ast.Call)
            ) and getattr(self.stmt.value.func, 'id', '') == 'RLPList'

            # Determine if it's an RLPList assignment.
            if is_valid_rlp_list_assign:
                pos = self.context.new_variable(self.stmt.target.id, sub.typ)
                variable_loc = LLLnode.from_list(
                    pos,
                    typ=sub.typ,
                    location='memory',
                    pos=getpos(self.stmt),
                    annotation=self.stmt.target.id,
                )
                o = make_setter(variable_loc, sub, 'memory', pos=getpos(self.stmt))
            else:
                # Error check when assigning to declared variable
                if isinstance(self.stmt.target, vy_ast.Name):
                    # Do not allow assignment to undefined variables without annotation
                    if self.stmt.target.id not in self.context.vars:
                        raise VariableDeclarationException("Variable type not defined", self.stmt)

                    # Check against implicit conversion
                    self._check_implicit_conversion(self.stmt.target.id, sub)

                is_valid_tuple_assign = (
                    isinstance(self.stmt.target, vy_ast.Tuple)
                ) and isinstance(self.stmt.value, vy_ast.Tuple)

                # Do no allow tuple-to-tuple assignment
                if is_valid_tuple_assign:
                    raise VariableDeclarationException(
                        "Tuple to tuple assignment not supported",
                        self.stmt,
                    )

                # Checks to see if assignment is valid
                target = self.get_target(self.stmt.target)
                if isinstance(target.typ, ContractType) and not isinstance(sub.typ, ContractType):
                    raise TypeMismatch(
                        'Contract assignment expects casted address: '
                        f'{target.typ}(<address_var>)',
                        self.stmt
                    )
                o = make_setter(target, sub, target.location, pos=getpos(self.stmt))

            o.pos = getpos(self.stmt)

        return o
예제 #22
0
def base_type_conversion(orig, frm, to, pos, in_function_call=False):
    orig = unwrap_location(orig)

    # do the base type check so we can use BaseType attributes
    if not isinstance(frm, BaseType) or not isinstance(to, BaseType):
        raise TypeMismatch(
            f"Base type conversion from or to non-base type: {frm} {to}", pos)

    if getattr(frm, 'is_literal', False):
        if frm.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(frm.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)

        if to.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(to.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)

    is_decimal_int128_conversion = frm.typ == 'int128' and to.typ == 'decimal'
    is_same_type = frm.typ == to.typ
    is_literal_conversion = frm.is_literal and (frm.typ, to.typ) == ('int128',
                                                                     'uint256')
    is_address_conversion = isinstance(frm,
                                       ContractType) and to.typ == 'address'
    if not (is_same_type or is_literal_conversion or is_address_conversion
            or is_decimal_int128_conversion):
        raise TypeMismatch(
            f"Typecasting from base type {frm} to {to} unavailable", pos)

    # handle None value inserted by `empty()`
    if orig.value is None:
        return LLLnode.from_list(0, typ=to)

    if is_decimal_int128_conversion:
        return LLLnode.from_list(
            ['mul', orig, DECIMAL_DIVISOR],
            typ=BaseType('decimal'),
        )

    return LLLnode(orig.value,
                   orig.args,
                   typ=to,
                   add_gas_estimate=orig.add_gas_estimate)
예제 #23
0
def pack_logging_topics(event_id, args, expected_topics, context, pos):
    topics = [event_id]
    code_pos = pos
    for pos, expected_topic in enumerate(expected_topics):
        expected_type = expected_topic.typ
        arg = args[pos]
        value = Expr(arg, context).lll_node
        arg_type = value.typ

        if isinstance(arg_type, ByteArrayLike) and isinstance(
                expected_type, ByteArrayLike):
            if arg_type.maxlen > expected_type.maxlen:
                raise TypeMismatch(
                    f"Topic input bytes are too big: {arg_type} {expected_type}",
                    code_pos)
            if isinstance(arg, vy_ast.Str):
                bytez, bytez_length = string_to_bytes(arg.s)
                if len(bytez) > 32:
                    raise InvalidLiteral(
                        "Can only log a maximum of 32 bytes at a time.",
                        code_pos)
                topics.append(
                    bytes_to_int(bytez + b'\x00' * (32 - bytez_length)))
            else:
                if value.location == "memory":
                    size = ['mload', value]
                elif value.location == "storage":
                    size = ['sload', ['sha3_32', value]]
                topics.append(byte_array_to_num(value, arg, 'uint256', size))
        else:
            if arg_type != expected_type:
                raise TypeMismatch(
                    f"Invalid type for logging topic, got {arg_type} expected {expected_type}",
                    value.pos)
            value = unwrap_location(value)
            value = base_type_conversion(value,
                                         arg_type,
                                         expected_type,
                                         pos=code_pos)
            topics.append(value)

    return topics
예제 #24
0
파일: stmt.py 프로젝트: 1holeshot/vyper
    def ann_assign(self):
        with self.context.assignment_scope():
            typ = parse_type(
                self.stmt.annotation,
                location='memory',
                custom_units=self.context.custom_units,
                custom_structs=self.context.structs,
                constants=self.context.constants,
            )
            if isinstance(self.stmt.target, vy_ast.Attribute):
                raise TypeMismatch(
                    f'May not set type for field {self.stmt.target.attr}',
                    self.stmt,
                )
            varname = self.stmt.target.id
            pos = self.context.new_variable(varname, typ)
            if self.stmt.value is None:
                raise StructureException(
                    'New variables must be initialized explicitly', self.stmt)

            sub = Expr(self.stmt.value, self.context).lll_node

            # Disallow assignment to None
            if isinstance(sub.typ, NullType):
                raise InvalidLiteral(
                    ('Assignment to None is not allowed, use a default '
                     'value or built-in `clear()`.'), self.stmt)

            is_literal_bytes32_assign = (isinstance(sub.typ, ByteArrayType)
                                         and sub.typ.maxlen == 32
                                         and isinstance(typ, BaseType)
                                         and typ.typ == 'bytes32'
                                         and sub.typ.is_literal)

            # If bytes[32] to bytes32 assignment rewrite sub as bytes32.
            if is_literal_bytes32_assign:
                sub = LLLnode(
                    bytes_to_int(self.stmt.value.s),
                    typ=BaseType('bytes32'),
                    pos=getpos(self.stmt),
                )

            self._check_valid_assign(sub)
            self._check_same_variable_assign(sub)
            variable_loc = LLLnode.from_list(
                pos,
                typ=typ,
                location='memory',
                pos=getpos(self.stmt),
            )
            o = make_setter(variable_loc, sub, 'memory', pos=getpos(self.stmt))
            # o.pos = getpos(self.stmt) # TODO: Should this be here like in assign()?

            return o
예제 #25
0
def _to_bytelike(expr, args, kwargs, context, bytetype):
    if bytetype == 'string':
        ReturnType = StringType
    elif bytetype == 'bytes':
        ReturnType = ByteArrayType
    else:
        raise TypeMismatch(f'Invalid {bytetype} supplied')

    in_arg = args[0]
    if in_arg.typ.maxlen > args[1].slice.value.n:
        raise TypeMismatch(
            f'Cannot convert as input {bytetype} are larger than max length',
            expr,
        )

    return LLLnode(value=in_arg.value,
                   args=in_arg.args,
                   typ=ReturnType(in_arg.typ.maxlen),
                   pos=getpos(expr),
                   location=in_arg.location)
예제 #26
0
    def parse_assert(self):

        with self.context.assertion_scope():
            test_expr = Expr.parse_value_expr(self.stmt.test, self.context)

        if not self.is_bool_expr(test_expr):
            raise TypeMismatch('Only boolean expressions allowed', self.stmt.test)
        if self.stmt.msg:
            return self._assert_reason(test_expr, self.stmt.msg)
        else:
            return LLLnode.from_list(['assert', test_expr], typ=None, pos=getpos(self.stmt))
예제 #27
0
파일: core.py 프로젝트: skellet0r/vyper
def make_byte_array_copier(dst, src, pos=None):
    assert isinstance(src.typ, ByteArrayLike)
    assert isinstance(dst.typ, ByteArrayLike)

    if src.typ.maxlen > dst.typ.maxlen:
        raise TypeMismatch(f"Cannot cast from {src.typ} to {dst.typ}")
    # stricter check for zeroing a byte array.
    if src.value == "~empty" and src.typ.maxlen != dst.typ.maxlen:
        raise TypeMismatch(
            f"Bad type for clearing bytes: expected {dst.typ} but got {src.typ}"
        )  # pragma: notest

    if src.value == "~empty":
        # set length word to 0.
        return LLLnode.from_list([store_op(dst.location), dst, 0], pos=pos)

    with src.cache_when_complex("src") as (builder, src):
        n_bytes = ["add", get_bytearray_length(src), 32]
        max_bytes = src.typ.memory_bytes_required

        return builder.resolve(
            copy_bytes(dst, src, n_bytes, max_bytes, pos=pos))
예제 #28
0
 def aug_assign(self):
     target = self.get_target(self.stmt.target)
     sub = Expr.parse_value_expr(self.stmt.value, self.context)
     if not isinstance(
         self.stmt.op, (vy_ast.Add, vy_ast.Sub, vy_ast.Mult, vy_ast.Div, vy_ast.Mod)
     ):
         raise StructureException("Unsupported operator for augassign", self.stmt)
     if not isinstance(target.typ, BaseType):
         raise TypeMismatch(
             "Can only use aug-assign operators with simple types!", self.stmt.target
         )
     if target.location == 'storage':
         o = Expr.parse_value_expr(
             vy_ast.BinOp(
                 left=LLLnode.from_list(['sload', '_stloc'], typ=target.typ, pos=target.pos),
                 right=sub,
                 op=self.stmt.op,
                 lineno=self.stmt.lineno,
                 col_offset=self.stmt.col_offset,
                 end_lineno=self.stmt.end_lineno,
                 end_col_offset=self.stmt.end_col_offset,
             ),
             self.context,
         )
         return LLLnode.from_list([
             'with', '_stloc', target, [
                 'sstore',
                 '_stloc',
                 base_type_conversion(o, o.typ, target.typ, pos=getpos(self.stmt)),
             ],
         ], typ=None, pos=getpos(self.stmt))
     elif target.location == 'memory':
         o = Expr.parse_value_expr(
             vy_ast.BinOp(
                 left=LLLnode.from_list(['mload', '_mloc'], typ=target.typ, pos=target.pos),
                 right=sub,
                 op=self.stmt.op,
                 lineno=self.stmt.lineno,
                 col_offset=self.stmt.col_offset,
                 end_lineno=self.stmt.end_lineno,
                 end_col_offset=self.stmt.end_col_offset,
             ),
             self.context,
         )
         return LLLnode.from_list([
             'with', '_mloc', target, [
                 'mstore',
                 '_mloc',
                 base_type_conversion(o, o.typ, target.typ, pos=getpos(self.stmt)),
             ],
         ], typ=None, pos=getpos(self.stmt))
예제 #29
0
    def boolean_operations(self):
        # Iterate through values
        for value in self.expr.values:
            # Check for calls at assignment
            if self.context.in_assignment and isinstance(value, vy_ast.Call):
                raise StructureException(
                    "Boolean operations with calls may not be performed on assignment",
                    self.expr,
                )

            # Check for boolean operations with non-boolean inputs
            _expr = Expr.parse_value_expr(value, self.context)
            if not is_base_type(_expr.typ, 'bool'):
                raise TypeMismatch(
                    "Boolean operations can only be between booleans!",
                    self.expr,
                )

            # TODO: Handle special case of literals and simplify at compile time

        # Check for valid ops
        if isinstance(self.expr.op, vy_ast.And):
            op = 'and'
        elif isinstance(self.expr.op, vy_ast.Or):
            op = 'or'
        else:
            raise Exception("Unsupported bool op: " + self.expr.op)

        # Handle different numbers of inputs
        count = len(self.expr.values)
        if count < 2:
            raise StructureException(
                "Expected at least two arguments for a bool op", self.expr)
        elif count == 2:
            left = Expr.parse_value_expr(self.expr.values[0], self.context)
            right = Expr.parse_value_expr(self.expr.values[1], self.context)
            return LLLnode.from_list([op, left, right],
                                     typ='bool',
                                     pos=getpos(self.expr))
        else:
            left = Expr.parse_value_expr(self.expr.values[0], self.context)
            right = Expr.parse_value_expr(self.expr.values[1], self.context)

            p = ['seq', [op, left, right]]
            values = self.expr.values[2:]
            while len(values) > 0:
                value = Expr.parse_value_expr(values[0], self.context)
                p = [op, value, p]
                values = values[1:]

            return LLLnode.from_list(p, typ='bool', pos=getpos(self.expr))
예제 #30
0
 def _check_valid_assign(self, sub):
     if (isinstance(self.stmt.annotation, vy_ast.Name)
             and self.stmt.annotation.id == 'bytes32'):
         # CMC 04/07/2020 this check could be much clearer, more like:
         # if isinstance(ByteArrayLike) and maxlen == 32
         #   or isinstance(BaseType) and typ.typ == 'bytes32'
         #   then GOOD
         #   else RAISE
         if isinstance(sub.typ, ByteArrayLike):
             if sub.typ.maxlen != 32:
                 raise TypeMismatch(
                     'Invalid type, expected: bytes32. String is incorrect length.',
                     self.stmt)
             return
         elif isinstance(sub.typ, BaseType):
             if sub.typ.typ != 'bytes32':
                 raise TypeMismatch('Invalid type, expected: bytes32',
                                    self.stmt)
             return
         else:
             raise TypeMismatch("Invalid type, expected: bytes32",
                                self.stmt)
     elif isinstance(self.stmt.annotation, vy_ast.Subscript):
         # check list assign:
         if not isinstance(sub.typ, (ListType, ByteArrayLike)):
             raise TypeMismatch(
                 f'Invalid type, expected: {self.stmt.annotation.value.id},'
                 f' got: {sub.typ}', self.stmt)
     elif sub.typ is None:
         # Check that the object to be assigned is not of NoneType
         raise TypeMismatch(
             f"Invalid type, expected {self.stmt.annotation.id}", self.stmt)
     elif isinstance(sub.typ, StructType):
         # This needs to get more sophisticated in the presence of
         # foreign structs.
         if not sub.typ.name == self.stmt.annotation.id:
             raise TypeMismatch(
                 f"Invalid type, expected {self.stmt.annotation.id}",
                 self.stmt)
     # Check that the integer literal, can be assigned to uint256 if necessary.
     elif (self.stmt.annotation.id,
           sub.typ.typ) == ('uint256', 'int128') and sub.typ.is_literal:
         if not SizeLimits.in_bounds('uint256', sub.value):
             raise InvalidLiteral(
                 'Invalid uint256 assignment, value not in uint256 range.',
                 self.stmt)
     elif self.stmt.annotation.id != sub.typ.typ:
         raise TypeMismatch(
             f'Invalid type {sub.typ.typ}, expected: {self.stmt.annotation.id}',
             self.stmt,
         )
     else:
         return True