Fix assertion error in python source due to invalid lineno increment inside llvm_cbuilder.translator.

This commit is contained in:
Siu Kwan Lam 2012-09-21 19:37:10 -07:00
commit b9584e1071

View file

@ -11,9 +11,20 @@ def translate(func):
wrapper = functools.wraps(func) wrapper = functools.wraps(func)
caller_frame = inspect.currentframe().f_back caller_frame = inspect.currentframe().f_back
tree = _get_ast(func) tree = _get_ast(func)
tree = ast.copy_location(ast.Module(body=tree.body), tree) tree = ast.Module(body=tree.body)
tree = ExpandControlFlow().visit(tree) tree = ExpandControlFlow().visit(tree)
tree = ast.fix_missing_locations(tree)
# NOTE: A hack to fix assertion error in debug mode due to bad lineno.
# Lineno must increase monotonically for co_lnotab,
# the "line number table" to work correctly.
# This script just set all lineno to 1 and col_offset = to 0.
# This makes it impossible to do traceback, but it is not possible
# anyway since we are dynamically changing the source code.
for node in ast.walk(tree):
# only ast.expr and ast.stmt and their subclass has lineno and col_offset.
if isinstance(node, ast.expr) or isinstance(node, ast.stmt):
node.lineno = 1
node.col_offset = 0
# prepare locals for execution # prepare locals for execution
local_dict = locals() local_dict = locals()
@ -21,7 +32,8 @@ def translate(func):
local_dict.update(caller_frame.f_globals) local_dict.update(caller_frame.f_globals)
try: try:
return eval(compile(tree, '<string>', 'exec')) compiled = compile(tree, '<string>', 'exec')
return eval(compiled)
except Exception, e: except Exception, e:
logger.debug(ast.dump(tree)) logger.debug(ast.dump(tree))
from ArminRonacher import codegen # uses Armin Ronacher's codegen to debug from ArminRonacher import codegen # uses Armin Ronacher's codegen to debug
@ -97,7 +109,7 @@ class ExpandControlFlow(ast.NodeTransformer):
ifelse = load_template(_if_else_template) ifelse = load_template(_if_else_template)
ifelse = MacroExpander(mapping).visit(ifelse) ifelse = MacroExpander(mapping).visit(ifelse)
newnode = self.generic_visit(ifelse) newnode = self.generic_visit(ifelse)
return ast.copy_location(newnode, node) return newnode
def visit_While(self, node): def visit_While(self, node):
mapping = { mapping = {
@ -107,7 +119,7 @@ class ExpandControlFlow(ast.NodeTransformer):
whileloop = load_template(_while_template) whileloop = load_template(_while_template)
whileloop = MacroExpander(mapping).visit(whileloop) whileloop = MacroExpander(mapping).visit(whileloop)
newnode = self.generic_visit(whileloop) newnode = self.generic_visit(whileloop)
return ast.copy_location(newnode, node) return newnode
def visit_For(self, node): def visit_For(self, node):
try: try:
@ -125,13 +137,13 @@ class ExpandControlFlow(ast.NodeTransformer):
forloop = load_template(_for_range_template) forloop = load_template(_for_range_template)
forloop = MacroExpander(mapping).visit(forloop) forloop = MacroExpander(mapping).visit(forloop)
newnode = self.generic_visit(forloop) newnode = self.generic_visit(forloop)
return ast.copy_location(newnode, node) return newnode
def visit_Return(self, node): def visit_Return(self, node):
mapping = {'__RETURN__' : node.value} mapping = {'__RETURN__' : node.value}
ret = load_template(_return_template) ret = load_template(_return_template)
repl = MacroExpander(mapping).visit(ret) repl = MacroExpander(mapping).visit(ret)
return ast.copy_location(repl, node) return repl
def visit_Num(self, node): def visit_Num(self, node):
'''convert immediate values '''convert immediate values
@ -148,7 +160,7 @@ class ExpandControlFlow(ast.NodeTransformer):
'__VALUE__' : node, '__VALUE__' : node,
} }
constant = MacroExpander(mapping).visit(template).value constant = MacroExpander(mapping).visit(template).value
newnode = ast.copy_location(constant, node) newnode = constant
return newnode return newnode
class MacroExpander(ast.NodeTransformer): class MacroExpander(ast.NodeTransformer):
@ -187,6 +199,7 @@ class MacroExpander(ast.NodeTransformer):
pass pass
else: else:
if repl is not None and not isinstance(repl, list): if repl is not None and not isinstance(repl, list):
return ast.copy_location(repl, node) return repl
return node return node