コード例 #1
0
    def visit_call_expr(self, expr: CallExpr) -> Register:
        if isinstance(expr.callee, MemberExpr):
            is_module_call = self.is_module_member_expr(expr.callee)
            if expr.callee.expr in self.types and not is_module_call:
                target = self.translate_special_method_call(expr.callee, expr)
                if target:
                    return target

            # Either its a module call or translating to a special method call failed, so we have
            # to fallback to a PyCall
            function = self.accept(expr.callee)
            return self.py_call(function, expr.args, self.node_type(expr))

        assert isinstance(expr.callee, NameExpr)
        fn = expr.callee.name  # TODO: fullname
        if fn == 'len' and len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]:
            target = self.alloc_target(IntRType())
            arg = self.accept(expr.args[0])

            expr_rtype = self.node_type(expr.args[0])
            if expr_rtype.name == 'list':
                self.add(PrimitiveOp(target, PrimitiveOp.LIST_LEN, arg))
            elif expr_rtype.name == 'sequence_tuple':
                self.add(
                    PrimitiveOp(target, PrimitiveOp.HOMOGENOUS_TUPLE_LEN, arg))
            elif isinstance(expr_rtype, TupleRType):
                self.add(LoadInt(target, len(expr_rtype.types)))
            else:
                assert False, "unsupported use of len"

        # Handle conversion to sequence tuple
        elif fn == 'tuple' and len(
                expr.args) == 1 and expr.arg_kinds == [ARG_POS]:
            target = self.alloc_target(SequenceTupleRType())
            arg = self.accept(expr.args[0])

            self.add(
                PrimitiveOp(target, PrimitiveOp.LIST_TO_HOMOGENOUS_TUPLE, arg))
        else:
            target_type = self.node_type(expr)
            if not (self.is_native_name_expr(expr.callee)):
                function = self.accept(expr.callee)
                return self.py_call(function, expr.args, target_type)

            target = self.alloc_target(target_type)
            args = [self.accept(arg) for arg in expr.args]
            self.add(Call(target, fn, args))
        return target
コード例 #2
0
 def test_list_get_item(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.n, PrimitiveOp.LIST_GET, self.m, self.k),
         """cpy_r_n = CPyList_GetItem(cpy_r_m, cpy_r_k);
                         if (!cpy_r_n)
                             abort();
                      """)
コード例 #3
0
    def assign_to_target(self, target: AssignmentTarget, rvalue: Expression,
                         rvalue_type: RType, needs_box: bool) -> Register:
        rvalue_type = rvalue_type or self.node_type(rvalue)

        if isinstance(target, AssignmentTargetRegister):
            if needs_box:
                unboxed = self.accept(rvalue)
                return self.box(unboxed, rvalue_type, target=target.register)
            else:
                return self.accept(rvalue, target=target.register)
        elif isinstance(target, AssignmentTargetAttr):
            rvalue_reg = self.accept(rvalue)
            if needs_box:
                rvalue_reg = self.box(rvalue_reg, rvalue_type)
            self.add(
                SetAttr(target.obj_reg, target.attr, rvalue_reg,
                        target.obj_type))
            return INVALID_REGISTER
        elif isinstance(target, AssignmentTargetIndex):
            item_reg = self.accept(rvalue)
            boxed_item_reg = self.box(item_reg, rvalue_type)
            if isinstance(target.rtype, ListRType):
                op = PrimitiveOp.LIST_SET
            elif isinstance(target.rtype, DictRType):
                op = PrimitiveOp.DICT_SET
            else:
                assert False, target.rtype
            self.add(
                PrimitiveOp(None, op, target.base_reg, target.index_reg,
                            boxed_item_reg))
            return INVALID_REGISTER

        assert False, 'Unsupported assignment target'
コード例 #4
0
 def test_list_len(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.n, PrimitiveOp.LIST_LEN, self.l),
         """long long __tmp1;
                         __tmp1 = PyList_GET_SIZE(cpy_r_l);
                         cpy_r_n = CPyTagged_ShortFromLongLong(__tmp1);
                      """)
コード例 #5
0
 def test_new_dict(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.d, PrimitiveOp.NEW_DICT),
         """cpy_r_d = PyDict_New();
                         if (!cpy_r_d)
                             abort();
                      """)
