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
|
"""Implements the main interface for flow graph creation: build_flow().
"""
from inspect import CO_NEWLOCALS, isgeneratorfunction
from rpython.flowspace.model import checkgraph
from rpython.flowspace.bytecode import HostCode
from rpython.flowspace.flowcontext import (FlowContext, fixeggblocks)
from rpython.flowspace.generator import (tweak_generator_graph,
make_generator_entry_graph)
from rpython.flowspace.pygraph import PyGraph
def _assert_rpythonic(func):
"""Raise ValueError if ``func`` is obviously not RPython"""
try:
func.func_code.co_cellvars
except AttributeError:
raise ValueError("%r is not RPython: it is likely an unexpected "
"built-in function or type" % (func,))
if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'):
raise ValueError("%r is tagged as NOT_RPYTHON" % (func,))
if func.func_code.co_cellvars:
raise ValueError(
"""RPython functions cannot create closures
Possible causes:
Function is inner function
Function uses generator expressions
Lambda expressions
in %r""" % (func,))
if not (func.func_code.co_flags & CO_NEWLOCALS):
raise ValueError("The code object for a RPython function should have "
"the flag CO_NEWLOCALS set.")
def build_flow(func):
"""
Create the flow graph (in SSA form) for the function.
"""
_assert_rpythonic(func)
if (isgeneratorfunction(func) and
not hasattr(func, '_generator_next_method_of_')):
return make_generator_entry_graph(func)
code = HostCode._from_code(func.func_code)
graph = PyGraph(func, code)
ctx = FlowContext(graph, code)
ctx.build_flow()
fixeggblocks(graph)
if code.is_generator:
tweak_generator_graph(graph)
return graph
|