Commit 1931d3b9 authored by Stefan Behnel's avatar Stefan Behnel

provide more context on compiler crashes during transforms

parent c3a11b9e
...@@ -63,7 +63,28 @@ class InternalError(Exception): ...@@ -63,7 +63,28 @@ class InternalError(Exception):
def __init__(self, message): def __init__(self, message):
Exception.__init__(self, "Internal compiler error: %s" Exception.__init__(self, "Internal compiler error: %s"
% message) % 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 listing_file = None
num_errors = 0 num_errors = 0
......
...@@ -6,6 +6,7 @@ import inspect ...@@ -6,6 +6,7 @@ import inspect
import Nodes import Nodes
import ExprNodes import ExprNodes
import Naming import Naming
import Errors
from StringEncoding import EncodedString from StringEncoding import EncodedString
class BasicVisitor(object): class BasicVisitor(object):
...@@ -91,9 +92,58 @@ class TreeVisitor(BasicVisitor): ...@@ -91,9 +92,58 @@ class TreeVisitor(BasicVisitor):
super(TreeVisitor, self).__init__() super(TreeVisitor, self).__init__()
self.access_path = [] 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): def visitchild(self, child, parent, attrname, idx):
self.access_path.append((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() self.access_path.pop()
return result return result
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment