1.1 --- a/templates/cexcept.h Fri Nov 18 17:25:24 2016 +0100
1.2 +++ b/templates/cexcept.h Fri Nov 18 23:48:13 2016 +0100
1.3 @@ -9,8 +9,8 @@
1.4 An interface for exception-handling in ANSI C (C89 and subsequent ISO
1.5 standards), developed jointly with Cosmin Truta.
1.6
1.7 + Copyright (c) 2016 Paul Boddie (modified for Lichen).
1.8 Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta.
1.9 - Copyright (c) 2016 Paul Boddie (modified for Lichen).
1.10 This software may be modified only if its author and version
1.11 information is updated accurately, and may be redistributed
1.12 only if accompanied by this unaltered notice. Subject to those
2.1 --- a/translator.py Fri Nov 18 17:25:24 2016 +0100
2.2 +++ b/translator.py Fri Nov 18 23:48:13 2016 +0100
2.3 @@ -234,6 +234,7 @@
2.4 # Exception raising adjustments.
2.5
2.6 self.in_try_finally = False
2.7 + self.in_try_except = False
2.8
2.9 # Attribute access counting.
2.10
2.11 @@ -1107,7 +1108,7 @@
2.12 "Process the given return node 'n'."
2.13
2.14 expr = self.process_structure_node(n.value) or PredefinedConstantRef("None")
2.15 - if self.in_try_finally:
2.16 + if self.in_try_finally or self.in_try_except:
2.17 self.writestmt("__Return(%s);" % expr)
2.18 else:
2.19 self.writestmt("return %s;" % expr)
2.20 @@ -1120,6 +1121,9 @@
2.21 Process the given "try...except" node 'n'.
2.22 """
2.23
2.24 + in_try_except = self.in_try_except
2.25 + self.in_try_except = True
2.26 +
2.27 # Use macros to implement exception handling.
2.28
2.29 self.writestmt("__Try")
2.30 @@ -1153,27 +1157,23 @@
2.31 self.indent -= 1
2.32 self.writeline("}")
2.33
2.34 + self.in_try_except = in_try_except
2.35 +
2.36 # Handlers are tests within a common handler block.
2.37
2.38 self.writeline("__Catch (__tmp_exc)")
2.39 self.writeline("{")
2.40 self.indent += 1
2.41
2.42 + # Introduce an if statement to handle the completion of a try block.
2.43 +
2.44 + self.process_try_completion()
2.45 +
2.46 # Handle exceptions in else blocks converted to __RaiseElse, converting
2.47 # them back to normal exceptions.
2.48
2.49 - else_str = ""
2.50 -
2.51 if n.else_:
2.52 - self.writeline("if (__tmp_exc.raising_else) __Raise(__tmp_exc.arg);")
2.53 - else_str = "else "
2.54 -
2.55 - # Handle the completion of try blocks or the execution of return
2.56 - # statements where finally blocks apply.
2.57 -
2.58 - if self.in_try_finally:
2.59 - self.writeline("%sif (__tmp_exc.completing) __Throw(__tmp_exc);" % else_str)
2.60 - else_str = "else "
2.61 + self.writeline("else if (__tmp_exc.raising_else) __Raise(__tmp_exc.arg);")
2.62
2.63 # Exception handling.
2.64
2.65 @@ -1183,10 +1183,9 @@
2.66
2.67 if name is not None:
2.68 name_ref = self.process_structure_node(name)
2.69 - self.writeline("%sif (__BOOL(__fn_native__isinstance((__attr[]) {__tmp_exc.arg, %s})))" % (else_str, name_ref))
2.70 + self.writeline("else if (__BOOL(__fn_native__isinstance((__attr[]) {__tmp_exc.arg, %s})))" % name_ref)
2.71 else:
2.72 - self.writeline("%sif (1)" % else_str)
2.73 - else_str = "else "
2.74 + self.writeline("else if (1)")
2.75
2.76 self.writeline("{")
2.77 self.indent += 1
2.78 @@ -1204,7 +1203,7 @@
2.79
2.80 # Re-raise unhandled exceptions.
2.81
2.82 - self.writeline("%s__Throw(__tmp_exc);" % else_str)
2.83 + self.writeline("else __Throw(__tmp_exc);")
2.84
2.85 # End the handler block.
2.86
2.87 @@ -1238,15 +1237,29 @@
2.88 self.indent += 1
2.89 self.process_structure_node(n.final)
2.90
2.91 - # Test for the completion of a try block.
2.92 + # Introduce an if statement to handle the completion of a try block.
2.93 +
2.94 + self.process_try_completion()
2.95 + self.writeline("else __Throw(__tmp_exc);")
2.96 +
2.97 + self.indent -= 1
2.98 + self.writeline("}")
2.99 +
2.100 + def process_try_completion(self):
2.101 +
2.102 + "Generate a test for the completion of a try block."
2.103
2.104 self.writestmt("if (__tmp_exc.completing)")
2.105 self.writeline("{")
2.106 self.indent += 1
2.107 - self.writeline("if (!__ISNULL(__tmp_exc.arg)) return __tmp_exc.arg;")
2.108 - self.indent -= 1
2.109 - self.writeline("}")
2.110 - self.writeline("else __Throw(__tmp_exc);")
2.111 +
2.112 + # Only use the normal return statement if no surrounding try blocks
2.113 + # apply.
2.114 +
2.115 + if not self.in_try_finally and not self.in_try_except:
2.116 + self.writeline("if (!__ISNULL(__tmp_exc.arg)) return __tmp_exc.arg;")
2.117 + else:
2.118 + self.writeline("if (!__ISNULL(__tmp_exc.arg)) __Throw(__tmp_exc);")
2.119
2.120 self.indent -= 1
2.121 self.writeline("}")