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)
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)
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)
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) else: