예제 #1
0
파일: stmt.py 프로젝트: skellet0r/vyper
 def parse_AugAssign(self):
     target = self._get_target(self.stmt.target)
     sub = Expr.parse_value_expr(self.stmt.value, self.context)
     if not isinstance(target.typ, BaseType):
         return
     if target.location == "storage":
         lll_node = 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,
                 node_source_code=self.stmt.get("node_source_code"),
             ),
             self.context,
         )
         return LLLnode.from_list(
             [
                 "with", "_stloc", target,
                 ["sstore", "_stloc",
                  unwrap_location(lll_node)]
             ],
             typ=None,
             pos=getpos(self.stmt),
         )
     elif target.location == "memory":
         lll_node = 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,
                 node_source_code=self.stmt.get("node_source_code"),
             ),
             self.context,
         )
         return LLLnode.from_list(
             [
                 "with", "_mloc", target,
                 ["mstore", "_mloc",
                  unwrap_location(lll_node)]
             ],
             typ=None,
             pos=getpos(self.stmt),
         )
예제 #2
0
def lll_for_external_call(stmt_expr, context):
    from vyper.codegen.expr import Expr  # TODO rethink this circular import

    pos = getpos(stmt_expr)

    contract_address = Expr.parse_value_expr(stmt_expr.func.value, context)
    value, gas, skip_contract_check = _get_special_kwargs(stmt_expr, context)
    args_lll = [Expr(x, context).lll_node for x in stmt_expr.args]

    assert isinstance(contract_address.typ, InterfaceType)
    contract_name = contract_address.typ.name
    method_name = stmt_expr.func.attr
    contract_sig = context.sigs[contract_name][method_name]

    ret = _external_call_helper(
        contract_address,
        contract_sig,
        args_lll,
        context,
        pos,
        value=value,
        gas=gas,
        skip_contract_check=skip_contract_check,
    )
    ret.annotation = stmt_expr.get("node_source_code")

    return ret
예제 #3
0
파일: stmt.py 프로젝트: fubuloubu/vyper
    def parse_Assert(self):
        test_expr = Expr.parse_value_expr(self.stmt.test, self.context)

        if self.stmt.msg:
            return self._assert_reason(test_expr, self.stmt.msg)
        else:
            return IRnode.from_list(["assert", test_expr])
예제 #4
0
def lll_for_external_call(stmt_expr, context):
    from vyper.codegen.expr import Expr  # TODO rethink this circular import

    pos = getpos(stmt_expr)
    value, gas, skip_contract_check = _get_special_kwargs(stmt_expr, context)
    args_lll = [Expr(x, context).lll_node for x in stmt_expr.args]

    if isinstance(stmt_expr.func, vy_ast.Attribute) and isinstance(
            stmt_expr.func.value, vy_ast.Call):
        # e.g. `Foo(address).bar()`

        # sanity check
        assert len(stmt_expr.func.value.args) == 1
        contract_name = stmt_expr.func.value.func.id
        contract_address = Expr.parse_value_expr(stmt_expr.func.value.args[0],
                                                 context)

    elif (isinstance(stmt_expr.func.value, vy_ast.Attribute)
          and stmt_expr.func.value.attr in context.globals
          # TODO check for self?
          and hasattr(context.globals[stmt_expr.func.value.attr].typ, "name")):
        # e.g. `self.foo.bar()`

        # sanity check
        assert stmt_expr.func.value.value.id == "self", stmt_expr

        contract_name = context.globals[stmt_expr.func.value.attr].typ.name
        type_ = stmt_expr.func.value._metadata["type"]
        var = context.globals[stmt_expr.func.value.attr]
        contract_address = unwrap_location(
            LLLnode.from_list(
                type_.position.position,
                typ=var.typ,
                location="storage",
                pos=pos,
                annotation="self." + stmt_expr.func.value.attr,
            ))
    else:
        # TODO catch this during type checking
        raise StructureException("Unsupported operator.", stmt_expr)

    method_name = stmt_expr.func.attr
    contract_sig = context.sigs[contract_name][method_name]

    ret = _external_call_helper(
        contract_address,
        contract_sig,
        args_lll,
        context,
        pos,
        value=value,
        gas=gas,
        skip_contract_check=skip_contract_check,
    )
    ret.annotation = stmt_expr.get("node_source_code")

    return ret
예제 #5
0
def _get_special_kwargs(stmt_expr, context):
    from vyper.codegen.expr import Expr  # TODO rethink this circular import

    value, gas, skip_contract_check = None, None, None
    for kw in stmt_expr.keywords:
        if kw.arg == "gas":
            gas = Expr.parse_value_expr(kw.value, context)
        elif kw.arg == "value":
            value = Expr.parse_value_expr(kw.value, context)
        elif kw.arg == "skip_contract_check":
            skip_contract_check = kw.value.value
            assert isinstance(skip_contract_check,
                              bool), "type checker missed this"
        else:
            raise TypeCheckFailure("Unexpected keyword argument")

    # TODO maybe return a small dataclass to reduce verbosity
    return value, gas, skip_contract_check
