def check_method_or_accessor_override_for_base(self, defn, base): """Check that function definition is compatible with any overridden definition in the specified supertype. """ if base: if defn.name() != '__init__': # Check method override (create is special). base_method = base.get_method(defn.name()) if base_method and base_method.info == base: # There is an overridden method in the supertype. # Construct the type of the overriding method. typ = method_type(defn) # Map the overridden method type to subtype context so that # it can be checked for compatibility. Note that multiple # types from multiple implemented interface instances may # be present. original_type = map_type_from_supertype( method_type(base_method), defn.info, base) # Check that the types are compatible. # TODO overloaded signatures self.check_override(typ, original_type, defn.name(), base_method.info.name(), defn) # Also check interface implementations. for iface in base.interfaces: self.check_method_or_accessor_override_for_base(defn, iface) # We have to check that the member is compatible with all # supertypes due to the dynamic type. Otherwise we could first # override with dynamic and then with an arbitary type. self.check_method_or_accessor_override_for_base(defn, base.base)
def type_object_type(self, info): """Return the type of a type object. For a generic type G with type variables T and S the type is of form def <T, S>(...) as G<T, S>, where ... are argument types for the __init__ method. """ if info.is_interface: return self.chk.type_type() init_method = info.get_method('__init__') if not init_method: # Must be an invalid class definition. return Any() else: # Construct callable type based on signature of __init__. Adjust # return type and insert type arguments. init_type = method_type(init_method) if isinstance(init_type, Callable): return self.class_callable(init_type, info) else: # Overloaded __init__. items = [] for it in (init_type).items(): items.append(self.class_callable(it, info)) return Overloaded(items)
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)
For a generic type G with type variables T and S the type is of form def <T, S>(...) as G<T, S>, where ... are argument types for the __init__ method. """ if info.is_interface: return self.chk.type_type() init_method = info.get_method('__init__') if not init_method: # Must be an invalid class definition. return Any() else: # Construct callable type based on signature of __init__. Adjust # return type and insert type arguments. init_type = method_type(init_method) if isinstance(init_type, Callable): return self.class_callable((Callable)init_type, info) else: # Overloaded __init__. Callable[] items = [] for it in ((Overloaded)init_type).items(): items.append(self.class_callable(it, info)) return Overloaded(items) Callable class_callable(self, Callable init_type, TypeInfo info): """Create a type object type based on the signature of __init__.""" variables = <TypeVarDef> [] for i in range(len(info.type_vars)): # TODO bounds variables.append(TypeVarDef(info.type_vars[i], i + 1, None))
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: