[pypy-svn] r33962 - in pypy/dist/pypy: jit/timeshifter/test lang/automata lang/automata/test

rxe at codespeak.net rxe at codespeak.net
Tue Oct 31 16:05:20 CET 2006


Author: rxe
Date: Tue Oct 31 16:05:15 2006
New Revision: 33962

Added:
   pypy/dist/pypy/lang/automata/   (props changed)
   pypy/dist/pypy/lang/automata/__init__.py   (contents, props changed)
   pypy/dist/pypy/lang/automata/dfa.py   (contents, props changed)
   pypy/dist/pypy/lang/automata/test/   (props changed)
   pypy/dist/pypy/lang/automata/test/test_dfa.py   (contents, props changed)
Modified:
   pypy/dist/pypy/jit/timeshifter/test/test_portal.py
Log:
add a first and extremely hackish attempt at a dfa engine, with a failing test to jit/.../test_portal.py - (arigo, rxe)

Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_portal.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_portal.py	Tue Oct 31 16:05:15 2006
@@ -9,6 +9,7 @@
 
 from pypy.rpython.objectmodel import hint
 
+import py.test
 
 class TestPortal(object):
     from pypy.jit.codegen.llgraph.rgenop import RGenOp
@@ -115,3 +116,15 @@
                                          policy=P_NOVIRTUAL)
         assert res == 68
         self.check_insns(int_floordiv=1, int_mul=0)
+
+    def test_dfa_compile(self):
+        py.test.skip("fails with debug_fatalerror() for some unknown reason")
+        from pypy.lang.automata.dfa import getautomaton, convertdfa, recognizetable
+        def main(gets):
+            a = getautomaton()
+            dfatable = convertdfa(a)
+            s = ["aaaaaaaaaab", "aaaa"][gets]
+            return recognizetable(dfatable, s)
+
+        res = self.timeshift_from_portal(main, recognizetable, [0], policy=P_NOVIRTUAL)
+        assert res >= 0

Added: pypy/dist/pypy/lang/automata/__init__.py
==============================================================================

Added: pypy/dist/pypy/lang/automata/dfa.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/automata/dfa.py	Tue Oct 31 16:05:15 2006
@@ -0,0 +1,143 @@
+" a very stripped down versio of cfbolz's algorithm/automaton module "
+
+from pypy.rpython.objectmodel import hint
+from pypy.rpython.lltypesystem.lltype import GcArray, Signed, malloc
+
+class LexerError(Exception):
+    def __init__(self, input, state, index):
+        self.input = input
+        self.state = state
+        self.index = index
+        self.args = (input, state, index)
+
+class DFA(object):
+    def __init__(self, num_states=0, transitions=None, final_states=None,
+                 names=None):
+        self.num_states = 0
+        if transitions is None:
+            transitions = {}
+        if final_states is None:
+            final_states = {}
+        if names is None:
+            names = []
+        self.transitions = transitions
+        self.final_states = final_states
+        self.names = names
+
+    def __repr__(self):
+        from pprint import pformat
+        return "DFA%s" % (pformat((
+            self.num_states, self.transitions, self.final_states,
+            self.names)), )
+
+    def add_state(self, name=None, final=False):
+        state = self.num_states
+        self.num_states += 1
+        if final:
+            self.final_states[state] = None
+        if name is None:
+            name = str(state)
+        self.names.append(name)
+        return self.num_states - 1
+
+    def add_transition(self, state, input, next_state):
+        self.transitions[state, input] = next_state
+
+    def get_transition(self, state, input):
+        return self.transitions[state, input]
+
+    def contains(self, (state, input)):
+        return (state, input) in self.transitions
+
+    def get_all_chars(self):
+        all_chars = {}
+        for state, input in self.transitions:
+            all_chars.add(input)
+        return all_chars
+
+    def get_runner(self):
+        return DFARunner(self)
+
+def getautomaton():
+    # simple example of handcrafted dfa
+    a = DFA()
+    s0 = a.add_state("start")
+    s1 = a.add_state()
+    s2 = a.add_state(final=True)
+    a.add_transition(s0, "a", s0) 
+    a.add_transition(s0, "c", s1) 
+    a.add_transition(s0, "b", s2) 
+    a.add_transition(s1, "b", s2) 
+    return a
+
+def recognize(automaton, s):
+    state = 0
+    try:
+        for char in s:
+            state = automaton.get_transition(state, char)
+    except KeyError:
+        return False
+
+    return state in automaton.final_states
+
+#________________________________________________________________________________
+
+# lower level version - more amenable to JIT
+
+# an earlier version to keep around, based of GcArray
+
+# A = GcArray(Signed, hints={'immutable': True})
+# def convertdfa(automaton):
+#     automaton.transitions
+#     size = automaton.num_states * 256
+#     dfatable = malloc(A, size)
+#     for ii in range(size):
+#         dfatable[ii] = -1
+#     for (s, c), r in automaton.transitions.items():
+#         dfatable[s * 256 + ord(c)] = r
+#     return dfatable
+
+# def recognizetable(dfatable, s):
+#     state = 0
+#     indx = 0
+#     while True:
+#         hint(None, global_merge_point=True)
+#         if indx >= len(s):
+#             break
+#         c = s[indx]
+#         c = hint(c, promote=True)
+#         state = dfatable[state * 256 + ord(c)]
+#         hint(state, concrete=True)
+#         if state < 0:
+#             break
+#         indx += 1
+#     return hint(state, variable=True)
+
+#________________________________________________________________________________
+
+# another lower level version - more amenable to JIT, this time converts
+# nice automata class to a table, represented as a big string 
+
+def convertdfa(automaton):
+    automaton.transitions
+    size = automaton.num_states * 256
+    dfatable = [chr(255)] * size
+    for (s, c), r in automaton.transitions.items():
+        dfatable[s * 256 + ord(c)] = chr(r)
+    return "".join(dfatable)
+
+def recognizetable(dfatable, s):
+    state = 0
+    indx = 0
+    while True:
+        hint(None, global_merge_point=True)
+        if indx >= len(s):
+            break
+        c = s[indx]
+        c = hint(c, promote=True)
+        state = ord(dfatable[state * 256 + ord(c)])
+        hint(state, concrete=True)
+        if state == 255:
+            break
+        indx += 1
+    return hint(state, variable=True)