예제 #6
0
파일: stmt.py 프로젝트: ProGamerCode/vyper
    def parse_AugAssign(self):
        target = self._get_target(self.stmt.target)
        sub = Expr.parse_value_expr(self.stmt.value, self.context)
        if not isinstance(target.typ, BaseType):
            return

        with target.cache_when_complex("_loc") as (b, target):
            rhs = Expr.parse_value_expr(
                vy_ast.BinOp(
                    left=IRnode.from_list(LOAD(target), typ=target.typ),
                    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,
                    node_source_code=self.stmt.get("node_source_code"),
                ),
                self.context,
            )
            return b.resolve(STORE(target, rhs))
예제 #7
0
파일: stmt.py 프로젝트: ProGamerCode/vyper
    def _parse_For_range(self):
        # attempt to use the type specified by type checking, fall back to `int256`
        # this is a stopgap solution to allow uint256 - it will be properly solved
        # once we refactor type system
        iter_typ = "int256"
        if "type" in self.stmt.target._metadata:
            iter_typ = self.stmt.target._metadata["type"]._id

        # Get arg0
        arg0 = self.stmt.iter.args[0]
        num_of_args = len(self.stmt.iter.args)

        # Type 1 for, e.g. for i in range(10): ...
        if num_of_args == 1:
            arg0_val = self._get_range_const_value(arg0)
            start = IRnode.from_list(0, typ=iter_typ)
            rounds = arg0_val

        # Type 2 for, e.g. for i in range(100, 110): ...
        elif self._check_valid_range_constant(self.stmt.iter.args[1],
                                              raise_exception=False)[0]:
            arg0_val = self._get_range_const_value(arg0)
            arg1_val = self._get_range_const_value(self.stmt.iter.args[1])
            start = IRnode.from_list(arg0_val, typ=iter_typ)
            rounds = IRnode.from_list(arg1_val - arg0_val, typ=iter_typ)

        # Type 3 for, e.g. for i in range(x, x + 10): ...
        else:
            arg1 = self.stmt.iter.args[1]
            rounds = self._get_range_const_value(arg1.right)
            start = Expr.parse_value_expr(arg0, self.context)

        r = rounds if isinstance(rounds, int) else rounds.value
        if r < 1:
            return

        varname = self.stmt.target.id
        i = IRnode.from_list(self.context.fresh_varname("range_ix"),
                             typ="uint256")
        iptr = self.context.new_variable(varname, BaseType(iter_typ))

        self.context.forvars[varname] = True

        loop_body = ["seq"]
        # store the current value of i so it is accessible to userland
        loop_body.append(["mstore", iptr, i])
        loop_body.append(parse_body(self.stmt.body, self.context))

        ir_node = IRnode.from_list(
            ["repeat", i, start, rounds, rounds, loop_body])
        del self.context.forvars[varname]

        return ir_node
예제 #8
0
    def parse_If(self):
        if self.stmt.orelse:
            with self.context.block_scope():
                add_on = [parse_body(self.stmt.orelse, self.context)]
        else:
            add_on = []

        with self.context.block_scope():
            test_expr = Expr.parse_value_expr(self.stmt.test, self.context)
            body = ["if", test_expr, parse_body(self.stmt.body, self.context)] + add_on
            lll_node = LLLnode.from_list(body, typ=None, pos=getpos(self.stmt))
        return lll_node
예제 #9
0
def ir_for_external_call(call_expr, context):
    from vyper.codegen.expr import Expr  # TODO rethink this circular import

    contract_address = Expr.parse_value_expr(call_expr.func.value, context)
    assert isinstance(contract_address.typ, InterfaceType)
    args_ir = [Expr(x, context).ir_node for x in call_expr.args]
    call_kwargs = _parse_kwargs(call_expr, context)

    with contract_address.cache_when_complex("external_contract") as (
            b1, contract_address):
        return b1.resolve(
            _external_call_helper(contract_address, args_ir, call_kwargs,
                                  call_expr, context))
예제 #10
0
파일: stmt.py 프로젝트: ProGamerCode/vyper
    def parse_If(self):
        if self.stmt.orelse:
            with self.context.block_scope():
                add_on = [parse_body(self.stmt.orelse, self.context)]
        else:
            add_on = []

        with self.context.block_scope():
            test_expr = Expr.parse_value_expr(self.stmt.test, self.context)
            body = ["if", test_expr,
                    parse_body(self.stmt.body, self.context)] + add_on
            ir_node = IRnode.from_list(body)
        return ir_node
예제 #11
0
    def parse_Assert(self):
        test_expr = Expr.parse_value_expr(self.stmt.test, self.context)
        if test_expr.typ.is_literal:
            if test_expr.value == 1:
                # skip literal assertions that always pass
                return LLLnode.from_list(["pass"], typ=None, pos=getpos(self.stmt))
            else:
                test_expr = test_expr.value

        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))
