Exemple #1
0
    def setUp(self) -> None:
        self.env = Environment()
        self.n = self.env.add_local(Var('n'), int_rprimitive)
        self.m = self.env.add_local(Var('m'), int_rprimitive)
        self.k = self.env.add_local(Var('k'), int_rprimitive)
        self.l = self.env.add_local(Var('l'), list_rprimitive)  # noqa
        self.ll = self.env.add_local(Var('ll'), list_rprimitive)
        self.o = self.env.add_local(Var('o'), object_rprimitive)
        self.o2 = self.env.add_local(Var('o2'), object_rprimitive)
        self.d = self.env.add_local(Var('d'), dict_rprimitive)
        self.b = self.env.add_local(Var('b'), bool_rprimitive)
        self.t = self.env.add_local(Var('t'),
                                    RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = self.env.add_local(
            Var('tt'),
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = self.env.add_local(Var('r'), RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
        self.emitter = Emitter(self.context, self.env)
        self.declarations = Emitter(self.context, self.env)
        self.visitor = FunctionEmitterVisitor(self.emitter, self.declarations,
                                              'prog.py', 'prog')
Exemple #2
0
    def gen_glue_ne_method(self, cls: ClassIR, line: int) -> FuncIR:
        """Generate a __ne__ method from a __eq__ method. """
        self.builder.enter()

        rt_args = (RuntimeArg("self", RInstance(cls)), RuntimeArg("rhs", object_rprimitive))

        # The environment operates on Vars, so we make some up
        fake_vars = [(Var(arg.name), arg.type) for arg in rt_args]
        args = [
            self.builder.read(
                self.builder.environment.add_local_reg(
                    var, type, is_arg=True
                ),
                line
            )
            for var, type in fake_vars
        ]  # type: List[Value]
        self.builder.ret_types[-1] = object_rprimitive

        # If __eq__ returns NotImplemented, then __ne__ should also
        not_implemented_block, regular_block = BasicBlock(), BasicBlock()
        eqval = self.add(MethodCall(args[0], '__eq__', [args[1]], line))
        not_implemented = self.primitive_op(not_implemented_op, [], line)
        self.add(Branch(
            self.builder.binary_op(eqval, not_implemented, 'is', line),
            not_implemented_block,
            regular_block,
            Branch.BOOL_EXPR))

        self.builder.activate_block(regular_block)
        retval = self.builder.coerce(
            self.builder.unary_op(eqval, 'not', line), object_rprimitive, line
        )
        self.add(Return(retval))

        self.builder.activate_block(not_implemented_block)
        self.add(Return(not_implemented))

        blocks, env, ret_type, _ = self.builder.leave()
        return FuncIR(
            FuncDecl('__ne__', cls.name, self.module_name,
                     FuncSignature(rt_args, ret_type)),
            blocks, env)
Exemple #3
0
    def generate_attr_defaults(self, cdef: ClassDef) -> None:
        """Generate an initialization method for default attr values (from class vars)"""
        cls = self.mapper.type_to_ir[cdef.info]
        if cls.builtin_base:
            return

        # Pull out all assignments in classes in the mro so we can initialize them
        # TODO: Support nested statements
        default_assignments = []
        for info in reversed(cdef.info.mro):
            if info not in self.mapper.type_to_ir:
                continue
            for stmt in info.defn.defs.body:
                if (isinstance(stmt, AssignmentStmt)
                        and isinstance(stmt.lvalues[0], NameExpr)
                        and not is_class_var(stmt.lvalues[0])
                        and not isinstance(stmt.rvalue, TempNode)):
                    if stmt.lvalues[0].name == '__slots__':
                        continue

                    # Skip type annotated assignments in dataclasses
                    if is_dataclass(cdef) and stmt.type:
                        continue

                    default_assignments.append(stmt)

        if not default_assignments:
            return

        self.builder.enter()
        self.builder.ret_types[-1] = bool_rprimitive

        rt_args = (RuntimeArg(SELF_NAME, RInstance(cls)),)
        self_var = self.builder.read(add_self_to_env(self.builder.environment, cls), -1)

        for stmt in default_assignments:
            lvalue = stmt.lvalues[0]
            assert isinstance(lvalue, NameExpr)
            if not stmt.is_final_def and not is_constant(stmt.rvalue):
                self.builder.warning('Unsupported default attribute value', stmt.rvalue.line)

            # If the attribute is initialized to None and type isn't optional,
            # don't initialize it to anything.
            attr_type = cls.attr_type(lvalue.name)
            if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None':
                if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type)
                        and not is_none_rprimitive(attr_type)):
                    continue
            val = self.builder.coerce(self.accept(stmt.rvalue), attr_type, stmt.line)
            self.add(SetAttr(self_var, lvalue.name, val, -1))

        self.add(Return(self.primitive_op(true_op, [], -1)))

        blocks, env, ret_type, _ = self.builder.leave()
        ir = FuncIR(
            FuncDecl('__mypyc_defaults_setup',
                     cls.name, self.module_name,
                     FuncSignature(rt_args, ret_type)),
            blocks, env)
        self.builder.functions.append(ir)
        cls.methods[ir.name] = ir
 def setUp(self) -> None:
     self.inst_a = RInstance(ClassIR('A', '__main__'))
     self.inst_b = RInstance(ClassIR('B', '__main__'))
Exemple #5
0
def add_self_to_env(environment: Environment, cls: ClassIR) -> AssignmentTargetRegister:
    return environment.add_local_reg(
        Var(SELF_NAME), RInstance(cls), is_arg=True
    )
def prepare_class_def(path: str, module_name: str, cdef: ClassDef,
                      errors: Errors, mapper: Mapper) -> None:

    ir = mapper.type_to_ir[cdef.info]
    info = cdef.info

    attrs = get_mypyc_attrs(cdef)
    if attrs.get("allow_interpreted_subclasses") is True:
        ir.allow_interpreted_subclasses = True

    # We sort the table for determinism here on Python 3.5
    for name, node in sorted(info.names.items()):
        # Currently all plugin generated methods are dummies and not included.
        if node.plugin_generated:
            continue

        if isinstance(node.node, Var):
            assert node.node.type, "Class member %s missing type" % name
            if not node.node.is_classvar and name != '__slots__':
                ir.attributes[name] = mapper.type_to_rtype(node.node.type)
        elif isinstance(node.node, (FuncDef, Decorator)):
            prepare_method_def(ir, module_name, cdef, mapper, node.node)
        elif isinstance(node.node, OverloadedFuncDef):
            # Handle case for property with both a getter and a setter
            if node.node.is_property:
                if is_valid_multipart_property_def(node.node):
                    for item in node.node.items:
                        prepare_method_def(ir, module_name, cdef, mapper, item)
                else:
                    errors.error("Unsupported property decorator semantics",
                                 path, cdef.line)

            # Handle case for regular function overload
            else:
                assert node.node.impl
                prepare_method_def(ir, module_name, cdef, mapper,
                                   node.node.impl)

    # Check for subclassing from builtin types
    for cls in info.mro:
        # Special case exceptions and dicts
        # XXX: How do we handle *other* things??
        if cls.fullname == 'builtins.BaseException':
            ir.builtin_base = 'PyBaseExceptionObject'
        elif cls.fullname == 'builtins.dict':
            ir.builtin_base = 'PyDictObject'
        elif cls.fullname.startswith('builtins.'):
            if not can_subclass_builtin(cls.fullname):
                # Note that if we try to subclass a C extension class that
                # isn't in builtins, bad things will happen and we won't
                # catch it here! But this should catch a lot of the most
                # common pitfalls.
                errors.error(
                    "Inheriting from most builtin types is unimplemented",
                    path, cdef.line)

    if ir.builtin_base:
        ir.attributes.clear()

    # Set up a constructor decl
    init_node = cdef.info['__init__'].node
    if not ir.is_trait and not ir.builtin_base and isinstance(
            init_node, FuncDef):
        init_sig = mapper.fdef_to_sig(init_node)

        defining_ir = mapper.type_to_ir.get(init_node.info)
        # If there is a nontrivial __init__ that wasn't defined in an
        # extension class, we need to make the constructor take *args,
        # **kwargs so it can call tp_init.
        if ((defining_ir is None or not defining_ir.is_ext_class
             or cdef.info['__init__'].plugin_generated)
                and init_node.info.fullname != 'builtins.object'):
            init_sig = FuncSignature([
                init_sig.args[0],
                RuntimeArg("args", tuple_rprimitive, ARG_STAR),
                RuntimeArg("kwargs", dict_rprimitive, ARG_STAR2)
            ], init_sig.ret_type)

        ctor_sig = FuncSignature(init_sig.args[1:], RInstance(ir))
        ir.ctor = FuncDecl(cdef.name, None, module_name, ctor_sig)
        mapper.func_to_decl[cdef.info] = ir.ctor

    # Set up the parent class
    bases = [
        mapper.type_to_ir[base.type] for base in info.bases
        if base.type in mapper.type_to_ir
    ]
    if not all(c.is_trait for c in bases[1:]):
        errors.error("Non-trait bases must appear first in parent list", path,
                     cdef.line)
    ir.traits = [c for c in bases if c.is_trait]

    mro = []
    base_mro = []
    for cls in info.mro:
        if cls not in mapper.type_to_ir:
            if cls.fullname != 'builtins.object':
                ir.inherits_python = True
            continue
        base_ir = mapper.type_to_ir[cls]
        if not base_ir.is_trait:
            base_mro.append(base_ir)
        mro.append(base_ir)

        if cls.defn.removed_base_type_exprs or not base_ir.is_ext_class:
            ir.inherits_python = True

    base_idx = 1 if not ir.is_trait else 0
    if len(base_mro) > base_idx:
        ir.base = base_mro[base_idx]
    ir.mro = mro
    ir.base_mro = base_mro

    for base in bases:
        if base.children is not None:
            base.children.append(ir)

    if is_dataclass(cdef):
        ir.is_augmented = True
    def type_to_rtype(self, typ: Optional[Type]) -> RType:
        if typ is None:
            return object_rprimitive

        typ = get_proper_type(typ)
        if isinstance(typ, Instance):
            if typ.type.fullname == 'builtins.int':
                return int_rprimitive
            elif typ.type.fullname == 'builtins.float':
                return float_rprimitive
            elif typ.type.fullname == 'builtins.str':
                return str_rprimitive
            elif typ.type.fullname == 'builtins.bool':
                return bool_rprimitive
            elif typ.type.fullname == 'builtins.list':
                return list_rprimitive
            # Dict subclasses are at least somewhat common and we
            # specifically support them, so make sure that dict operations
            # get optimized on them.
            elif any(cls.fullname == 'builtins.dict' for cls in typ.type.mro):
                return dict_rprimitive
            elif typ.type.fullname == 'builtins.set':
                return set_rprimitive
            elif typ.type.fullname == 'builtins.tuple':
                return tuple_rprimitive  # Varying-length tuple
            elif typ.type in self.type_to_ir:
                return RInstance(self.type_to_ir[typ.type])
            else:
                return object_rprimitive
        elif isinstance(typ, TupleType):
            # Use our unboxed tuples for raw tuples but fall back to
            # being boxed for NamedTuple.
            if typ.partial_fallback.type.fullname == 'builtins.tuple':
                return RTuple([self.type_to_rtype(t) for t in typ.items])
            else:
                return tuple_rprimitive
        elif isinstance(typ, CallableType):
            return object_rprimitive
        elif isinstance(typ, NoneTyp):
            return none_rprimitive
        elif isinstance(typ, UnionType):
            return RUnion([self.type_to_rtype(item)
                           for item in typ.items])
        elif isinstance(typ, AnyType):
            return object_rprimitive
        elif isinstance(typ, TypeType):
            return object_rprimitive
        elif isinstance(typ, TypeVarType):
            # Erase type variable to upper bound.
            # TODO: Erase to union if object has value restriction?
            return self.type_to_rtype(typ.upper_bound)
        elif isinstance(typ, PartialType):
            assert typ.var.type is not None
            return self.type_to_rtype(typ.var.type)
        elif isinstance(typ, Overloaded):
            return object_rprimitive
        elif isinstance(typ, TypedDictType):
            return dict_rprimitive
        elif isinstance(typ, LiteralType):
            return self.type_to_rtype(typ.fallback)
        elif isinstance(typ, (UninhabitedType, UnboundType)):
            # Sure, whatever!
            return object_rprimitive

        # I think we've covered everything that is supposed to
        # actually show up, so anything else is a bug somewhere.
        assert False, 'unexpected type %s' % type(typ)