# HG changeset patch # User Paul Boddie # Date 1488911313 -3600 # Node ID 70b8e82cdcb8b5c2f5e291e083be9f55b8430127 # Parent d3e1284d1590182a302d6b3c5b57b4ebb1a45740# Parent ff6b931a4b0eca281cb9c3d7e8921e11c7ac0184 Merged changes from the default branch. diff -r d3e1284d1590 -r 70b8e82cdcb8 translator.py --- a/translator.py Tue Mar 07 18:10:00 2017 +0100 +++ b/translator.py Tue Mar 07 19:28:33 2017 +0100 @@ -804,6 +804,10 @@ self.in_conditional = False self.function_target = 0 + # Volatile locals for exception handling. + + self.volatile_locals = set() + # Process any guards defined for the parameters. for name in self.importer.function_parameters.get(function_name): @@ -1388,12 +1392,23 @@ location = self.get_access_location(n.name) + # Mark any local assignments as volatile in exception blocks. + + if expr and self.in_function and not is_global and self.in_try_except: + self.make_volatile(n.name) + # Qualified names are used for resolved static references or for # static namespace members. The reference should be configured to return # such names. return TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global, location=location) + def make_volatile(self, name): + + "Record 'name' as volatile in the current namespace." + + self.volatile_locals.add(name) + def process_not_node(self, n): "Process the given operator node 'n'." @@ -1714,23 +1729,23 @@ self.out = StringIO() - def end_unit(self, name): - - "Add declarations and generated code." - - # Restore the output stream. + def end_unit(self): + + "Restore the output stream." out = self.out self.out = self.out_toplevel + return out + + def flush_unit(self, name, out): + + "Add declarations and generated code." self.write_temporaries(name) print >>self.out out.seek(0) self.out.write(out.read()) - self.indent -= 1 - print >>self.out, "}" - def start_module(self): "Write the start of each module's main function." @@ -1757,22 +1772,38 @@ "End each module by closing its main function." - self.end_unit(self.name) + out = self.end_unit() + self.flush_unit(self.name, out) + + self.indent -= 1 + print >>self.out, "}" def start_function(self, name): "Start the function having the given 'name'." + self.indent += 1 + + self.start_unit() + + def end_function(self, name): + + "End the function having the given 'name'." + + out = self.end_unit() + + # Write the signature at the top indentation level. + + self.indent -= 1 self.write_parameters(name) - print >>self.out, "{" - self.indent += 1 # Obtain local names from parameters. parameters = self.importer.function_parameters[name] locals = self.importer.function_locals[name].keys() names = [] + volatile_names = [] for n in locals: @@ -1782,21 +1813,27 @@ if n.startswith("$l") or n in parameters or n == "self": continue - names.append(encode_path(n)) - - # Emit required local names. + if n in self.volatile_locals: + volatile_names.append(encode_path(n)) + else: + names.append(encode_path(n)) + + # Emit required local names at the function indentation level. + + self.indent += 1 if names: names.sort() self.writeline("__attr %s;" % ", ".join(names)) - self.start_unit() - - def end_function(self, name): - - "End the function having the given 'name'." - - self.end_unit(name) + if volatile_names: + volatile_names.sort() + self.writeline("volatile __attr %s;" % ", ".join(volatile_names)) + + self.flush_unit(name, out) + + self.indent -= 1 + print >>self.out, "}" print >>self.out def write_parameters(self, name): @@ -1818,7 +1855,9 @@ # Generate aliases for the parameters. for parameter in self.importer.function_parameters[name]: - l.append("__attr %s" % encode_path(parameter)) + l.append("%s__attr %s" % ( + parameter in self.volatile_locals and "volatile " or "", + encode_path(parameter))) self.writeline("__attr %s(%s)" % ( encode_function_pointer(name), ", ".join(l)))