コード例 #6
0
    def visit_index_expr(self, expr: IndexExpr) -> Register:
        base_rtype = self.node_type(expr.base)
        base_reg = self.accept(expr.base)
        target_type = self.node_type(expr)

        if isinstance(base_rtype, (ListRType, SequenceTupleRType, DictRType)):
            index_type = self.node_type(expr.index)
            if not isinstance(base_rtype, DictRType):
                assert isinstance(
                    index_type,
                    IntRType), 'Unsupported indexing operation'  # TODO
            if isinstance(base_rtype, ListRType):
                op = PrimitiveOp.LIST_GET
            elif isinstance(base_rtype, DictRType):
                op = PrimitiveOp.DICT_GET
            else:
                op = PrimitiveOp.HOMOGENOUS_TUPLE_GET
            index_reg = self.accept(expr.index)
            if isinstance(base_rtype, DictRType):
                index_reg = self.box(index_reg, index_type)
            tmp = self.alloc_temp(ObjectRType())
            self.add(PrimitiveOp(tmp, op, base_reg, index_reg))
            target = self.alloc_target(target_type)
            return self.unbox_or_cast(tmp, target_type, target)
        elif isinstance(base_rtype, TupleRType):
            assert isinstance(expr.index, IntExpr)  # TODO
            target = self.alloc_target(target_type)
            self.add(
                TupleGet(target, base_reg, expr.index.value,
                         base_rtype.types[expr.index.value]))
            return target

        assert False, 'Unsupported indexing operation'
コード例 #7
0
 def binary_op(self,
               ltype: RType,
               lreg: Register,
               rtype: RType,
               rreg: Register,
               expr_op: str,
               target: Optional[Register] = None) -> Register:
     if ltype.name == 'int' and rtype.name == 'int':
         # Primitive int operation
         if target is None:
             target = self.alloc_target(IntRType())
         op = self.int_binary_ops[expr_op]
     elif (ltype.name == 'list' or rtype.name == 'list') and expr_op == '*':
         if rtype.name == 'list':
             ltype, rtype = rtype, ltype
             lreg, rreg = rreg, lreg
         if rtype.name != 'int':
             assert False, 'Unsupported binary operation'  # TODO: Operator overloading
         if target is None:
             target = self.alloc_target(ListRType())
         op = PrimitiveOp.LIST_REPEAT
     elif isinstance(rtype, DictRType):
         if expr_op == 'in':
             if target is None:
                 target = self.alloc_target(BoolRType())
             lreg = self.box(lreg, ltype)
             op = PrimitiveOp.DICT_CONTAINS
         else:
             assert False, 'Unsupported binary operation'
     else:
         assert False, 'Unsupported binary operation'
     self.add(PrimitiveOp(target, op, lreg, rreg))
     return target
コード例 #8
0
 def test_dict_get_item(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.o, PrimitiveOp.DICT_GET, self.d, self.o2),
         """cpy_r_o = PyDict_GetItem(cpy_r_d, cpy_r_o2);
                         if (!cpy_r_o)
                             abort();
                         Py_INCREF(cpy_r_o);
                      """)
コード例 #9
0
ファイル: test_emitfunc.py プロジェクト: mrwright/mypyc
 def test_dict_get_item(self) -> None:
     self.assert_emit(PrimitiveOp([self.d, self.o2], dict_get_item_op, 1),
                      """cpy_r_r0 = PyDict_GetItemWithError(cpy_r_d, cpy_r_o2);
                         if (!cpy_r_r0)
                             PyErr_SetObject(PyExc_KeyError, cpy_r_o2);
                         else
                             Py_INCREF(cpy_r_r0);
                      """)
コード例 #10
0
 def visit_return_stmt(self, stmt: ReturnStmt) -> Register:
     if stmt.expr:
         retval = self.accept(stmt.expr)
     else:
         retval = self.environment.add_temp(NoneRType())
         self.add(PrimitiveOp(retval, PrimitiveOp.NONE))
     self.add(Return(retval))
     return INVALID_REGISTER
コード例 #11
0
    def visit_tuple_expr(self, expr: TupleExpr) -> Register:
        tuple_type = self.types[expr]
        assert isinstance(tuple_type, TupleType)

        target = self.alloc_target(self.type_to_rtype(tuple_type))
        items = [self.accept(i) for i in expr.items]
        self.add(PrimitiveOp(target, PrimitiveOp.NEW_TUPLE, *items))
        return target
コード例 #12
0
 def test_dict_contains(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.b, PrimitiveOp.DICT_CONTAINS, self.o, self.d),
         """int __tmp1 = PyDict_Contains(cpy_r_d, cpy_r_o);
                         if (__tmp1 < 0)
                             abort();
                         cpy_r_b = __tmp1;
                      """)
コード例 #13
0
 def test_new_list(self) -> None:
     self.assert_emit(
         PrimitiveOp([self.n, self.m], new_list_op, 55),
         """cpy_r_r0 = PyList_New(2);
                         if (likely(cpy_r_r0 != NULL)) {
                             PyList_SET_ITEM(cpy_r_r0, 0, cpy_r_n);
                             PyList_SET_ITEM(cpy_r_r0, 1, cpy_r_m);
                         }
                      """)
