unpack exception test tuples in 'except' clauses, results in shorter, faster and...
authorStefan Behnel <scoder@users.berlios.de>
Fri, 13 Aug 2010 12:19:09 +0000 (14:19 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Fri, 13 Aug 2010 12:19:09 +0000 (14:19 +0200)
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py

index 05ce3c965aba325ca363235870b15a4b483abebf..1672f0a49ff09e1b5d039d6d52c315f50011a1db 100644 (file)
@@ -4702,7 +4702,7 @@ class TryExceptStatNode(StatNode):
 class ExceptClauseNode(Node):
     #  Part of try ... except statement.
     #
-    #  pattern        ExprNode
+    #  pattern        [ExprNode]
     #  target         ExprNode or None
     #  body           StatNode
     #  excinfo_target NameNode or None   optional target for exception info
@@ -4732,8 +4732,10 @@ class ExceptClauseNode(Node):
         genv = env.global_scope()
         self.function_name = env.qualified_name
         if self.pattern:
-            self.pattern.analyse_expressions(env)
-            self.pattern = self.pattern.coerce_to_pyobject(env)
+            # normalise/unpack self.pattern into a list
+            for i, pattern in enumerate(self.pattern):
+                pattern.analyse_expressions(env)
+                self.pattern[i] = pattern.coerce_to_pyobject(env)
 
         if self.target:
             self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
@@ -4750,15 +4752,17 @@ class ExceptClauseNode(Node):
     def generate_handling_code(self, code, end_label):
         code.mark_pos(self.pos)
         if self.pattern:
-            self.pattern.generate_evaluation_code(code)
-            
+            exc_tests = []
+            for pattern in self.pattern:
+                pattern.generate_evaluation_code(code)
+                exc_tests.append("PyErr_ExceptionMatches(%s)" % pattern.py_result())
+
             match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
             code.putln(
-                "%s = PyErr_ExceptionMatches(%s);" % (
-                    match_flag,
-                    self.pattern.py_result()))
-            self.pattern.generate_disposal_code(code)
-            self.pattern.free_temps(code)
+                "%s = %s;" % (match_flag, ' || '.join(exc_tests)))
+            for pattern in self.pattern:
+                pattern.generate_disposal_code(code)
+                pattern.free_temps(code)
             code.putln(
                 "if (%s) {" %
                     match_flag)
@@ -4837,7 +4841,8 @@ class ExceptClauseNode(Node):
         
     def annotate(self, code):
         if self.pattern:
-            self.pattern.annotate(code)
+            for pattern in self.pattern:
+                pattern.annotate(code)
         if self.target:
             self.target.annotate(code)
         self.body.annotate(code)
index 0596c93d5e1bd0c838956742d5cd7b554e363740..6a040a54d5a891370f39492f5a1bdab83d885c36 100644 (file)
@@ -1426,6 +1426,11 @@ def p_except_clause(s):
     exc_value = None
     if s.sy != ':':
         exc_type = p_test(s)
+        # normalise into list of single exception tests
+        if isinstance(exc_type, ExprNodes.TupleNode):
+            exc_type = exc_type.args
+        else:
+            exc_type = [exc_type]
         if s.sy == ',' or (s.sy == 'IDENT' and s.systring == 'as'):
             s.next()
             exc_value = p_test(s)