Пример #1
0
def make_type_info(name: str,
                   is_abstract: bool = False,
                   mro: List[TypeInfo] = None,
                   bases: List[Instance] = None,
                   typevars: List[str] = None) -> TypeInfo:
    """Make a TypeInfo suitable for use in unit tests."""

    type_def = TypeDef(name, Block([]), None, [])
    type_def.fullname = name

    if typevars:
        v = []  # type: List[TypeVarDef]
        id = 1
        for n in typevars:
            v.append(TypeVarDef(n, id, None))
            id += 1
        type_def.type_vars = v

    info = TypeInfo(SymbolTable(), type_def)
    if mro is None:
        mro = []
    info.mro = [info] + mro
    if bases is None:
        if mro:
            # By default, assume that there is a single non-generic base.
            bases = [Instance(mro[0], [])]
        else:
            bases = []
    info.bases = bases

    return info
Пример #2
0
def make_type_info(name: str,
                   is_abstract: bool = False,
                   mro: List[TypeInfo] = None,
                   bases: List[Instance] = None,
                   typevars: List[str] = None) -> TypeInfo:
    """Make a TypeInfo suitable for use in unit tests."""
    
    type_def = TypeDef(name, Block([]), None, [])
    type_def.fullname = name
    
    if typevars:
        v = [] # type: List[TypeVarDef]
        id = 1
        for n in typevars:
            v.append(TypeVarDef(n, id, None))
            id += 1
        type_def.type_vars = v
    
    info = TypeInfo(SymbolTable(), type_def)
    if mro is None:
        mro = []
    info.mro = [info] + mro
    if bases is None:
        if mro:
            # By default, assume that there is a single non-generic base.
            bases = [Instance(mro[0], [])]
        else:
            bases = []
    info.bases = bases
    
    return info
Пример #3
0
    def transform_type_def(self, tdef: TypeDef) -> List[Node]:        
        """Transform a type definition.

        The result may be one or two definitions.  The first is the
        transformation of the original TypeDef. The second is a
        wrapper type, which is generated for generic types only.
        """
        defs = [] # type: List[Node]
        
        if tdef.info.type_vars:
            # This is a generic type. Insert type variable slots in
            # the class definition for new type variables, i.e. type
            # variables not mapped to superclass type variables.
            defs.extend(self.make_tvar_representation(tdef.info))
        
        # Iterate over definitions and transform each of them.
        vars = set() # type: Set[Var]
        for d in tdef.defs.body:
            if isinstance(d, FuncDef):
                # Implicit cast from FuncDef[] to Node[] is safe below.
                defs.extend(Any(self.func_tf.transform_method(d)))
            elif isinstance(d, VarDef):
                defs.extend(self.transform_var_def(d))
                for n in d.items:
                    vars.add(n)
            elif isinstance(d, AssignmentStmt):
                self.transform_assignment(d)
                defs.append(d)

        # Add accessors for implicitly defined attributes.
        for node in tdef.info.names.values():
            if isinstance(node.node, Var):
                v = cast(Var, node.node)
                if v.info == tdef.info and v not in vars:
                    defs.extend(self.make_accessors(v))
        
        # For generic classes, add an implicit __init__ wrapper.
        defs.extend(self.make_init_wrapper(tdef))
        
        if tdef.is_generic() or (tdef.info.bases and
                                 tdef.info.mro[1].is_generic()):
            self.make_instance_tvar_initializer(
                cast(FuncDef, tdef.info.get_method('__init__')))

        if not defs:
            defs.append(PassStmt())

        if tdef.is_generic():
            gen_wrapper = self.generic_class_wrapper(tdef)

        tdef.defs = Block(defs)

        dyn_wrapper = self.make_type_object_wrapper(tdef)
        
        if not tdef.is_generic():
            return [tdef, dyn_wrapper]
        else:
            return [tdef, dyn_wrapper, gen_wrapper]
Пример #4
0
 def visit_type_def(self, node: TypeDef) -> Node:
     new = TypeDef(node.name,
                   self.block(node.defs),
                   node.type_vars,
                   self.types(node.base_types),
                   node.metaclass)
     new.fullname = node.fullname
     new.info = node.info
     return new