コード例 #14
0
ファイル: ir_builder.py プロジェクト: swetavooda/mypy
 def primitive_op(self, desc: OpDescription, args: List[Value], line: int) -> Value:
     assert desc.result_type is not None
     coerced = []
     for i, arg in enumerate(args):
         formal_type = self.op_arg_type(desc, i)
         arg = self.coerce(arg, formal_type, line)
         coerced.append(arg)
     target = self.add(PrimitiveOp(coerced, desc, line))
     return target
コード例 #15
0
 def test_new_list(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.l, PrimitiveOp.NEW_LIST, self.n, self.m),
         """cpy_r_l = PyList_New(2);
                         Py_INCREF(cpy_r_n);
                         PyList_SET_ITEM(cpy_r_l, 0, cpy_r_n);
                         Py_INCREF(cpy_r_m);
                         PyList_SET_ITEM(cpy_r_l, 1, cpy_r_m);
                      """)
コード例 #16
0
 def assert_emit_binary_op(self, op: str, dest: Value, left: Value,
                           right: Value, expected: str) -> None:
     ops = binary_ops[op]
     for desc in ops:
         if (is_subtype(left.type, desc.arg_types[0])
                 and is_subtype(right.type, desc.arg_types[1])):
             self.assert_emit(PrimitiveOp([left, right], desc, 55),
                              expected)
             break
     else:
         assert False, 'Could not find matching op'
コード例 #17
0
 def test_list_repeat(self) -> None:
     self.assert_emit(
         PrimitiveOp(self.ll, PrimitiveOp.LIST_REPEAT, self.l, self.n),
         """long long __tmp1;
                         __tmp1 = CPyTagged_AsLongLong(cpy_r_n);
                         if (__tmp1 == -1 && PyErr_Occurred())
                             abort();
                         cpy_r_ll = PySequence_Repeat(cpy_r_l, __tmp1);
                         if (!cpy_r_ll)
                             abort();
                      """)
コード例 #18
0
 def visit_list_expr(self, expr: ListExpr) -> Register:
     list_type = self.types[expr]
     assert isinstance(list_type, Instance)
     item_type = self.type_to_rtype(list_type.args[0])
     target = self.alloc_target(ListRType())
     items = []
     for item in expr.items:
         item_reg = self.accept(item)
         boxed = self.box(item_reg, item_type)
         items.append(boxed)
     self.add(PrimitiveOp(target, PrimitiveOp.NEW_LIST, *items))
     return target
コード例 #19
0
 def translate_special_method_call(self, callee: MemberExpr,
                                   expr: CallExpr) -> Register:
     base_type = self.node_type(callee.expr)
     result_type = self.node_type(expr)
     base = self.accept(callee.expr)
     if callee.name == 'append' and base_type.name == 'list':
         target = INVALID_REGISTER  # TODO: Do we sometimes need to allocate a register?
         arg = self.box_expr(expr.args[0])
         self.add(PrimitiveOp(target, PrimitiveOp.LIST_APPEND, base, arg))
     else:
         assert False, 'Unsupported method call: %s.%s' % (base_type.name,
                                                           callee.name)
     return target
コード例 #20
0
    def visit_name_expr(self, expr: NameExpr) -> Register:
        if expr.node.fullname() == 'builtins.None':
            target = self.alloc_target(NoneRType())
            self.add(PrimitiveOp(target, PrimitiveOp.NONE))
            return target
        elif expr.node.fullname() == 'builtins.True':
            target = self.alloc_target(BoolRType())
            self.add(PrimitiveOp(target, PrimitiveOp.TRUE))
            return target
        elif expr.node.fullname() == 'builtins.False':
            target = self.alloc_target(BoolRType())
            self.add(PrimitiveOp(target, PrimitiveOp.FALSE))
            return target

        if not self.is_native_name_expr(expr):
            return self.load_static_module_attr(expr)

        # TODO: We assume that this is a Var node, which is very limited
        assert isinstance(expr.node, Var)

        reg = self.environment.lookup(expr.node)
        return self.get_using_binder(reg, expr.node, expr)
コード例 #21
0
    def visit_unary_expr(self, expr: UnaryExpr) -> Register:
        if expr.op != '-':
            assert False, 'Unsupported unary operation'

        etype = self.node_type(expr.expr)
        reg = self.accept(expr.expr)
        if etype.name != 'int':
            assert False, 'Unsupported unary operation'

        target = self.alloc_target(IntRType())
        zero = self.accept(IntExpr(0))
        self.add(PrimitiveOp(target, PrimitiveOp.INT_SUB, zero, reg))

        return target