예제 #12
0
파일: stmt.py 프로젝트: ProGamerCode/vyper
    def _check_valid_range_constant(self, arg_ast_node, raise_exception=True):
        with self.context.range_scope():
            # TODO should catch if raise_exception == False?
            arg_expr = Expr.parse_value_expr(arg_ast_node, self.context)

        is_integer_literal = (isinstance(arg_expr.typ, BaseType)
                              and arg_expr.typ.is_literal
                              and arg_expr.typ.typ in {"uint256", "int256"})
        if not is_integer_literal and raise_exception:
            raise StructureException(
                "Range only accepts literal (constant) values of type uint256 or int256",
                arg_ast_node,
            )
        return is_integer_literal, arg_expr
예제 #13
0
파일: stmt.py 프로젝트: ProGamerCode/vyper
    def parse_Assert(self):
        test_expr = Expr.parse_value_expr(self.stmt.test, self.context)
        if test_expr.typ.is_literal:
            if test_expr.value == 1:
                # skip literal assertions that always pass
                # TODO move this to optimizer
                return IRnode.from_list(["pass"])
            else:
                test_expr = test_expr.value

        if self.stmt.msg:
            return self._assert_reason(test_expr, self.stmt.msg)
        else:
            return IRnode.from_list(["assert", test_expr])
예제 #14
0
def process_arg(arg, expected_arg_type, context):
    # If the input value is a typestring, return the equivalent codegen type for IR generation
    if isinstance(expected_arg_type, TypeTypeDefinition):
        return new_type_to_old_type(expected_arg_type.typedef)

    # if it is a word type, return a stack item.
    # TODO: Builtins should not require value expressions
    if isinstance(expected_arg_type, ValueTypeDefinition) and not isinstance(
            expected_arg_type, (StructDefinition, ArrayValueAbstractType)):
        return Expr.parse_value_expr(arg, context)

    if isinstance(expected_arg_type, BaseTypeDefinition):
        return Expr(arg, context).ir_node

    raise CompilerPanic(
        f"Unexpected type: {expected_arg_type}")  # pragma: notest
예제 #15
0
파일: stmt.py 프로젝트: vyperlang/vyper
 def _check_valid_range_constant(self, arg_ast_node):
     with self.context.range_scope():
         arg_expr = Expr.parse_value_expr(arg_ast_node, self.context)
     return arg_expr
예제 #16
0
def process_arg(index, arg, expected_arg_typelist, function_name, context):

    # temporary hack to support abstract types
    if hasattr(expected_arg_typelist, "_id_list"):
        expected_arg_typelist = expected_arg_typelist._id_list

    if isinstance(expected_arg_typelist, Optional):
        expected_arg_typelist = expected_arg_typelist.typ
    if not isinstance(expected_arg_typelist, tuple):
        expected_arg_typelist = (expected_arg_typelist, )

    vsub = None
    for expected_arg in expected_arg_typelist:

        # temporary hack, once we refactor this package none of this will exist
        if hasattr(expected_arg, "_id"):
            expected_arg = expected_arg._id

        if expected_arg == "num_literal":
            if isinstance(arg, (vy_ast.Int, vy_ast.Decimal)):
                return arg.n
        elif expected_arg == "str_literal":
            if isinstance(arg, vy_ast.Str):
                bytez = b""
                for c in arg.s:
                    if ord(c) >= 256:
                        raise InvalidLiteral(
                            f"Cannot insert special character {c} into byte array",
                            arg,
                        )
                    bytez += bytes([ord(c)])
                return bytez
        elif expected_arg == "bytes_literal":
            if isinstance(arg, vy_ast.Bytes):
                return arg.s
        elif expected_arg == "name_literal":
            if isinstance(arg, vy_ast.Name):
                return arg.id
            elif isinstance(arg, vy_ast.Subscript) and arg.value.id == "Bytes":
                return f"Bytes[{arg.slice.value.n}]"
        elif expected_arg == "*":
            return arg
        elif expected_arg == "Bytes":
            sub = Expr(arg, context).ir_node
            if isinstance(sub.typ, ByteArrayType):
                return sub
        elif expected_arg == "String":
            sub = Expr(arg, context).ir_node
            if isinstance(sub.typ, StringType):
                return sub
        else:
            parsed_expected_type = context.parse_type(
                vy_ast.parse_to_ast(expected_arg)[0].value)
            if isinstance(parsed_expected_type, BaseType):
                vsub = vsub or Expr.parse_value_expr(arg, context)

                is_valid_integer = (
                    (expected_arg in INTEGER_TYPES
                     and isinstance(vsub.typ, BaseType))
                    and (vsub.typ.typ in INTEGER_TYPES and vsub.typ.is_literal)
                    and (SizeLimits.in_bounds(expected_arg, vsub.value)))

                if is_base_type(vsub.typ, expected_arg):
                    return vsub
                elif is_valid_integer:
                    return vsub
            else:
                vsub = vsub or Expr(arg, context).ir_node
                if vsub.typ == parsed_expected_type:
                    return Expr(arg, context).ir_node

    if len(expected_arg_typelist) == 1:
        raise TypeMismatch(
            f"Expecting {expected_arg} for argument {index} of {function_name}",
            arg)
    else:
        raise TypeMismatch(
            f"Expecting one of {expected_arg_typelist} for argument {index} of {function_name}",
            arg)