def test_basic(self): """ A ExtFuncEntry provides an annotation for a function, no need to flow its graph. """ def b(x): "NOT_RPYTHON" return eval("x+40") class BTestFuncEntry(ExtFuncEntry): _about_ = b name = 'b' signature_args = [annmodel.SomeInteger()] signature_result = annmodel.SomeInteger() def f(): return b(2) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInteger) res = interpret(f, []) assert res == 42
def test_callback(self): """ Verify annotation when a callback function is in the arguments list. """ def d(y): return eval("y()") class DTestFuncEntry(ExtFuncEntry): _about_ = d name = 'd' signature_args = [ annmodel.SomeGenericCallable(args=[], result=annmodel.SomeFloat()) ] signature_result = annmodel.SomeFloat() def callback(): return 2.5 def f(): return d(callback) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeFloat) assert a.translator._graphof(callback)
def annotate(func, values, inline=None, backendoptimize=True, type_system="lltype", translationoptions={}): # build the normal ll graphs for ll_function t = TranslationContext() for key, value in translationoptions.items(): setattr(t.config.translation, key, value) annpolicy = AnnotatorPolicy() annpolicy.allow_someobjects = False a = t.buildannotator(policy=annpolicy) argtypes = getargtypes(a, values) a.build_types(func, argtypes, main_entry_point=True) rtyper = t.buildrtyper(type_system=type_system) rtyper.specialize() #if inline: # auto_inlining(t, threshold=inline) if backendoptimize: from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(t, inline_threshold=inline or 0, remove_asserts=True, really_remove_asserts=True) return rtyper
def rcompile(rgenop, entrypoint, argtypes, random_seed=0, type_system='lltype'): from pypy.translator.translator import TranslationContext from pypy.annotation.policy import AnnotatorPolicy from pypy import conftest t = TranslationContext() policy = AnnotatorPolicy() policy.allow_someobjects = False t.buildannotator(policy=policy).build_types(entrypoint, argtypes) t.buildrtyper(type_system=type_system).specialize() # note that backend optimizations will constant-fold simple operations, # which is required by some backends that don't accept calls like # genop1("add", constant, constant). from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(t) if conftest.option.view: t.view() entrygraph = t._graphof(entrypoint) return compile_graph(rgenop, entrygraph, random_seed=random_seed)
def annotate(func, values, inline=None, backendoptimize=True, type_system="lltype"): # build the normal ll graphs for ll_function t = TranslationContext() annpolicy = AnnotatorPolicy() annpolicy.allow_someobjects = False a = t.buildannotator(policy=annpolicy) argtypes = getargtypes(a, values) a.build_types(func, argtypes) rtyper = t.buildrtyper(type_system=type_system) rtyper.specialize() if inline: auto_inlining(t, threshold=inline) if backendoptimize: from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(t, inline_threshold=inline or 0, remove_asserts=True, really_remove_asserts=True) #if conftest.option.view: # t.view() return rtyper
def annotate_helper(self, function, args_s, policy=None): if policy is None: from pypy.annotation.policy import AnnotatorPolicy policy = AnnotatorPolicy() graph, inputcells = self.get_call_parameters(function, args_s, policy) self.build_graph_types(graph, inputcells, complete_now=False) self.complete_helpers(policy) return graph
def test_annotation_b(): def f(): return b(1) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInteger)
def test_register_external_signature(): def f(): return dd(3) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInteger)
def test_register_external_specialcase(): def f(): x = function_withspecialcase return x(33) + x("aaa") + x([]) + "\n" policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeString)
def test_callback(): def callback(): return 2.5 def f(): return d(callback) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeFloat) assert a.translator._graphof(callback)
def test_register_external_return_goes_back(): """ Check whether it works to pass the same list from one external fun to another [bookkeeper and list joining issues] """ def f(): return function_with_list(function_returning_list()) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInteger)
def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", backendopt=False, config=None, malloc_check=True, **extraconfigopts): extra_key = [(key, value) for key, value in extraconfigopts.iteritems()] extra_key.sort() extra_key = tuple(extra_key) key = ((func, ) + tuple([typeOf(x) for x in values]) + (someobjects, backendopt, extra_key)) try: (t, interp, graph) = _tcache[key] except KeyError: def annotation(x): T = typeOf(x) if T == Ptr(PyObject) and someobjects: return object else: return lltype_to_annotation(T) if policy is None and not someobjects: from pypy.annotation.policy import AnnotatorPolicy policy = AnnotatorPolicy() policy.allow_someobjects = False t, typer, graph = gengraph(func, [annotation(x) for x in values], viewbefore, policy, type_system=type_system, backendopt=backendopt, config=config, **extraconfigopts) interp = LLInterpreter(typer, malloc_check=malloc_check) _tcache[key] = (t, interp, graph) # keep the cache small _lastinterpreted.append(key) if len(_lastinterpreted) >= 4: del _tcache[_lastinterpreted.pop(0)] if view == 'auto': view = getattr(conftest.option, 'view', False) if view: t.view() return interp, graph
def test_register_external_tuple_args(): """ Verify the annotation of a registered external function which takes a tuple argument. """ def f(): return function_with_tuple_arg((1, )) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) # Not a very good assertion, but at least it means _something_ happened. assert isinstance(s, annmodel.SomeInteger)
def __init__(self, translator=None, policy=None, bookkeeper=None): import pypy.rpython.ootypesystem.ooregistry # has side effects import pypy.rpython.ootypesystem.bltregistry # has side effects import pypy.rpython.extfuncregistry # has side effects import pypy.rlib.nonconst # has side effects if translator is None: # interface for tests from pypy.translator.translator import TranslationContext translator = TranslationContext() translator.annotator = self self.translator = translator self.pendingblocks = {} # map {block: graph-containing-it} self.bindings = {} # map Variables to SomeValues self.annotated = {} # set of blocks already seen self.added_blocks = None # see processblock() below self.links_followed = {} # set of links that have ever been followed self.notify = {} # {block: {positions-to-reflow-from-when-done}} self.fixed_graphs = {} # set of graphs not to annotate again self.blocked_blocks = {} # set of {blocked_block: graph} # --- the following information is recorded for debugging only --- # --- and only if annotation.model.DEBUG is kept to True self.why_not_annotated = { } # {block: (exc_type, exc_value, traceback)} # records the location of BlockedInference # exceptions that blocked some blocks. self.blocked_graphs = {} # set of graphs that have blocked blocks self.bindingshistory = {} # map Variables to lists of SomeValues self.binding_caused_by = {} # map Variables to position_keys # records the caller position that caused bindings of inputargs # to be updated self.binding_cause_history = {} # map Variables to lists of positions # history of binding_caused_by, kept in sync with # bindingshistory self.reflowcounter = {} self.return_bindings = {} # map return Variables to their graphs # --- end of debugging information --- self.frozen = False if policy is None: from pypy.annotation.policy import AnnotatorPolicy self.policy = AnnotatorPolicy() else: self.policy = policy if bookkeeper is None: bookkeeper = Bookkeeper(self) self.bookkeeper = bookkeeper
def test_register_external_signature(self): """ Test the standard interface for external functions. """ def dd(): pass register_external(dd, [int], int) def f(): return dd(3) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInteger)
def test_register_external_specialcase(self): """ When args=None, the external function accepts any arguments unmodified. """ def function_withspecialcase(arg): return repr(arg) register_external(function_withspecialcase, args=None, result=str) def f(): x = function_withspecialcase return x(33) + x("aaa") + x([]) + "\n" policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) assert isinstance(s, annmodel.SomeString)
def __init__(self, function, annotations, stackless=False, view=False, html=None, is_interactive=False, root=None, run_browser=True, policy=None): if not use_browsertest and not _CLI_is_on_path(): py.test.skip('Javascript CLI (js) not found') self.html = html self.is_interactive = is_interactive t = TranslationContext() if policy is None: from pypy.annotation.policy import AnnotatorPolicy policy = AnnotatorPolicy() policy.allow_someobjects = False ann = t.buildannotator(policy=policy) ann.build_types(function, annotations) if view or option.view: t.view() t.buildrtyper(type_system="ootype").specialize() if view or option.view: t.view() #self.js = JS(t, [function, callback_function], stackless) self.js = JS(t, function, stackless) self.js.write_source() if root is None and use_tg: from pypy.translator.js.demo.jsdemo.controllers import Root self.root = Root else: self.root = root self.run_browser = run_browser self.function_calls = []
def build_types(self, function, input_arg_types, complete_now=True, main_entry_point=False): """Recursively build annotations about the specific entry point.""" assert isinstance(function, types.FunctionType), "fix that!" from pypy.annotation.policy import AnnotatorPolicy policy = AnnotatorPolicy() # make input arguments and set their type args_s = [self.typeannotation(t) for t in input_arg_types] # XXX hack annmodel.TLS.check_str_without_nul = ( self.translator.config.translation.check_str_without_nul) flowgraph, inputcells = self.get_call_parameters(function, args_s, policy) if not isinstance(flowgraph, FunctionGraph): assert isinstance(flowgraph, annmodel.SomeObject) return flowgraph if main_entry_point: self.translator.entry_point_graph = flowgraph return self.build_graph_types(flowgraph, inputcells, complete_now=complete_now)
def annotate_helper_method(self, _class, attr, args_s, policy=None): """ Warning! this method is meant to be used between annotation and rtyping """ if policy is None: from pypy.annotation.policy import AnnotatorPolicy policy = AnnotatorPolicy() assert attr != '__class__' classdef = self.bookkeeper.getuniqueclassdef(_class) attrdef = classdef.find_attribute(attr) s_result = attrdef.getvalue() classdef.add_source_for_attribute(attr, classdef.classdesc) self.bookkeeper assert isinstance(s_result, annmodel.SomePBC) olddesc = s_result.descriptions.iterkeys().next() desc = olddesc.bind_self(classdef) args = self.bookkeeper.build_args("simple_call", args_s[:]) desc.consider_call_site(self.bookkeeper, desc.getcallfamily(), [desc], args, annmodel.s_ImpossibleValue) result = [] def schedule(graph, inputcells): result.append((graph, inputcells)) return annmodel.s_ImpossibleValue prevpolicy = self.policy self.policy = policy self.bookkeeper.enter(None) try: desc.pycall(schedule, args, annmodel.s_ImpossibleValue) finally: self.bookkeeper.leave() self.policy = prevpolicy [(graph, inputcells)] = result self.build_graph_types(graph, inputcells, complete_now=False) self.complete_helpers(policy) return graph
def test_register_external_tuple_args(self): """ Verify the annotation of a registered external function which takes a tuple argument. """ def function_with_tuple_arg(): """ Dummy function which is declared via register_external to take a tuple as an argument so that register_external's behavior for tuple-taking functions can be verified. """ register_external(function_with_tuple_arg, [(int, )], int) def f(): return function_with_tuple_arg((1, )) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) s = a.build_types(f, []) # Not a very good assertion, but at least it means _something_ happened. assert isinstance(s, annmodel.SomeInteger)
def test_list_of_str0(self): str0 = annmodel.SomeString(no_nul=True) def os_execve(l): pass register_external(os_execve, [[str0]], None) def f(l): return os_execve(l) policy = AnnotatorPolicy() policy.allow_someobjects = False a = RPythonAnnotator(policy=policy) a.build_types(f, [[str]]) # Does not raise assert a.translator.config.translation.check_str_without_nul == False # Now enable the str0 check, and try again with a similar function a.translator.config.translation.check_str_without_nul = True def g(l): return os_execve(l) raises(Exception, a.build_types, g, [[str]]) a.build_types(g, [[str0]]) # Does not raise
def test_compile_timer(): policy = AnnotatorPolicy() policy.allow_someobjects = False f_compiled = compile(timer_user, [], annotatorpolicy=policy) f_compiled(expected_extra_mallocs=2)