# HG changeset patch # User Paul Boddie # Date 1488909813 -3600 # Node ID 92216ba519acc0e1f94e72937d8f3ae81f7405bb # Parent 374ccaa7be71efc510fca4dd22a48edb1c0d1719 Made locals volatile when set within try...except blocks. Reorganised unit output so that names can be declared volatile once a function body has been generated. diff -r 374ccaa7be71 -r 92216ba519ac translator.py --- a/translator.py Tue Mar 07 17:19:16 2017 +0100 +++ b/translator.py Tue Mar 07 19:03: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): @@ -1386,12 +1390,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, parameter=parameter, 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'." @@ -1712,14 +1727,17 @@ 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 @@ -1755,7 +1773,8 @@ "End each module by closing its main function." - self.end_unit(self.name) + out = self.end_unit() + self.flush_unit(self.name, out) def start_function(self, name): @@ -1765,11 +1784,20 @@ print >>self.out, "{" self.indent += 1 + self.start_unit() + + def end_function(self, name): + + "End the function having the given 'name'." + + out = self.end_unit() + # 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: @@ -1779,7 +1807,10 @@ if n.startswith("$l") or n in parameters or n == "self": continue - names.append(encode_path(n)) + if n in self.volatile_locals: + volatile_names.append(encode_path(n)) + else: + names.append(encode_path(n)) # Emit required local names. @@ -1787,14 +1818,13 @@ names.sort() self.writeline("__attr %s;" % ", ".join(names)) + if volatile_names: + volatile_names.sort() + self.writeline("volatile __attr %s;" % ", ".join(volatile_names)) + self.write_parameters(name) - self.start_unit() - - def end_function(self, name): - - "End the function having the given 'name'." - - self.end_unit(name) + + self.flush_unit(name, out) print >>self.out def write_temporaries(self, name):