Ejemplo n.º 1
0
 def visit_instance(self, template):
     actual = self.actual
     if isinstance(actual, Instance):
         res = []
         instance = actual
         if (self.direction == SUBTYPE_OF and
                 template.typ.has_base(instance.typ.full_name())):
             mapped = map_instance_to_supertype(template, instance.typ)
             for i in range(len(instance.args)):
                 # The constraints for generic type parameters are
                 # invariant. Include the default constraint and its
                 # negation to achieve the effect.
                 cb = infer_constraints(mapped.args[i], instance.args[i],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             return res
         elif (self.direction == SUPERTYPE_OF and
                 instance.typ.has_base(template.typ.full_name())):
             mapped = map_instance_to_supertype(instance, template.typ)
             for j in range(len(template.args)):
                 # The constraints for generic type parameters are
                 # invariant.
                 cb = infer_constraints(template.args[j], mapped.args[j],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             return res
     if isinstance(actual, Any):
         # IDEA: Include both ways, i.e. add negation as well?
         return self.infer_against_any(template.args)
     else:
         return []
Ejemplo n.º 2
0
def map_type_from_supertype( typ, sub_info, super_info):
    """Map type variables in a type defined in a supertype context to be valid
    in the subtype context. Assume that the result is unique; if more than
    one type is possible, return one of the alternatives.
    
    For example, assume
    
      class D<S> ...
      class C<T> is D<E<T>> ...
    
    Now S in the context of D would be mapped to E<T> in the context of C.
    """
    # Create the type of self in subtype, of form t<a1, ...>.
    inst_type = self_type(sub_info)
    # Map the type of self to supertype. This gets us a description of the
    # supertype type variables in terms of subtype variables, i.e. t<t1, ...>
    # so that any type variables in tN are to be interpreted in subtype
    # context.
    inst_type = map_instance_to_supertype(inst_type, super_info)
    # Finally expand the type variables in type with those in the previously
    # constructed type. Note that both type and inst_type may have type
    # variables, but in type they are interpreterd in supertype context while
    # in inst_type they are interpreted in subtype context. This works even if
    # the names of type variables in supertype and subtype overlap.
    return expand_type_by_instance(typ, inst_type)
Ejemplo n.º 3
0
def analyse_member_var_access( name, itype, info, node, is_lvalue, is_super, msg):
    """Analyse member access that does not target a method. This is logically
    part of analyse_member_access and the arguments are similar.
    """
    # It was not a method. Try looking up a variable.
    v = lookup_member_var_or_accessor(info, name, is_lvalue)
    
    if isinstance(v, Var):
        # Found a member variable.
        var = v
        itype = map_instance_to_supertype(itype, var.info)
        # FIX what if more than one?
        if var.typ:
            return expand_type_by_instance(var.typ.typ, itype)
        else:
            # Implicit dynamic type.
            return Any()
    elif isinstance(v, FuncDef):
        # Found a getter or a setter.
        raise NotImplementedError()
        #func = (FuncDef)v
        #itype = map_instance_to_supertype(itype, func.info)
        #return expand_type_by_instance(checker.accessor_type(v), itype)
    
    # Could not find the member.
    if is_super:
        msg.undefined_in_superclass(name, node)
        return Any()
    else:
        return msg.has_no_member(itype, name, node)
Ejemplo n.º 4
0
def implemented_interfaces(t):
    """If t is a class instance, return all the directly implemented interface
    types by t and its supertypes, including mapped type arguments.
    """
    if t.typ.is_interface:
        return [t]
    else:
        res = []
        
        for iface in t.typ.interfaces:
            res.append(map_instance_to_supertype(t, iface))
        
        if t.typ.base is not None:
            tt = map_instance_to_supertype(t, t.typ.base)
            res.extend(implemented_interfaces(tt))
        
        return res
Ejemplo n.º 5
0
def join_instances_via_supertype(t, s, allow_interfaces, basic):
    res = s
    mapped = map_instance_to_supertype(t, t.typ.base)
    join = join_instances(mapped, res, False, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = join
    
    if (res.typ == basic.object.typ and not t.typ.is_interface and
            allow_interfaces):
        return join_instances_as_interface(t, s, basic)
    else:
        return res
Ejemplo n.º 6
0
def analyse_member_access( name, typ, node, is_lvalue, is_super, tuple_type, msg, override_info=None):
    """Analyse member access. This is a general operation that supports various
    different variations:
    
      1. lvalue or non-lvalue access (i.e. setter or getter access)
      2. supertype access (when using the super keyword; is_super == True and
         override_info should refer to the supertype)
    
    Note that this function may return a RangeCallable type.
    """
    if isinstance(typ, Instance):
        # The base object has an instance type.
        itype = typ
        
        info = itype.typ
        if override_info:
            info = override_info
        
        # Look up the member. First look up the method dictionary.
        method = None
        if not is_lvalue:
            method = info.get_method(name)
        
        if method:
            # Found a method. The call below has a unique result for all valid
            # programs.
            itype = map_instance_to_supertype(itype, method.info)
            return expand_type_by_instance(method_type(method), itype)
        else:
            # Not a method.
            return analyse_member_var_access(name, itype, info, node,
                                             is_lvalue, is_super, msg)
    elif isinstance(typ, Any):
        # The base object has dynamic type.
        return Any()
    elif isinstance(typ, TupleType):
        # Actually look up from the tuple type.
        return analyse_member_access(name, tuple_type, node, is_lvalue,
                                     is_super, tuple_type, msg)
    else:
        # The base object has an unsupported type.
        return msg.has_no_member(typ, name, node)
Ejemplo n.º 7
0
     # The base object has an instance type.
     itype = (Instance)typ
     
     info = itype.type
     if override_info:
         info = override_info
     
     # Look up the member. First look up the method dictionary.
     FuncBase method = None
     if not is_lvalue:
         method = info.get_method(name)
     
     if method:
         # Found a method. The call below has a unique result for all valid
         # programs.
         itype = map_instance_to_supertype(itype, method.info)
         return expand_type_by_instance(method_type(method), itype)
     else:
         # Not a method.
         return analyse_member_var_access(name, itype, info, node,
                                          is_lvalue, is_super, msg)
 elif isinstance(typ, Any):
     # The base object has dynamic type.
     return Any()
 elif isinstance(typ, TupleType):
     # Actually look up from the tuple type.
     return analyse_member_access(name, tuple_type, node, is_lvalue,
                                  is_super, tuple_type, msg)
 elif isinstance(typ, Callable) and ((Callable)typ).is_type_obj():
     # Class attribute access.
     return msg.not_implemented('class attributes', node)
Ejemplo n.º 8
0
 
 # Non-trivial leaf type
 
 Constraint[] visit_type_var(self, TypeVar template):
     return [Constraint(template.id, SUPERTYPE_OF, self.actual)]
 
 # Non-leaf types
 
 Constraint[] visit_instance(self, Instance template):
     actual = self.actual
     if isinstance(actual, Instance):
         res = <Constraint> []
         instance = (Instance)actual
         if (self.direction == SUBTYPE_OF and
                 template.typ.has_base(instance.typ.full_name())):
             mapped = map_instance_to_supertype(template, instance.typ)
             for i in range(len(instance.args)):
                 # The constraints for generic type parameters are
                 # invariant. Include the default constraint and its
                 # negation to achieve the effect.
                 cb = infer_constraints(mapped.args[i], instance.args[i],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             return res
         elif (self.direction == SUPERTYPE_OF and
                 instance.typ.has_base(template.typ.full_name())):
             mapped = map_instance_to_supertype(instance, template.typ)
             for j in range(len(template.args)):
                 # The constraints for generic type parameters are
                 # invariant.
Ejemplo n.º 9
0
            # 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.
            
            selftype = self_type(info)    
            callee_type = (Callable)analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                info.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, info.base))
            
            super_init = (FuncDef)info.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,
                            <Node> [None] * len(args),
Ejemplo n.º 10
0
Archivo: join.py Proyecto: khukri/mypy
        return join_instances_as_interface(t, s, basic)
    elif t.typ.base is not None and is_subtype(t, s):
        return join_instances_via_supertype(t, s, allow_interfaces, basic)
    elif s.typ.base is not None:
        return join_instances_via_supertype(s, t, allow_interfaces, basic)
    elif allow_interfaces and not t.typ.is_interface:
        return join_instances_as_interface(t, s, basic)
    else:
        return basic.object


Typ join_instances_via_supertype(Instance t, Instance s,
                                 bool allow_interfaces,
                                 checker.BasicTypes basic):
    res = s
    mapped = map_instance_to_supertype(t, t.typ.base)
    join = join_instances(mapped, res, False, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = (Instance)join
    
    if (res.typ == basic.object.typ and not t.typ.is_interface and
            allow_interfaces):
        return join_instances_as_interface(t, s, basic)
    else:
        return res

Ejemplo n.º 11
0
    . class D<S>(object): ...
    
    Now slot mappings for C is [E<S>, T] (S and T refer to type variables of
    C).
    """
    Type[] exprs = []
    
    for slot in range(num_slots(typ)):
        # Figure out the superclass which defines the slot; also figure out
        # the tvar index that maps to the slot.
        origin, tv = find_slot_origin(typ, slot)
        
        # Map self type to the superclass -> extract tvar with target index
        # (only contains subclass tvars?? PROBABLY NOT).
        selftype = self_type(typ)
        selftype = map_instance_to_supertype(selftype, origin)
        tvar = selftype.args[tv - 1]
        
        # tvar is the representation of the slot in terms of type arguments.
        exprs.append(tvar)
    
    return exprs


tuple<TypeInfo, int> find_slot_origin(TypeInfo info, int slot):
    """Determine class and type variable index that directly maps to the slot.

    The result defines which class in inheritance hierarchy of info introduced
    the slot. All subclasses inherit this slot. The result TypeInfo always
    refers to one of the base classes of info (or info itself).