Added: pypy/dist/pypy/lang/automata/test/test_dfa.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/automata/test/test_dfa.py	Tue Oct 31 16:05:15 2006
@@ -0,0 +1,93 @@
+import py
+from pypy import conftest
+
+from pypy.rpython.test.test_llinterp import interpret 
+from pypy.translator.translator import graphof
+from pypy.jit.timeshifter.test.test_timeshift import hannotate
+from pypy.jit.timeshifter.rtyper import HintRTyper
+from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.objspace.flow.model import checkgraph
+from pypy.rpython.objectmodel import hint
+
+from pypy.lang.automata.dfa import *
+
+def rundfa():
+    a = getautomaton()
+    assert recognize(a, "aaaaaaaaaab")
+    assert recognize(a, "b")
+    assert not recognize(a, "a")
+    assert not recognize(a, "xyza")
+    assert recognize(a, "aaaacb")
+
+def test_dfa_simple():
+    rundfa()
+
+def test_dfa_interp():
+    interpret(rundfa, [])
+
+def test_dfa_compiledummy():
+    def main(gets):
+        a = getautomaton()
+        dfatable = convertdfa(a)
+        s = ["aaaaaaaaaab", "aaaa"][gets]
+        return recognizetable(dfatable, s)
+    
+    interpret(main, [0])
+    
+# class TestWithPortal(object):
+#     from pypy.jit.codegen.llgraph.rgenop import RGenOp
+
+#     def setup_class(cls):
+#         cls._cache = {}
+#         cls._cache_order = []
+
+#     def teardown_class(cls):
+#         del cls._cache
+#         del cls._cache_order
+
+#     def timeshift_from_portal(self, main, portal, main_args,
+#                               inline=None, policy=None,
+#                               backendoptimize=False):
+
+#         key = main, portal, inline, policy, backendoptimize
+#         try:
+#             maingraph, rtyper = self._cache[key]
+#         except KeyError:
+#             if len(self._cache_order) >= 3:
+#                 del self._cache[self._cache_order.pop(0)]
+
+#             hs, ha, rtyper = hannotate(main, main_args, portal=portal,
+#                                        policy=policy, inline=inline,
+#                                        backendoptimize=backendoptimize)
+
+#             t = rtyper.annotator.translator
+#             maingraph = graphof(t, main)
+#             # make the timeshifted graphs
+#             hrtyper = HintRTyper(ha, rtyper, self.RGenOp)
+#             origportalgraph = graphof(t, portal)
+#             hrtyper.specialize(origportalgraph=origportalgraph,
+#                                view = conftest.option.view)
+
+#             for graph in ha.translator.graphs:
+#                 checkgraph(graph)
+#                 t.graphs.append(graph)
+
+#             if conftest.option.view:
+#                 t.view()
+
+#             self._cache[key] = maingraph, rtyper
+#             self._cache_order.append(key)
+
+#         llinterp = LLInterpreter(rtyper)
+#         return llinterp.eval_graph(maingraph, main_args)
+
+#     def test_dfa_compile(self):
+#         def main(gets):
+#             a = getautomaton()
+#             dfatable = convertdfa(a)
+#             s = ["aaaaaaaaaab", "aaaa"][gets]
+#             return recognizetable(dfatable, s)
+
+#         res = self.timeshift_from_portal(main, recognizetable, [0], policy=P_NOVIRTUAL)
+#         assert res >= 0



More information about the Pypy-commit mailing list