Abort compilation prior to code generation transforms if errors were recorded
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Fri, 15 Aug 2008 12:12:51 +0000 (14:12 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Fri, 15 Aug 2008 12:12:51 +0000 (14:12 +0200)
Cython/Compiler/Errors.py
Cython/Compiler/Main.py
tests/errors/e_switch.pyx

index a8ad03aff4dfeb8d89abcec68802fb2a4988a473..db0572ebac9b8490947c2dfd2da3f6ea0173fc53 100644 (file)
@@ -63,11 +63,16 @@ class InternalError(Exception):
     def __init__(self, message):
         Exception.__init__(self, "Internal compiler error: %s"
             % message)
-            
+
+class AbortCompilationError(Exception):
+    """
+    Raised in order to abort compilation.
+    """
 
 listing_file = None
 num_errors = 0
 echo_file = None
+last_error = None
 
 def open_listing_file(path, echo_to_stderr = 1):
     # Begin a new error listing. If path is None, no file
@@ -90,7 +95,7 @@ def close_listing_file():
         listing_file = None
 
 def report_error(err):
-    global num_errors
+    global num_errors, last_error
     # See Main.py for why dual reporting occurs. Quick fix for now.
     if err.reported: return
     err.reported = True
@@ -100,6 +105,7 @@ def report_error(err):
     if echo_file:
         echo_file.write(line)
     num_errors = num_errors + 1
+    last_error = err
 
 def error(position, message):
     #print "Errors.error:", repr(position), repr(message) ###
index 2d8c3dd60380d61aad90acf8c7abfe80b8d0fddf..10e9049e5d03ada37ef5b9c1a5568cff3f3d00a4 100644 (file)
@@ -84,6 +84,11 @@ class Context:
         from Buffer import IntroduceBufferAuxiliaryVars
         from ModuleNode import check_c_classes
 
+        def abort_if_errors(t):
+            if Errors.num_errors > 0:
+                raise Errors.AbortCompilationError()
+            return t
+
         if pxd:
             _check_c_classes = None
             _specific_post_parse = PxdPostParse(self)
@@ -123,10 +128,10 @@ class Context:
                 # (this seems strange -- I believe the right concept is to split
                 # ModuleNode into a ModuleNode and a CodeGenerator, and tell that
                 # CodeGenerator to generate code both from the pyx and pxd ModuleNodes.
-                 stats.append(statlistnode)
-                 # Until utility code is moved to code generation phase everywhere,
-                 # we need to copy it over to the main scope
-                 module_node.scope.utility_code_list.extend(scope.utility_code_list)
+                stats.append(statlistnode)
+                # Until utility code is moved to code generation phase everywhere,
+                # we need to copy it over to the main scope
+                module_node.scope.utility_code_list.extend(scope.utility_code_list)
             return module_node
 
         return ([
@@ -167,10 +172,16 @@ class Context:
             for phase in pipeline:
                 if phase is not None:
                     data = phase(data)
+                print Errors.num_errors
         except CompileError, err:
-            # err is set
+            print "hello", err
             Errors.report_error(err)
-        return (err, data)
+            raise err
+        except Errors.AbortCompilationError:
+            print "abort", Errors.num_errors
+            pass
+        print "normal"
+        return data
 
     def find_module(self, module_name, 
             relative_to = None, pos = None, need_pxd = 1):
@@ -227,10 +238,7 @@ class Context:
                     if debug_find_module:
                         print("Context.find_module: Parsing %s" % pxd_pathname)
                     source_desc = FileSourceDescriptor(pxd_pathname)
-                    err, result = self.process_pxd(source_desc, scope, module_name)
-                    if err:
-                        raise err
-                    (pxd_codenodes, pxd_scope) = result
+                    pxd_codenodes, pxd_scope = self.process_pxd(source_desc, scope, module_name)
                     self.pxds[module_name] = (pxd_codenodes, pxd_scope)
                 except CompileError:
                     pass
@@ -399,7 +407,7 @@ class Context:
         except UnicodeDecodeError, msg:
             error((source_desc, 0, 0), "Decoding error, missing or incorrect coding=<encoding-name> at top of source (%s)" % msg)
         if Errors.num_errors > 0:
-            raise CompileError
+            raise Errors.AbortCompilationError()
         return tree
 
     def extract_module_name(self, path, options):
@@ -429,15 +437,13 @@ class Context:
         else:
             Errors.open_listing_file(None)
 
-    def teardown_errors(self, err, options, result):
+    def teardown_errors(self, options, result):
         source_desc = result.compilation_source.source_desc
         if not isinstance(source_desc, FileSourceDescriptor):
             raise RuntimeError("Only file sources for code supported")
         Errors.close_listing_file()
         result.num_errors = Errors.num_errors
-        if result.num_errors > 0:
-            err = True
-        if err and result.c_file:
+        if result.num_errors > 0 and result.c_file:
             try:
                 Utils.castrate_file(result.c_file, os.stat(source_desc.filename))
             except EnvironmentError:
@@ -498,8 +504,13 @@ def run_pipeline(source, options, full_module_name = None):
     pipeline = context.create_pyx_pipeline(options, result)
 
     context.setup_errors(options)
-    err, enddata = context.run_pipeline(pipeline, source)
-    context.teardown_errors(err, options, result)
+    try:
+        enddata = context.run_pipeline(pipeline, source)
+    except Errors.CompileError:
+        pass
+    except Errors.AbortCompilationError:
+        pass
+    context.teardown_errors(options, result)
     return result
 
 #------------------------------------------------------------------------
index 405fd0109761d25e3274ab615111732b79c57733..9d0b4453d1b8f5da6ddfeb8e1a901edf85944a65 100644 (file)
@@ -8,5 +8,5 @@ elif x == 4:
     print 34
 
 _ERRORS = """
-4:23: undeclared name not builtin: NONEXISTING
+3:19: undeclared name not builtin: NONEXISTING
 """