cleanup
[cython.git] / Cython / Compiler / Errors.py
index 42e139d3ad4ca0d2983f44e1d8d92bb85c5f2f44..1e7a44a3a2bd2f1635ed36115090eafcab8e553f 100644 (file)
@@ -32,6 +32,8 @@ class CompileError(PyrexError):
     
     def __init__(self, position = None, message = ""):
         self.position = position
+        self.message_only = message
+        self.reported = False
     # Deprecated and withdrawn in 2.6:
     #   self.message = message
         if position:
@@ -61,7 +63,28 @@ class InternalError(Exception):
     def __init__(self, message):
         Exception.__init__(self, "Internal compiler error: %s"
             % message)
-            
+
+
+class CompilerCrash(CompileError):
+    # raised when an unexpected exception occurs in a transform
+    def __init__(self, pos, context, message, cause, stacktrace=None):
+        if message:
+            message = u'\n' + message
+        else:
+            message = u'\n'
+        if context:
+            message = "Compiler crash in " + context + message
+        if stacktrace:
+            import traceback
+            message += (
+                u'\n\nCompiler crash traceback from this point on:\n' +
+                u''.join(traceback.format_tb(stacktrace)))
+        if cause:
+            if not stacktrace:
+                message += u'\n'
+            message += u'%s: %s' % (cause.__class__.__name__, cause)
+        CompileError.__init__(self, pos, message)
+
 
 listing_file = None
 num_errors = 0
@@ -87,16 +110,26 @@ def close_listing_file():
         listing_file.close()
         listing_file = None
 
+def report_error(err):
+    if error_stack:
+        error_stack[-1].append(err)
+    else:
+        global num_errors
+        # See Main.py for why dual reporting occurs. Quick fix for now.
+        if err.reported: return
+        err.reported = True
+        line = "%s\n" % err
+        if listing_file:
+            listing_file.write(line)
+        if echo_file:
+            echo_file.write(line)
+        num_errors = num_errors + 1
+
 def error(position, message):
     #print "Errors.error:", repr(position), repr(message) ###
-    global num_errors
     err = CompileError(position, message)
-    line = "%s\n" % err
-    if listing_file:
-        listing_file.write(line)
-    if echo_file:
-        echo_file.write(line)
-    num_errors = num_errors + 1
+    #if position is not None: raise Exception(err) # debug
+    report_error(err)
     return err
 
 LEVEL=1 # warn about all errors level 1 or higher
@@ -111,3 +144,19 @@ def warning(position, message, level=0):
     if echo_file:
         echo_file.write(line)
     return warn
+
+# These functions can be used to momentarily suppress errors. 
+
+error_stack = []
+
+def hold_errors():
+    error_stack.append([])
+
+def release_errors(ignore=False):
+    held_errors = error_stack.pop()
+    if not ignore:
+        for err in held_errors:
+            report_error(err)
+
+def held_errors():
+    return error_stack[-1]