Lichen

Change of deducer.py

721:823020deac33
deducer.py
     1.1 --- a/deducer.py	Mon Mar 13 01:46:58 2017 +0100
     1.2 +++ b/deducer.py	Mon Mar 13 01:49:11 2017 +0100
     1.3 @@ -1623,11 +1623,19 @@
     1.4              provider_instance_types = self.provider_instance_types[accessor_location]
     1.5              provider_module_types = self.provider_module_types[accessor_location]
     1.6  
     1.7 +            accessor_class_types = self.accessor_class_types[accessor_location]
     1.8 +            accessor_instance_types = self.accessor_instance_types[accessor_location]
     1.9 +            accessor_module_types = self.accessor_module_types[accessor_location]
    1.10 +
    1.11              # Find details for any corresponding access.
    1.12  
    1.13 -            all_class_types = set()
    1.14 -            all_instance_types = set()
    1.15 -            all_module_types = set()
    1.16 +            new_provider_class_types = set()
    1.17 +            new_provider_instance_types = set()
    1.18 +            new_provider_module_types = set()
    1.19 +
    1.20 +            new_accessor_class_types = set()
    1.21 +            new_accessor_instance_types = set()
    1.22 +            new_accessor_module_types = set()
    1.23  
    1.24              for access_location in self.alias_index[accessor_location]:
    1.25                  location, name, attrnames, access_number = access_location
    1.26 @@ -1650,10 +1658,20 @@
    1.27                      # Obtain references and attribute types for the access.
    1.28  
    1.29                      attrs = self.get_references_for_access(access_location)
    1.30 -                    attrs = self.convert_invocation_providers(attrs, invocation)
    1.31 +
    1.32 +                    # Where no specific attributes are defined, do not attempt
    1.33 +                    # to refine the alias's types.
    1.34 +
    1.35 +                    if not attrs:
    1.36 +                        return
    1.37 +
    1.38 +                    # Invocations converting class accessors to instances do not
    1.39 +                    # change the nature of class providers.
    1.40 +
    1.41 +                    provider_attrs = self.convert_invocation_providers(attrs, invocation)
    1.42  
    1.43                      (class_types, instance_types, module_types, function_types,
    1.44 -                        var_types) = separate_types(attrs)
    1.45 +                        var_types) = separate_types(provider_attrs)
    1.46  
    1.47                      # Where non-accessor types are found, do not attempt to refine
    1.48                      # the defined accessor types.
    1.49 @@ -1661,13 +1679,30 @@
    1.50                      if function_types or var_types:
    1.51                          return
    1.52  
    1.53 -                    # Invocations converting class accessors to instances do not
    1.54 -                    # change the nature of class providers.
    1.55 -
    1.56                      class_types = set(provider_class_types).intersection(class_types)
    1.57                      instance_types = set(provider_instance_types).intersection(instance_types)
    1.58                      module_types = set(provider_module_types).intersection(module_types)
    1.59  
    1.60 +                    new_provider_class_types.update(class_types)
    1.61 +                    new_provider_instance_types.update(instance_types)
    1.62 +                    new_provider_module_types.update(module_types)
    1.63 +
    1.64 +                    # Accessors are updated separately, employing invocation
    1.65 +                    # result details.
    1.66 +
    1.67 +                    accessor_attrs = self.convert_invocations(attrs, invocation)
    1.68 +
    1.69 +                    (class_types, instance_types, module_types, function_types,
    1.70 +                        var_types) = separate_types(accessor_attrs)
    1.71 +
    1.72 +                    class_types = set(accessor_class_types).intersection(class_types)
    1.73 +                    instance_types = set(accessor_instance_types).intersection(instance_types)
    1.74 +                    module_types = set(accessor_module_types).intersection(module_types)
    1.75 +
    1.76 +                    new_accessor_class_types.update(class_types)
    1.77 +                    new_accessor_instance_types.update(instance_types)
    1.78 +                    new_accessor_module_types.update(module_types)
    1.79 +
    1.80                  # Alias references a name, not an access.
    1.81  
    1.82                  else:
    1.83 @@ -1675,10 +1710,32 @@
    1.84  
    1.85                      attr = self.get_initialised_name(access_location)
    1.86                      if attr:
    1.87 -                        attrs = self.convert_invocation_providers([attr], invocation)
    1.88 +                        attrs = [attr]
    1.89 +                        provider_attrs = self.convert_invocation_providers(attrs, invocation)
    1.90  
    1.91                          (class_types, instance_types, module_types, function_types,
    1.92 -                            var_types) = separate_types(attrs)
    1.93 +                            var_types) = separate_types(provider_attrs)
    1.94 +
    1.95 +                        class_types = set(provider_class_types).intersection(class_types)
    1.96 +                        instance_types = set(provider_instance_types).intersection(instance_types)
    1.97 +                        module_types = set(provider_module_types).intersection(module_types)
    1.98 +
    1.99 +                        new_provider_class_types.update(class_types)
   1.100 +                        new_provider_instance_types.update(instance_types)
   1.101 +                        new_provider_module_types.update(module_types)
   1.102 +
   1.103 +                        accessor_attrs = self.convert_invocations(attrs, invocation)
   1.104 +
   1.105 +                        (class_types, instance_types, module_types, function_types,
   1.106 +                            var_types) = separate_types(accessor_attrs)
   1.107 +
   1.108 +                        class_types = set(accessor_class_types).intersection(class_types)
   1.109 +                        instance_types = set(accessor_instance_types).intersection(instance_types)
   1.110 +                        module_types = set(accessor_module_types).intersection(module_types)
   1.111 +
   1.112 +                        new_accessor_class_types.update(class_types)
   1.113 +                        new_accessor_instance_types.update(instance_types)
   1.114 +                        new_accessor_module_types.update(module_types)
   1.115  
   1.116                      # Where no further information is found, do not attempt to
   1.117                      # refine the defined accessor types.
   1.118 @@ -1686,14 +1743,11 @@
   1.119                      else:
   1.120                          return
   1.121  
   1.122 -                all_class_types.update(class_types)
   1.123 -                all_instance_types.update(instance_types)
   1.124 -                all_module_types.update(module_types)
   1.125 -
   1.126              # Record refined type details for the alias as an accessor.
   1.127  
   1.128              self.init_definition_details(accessor_location)
   1.129 -            self.record_reference_types(accessor_location, all_class_types, all_instance_types, all_module_types, False)
   1.130 +            self.update_provider_types(accessor_location, new_provider_class_types, new_provider_instance_types, new_provider_module_types)
   1.131 +            self.update_accessor_types(accessor_location, new_accessor_class_types, new_accessor_instance_types, new_accessor_module_types)
   1.132  
   1.133          # Without an access, attempt to identify references for the alias.
   1.134          # Invocations convert classes to instances and also attempt to find
   1.135 @@ -1724,9 +1778,7 @@
   1.136  
   1.137                  # Alias references an attribute access.
   1.138  
   1.139 -                attrname = attrnames and attrnames[0]
   1.140 -
   1.141 -                if attrname:
   1.142 +                if attrnames:
   1.143  
   1.144                      # Obtain references and attribute types for the access.
   1.145  
   1.146 @@ -1751,7 +1803,8 @@
   1.147                          instance_types = self.provider_instance_types[access_location]
   1.148                          module_types = self.provider_module_types[access_location]
   1.149  
   1.150 -                        refs.update(combine_types(class_types, instance_types, module_types))
   1.151 +                        types = combine_types(class_types, instance_types, module_types)
   1.152 +                        refs.update(self.convert_invocation_providers(types, invocation))
   1.153  
   1.154              # Record reference details for the alias separately from accessors.
   1.155  
   1.156 @@ -1858,15 +1911,13 @@
   1.157  
   1.158          # Update the type details for the location.
   1.159  
   1.160 -        self.provider_class_types[location].update(class_types)
   1.161 -        self.provider_instance_types[location].update(instance_types)
   1.162 -        self.provider_module_types[location].update(module_types)
   1.163 +        self.update_provider_types(location, class_types, instance_types, module_types)
   1.164  
   1.165          # Class types support classes and instances as accessors.
   1.166          # Instance-only and module types support only their own kinds as
   1.167          # accessors.
   1.168  
   1.169 -        path, name, version, attrnames = location
   1.170 +        path, name, attrnames, version = location
   1.171  
   1.172          if invocations:
   1.173              class_only_types = self.filter_for_invocations(class_types, invocations)
   1.174 @@ -1890,6 +1941,28 @@
   1.175          if constrained:
   1.176              self.accessor_constrained.add(location)
   1.177  
   1.178 +    def update_provider_types(self, location, class_types, instance_types, module_types):
   1.179 +
   1.180 +        """
   1.181 +        Update provider types for the given 'location', adding 'class_types',
   1.182 +        'instance_types' and 'module_types' to those already stored.
   1.183 +        """
   1.184 +
   1.185 +        self.provider_class_types[location].update(class_types)
   1.186 +        self.provider_instance_types[location].update(instance_types)
   1.187 +        self.provider_module_types[location].update(module_types)
   1.188 +
   1.189 +    def update_accessor_types(self, location, class_types, instance_types, module_types):
   1.190 +
   1.191 +        """
   1.192 +        Update accessor types for the given 'location', adding 'class_types',
   1.193 +        'instance_types' and 'module_types' to those already stored.
   1.194 +        """
   1.195 +
   1.196 +        self.accessor_class_types[location].update(class_types)
   1.197 +        self.accessor_instance_types[location].update(instance_types)
   1.198 +        self.accessor_module_types[location].update(module_types)
   1.199 +
   1.200      def filter_for_invocations(self, class_types, attrnames):
   1.201  
   1.202          """