#344, stop pipeline before code generation in case of errors
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 10 Sep 2009 09:20:16 +0000 (02:20 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 10 Sep 2009 09:20:16 +0000 (02:20 -0700)
Cython/Compiler/Main.py
Cython/Compiler/Nodes.py
tests/errors/e_argdefault.pyx
tests/errors/e_del.pyx
tests/errors/e_del2.pyx [new file with mode: 0644]
tests/errors/nogil.pyx

index 61576421bbaecfcbab6bf61f672da3c5d948b2fe..804e3221b9d97276b3865e6d3e8fb1ac2981636c 100644 (file)
@@ -34,6 +34,12 @@ def dumptree(t):
     print t.dump()
     return t
 
+def abort_on_errors(node):
+    # Stop the pipeline if there are any errors.
+    if Errors.num_errors != 0:
+        raise InternalError, "abort"
+    return node
+
 class CompilationData(object):
     #  Bundles the information that is passed from transform to transform.
     #  (For now, this is only)
@@ -157,6 +163,7 @@ class Context(object):
                 create_parse(self),
             ] + self.create_pipeline(pxd=False, py=py) + [
                 inject_pxd_code,
+                abort_on_errors,
                 generate_pyx_code,
             ])
 
index efba286bb1e1cbd9dd9867bdf2ea859e6d2a3bd6..d255628460363ddf3376a473ba68ca8f6f189aa0 100644 (file)
@@ -1006,8 +1006,10 @@ class FuncDefNode(StatNode, BlockNode):
     
     def analyse_default_values(self, env):
         genv = env.global_scope()
+        default_seen = 0
         for arg in self.args:
             if arg.default:
+                default_seen = 1
                 if arg.is_generic:
                     if not hasattr(arg, 'default_entry'):
                         arg.default.analyse_types(env)
@@ -1028,6 +1030,10 @@ class FuncDefNode(StatNode, BlockNode):
                     error(arg.pos,
                         "This argument cannot have a default value")
                     arg.default = None
+            elif arg.kw_only:
+                default_seen = 1
+            elif default_seen:
+                error(arg.pos, "Non-default argument following default argument")
     
     def need_gil_acquisition(self, lenv):
         return 0
@@ -1106,7 +1112,7 @@ class FuncDefNode(StatNode, BlockNode):
         # ----- Extern library function declarations
         lenv.generate_library_function_declarations(code)
         # ----- GIL acquisition
-        acquire_gil = self.need_gil_acquisition(lenv)
+        acquire_gil = self.acquire_gil
         if acquire_gil:
             env.use_utility_code(force_init_threads_utility_code)
             code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
@@ -1446,6 +1452,7 @@ class CFuncDefNode(FuncDefNode):
         self.analyse_default_values(env)
         if self.py_func is not None:
             self.py_func.analyse_expressions(env)
+        self.acquire_gil = self.need_gil_acquisition(self.local_scope)
 
     def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
         arg_decls = []
@@ -1869,6 +1876,7 @@ class DefNode(FuncDefNode):
         self.analyse_default_values(env)
         if env.is_py_class_scope:
             self.synthesize_assignment_node(env)
+        self.acquire_gil = 0
     
     def synthesize_assignment_node(self, env):
         import ExprNodes
@@ -1971,12 +1979,10 @@ class DefNode(FuncDefNode):
         else:
             positional_args = []
             kw_only_args = []
-            default_seen = 0
             for arg in self.args:
                 arg_entry = arg.entry
                 if arg.is_generic:
                     if arg.default:
-                        default_seen = 1
                         if not arg.is_self_arg:
                             if arg.kw_only:
                                 kw_only_args.append(arg)
@@ -1984,9 +1990,6 @@ class DefNode(FuncDefNode):
                                 positional_args.append(arg)
                     elif arg.kw_only:
                         kw_only_args.append(arg)
-                        default_seen = 1
-                    elif default_seen:
-                        error(arg.pos, "Non-default argument following default argument")
                     elif not arg.is_self_arg:
                         positional_args.append(arg)
 
index 752e738bc49bbe4abcf0237c2acaad84e53db2ff..70c472dd6be9bd9b03c36696605f8ed965d18677 100644 (file)
@@ -11,6 +11,7 @@ cdef class Grail:
 
 _ERRORS = u"""
 1:10: Non-default argument follows default argument
-9:16: This argument cannot have a default value
+1:36: Non-default argument following default argument
 4:23: Non-default argument following default argument
+9:16: This argument cannot have a default value
 """
index befed049bb1b26c761988ab6ec0c080da2b77ce8..548f9ad58b341db6a93e1d0019f406684391cccf 100644 (file)
@@ -8,13 +8,11 @@ def f(a):
        del f() # error
        del i # error: deletion of non-Python object
        del j # error: deletion of non-Python object
-       del a # error: deletion of local name not supported
        del x[i] # error: deletion of non-Python object
        del s.m # error: deletion of non-Python object
 _ERRORS = u"""
 8:6: Cannot assign to or delete this
 9:45: Deletion of non-Python object
+11:6: Deletion of non-Python object
 12:6: Deletion of non-Python object
-13:6: Deletion of non-Python object
-11:52: Deletion of local or C global name not supported
 """
diff --git a/tests/errors/e_del2.pyx b/tests/errors/e_del2.pyx
new file mode 100644 (file)
index 0000000..20dac71
--- /dev/null
@@ -0,0 +1,12 @@
+# Errors reported during code generation.
+
+cdef int i
+
+def f(a):
+       del a # error: deletion of local name not supported
+       del i # error: deletion of local name not supported
+
+_ERRORS = u"""
+6:52: Deletion of local or C global name not supported
+7:52: Deletion of local or C global name not supported
+"""
index 570aeb1425f226e3ed8d8b5b85371064b27be23f..a72848d03bb672617ba432123f9600032208c160 100644 (file)
@@ -103,7 +103,7 @@ _ERRORS = u"""
 38:11: Accessing Python attribute not allowed without gil
 39: 9: Constructing Python tuple not allowed without gil
 40: 8: Constructing Python list not allowed without gil
-41: 8: Constructing Python dict not allowed without gil
+#41: 8: Constructing Python dict not allowed without gil
 42:12: Truth-testing Python object not allowed without gil
 43:13: Python type test not allowed without gil
 #44: 4: Converting to Python object not allowed without gil