1.1 --- a/translator.py Fri Nov 18 17:25:24 2016 +0100
1.2 +++ b/translator.py Fri Nov 18 23:48:13 2016 +0100
1.3 @@ -234,6 +234,7 @@
1.4 # Exception raising adjustments.
1.5
1.6 self.in_try_finally = False
1.7 + self.in_try_except = False
1.8
1.9 # Attribute access counting.
1.10
1.11 @@ -1107,7 +1108,7 @@
1.12 "Process the given return node 'n'."
1.13
1.14 expr = self.process_structure_node(n.value) or PredefinedConstantRef("None")
1.15 - if self.in_try_finally:
1.16 + if self.in_try_finally or self.in_try_except:
1.17 self.writestmt("__Return(%s);" % expr)
1.18 else:
1.19 self.writestmt("return %s;" % expr)
1.20 @@ -1120,6 +1121,9 @@
1.21 Process the given "try...except" node 'n'.
1.22 """
1.23
1.24 + in_try_except = self.in_try_except
1.25 + self.in_try_except = True
1.26 +
1.27 # Use macros to implement exception handling.
1.28
1.29 self.writestmt("__Try")
1.30 @@ -1153,27 +1157,23 @@
1.31 self.indent -= 1
1.32 self.writeline("}")
1.33
1.34 + self.in_try_except = in_try_except
1.35 +
1.36 # Handlers are tests within a common handler block.
1.37
1.38 self.writeline("__Catch (__tmp_exc)")
1.39 self.writeline("{")
1.40 self.indent += 1
1.41
1.42 + # Introduce an if statement to handle the completion of a try block.
1.43 +
1.44 + self.process_try_completion()
1.45 +
1.46 # Handle exceptions in else blocks converted to __RaiseElse, converting
1.47 # them back to normal exceptions.
1.48
1.49 - else_str = ""
1.50 -
1.51 if n.else_:
1.52 - self.writeline("if (__tmp_exc.raising_else) __Raise(__tmp_exc.arg);")
1.53 - else_str = "else "
1.54 -
1.55 - # Handle the completion of try blocks or the execution of return
1.56 - # statements where finally blocks apply.
1.57 -
1.58 - if self.in_try_finally:
1.59 - self.writeline("%sif (__tmp_exc.completing) __Throw(__tmp_exc);" % else_str)
1.60 - else_str = "else "
1.61 + self.writeline("else if (__tmp_exc.raising_else) __Raise(__tmp_exc.arg);")
1.62
1.63 # Exception handling.
1.64
1.65 @@ -1183,10 +1183,9 @@
1.66
1.67 if name is not None:
1.68 name_ref = self.process_structure_node(name)
1.69 - self.writeline("%sif (__BOOL(__fn_native__isinstance((__attr[]) {__tmp_exc.arg, %s})))" % (else_str, name_ref))
1.70 + self.writeline("else if (__BOOL(__fn_native__isinstance((__attr[]) {__tmp_exc.arg, %s})))" % name_ref)
1.71 else:
1.72 - self.writeline("%sif (1)" % else_str)
1.73 - else_str = "else "
1.74 + self.writeline("else if (1)")
1.75
1.76 self.writeline("{")
1.77 self.indent += 1
1.78 @@ -1204,7 +1203,7 @@
1.79
1.80 # Re-raise unhandled exceptions.
1.81
1.82 - self.writeline("%s__Throw(__tmp_exc);" % else_str)
1.83 + self.writeline("else __Throw(__tmp_exc);")
1.84
1.85 # End the handler block.
1.86
1.87 @@ -1238,15 +1237,29 @@
1.88 self.indent += 1
1.89 self.process_structure_node(n.final)
1.90
1.91 - # Test for the completion of a try block.
1.92 + # Introduce an if statement to handle the completion of a try block.
1.93 +
1.94 + self.process_try_completion()
1.95 + self.writeline("else __Throw(__tmp_exc);")
1.96 +
1.97 + self.indent -= 1
1.98 + self.writeline("}")
1.99 +
1.100 + def process_try_completion(self):
1.101 +
1.102 + "Generate a test for the completion of a try block."
1.103
1.104 self.writestmt("if (__tmp_exc.completing)")
1.105 self.writeline("{")
1.106 self.indent += 1
1.107 - self.writeline("if (!__ISNULL(__tmp_exc.arg)) return __tmp_exc.arg;")
1.108 - self.indent -= 1
1.109 - self.writeline("}")
1.110 - self.writeline("else __Throw(__tmp_exc);")
1.111 +
1.112 + # Only use the normal return statement if no surrounding try blocks
1.113 + # apply.
1.114 +
1.115 + if not self.in_try_finally and not self.in_try_except:
1.116 + self.writeline("if (!__ISNULL(__tmp_exc.arg)) return __tmp_exc.arg;")
1.117 + else:
1.118 + self.writeline("if (!__ISNULL(__tmp_exc.arg)) __Throw(__tmp_exc);")
1.119
1.120 self.indent -= 1
1.121 self.writeline("}")