1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
"""PyPy Translator Frontend
The Translator is a glue class putting together the various pieces of the
translation-related code. It can be used for interactive testing of the
translator; see pypy/bin/translatorshell.py.
"""
import sys
import types
from rpython.translator import simplify
from rpython.flowspace.model import FunctionGraph, checkgraph, Block
from rpython.flowspace.objspace import build_flow
from rpython.tool.ansi_print import AnsiLogger
from rpython.tool.sourcetools import nice_repr_for_func
from rpython.config.translationoption import get_platform
log = AnsiLogger("flowgraph")
class TranslationContext(object):
FLOWING_FLAGS = {
'verbose': False,
'list_comprehension_operations': False, # True, - not super-tested
}
def __init__(self, config=None, **flowing_flags):
if config is None:
from rpython.config.translationoption import get_combined_translation_config
config = get_combined_translation_config(translating=True)
# ZZZ should go away in the end
for attr in ['verbose', 'list_comprehension_operations']:
if attr in flowing_flags:
setattr(config.translation, attr, flowing_flags[attr])
self.config = config
self.platform = get_platform(config)
self.annotator = None
self.rtyper = None
self.exceptiontransformer = None
self.graphs = [] # [graph]
self.callgraph = {} # {opaque_tag: (caller-graph, callee-graph)}
self._prebuilt_graphs = {} # only used by the pygame viewer
self._call_at_startup = []
def buildflowgraph(self, func, mute_dot=False):
"""Get the flow graph for a function."""
if not isinstance(func, types.FunctionType):
raise TypeError("buildflowgraph() expects a function, "
"got %r" % (func,))
if func in self._prebuilt_graphs:
graph = self._prebuilt_graphs.pop(func)
else:
if self.config.translation.verbose:
log(nice_repr_for_func(func))
graph = build_flow(func)
simplify.simplify_graph(graph)
if self.config.translation.list_comprehension_operations:
simplify.detect_list_comprehension(graph)
if not self.config.translation.verbose and not mute_dot:
log.dot()
self.graphs.append(graph) # store the graph in our list
return graph
def update_call_graph(self, caller_graph, callee_graph, position_tag):
# update the call graph
key = caller_graph, callee_graph, position_tag
self.callgraph[key] = caller_graph, callee_graph
def buildannotator(self, policy=None):
if self.annotator is not None:
raise ValueError("we already have an annotator")
from rpython.annotator.annrpython import RPythonAnnotator
self.annotator = RPythonAnnotator(
self, policy=policy, keepgoing=self.config.translation.keepgoing)
return self.annotator
def buildrtyper(self):
if self.annotator is None:
raise ValueError("no annotator")
if self.rtyper is not None:
raise ValueError("we already have an rtyper")
from rpython.rtyper.rtyper import RPythonTyper
self.rtyper = RPythonTyper(self.annotator)
return self.rtyper
def getexceptiontransformer(self):
if self.rtyper is None:
raise ValueError("no rtyper")
if self.exceptiontransformer is not None:
return self.exceptiontransformer
from rpython.translator.exceptiontransform import ExceptionTransformer
self.exceptiontransformer = ExceptionTransformer(self)
return self.exceptiontransformer
def checkgraphs(self):
for graph in self.graphs:
checkgraph(graph)
# debug aids
def about(self, x, f=None):
"""Interactive debugging helper """
if f is None:
f = sys.stdout
if isinstance(x, Block):
for graph in self.graphs:
if x in graph.iterblocks():
print >>f, '%s is a %s' % (x, x.__class__)
print >>f, 'in %s' % (graph,)
break
else:
print >>f, '%s is a %s at some unknown location' % (
x, x.__class__.__name__)
print >>f, 'containing the following operations:'
for op in x.operations:
print >>f, " ",op
print >>f, '--end--'
return
raise TypeError("don't know about %r" % x)
def view(self):
"""Shows the control flow graph with annotations if computed.
Requires 'dot' and pygame."""
from rpython.translator.tool.graphpage import FlowGraphPage
FlowGraphPage(self).display()
show = view
def viewcg(self, center_graph=None, huge=100):
"""Shows the whole call graph and the class hierarchy, based on
the computed annotations."""
from rpython.translator.tool.graphpage import TranslatorPage
TranslatorPage(self, center_graph=center_graph, huge=huge).display()
showcg = viewcg
# _______________________________________________________________
# testing helper
def graphof(translator, func):
if isinstance(func, FunctionGraph):
return func
result = []
if hasattr(func, 'im_func'):
# make it possible to translate bound methods
func = func.im_func
for graph in translator.graphs:
if getattr(graph, 'func', None) is func:
result.append(graph)
assert len(result) == 1
return result[0]
TranslationContext._graphof = graphof
|