Beispiel #1
0
def _parse_kwargs(call_expr, context):
    from vyper.codegen.expr import Expr  # TODO rethink this circular import

    def _bool(x):
        assert x.value in (0, 1), "type checker missed this"
        return bool(x.value)

    # note: codegen for kwarg values in AST order
    call_kwargs = {
        kw.arg: Expr(kw.value, context).ir_node
        for kw in call_expr.keywords
    }

    ret = _CallKwargs(
        value=unwrap_location(call_kwargs.pop("value", IRnode(0))),
        gas=unwrap_location(call_kwargs.pop("gas", IRnode("gas"))),
        skip_contract_check=_bool(
            call_kwargs.pop("skip_contract_check", IRnode(0))),
        default_return_value=call_kwargs.pop("default_return_value", None),
    )

    if len(call_kwargs) != 0:
        raise TypeCheckFailure(f"Unexpected keyword arguments: {call_kwargs}")

    return ret
Beispiel #2
0
 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),
         )
Beispiel #3
0
def convert(expr, context):
    if len(expr.args) != 2:
        raise StructureException(
            "The convert function expects two parameters.", expr)

    arg_ast = expr.args[0]
    arg = Expr(arg_ast, context).ir_node
    out_typ = context.parse_type(expr.args[1])

    if isinstance(arg.typ, BaseType):
        arg = unwrap_location(arg)
    with arg.cache_when_complex("arg") as (b, arg):
        if is_base_type(out_typ, "bool"):
            ret = to_bool(arg_ast, arg, out_typ)
        elif is_base_type(out_typ, "address"):
            ret = to_address(arg_ast, arg, out_typ)
        elif is_integer_type(out_typ):
            ret = to_int(arg_ast, arg, out_typ)
        elif is_bytes_m_type(out_typ):
            ret = to_bytes_m(arg_ast, arg, out_typ)
        elif is_decimal_type(out_typ):
            ret = to_decimal(arg_ast, arg, out_typ)
        elif isinstance(out_typ, ByteArrayType):
            ret = to_bytes(arg_ast, arg, out_typ)
        elif isinstance(out_typ, StringType):
            ret = to_string(arg_ast, arg, out_typ)
        else:
            raise StructureException(f"Conversion to {out_typ} is invalid.",
                                     arg_ast)

        ret = b.resolve(ret)

    return IRnode.from_list(ret)
Beispiel #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
Beispiel #5
0
def _encode_log_topics(expr, event_id, arg_nodes, context):
    topics = [event_id]

    for arg in arg_nodes:
        if isinstance(arg.typ, BaseType):
            value = unwrap_location(arg)

        elif isinstance(arg.typ, ByteArrayLike):
            value = keccak256_helper(expr, arg, context=context)
        else:
            # TODO block at higher level
            raise TypeMismatch("Event indexes may only be value types", expr)

        topics.append(value)

    return topics
Beispiel #6
0
def convert(expr, context):
    if len(expr.args) != 2:
        raise StructureException(
            "The convert function expects two parameters.", expr)

    arg_ast = expr.args[0]
    arg = Expr(arg_ast, context).ir_node
    original_arg = arg
    out_typ = context.parse_type(expr.args[1])

    if isinstance(arg.typ, BaseType):
        arg = unwrap_location(arg)
    with arg.cache_when_complex("arg") as (b, arg):
        if is_base_type(out_typ, "bool"):
            ret = to_bool(arg_ast, arg, out_typ)
        elif is_base_type(out_typ, "address"):
            ret = to_address(arg_ast, arg, out_typ)
        elif isinstance(out_typ, EnumType):
            ret = to_enum(arg_ast, arg, out_typ)
        elif is_integer_type(out_typ):
            ret = to_int(arg_ast, arg, out_typ)
        elif is_bytes_m_type(out_typ):
            ret = to_bytes_m(arg_ast, arg, out_typ)
        elif is_decimal_type(out_typ):
            ret = to_decimal(arg_ast, arg, out_typ)
        elif isinstance(out_typ, ByteArrayType):
            ret = to_bytes(arg_ast, arg, out_typ)
        elif isinstance(out_typ, StringType):
            ret = to_string(arg_ast, arg, out_typ)
        else:
            raise StructureException(f"Conversion to {out_typ} is invalid.",
                                     arg_ast)

        # test if arg actually changed. if not, we do not need to use
        # unwrap_location (this can reduce memory traffic for downstream
        # operations which are in-place, like the returndata routine)
        test_arg = IRnode.from_list(arg, typ=out_typ)
        if test_arg == ret:
            original_arg.typ = out_typ
            return original_arg

        return IRnode.from_list(b.resolve(ret))
Beispiel #7
0
    def build_in_comparator(self):
        left = Expr(self.expr.left, self.context).lll_node
        right = Expr(self.expr.right, self.context).lll_node

        # temporary kludge to block #2637 bug
        # TODO actually fix the bug
        if not isinstance(left.typ, BaseType):
            raise TypeMismatch(
                "`in` not allowed for arrays of non-base types, tracked in issue #2637",
                self.expr)

        if isinstance(self.expr.op, vy_ast.In):
            found, not_found = 1, 0
        elif isinstance(self.expr.op, vy_ast.NotIn):
            found, not_found = 0, 1
        else:
            return  # pragma: notest

        i = LLLnode.from_list(self.context.fresh_varname("in_ix"),
                              typ="uint256")

        found_ptr = self.context.new_internal_variable(BaseType("bool"))

        ret = ["seq"]

        left = unwrap_location(left)
        with left.cache_when_complex("needle") as (
                b1, left), right.cache_when_complex("haystack") as (b2, right):
            if right.value == "multi":
                # Copy literal to memory to be compared.
                tmp_list = LLLnode.from_list(
                    self.context.new_internal_variable(right.typ),
                    typ=right.typ,
                    location="memory",
                )
                ret.append(make_setter(tmp_list, right, pos=getpos(self.expr)))

                right = tmp_list

            # location of i'th item from list
            pos = getpos(self.expr)
            ith_element_ptr = get_element_ptr(right,
                                              i,
                                              array_bounds_check=False,
                                              pos=pos)
            ith_element = unwrap_location(ith_element_ptr)

            if isinstance(right.typ, SArrayType):
                len_ = right.typ.count
            else:
                len_ = get_dyn_array_count(right)

            # Condition repeat loop has to break on.
            # TODO maybe put result on the stack
            loop_body = [
                "if",
                ["eq", left, ith_element],
                ["seq", ["mstore", found_ptr, found], "break"],  # store true.
            ]
            loop = ["repeat", i, 0, len_, right.typ.count, loop_body]

            ret.append([
                "seq",
                ["mstore", found_ptr, not_found],
                loop,
                ["mload", found_ptr],
            ])

            return LLLnode.from_list(b1.resolve(b2.resolve(ret)), typ="bool")
Beispiel #8
0
 def parse_value_expr(cls, expr, context):
     return unwrap_location(cls(expr, context).lll_node)