From: Stefan Behnel Date: Sat, 10 Jan 2009 14:32:22 +0000 (+0100) Subject: provide more context on compiler crashes during transforms X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1931d3b9ce56fadd0e977b77ac1aa42e3d6544ff;p=cython.git provide more context on compiler crashes during transforms --- diff --git a/Cython/Compiler/Errors.py b/Cython/Compiler/Errors.py index c7c6cae9..821ef01f 100644 --- a/Cython/Compiler/Errors.py +++ b/Cython/Compiler/Errors.py @@ -63,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, sys + message += ( + u'\n\nCompiler crash traceback up to this point:\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 diff --git a/Cython/Compiler/Visitor.py b/Cython/Compiler/Visitor.py index ad5b33ab..72702026 100644 --- a/Cython/Compiler/Visitor.py +++ b/Cython/Compiler/Visitor.py @@ -6,6 +6,7 @@ import inspect import Nodes import ExprNodes import Naming +import Errors from StringEncoding import EncodedString class BasicVisitor(object): @@ -91,9 +92,58 @@ class TreeVisitor(BasicVisitor): super(TreeVisitor, self).__init__() self.access_path = [] + def dump_node(self, node, indent=0): + ignored = list(node.child_attrs) + [u'child_attrs', u'pos'] + values = [] + pos = node.pos + if pos: + source = pos[0] + if source: + import os.path + source = os.path.basename(source.get_description()) + values.append(u'%s:%s:%s' % (source, pos[1], pos[2])) + attribute_names = dir(node) + attribute_names.sort() + for attr in attribute_names: + if attr in ignored: + continue + if attr.startswith(u'_') or attr.endswith(u'_'): + continue + value = getattr(node, attr, None) + if value is None: + continue + elif isinstance(value, list): + value = u'[...]' + elif not isinstance(value, (str, unicode, long, int, float)): + continue + else: + value = repr(value) + values.append(u'%s = %s' % (attr, value)) + return u'%s(%s)' % (node.__class__.__name__, + u',\n '.join(values)) + def visitchild(self, child, parent, attrname, idx): self.access_path.append((parent, attrname, idx)) - result = self.visit(child) + try: + result = self.visit(child) + except Errors.CompilerCrash: + raise + except Exception, e: + import sys + trace = [''] + for parent, attribute, index in self.access_path: + node = getattr(parent, attribute) + if index is None: + index = '' + else: + node = node[index] + index = u'[%d]' % index + trace.append(u'%s.%s%s = %s' % ( + parent.__class__.__name__, attribute, index, + self.dump_node(node))) + raise Errors.CompilerCrash( + node.pos, self.__class__.__name__, + u'\n'.join(trace), e, sys.exc_info()[2]) self.access_path.pop() return result