Пример #5
0
 def generic_class_wrapper(self, tdef: TypeDef) -> TypeDef:
     """Construct a wrapper class for a generic type."""
     # FIX semanal meta-info for nodes + TypeInfo
     
     defs = [] # type: List[Node]
     
     # Does the type have a superclass, other than builtins.object?
     base = tdef.info.mro[1]
     has_proper_superclass = base.fullname() != 'builtins.object'
     
     if not has_proper_superclass or self.tf.is_java:
         # Generate member variables for wrapper object.
         defs.extend(self.make_generic_wrapper_member_vars(tdef))
     
     for alt in [False, BOUND_VAR]:
         defs.extend(self.make_tvar_representation(tdef.info, alt))
     
     # Generate constructor.
     defs.append(self.make_generic_wrapper_init(tdef.info))
     
     # Generate method wrappers.
     for d in tdef.defs.body:
         if isinstance(d, FuncDef):
             if not d.is_constructor():
                 defs.extend(self.func_tf.generic_method_wrappers(d))
         elif isinstance(d, AssignmentStmt):
             defs.extend(self.generic_accessor_wrappers(d))
         elif not isinstance(d, PassStmt):
             raise RuntimeError(
                 'Definition {} at line {} not supported'.format(
                     type(d), d.line))
     
     base_type = self.tf.named_type('builtins.object') # type: Type
     # Inherit superclass wrapper if there is one.
     if has_proper_superclass:
         base = self.find_generic_base_class(tdef.info)
         if base:
             # TODO bind the type somewhere
             base_type = UnboundType(base.defn.name +
                                     self.tf.wrapper_class_suffix())
     
     # Build the type definition.
     wrapper = TypeDef(tdef.name + self.tf.wrapper_class_suffix(),
                       Block(defs),
                       None,
                       [base_type])
     # FIX fullname
     
     self.tf.add_line_mapping(tdef, wrapper)
     
     return wrapper
Пример #6
0
 def visit_type_def(self, node: TypeDef) -> Node:
     new = TypeDef(node.name, self.block(node.defs), node.type_vars,
                   self.types(node.base_types), node.metaclass)
     new.fullname = node.fullname
     new.info = node.info
     return new
Пример #7
0
    def make_init_wrapper(self, tdef: TypeDef) -> List[Node]:
        """Make and return an implicit __init__ if class needs it.
        
        Otherwise, return an empty list. We include an implicit
        __init__ if the class is generic or if it extends a generic class
        and if it does not define __init__.
        
        The __init__ of a generic class requires one or more extra type
        variable arguments. The inherited __init__ may not accept these.

        For example, assume these definitions:
        
        . class A(Generic[T]): pass
        . class B(A[int]): pass
        
        The constructor for B will be (equivalent to)
        
        . def __init__(self: B) -> None:
        .     self.__tv = <int>
        .     super().__init__(<int>)
        """
        
        # FIX overloading, default args / varargs, keyword args

        info = tdef.info
        
        if '__init__' not in info.names and (
                tdef.is_generic() or (info.bases and
                                      info.mro[1].is_generic())):
            # Generic class with no explicit __init__ method
            # (i.e. __init__ inherited from superclass). Generate a
            # wrapper that initializes type variable slots and calls
            # the superclass __init__ method.

            base = info.mro[1]
            selftype = self_type(info)    
            callee_type = cast(Callable, analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                base))
            
            # Now the callee type may contain the type variables of a
            # grandparent as bound type variables, but we want the
            # type variables of the parent class. Explicitly set the
            # bound type variables.
            callee_type = self.fix_bound_init_tvars(callee_type,
                map_instance_to_supertype(selftype, base))
            
            super_init = cast(FuncDef, base.get_method('__init__'))
            
            # Build argument list.
            args = [Var('self')]
            for i in range(1, len(super_init.args)):
                args.append(Var(super_init.args[i].name()))
                args[-1].type = callee_type.arg_types[i - 1]

            selft = self_type(self.tf.type_context())
            callee_type = prepend_arg_type(callee_type, selft)
            
            creat = FuncDef('__init__', args,
                            super_init.arg_kinds, [None] * len(args),
                            Block([]))
            creat.info = tdef.info
            creat.type = callee_type
            creat.is_implicit = False
            tdef.info.names['__init__'] = SymbolTableNode(MDEF, creat,
                                                          typ=creat.type)
            
            # Insert a call to superclass constructor. If the
            # superclass is object, the constructor does nothing =>
            # omit the call.
            if base.fullname() != 'builtins.object':
                creat.body.body.append(
                    self.make_superclass_constructor_call(tdef.info,
                                                          callee_type))
            
            # Implicit cast from FuncDef[] to Node[] is safe below.
            return Any(self.func_tf.transform_method(creat))
        else:
            return []
Пример #8
0
    
        # class M1 implements GF<A>
        self.m1i = make_type_info('M1', (INTERFACES, [self.gfi]),
                                  (BASE_DEFS, [Instance(self.gfi, [self.a])]))

        self.gfa = Instance(self.gfi, [self.a]) # GF<A>
        self.gfb = Instance(self.gfi, [self.b]) # GF<B>

        self.m1 = Instance(self.m1i, []) # M1


TypeInfo make_type_info(any name, any *args):
    """Make a TypeInfo suitable for use in unit tests."""
    map = dict(args)
    
    type_def = TypeDef(name, Block([]), None, [])
    type_def.fullname = name
    
    if VARS in map:
        TypeVarDef[] v = []
        id = 1
        for n in map[VARS]:
            v.append(TypeVarDef(n, id))
            id += 1
        type_def.type_vars = TypeVars(v)
    
    info = TypeInfo(SymbolTable(), type_def)
    info.base = map.get(BASE, None)
    info.bases = map.get(BASE_DEFS, [])
    info.interfaces = map.get(INTERFACES, []) # TODO fix