1.1 --- a/inspector.py Fri Jan 20 00:08:26 2017 +0100
1.2 +++ b/inspector.py Fri Jan 20 00:09:45 2017 +0100
1.3 @@ -4,7 +4,7 @@
1.4 Inspect and obtain module structure.
1.5
1.6 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013,
1.7 - 2014, 2015, 2016 Paul Boddie <paul@boddie.org.uk>
1.8 + 2014, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -920,6 +920,8 @@
1.13 Process the given "try...except" node 'n'.
1.14 """
1.15
1.16 + self.record_exception_handler()
1.17 +
1.18 tracker = self.trackers[-1]
1.19 tracker.new_branchpoint()
1.20
1.21 @@ -967,6 +969,8 @@
1.22 Process the given "try...finally" node 'n'.
1.23 """
1.24
1.25 + self.record_exception_handler()
1.26 +
1.27 tracker = self.trackers[-1]
1.28 self.process_structure_node(n.body)
1.29
1.30 @@ -1492,4 +1496,12 @@
1.31 self.function_targets[path][0] -= 1
1.32 self.function_arguments[path][0] -= len(args) + 1
1.33
1.34 + # Exceptions.
1.35 +
1.36 + def record_exception_handler(self):
1.37 +
1.38 + "Record the current namespace as employing an exception handler."
1.39 +
1.40 + self.exception_namespaces.add(self.get_namespace_path())
1.41 +
1.42 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/modules.py Fri Jan 20 00:08:26 2017 +0100
2.2 +++ b/modules.py Fri Jan 20 00:09:45 2017 +0100
2.3 @@ -4,7 +4,7 @@
2.4 Module abstractions.
2.5
2.6 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2.7 - 2014, 2015, 2016 Paul Boddie <paul@boddie.org.uk>
2.8 + 2014, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -71,6 +71,10 @@
2.13 self.function_targets = {}
2.14 self.function_arguments = {}
2.15
2.16 + # Exception handler details.
2.17 +
2.18 + self.exception_namespaces = set()
2.19 +
2.20 # Attribute usage at module and function levels.
2.21
2.22 self.attr_usage = {}
2.23 @@ -401,6 +405,7 @@
2.24 self._get_attr_access_modifiers(f)
2.25 self._get_constant_literals(f)
2.26 self._get_constant_values(f)
2.27 + self._get_exception_namespaces(f)
2.28
2.29 finally:
2.30 f.close()
2.31 @@ -633,6 +638,12 @@
2.32 self.constant_values[name] = value, value_type, encoding
2.33 line = f.readline().rstrip()
2.34
2.35 + def _get_exception_namespaces(self, f):
2.36 + f.readline() # "exception namespaces:"
2.37 + values = f.readline.rstrip().split(", ")
2.38 + self.exception_namespaces = set(values)
2.39 + f.readline()
2.40 +
2.41 # Generic parsing methods.
2.42
2.43 def from_lines(self, f, d):
2.44 @@ -759,10 +770,15 @@
2.45 (empty line)
2.46 "attribute access modifiers:"
2.47 zero or more: qualified function name " " local/global variable name " " attribute name " " access modifiers
2.48 + (empty line)
2.49 "constant literals:"
2.50 zero or more: qualified scope name " " value type " " constant literal
2.51 + (empty line)
2.52 "constant values:"
2.53 zero or more: qualified name " " value type " " constant literal
2.54 + (empty line)
2.55 + "exception namespaces:"
2.56 + qualified names
2.57
2.58 All collections of names are separated by ", " characters.
2.59
2.60 @@ -995,6 +1011,12 @@
2.61 value, value_type, encoding = self.constant_values[name]
2.62 print >>f, name, value_type, encoding or "{}", repr(value)
2.63
2.64 + print >>f
2.65 + print >>f, "exception namespaces:"
2.66 + paths = list(self.exception_namespaces)
2.67 + paths.sort()
2.68 + print >>f, ", ".join(paths)
2.69 +
2.70 finally:
2.71 f.close()
2.72
3.1 --- a/translator.py Fri Jan 20 00:08:26 2017 +0100
3.2 +++ b/translator.py Fri Jan 20 00:09:45 2017 +0100
3.3 @@ -1722,7 +1722,10 @@
3.4
3.5 self.writeline("__ref __tmp_context, __tmp_value, __tmp_target_value;")
3.6 self.writeline("__attr %s__tmp_result;" % targets)
3.7 - self.writeline("__exc __tmp_exc;")
3.8 +
3.9 + module = self.importer.get_module(self.name)
3.10 + if self.get_namespace_path() in module.exception_namespaces:
3.11 + self.writeline("__exc __tmp_exc;")
3.12
3.13 def write_parameters(self, name):
3.14