1.1 --- a/deducer.py Mon Mar 13 17:59:13 2017 +0100
1.2 +++ b/deducer.py Tue Mar 14 16:40:04 2017 +0100
1.3 @@ -1864,9 +1864,7 @@
1.4 if ref.has_kind("<class>"):
1.5 return ref
1.6 elif ref.has_kind("<function>"):
1.7 - refs = self.importer.all_return_values.get(ref.get_origin())
1.8 - if refs and len(refs) == 1:
1.9 - return first(refs)
1.10 + return self.convert_function_invocation(ref)
1.11
1.12 return Reference("<var>")
1.13
1.14 @@ -1887,9 +1885,19 @@
1.15 if ref.has_kind("<class>"):
1.16 return ref.instance_of()
1.17 elif ref.has_kind("<function>"):
1.18 - refs = self.importer.all_return_values.get(ref.get_origin())
1.19 - if refs and len(refs) == 1:
1.20 - return first(refs)
1.21 + return self.convert_function_invocation(ref)
1.22 +
1.23 + return Reference("<var>")
1.24 +
1.25 + def convert_function_invocation(self, ref):
1.26 +
1.27 + "Convert the function 'ref' to its return value reference."
1.28 +
1.29 + initialised_names = self.importer.all_initialised_names.get((ref.get_origin(), "$return"))
1.30 + if initialised_names:
1.31 + refs = set(initialised_names.values())
1.32 + if len(refs) == 1:
1.33 + return first(refs)
1.34
1.35 return Reference("<var>")
1.36
2.1 --- a/importer.py Mon Mar 13 17:59:13 2017 +0100
2.2 +++ b/importer.py Tue Mar 14 16:40:04 2017 +0100
2.3 @@ -116,10 +116,6 @@
2.4 self.all_constants = {}
2.5 self.all_constant_values = {}
2.6
2.7 - # Return values.
2.8 -
2.9 - self.all_return_values = {}
2.10 -
2.11 self.make_cache()
2.12
2.13 def give_warning(self, name):
3.1 --- a/inspector.py Mon Mar 13 17:59:13 2017 +0100
3.2 +++ b/inspector.py Tue Mar 14 16:40:04 2017 +0100
3.3 @@ -1487,7 +1487,7 @@
3.4 "Record the given return 'expr'."
3.5
3.6 path = self.get_namespace_path()
3.7 - init_item(self.return_values, path, set)
3.8 - self.return_values[path].add(expr)
3.9 + init_item(self.return_values, path, list)
3.10 + self.return_values[path].append(expr)
3.11
3.12 # vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/modules.py Mon Mar 13 17:59:13 2017 +0100
4.2 +++ b/modules.py Tue Mar 14 16:40:04 2017 +0100
4.3 @@ -115,7 +115,6 @@
4.4 self.propagate_name_references()
4.5 self.propagate_attr_accesses()
4.6 self.propagate_constants()
4.7 - self.propagate_return_values()
4.8
4.9 def unpropagate(self):
4.10
4.11 @@ -152,7 +151,6 @@
4.12 remove_items(self.importer.all_attr_access_modifiers, self.attr_access_modifiers)
4.13 remove_items(self.importer.all_constants, self.constants)
4.14 remove_items(self.importer.all_constant_values, self.constant_values)
4.15 - remove_items(self.importer.all_return_values, self.return_values)
4.16
4.17 # Remove this module's objects from the importer. Objects are
4.18 # automatically propagated when defined.
4.19 @@ -222,12 +220,6 @@
4.20 self.importer.all_instance_attrs[name] = self.instance_attrs.get(name) or {}
4.21 self.importer.all_instance_attr_constants[name] = self.instance_attr_constants.get(name) or {}
4.22
4.23 - def propagate_return_values(self):
4.24 -
4.25 - "Propagate return values for the module."
4.26 -
4.27 - self.importer.all_return_values.update(self.return_values)
4.28 -
4.29 def set_object(self, name, value=None):
4.30
4.31 "Set an object with the given 'name' and the given 'value'."
4.32 @@ -410,7 +402,6 @@
4.33 self._get_constant_literals(f)
4.34 self._get_constant_values(f)
4.35 self._get_exception_namespaces(f)
4.36 - self._get_return_values(f)
4.37
4.38 finally:
4.39 f.close()
4.40 @@ -631,15 +622,6 @@
4.41 self.exception_namespaces = value and set(value.split(", ")) or set()
4.42 f.readline()
4.43
4.44 - def _get_return_values(self, f):
4.45 - f.readline() # "return values:"
4.46 - line = f.readline().rstrip()
4.47 - while line:
4.48 - path, values = self._get_fields(line)
4.49 - values = values.split(", ")
4.50 - self.return_values[path] = map(decode_reference, values)
4.51 - line = f.readline().rstrip()
4.52 -
4.53 # Generic parsing methods.
4.54
4.55 def from_lines(self, f, d):
4.56 @@ -897,13 +879,6 @@
4.57 paths.sort()
4.58 print >>f, ", ".join(paths)
4.59
4.60 - print >>f
4.61 - print >>f, "return values:"
4.62 - paths = self.return_values.keys()
4.63 - paths.sort()
4.64 - for path in paths:
4.65 - print >>f, path, ", ".join(map(str, self.return_values[path]))
4.66 -
4.67 finally:
4.68 f.close()
4.69
5.1 --- a/resolving.py Mon Mar 13 17:59:13 2017 +0100
5.2 +++ b/resolving.py Tue Mar 14 16:40:04 2017 +0100
5.3 @@ -259,26 +259,26 @@
5.4
5.5 "Resolve return values using name references."
5.6
5.7 - return_values = {}
5.8 -
5.9 # Get the return values from each namespace.
5.10
5.11 for path, values in self.return_values.items():
5.12 - l = set()
5.13 +
5.14 + # Resolve each return value provided by the scope.
5.15
5.16 - for value in values:
5.17 - if not value:
5.18 - ref = None
5.19 - else:
5.20 - ref, aliased_name = self.resolve_reference(path, value)
5.21 + initialised_names = {}
5.22 + aliased_names = {}
5.23
5.24 - l.add(ref or Reference("<var>"))
5.25 -
5.26 - return_values[path] = l
5.27 + for i, name_ref in enumerate(values):
5.28 + initialised_ref, aliased_name = self.resolve_reference(path, name_ref)
5.29 + if initialised_ref:
5.30 + initialised_names[i] = initialised_ref
5.31 + if aliased_name:
5.32 + aliased_names[i] = aliased_name
5.33
5.34 - # Replace the original values.
5.35 -
5.36 - self.return_values = return_values
5.37 + if initialised_names:
5.38 + self.initialised_names[(path, "$return")] = initialised_names
5.39 + if aliased_names:
5.40 + self.aliased_names[(path, "$return")] = aliased_names
5.41
5.42 def resolve_reference(self, path, name_ref):
5.43