1.1 --- a/translator.py Tue Mar 07 17:19:16 2017 +0100
1.2 +++ b/translator.py Tue Mar 07 19:03:33 2017 +0100
1.3 @@ -804,6 +804,10 @@
1.4 self.in_conditional = False
1.5 self.function_target = 0
1.6
1.7 + # Volatile locals for exception handling.
1.8 +
1.9 + self.volatile_locals = set()
1.10 +
1.11 # Process any guards defined for the parameters.
1.12
1.13 for name in self.importer.function_parameters.get(function_name):
1.14 @@ -1386,12 +1390,23 @@
1.15
1.16 location = self.get_access_location(n.name)
1.17
1.18 + # Mark any local assignments as volatile in exception blocks.
1.19 +
1.20 + if expr and self.in_function and not is_global and self.in_try_except:
1.21 + self.make_volatile(n.name)
1.22 +
1.23 # Qualified names are used for resolved static references or for
1.24 # static namespace members. The reference should be configured to return
1.25 # such names.
1.26
1.27 return TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global, parameter=parameter, location=location)
1.28
1.29 + def make_volatile(self, name):
1.30 +
1.31 + "Record 'name' as volatile in the current namespace."
1.32 +
1.33 + self.volatile_locals.add(name)
1.34 +
1.35 def process_not_node(self, n):
1.36
1.37 "Process the given operator node 'n'."
1.38 @@ -1712,14 +1727,17 @@
1.39
1.40 self.out = StringIO()
1.41
1.42 - def end_unit(self, name):
1.43 -
1.44 - "Add declarations and generated code."
1.45 -
1.46 - # Restore the output stream.
1.47 + def end_unit(self):
1.48 +
1.49 + "Restore the output stream."
1.50
1.51 out = self.out
1.52 self.out = self.out_toplevel
1.53 + return out
1.54 +
1.55 + def flush_unit(self, name, out):
1.56 +
1.57 + "Add declarations and generated code."
1.58
1.59 self.write_temporaries(name)
1.60 print >>self.out
1.61 @@ -1755,7 +1773,8 @@
1.62
1.63 "End each module by closing its main function."
1.64
1.65 - self.end_unit(self.name)
1.66 + out = self.end_unit()
1.67 + self.flush_unit(self.name, out)
1.68
1.69 def start_function(self, name):
1.70
1.71 @@ -1765,11 +1784,20 @@
1.72 print >>self.out, "{"
1.73 self.indent += 1
1.74
1.75 + self.start_unit()
1.76 +
1.77 + def end_function(self, name):
1.78 +
1.79 + "End the function having the given 'name'."
1.80 +
1.81 + out = self.end_unit()
1.82 +
1.83 # Obtain local names from parameters.
1.84
1.85 parameters = self.importer.function_parameters[name]
1.86 locals = self.importer.function_locals[name].keys()
1.87 names = []
1.88 + volatile_names = []
1.89
1.90 for n in locals:
1.91
1.92 @@ -1779,7 +1807,10 @@
1.93
1.94 if n.startswith("$l") or n in parameters or n == "self":
1.95 continue
1.96 - names.append(encode_path(n))
1.97 + if n in self.volatile_locals:
1.98 + volatile_names.append(encode_path(n))
1.99 + else:
1.100 + names.append(encode_path(n))
1.101
1.102 # Emit required local names.
1.103
1.104 @@ -1787,14 +1818,13 @@
1.105 names.sort()
1.106 self.writeline("__attr %s;" % ", ".join(names))
1.107
1.108 + if volatile_names:
1.109 + volatile_names.sort()
1.110 + self.writeline("volatile __attr %s;" % ", ".join(volatile_names))
1.111 +
1.112 self.write_parameters(name)
1.113 - self.start_unit()
1.114 -
1.115 - def end_function(self, name):
1.116 -
1.117 - "End the function having the given 'name'."
1.118 -
1.119 - self.end_unit(name)
1.120 +
1.121 + self.flush_unit(name, out)
1.122 print >>self.out
1.123
1.124 def write_temporaries(self, name):