1.1 --- a/deducer.py Thu Sep 29 15:21:55 2016 +0200
1.2 +++ b/deducer.py Thu Sep 29 15:37:09 2016 +0200
1.3 @@ -111,9 +111,6 @@
1.4 # Accumulated information about accessed attributes and
1.5 # access/attribute-specific accessor tests.
1.6
1.7 - self.reference_class_attrs = {}
1.8 - self.reference_instance_attrs = {}
1.9 - self.reference_module_attrs = {}
1.10 self.reference_all_attrs = {}
1.11 self.reference_all_attrtypes = {}
1.12 self.reference_all_accessor_types = {}
1.13 @@ -421,18 +418,18 @@
1.14
1.15 # Collect specific and general type information.
1.16
1.17 - self.provider_all_types[location] = all_types = \
1.18 + self.provider_all_types[location] = \
1.19 combine_types(class_types, instance_types, module_types)
1.20
1.21 # Accessor information.
1.22
1.23 class_types = self.accessor_class_types[location]
1.24 self.accessor_general_class_types[location] = \
1.25 - general_class_types = self.get_most_general_types(class_types)
1.26 + general_class_types = self.get_most_general_class_types(class_types)
1.27
1.28 instance_types = self.accessor_instance_types[location]
1.29 self.accessor_general_instance_types[location] = \
1.30 - general_instance_types = self.get_most_general_types(instance_types)
1.31 + general_instance_types = self.get_most_general_class_types(instance_types)
1.32
1.33 module_types = self.accessor_module_types[location]
1.34 self.accessor_general_module_types[location] = \
1.35 @@ -478,7 +475,7 @@
1.36 for location in locations:
1.37 constrained = location in self.access_constrained
1.38
1.39 - # Determine whether the attribute access is guarded or not.
1.40 + # Combine type information from all accessors supplying the access.
1.41
1.42 accessor_locations = self.get_accessors_for_access(location)
1.43
1.44 @@ -498,7 +495,7 @@
1.45 all_accessor_types.update(self.accessor_all_types.get(accessor_location))
1.46 all_accessor_general_types.update(self.accessor_all_general_types.get(accessor_location))
1.47
1.48 - # Determine the basis on which the access has been guarded.
1.49 + # Determine whether the attribute access is guarded or not.
1.50
1.51 guarded = (
1.52 len(all_accessor_types) == 1 or
1.53 @@ -528,23 +525,16 @@
1.54 all_accessed_attrs = set()
1.55 all_accessed_attrtypes = set()
1.56 all_providers = set()
1.57 - all_general_providers = set()
1.58 -
1.59 - for attrtype, d, general in [
1.60 - ("<class>", self.reference_class_attrs, self.get_most_general_types),
1.61 - ("<instance>", self.reference_instance_attrs, self.get_most_general_types),
1.62 - ("<module>", self.reference_module_attrs, self.get_most_general_module_types)]:
1.63 -
1.64 - attrs = [attr for _attrtype, object_type, attr in referenced_attrs if _attrtype == attrtype]
1.65 - providers = [object_type for _attrtype, object_type, attr in referenced_attrs if _attrtype == attrtype]
1.66 - general_providers = general(providers)
1.67 - d[location] = set(attrs)
1.68 -
1.69 - if attrs:
1.70 - all_accessed_attrs.update(attrs)
1.71 - all_accessed_attrtypes.add(attrtype)
1.72 - all_providers.update(providers)
1.73 - all_general_providers.update(general_providers)
1.74 +
1.75 + # Obtain provider and attribute details for this kind of
1.76 + # object.
1.77 +
1.78 + for attrtype, object_type, attr in referenced_attrs:
1.79 + all_accessed_attrs.add(attr)
1.80 + all_accessed_attrtypes.add(attrtype)
1.81 + all_providers.add(object_type)
1.82 +
1.83 + all_general_providers = self.get_most_general_types(all_providers)
1.84
1.85 # Determine which attributes would be provided by the
1.86 # accessor types upheld by a guard.
1.87 @@ -624,14 +614,12 @@
1.88 'attrname' as a list of (attribute type, attribute set) tuples.
1.89 """
1.90
1.91 - ca = self.reference_class_attrs[location]
1.92 - ia = self.reference_instance_attrs[location]
1.93 - ma = self.reference_module_attrs[location]
1.94 -
1.95 - l = []
1.96 - for attrtype, attrs in (("<class>", ca), ("<instance>", ia), ("<module>", ma)):
1.97 - if attrs:
1.98 - l.append((attrtype, attrs))
1.99 + d = {}
1.100 + for attrtype, objtype, attr in self.referenced_attrs[location]:
1.101 + init_item(d, attrtype, set)
1.102 + d[attrtype].add(attr)
1.103 + l = d.items()
1.104 + l.sort() # class, module, instance
1.105 return l
1.106
1.107 # Initialisation methods.
1.108 @@ -913,7 +901,25 @@
1.109
1.110 # Simplification of types.
1.111
1.112 - def get_most_general_types(self, class_types):
1.113 + def get_most_general_types(self, types):
1.114 +
1.115 + "Return the most general types for the given 'types'."
1.116 +
1.117 + module_types = set()
1.118 + class_types = set()
1.119 +
1.120 + for type in types:
1.121 + ref = self.importer.identify(type)
1.122 + if ref.has_kind("<module>"):
1.123 + module_types.add(type)
1.124 + else:
1.125 + class_types.add(type)
1.126 +
1.127 + types = set(self.get_most_general_module_types(module_types))
1.128 + types.update(self.get_most_general_class_types(class_types))
1.129 + return types
1.130 +
1.131 + def get_most_general_class_types(self, class_types):
1.132
1.133 "Return the most general types for the given 'class_types'."
1.134