コード例 #22
0
    def visit_name_expr(self, expr: NameExpr) -> Value:
        assert expr.node, "RefExpr not resolved"
        fullname = expr.node.fullname
        if fullname in name_ref_ops:
            # Use special access op for this particular name.
            desc = name_ref_ops[fullname]
            assert desc.result_type is not None
            return self.builder.add(PrimitiveOp([], desc, expr.line))

        if isinstance(expr.node, Var) and expr.node.is_final:
            value = self.builder.emit_load_final(
                expr.node,
                fullname,
                expr.name,
                self.builder.is_native_ref_expr(expr),
                self.builder.types[expr],
                expr.line,
            )
            if value is not None:
                return value

        if isinstance(expr.node,
                      MypyFile) and expr.node.fullname in self.builder.imports:
            return self.builder.load_module(expr.node.fullname)

        # If the expression is locally defined, then read the result from the corresponding
        # assignment target and return it. Otherwise if the expression is a global, load it from
        # the globals dictionary.
        # Except for imports, that currently always happens in the global namespace.
        if expr.kind == LDEF and not (isinstance(expr.node, Var)
                                      and expr.node.is_suppressed_import):
            # Try to detect and error when we hit the irritating mypy bug
            # where a local variable is cast to None. (#5423)
            if (isinstance(expr.node, Var)
                    and is_none_rprimitive(self.builder.node_type(expr))
                    and expr.node.is_inferred):
                self.builder.error(
                    "Local variable '{}' has inferred type None; add an annotation"
                    .format(expr.node.name), expr.node.line)

            # TODO: Behavior currently only defined for Var and FuncDef node types.
            return self.builder.read(self.builder.get_assignment_target(expr),
                                     expr.line)

        return self.builder.load_global(expr)
コード例 #23
0
def transform_del_item(builder: IRBuilder, target: AssignmentTarget, line: int) -> None:
    if isinstance(target, AssignmentTargetIndex):
        builder.gen_method_call(
            target.base,
            '__delitem__',
            [target.index],
            result_type=None,
            line=line
        )
    elif isinstance(target, AssignmentTargetAttr):
        key = builder.load_static_unicode(target.attr)
        builder.add(PrimitiveOp([target.obj, key], py_delattr_op, line))
    elif isinstance(target, AssignmentTargetRegister):
        # Delete a local by assigning an error value to it, which will
        # prompt the insertion of uninit checks.
        builder.add(Assign(target.register,
                           builder.add(LoadErrorValue(target.type, undefines=True))))
    elif isinstance(target, AssignmentTargetTuple):
        for subtarget in target.items:
            transform_del_item(builder, subtarget, line)
コード例 #24
0
 def test_load_None(self) -> None:
     self.assert_emit(PrimitiveOp([], none_object_op, 0),
                      "cpy_r_r0 = Py_None;")
コード例 #25
0
 def test_new_dict(self) -> None:
     self.assert_emit(PrimitiveOp([], new_dict_op, 1),
                      """cpy_r_r0 = PyDict_New();""")
コード例 #26
0
 def test_dict_update(self) -> None:
     self.assert_emit(
         PrimitiveOp([self.d, self.o], dict_update_op, 1),
         """cpy_r_r0 = CPyDict_Update(cpy_r_d, cpy_r_o) >= 0;""")
コード例 #27
0
 def test_dict_set_item(self) -> None:
     self.assert_emit(
         PrimitiveOp([self.d, self.o, self.o2], dict_set_item_op, 1),
         """cpy_r_r0 = CPyDict_SetItem(cpy_r_d, cpy_r_o, cpy_r_o2) >= 0;""")
コード例 #28
0
 def test_list_append(self) -> None:
     self.assert_emit(
         PrimitiveOp([self.l, self.o], list_append_op, 1),
         """cpy_r_r0 = PyList_Append(cpy_r_l, cpy_r_o) >= 0;""")
コード例 #29
0
 def test_list_get_item(self) -> None:
     self.assert_emit(PrimitiveOp([self.m, self.k], list_get_item_op, 55),
                      """cpy_r_r0 = CPyList_GetItem(cpy_r_m, cpy_r_k);""")
コード例 #30
0
 def test_list_set_item(self) -> None:
     self.assert_emit(
         PrimitiveOp([self.l, self.n, self.o], list_set_item_op, 55),
         """cpy_r_r0 = CPyList_SetItem(cpy_r_l, cpy_r_n, cpy_r_o);""")