[pypy-svn] r34536 - in pypy/dist/pypy/lang/prolog: . builtin builtin/test interpreter interpreter/test

cfbolz at codespeak.net cfbolz at codespeak.net
Sun Nov 12 22:16:21 CET 2006


Author: cfbolz
Date: Sun Nov 12 22:16:10 2006
New Revision: 34536

Added:
   pypy/dist/pypy/lang/prolog/   (props changed)
   pypy/dist/pypy/lang/prolog/__init__.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/   (props changed)
   pypy/dist/pypy/lang/prolog/builtin/__init__.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/allsolution.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/atomconstruction.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/control.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/database.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/exception.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/formatting.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/metacall.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/parseraccess.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/register.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/source.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/termconstruction.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/test/   (props changed)
   pypy/dist/pypy/lang/prolog/builtin/test/__init__.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/test/test_formatting.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/type.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/builtin/unify.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/   (props changed)
   pypy/dist/pypy/lang/prolog/interpreter/__init__.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/choice.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/conftest.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/engine.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/error.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/helper.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/main.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/parsing.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/term.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/   (props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/__init__.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/dont_test_translate.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/test_standard.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/test/tool.py   (contents, props changed)
   pypy/dist/pypy/lang/prolog/interpreter/translatedmain.py   (contents, props changed)
Log:
import the prolog interpreter


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

Added: pypy/dist/pypy/lang/prolog/builtin/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/__init__.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,16 @@
+# all builtins
+builtins = {}
+
+# imports to register builtins
+import pypy.lang.prolog.builtin.allsolution
+import pypy.lang.prolog.builtin.arithmeticbuiltin
+import pypy.lang.prolog.builtin.atomconstruction
+import pypy.lang.prolog.builtin.control
+import pypy.lang.prolog.builtin.database
+import pypy.lang.prolog.builtin.exception
+import pypy.lang.prolog.builtin.formatting
+import pypy.lang.prolog.builtin.metacall
+import pypy.lang.prolog.builtin.parseraccess
+import pypy.lang.prolog.builtin.source
+import pypy.lang.prolog.builtin.termconstruction
+import pypy.lang.prolog.builtin.unify

Added: pypy/dist/pypy/lang/prolog/builtin/allsolution.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/allsolution.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,33 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# finding all solutions to a goal
+
+class FindallContinuation(engine.Continuation):
+    def __init__(self, template):
+        self.found = []
+        self.template = template
+
+    def call(self, engine):
+        clone = self.template.getvalue(engine.frame)
+        self.found.append(clone)
+        raise error.UnificationFailed()
+
+def impl_findall(engine, template, goal, bag):
+    oldstate = engine.frame.branch()
+    collector = FindallContinuation(template)
+    try:
+        engine.call(goal, collector)
+    except error.UnificationFailed:
+        engine.frame.revert(oldstate)
+    result = term.Atom("[]")
+    for i in range(len(collector.found) - 1, -1, -1):
+        copy = collector.found[i]
+        d = {}
+        copy = copy.clone_compress_vars(d, engine.frame.maxvar())
+        engine.frame.extend(len(d))
+        result = term.Term(".", [copy, result])
+    bag.unify(result, engine.frame)
+expose_builtin(impl_findall, "findall", unwrap_spec=['raw', 'callable', 'raw'])

Added: pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,51 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# arithmetic
+
+
+def impl_between(engine, lower, upper, varorint, continuation):
+    if isinstance(varorint, term.Var):
+        for i in range(lower, upper):
+            oldstate = engine.frame.branch()
+            try:
+                varorint.unify(term.Number(i), engine.frame)
+                return continuation.call(engine)
+            except error.UnificationFailed:
+                engine.frame.revert(oldstate)
+        varorint.unify(term.Number(upper), engine.frame)
+        return continuation.call(engine)
+    else:
+        integer = helper.unwrap_int(varorint)
+        if not (lower <= integer <= upper):
+            raise error.UnificationFailed
+    return continuation.call(engine)
+expose_builtin(impl_between, "between", unwrap_spec=["int", "int", "obj"],
+               handles_continuation=True)
+
+def impl_is(engine, var, num):
+    var.unify(num, engine.frame)
+expose_builtin(impl_is, "is", unwrap_spec=["raw", "arithmetic"])
+
+for ext, prolog, python in [("eq", "=:=", "=="),
+                            ("ne", "=\\=", "!="),
+                            ("lt", "<", "<"),
+                            ("le", "=<", "<="),
+                            ("gt", ">", ">"),
+                            ("ge", ">=", ">=")]:
+    exec py.code.Source("""
+def impl_arith_%s(engine, num1, num2):
+    eq = False
+    if isinstance(num1, term.Number):
+        if isinstance(num2, term.Number):
+            eq = num1.num %s num2.num
+    elif isinstance(num1, term.Float):
+        if isinstance(num2, term.Float):
+            eq = num1.num %s num2.num
+    if not eq:
+        raise error.UnificationFailed()""" % (ext, python, python)).compile()
+    expose_builtin(globals()["impl_arith_%s" % (ext, )], prolog,
+                   unwrap_spec=["arithmetic", "arithmetic"])
+ 

Added: pypy/dist/pypy/lang/prolog/builtin/atomconstruction.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/atomconstruction.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,125 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# analysing and construction atoms
+
+def impl_atom_concat(engine, a1, a2, result, continuation):
+    if isinstance(a1, term.Var):
+        if isinstance(a2, term.Var):
+            # nondeterministic splitting of result
+            r = helper.convert_to_str(result)
+            for i in range(len(r) + 1):
+                oldstate = engine.frame.branch()
+                try:
+                    a1.unify(term.Atom(r[:i]), engine.frame)
+                    a2.unify(term.Atom(r[i:]), engine.frame)
+                    return continuation.call(engine)
+                except error.UnificationFailed:
+                    engine.frame.revert(oldstate)
+            raise error.UnificationFailed()
+        else:
+            s2 = helper.convert_to_str(a2)
+            r = helper.convert_to_str(result)
+            if r.endswith(s2):
+                stop = len(r) - len(s2)
+                assert stop > 0
+                a1.unify(term.Atom(r[:stop]), engine.frame)
+            else:
+                raise error.UnificationFailed()
+    else:
+        s1 = helper.convert_to_str(a1)
+        if isinstance(a2, term.Var):
+            r = helper.convert_to_str(result)
+            if r.startswith(s1):
+                a2.unify(term.Atom(r[len(s1):]), engine.frame)
+            else:
+                raise error.UnificationFailed()
+        else:
+            s2 = helper.convert_to_str(a2)
+            result.unify(term.Atom(s1 + s2), engine.frame)
+    return continuation.call(engine)
+expose_builtin(impl_atom_concat, "atom_concat",
+               unwrap_spec=["obj", "obj", "obj"],
+               handles_continuation=True)
+
+def impl_atom_length(engine, s, length):
+    if not (isinstance(length, term.Var) or isinstance(length, term.Number)):
+        error.throw_type_error("integer", length)
+    term.Number(len(s)).unify(length, engine.frame)
+expose_builtin(impl_atom_length, "atom_length", unwrap_spec = ["atom", "obj"])
+
+def impl_sub_atom(engine, s, before, length, after, sub, continuation):
+    # XXX can possibly be optimized
+    if isinstance(length, term.Var):
+        startlength = 0
+        stoplength = len(s) + 1
+    else:
+        startlength = helper.unwrap_int(length)
+        stoplength = startlength + 1
+        if startlength < 0:
+            startlength = 0
+            stoplength = len(s) + 1
+    if isinstance(before, term.Var):
+        startbefore = 0
+        stopbefore = len(s) + 1
+    else:
+        startbefore = helper.unwrap_int(before)
+        stopbefore = startbefore + 1
+        if startbefore < 0:
+            startbefore = 0
+            stopbefore = len(s) + 1
+    if not isinstance(sub, term.Var):
+        s1 = helper.unwrap_atom(sub)
+        if len(s1) >= stoplength or len(s1) < startlength:
+            raise error.UnificationFailed()
+        i = s.find(s1)
+        if not startbefore <= i < stopbefore:
+            raise error.UnificationFailed()
+        if not startlength <= len(s1) < stoplength:
+            raise error.UnificationFailed()
+    if isinstance(after, term.Var):
+        for b in range(startbefore, stopbefore):
+            for l in range(startlength, stoplength):
+                if l + b > len(s):
+                    continue
+                oldstate = engine.frame.branch()
+                try:
+                    try:
+                        before.unify(term.Number(b), engine.frame)
+                        after.unify(term.Number(len(s) - l - b), engine.frame)
+                        length.unify(term.Number(l), engine.frame)
+                        sub.unify(term.Atom(s[b:b + l]), engine.frame)
+                        return continuation.call(engine)
+                    except:
+                        engine.frame.revert(oldstate)
+                        raise
+                except error.UnificationFailed:
+                    pass
+    else:
+        a = helper.unwrap_int(after)
+        for l in range(startlength, stoplength):
+            b = len(s) - l - a
+            assert b >= 0
+            if l + b > len(s):
+                continue
+            oldstate = engine.frame.branch()
+            try:
+                try:
+                    before.unify(term.Number(b), engine.frame)
+                    after.unify(term.Number(a), engine.frame)
+                    length.unify(term.Number(l), engine.frame)
+                    sub.unify(term.Atom(s[b:b + l]), engine.frame)
+                    return continuation.call(engine)
+                    return None
+                except:
+                    engine.frame.revert(oldstate)
+                    raise
+            except error.UnificationFailed:
+                pass
+    raise error.UnificationFailed()
+expose_builtin(impl_sub_atom, "sub_atom",
+               unwrap_spec=["atom", "obj", "obj", "obj", "obj"],
+               handles_continuation=True)
+

Added: pypy/dist/pypy/lang/prolog/builtin/control.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/control.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,83 @@
+import py
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# control predicates
+
+def impl_fail(engine):
+    raise error.UnificationFailed()
+expose_builtin(impl_fail, "fail", unwrap_spec=[])
+
+def impl_true(engine):
+    pass
+expose_builtin(impl_true, "true", unwrap_spec=[])
+
+def impl_repeat(engine, continuation):
+    while 1:
+        try:
+            return continuation.call(engine)
+        except error.UnificationFailed:
+            pass
+expose_builtin(impl_repeat, "repeat", unwrap_spec=[], handles_continuation=True)
+
+def impl_cut(engine, continuation):
+    raise error.CutException(continuation)
+expose_builtin(impl_cut, "!", unwrap_spec=[],
+               handles_continuation=True)
+
+class AndContinuation(engine.Continuation):
+    def __init__(self, next_call, continuation):
+        self.next_call = next_call
+        self.continuation = continuation
+
+    def call(self, engine):
+        next_call = self.next_call.dereference(engine.frame)
+        if isinstance(next_call, term.Var):
+            error.throw_instantiation_error()
+        if not isinstance(next_call, term.Callable):
+            error.throw_type_error('callable', next_call)
+        return engine.call(next_call, self.continuation)
+
+def impl_and(engine, call1, call2, continuation):
+    if not isinstance(call2, term.Var) and not isinstance(call2, term.Callable):
+        error.throw_type_error('callable', call2)
+    and_continuation = AndContinuation(call2, continuation)
+    return engine.call(call1, and_continuation)
+expose_builtin(impl_and, ",", unwrap_spec=["callable", "raw"],
+               handles_continuation=True)
+
+def impl_or(engine, call1, call2, continuation):
+    oldstate = engine.frame.branch()
+    try:
+        return engine.call(call1, continuation)
+    except error.UnificationFailed:
+        engine.frame.revert(oldstate)
+    return engine.call(call2, continuation)
+
+expose_builtin(impl_or, ";", unwrap_spec=["callable", "callable"],
+               handles_continuation=True)
+
+def impl_not(engine, call):
+    try:
+        try:
+            engine.call(call)
+        except error.CutException, e:
+            engine.continue_after_cut(e.continuation)
+    except error.UnificationFailed:
+        return None
+    raise error.UnificationFailed()
+expose_builtin(impl_not, ["not", "\\+"], unwrap_spec=["callable"])
+
+def impl_if(engine, if_clause, then_clause, continuation):
+    oldstate = engine.frame.branch()
+    try:
+        engine.call(if_clause)
+    except error.UnificationFailed:
+        engine.frame.revert(oldstate)
+        raise
+    return engine.call(helper.ensure_callable(then_clause), continuation)
+expose_builtin(impl_if, "->", unwrap_spec=["callable", "raw"],
+               handles_continuation=True)
+

Added: pypy/dist/pypy/lang/prolog/builtin/database.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/database.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,60 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# database
+
+def impl_abolish(engine, predicate):
+    from pypy.lang.prolog.builtin import builtins
+    name, arity = helper.unwrap_predicate_indicator(predicate)
+    if arity < 0:
+        error.throw_domain_error("not_less_than_zero", term.Number(arity))
+    signature = name + "/" + str(arity)
+    if signature in builtins:
+        error.throw_permission_error("modify", "static_procedure",
+                                     predicate)
+    if signature in engine.signature2rules:
+        del engine.signature2rules[signature]
+expose_builtin(impl_abolish, "abolish", unwrap_spec=["obj"])
+
+def impl_assert(engine, rule):
+    engine.add_rule(rule.getvalue(engine.frame))
+expose_builtin(impl_assert, ["assert", "assertz"], unwrap_spec=["callable"])
+
+def impl_asserta(engine, rule):
+    engine.add_rule(rule.getvalue(engine.frame), end=False)
+expose_builtin(impl_asserta, "asserta", unwrap_spec=["callable"])
+
+
+def impl_retract(engine, pattern):
+    from pypy.lang.prolog.builtin import builtins
+    if isinstance(pattern, term.Term) and pattern.name == ":-":
+        head = helper.ensure_callable(pattern.args[0])
+        body = helper.ensure_callable(pattern.args[1])
+    else:
+        head = pattern
+        body = None
+    if head.signature in builtins:
+        assert isinstance(head, term.Callable)
+        error.throw_permission_error("modify", "static_procedure", 
+                                     head.get_prolog_signature())
+    rules = engine.signature2rules.get(head.signature, [])
+    for i in range(len(rules)):
+        rule = rules[i]
+        oldstate = engine.frame.branch()
+        # standardizing apart
+        try:
+            deleted_body = rule.clone_and_unify_head(engine.frame, head)
+            if body is not None:
+                body.unify(deleted_body, engine.frame)
+        except error.UnificationFailed:
+            engine.frame.revert(oldstate)
+        else:
+            del rules[i]
+            break
+    else:
+        raise error.UnificationFailed()
+expose_builtin(impl_retract, "retract", unwrap_spec=["callable"])
+
+

Added: pypy/dist/pypy/lang/prolog/builtin/exception.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/exception.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,47 @@
+import py
+from pypy.lang.prolog.interpreter import engine as enginemod, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+from pypy.lang.prolog.builtin.type import impl_ground
+
+# ___________________________________________________________________
+# exception handling
+
+def impl_catch(engine, goal, catcher, recover, continuation):
+    catching_continuation = enginemod.LimitedScopeContinuation(continuation)
+    old_state = engine.frame.branch()
+    try:
+        return engine.call(goal, catching_continuation)
+    except error.CatchableError, e:
+        if not catching_continuation.scope_active:
+            raise
+        exc_term = e.term.getvalue(engine.frame)
+        engine.frame.revert(old_state)
+        d = {}
+        exc_term = exc_term.clone_compress_vars(d, engine.frame.maxvar())
+        engine.frame.extend(len(d))
+        try:
+            impl_ground(engine, exc_term)
+        except error.UnificationFailed:
+            raise error.UncatchableError(
+                "not implemented: catching of non-ground terms")
+        try:
+            catcher.unify(exc_term, engine.frame)
+        except error.UnificationFailed:
+            if isinstance(e, error.UserError):
+                raise error.UserError(exc_term)
+            if isinstance(e, error.CatchableError):
+                raise error.CatchableError(exc_term)
+        return engine.call(recover, continuation)
+expose_builtin(impl_catch, "catch", unwrap_spec=["callable", "obj", "callable"],
+               handles_continuation=True)
+
+def impl_throw(engine, exc):
+    try:
+        impl_ground(engine, exc)
+    except error.UnificationFailed:
+        raise error.UncatchableError(
+            "not implemented: raising of non-ground terms")
+    raise error.UserError(exc)
+expose_builtin(impl_throw, "throw", unwrap_spec=["obj"])
+
+

Added: pypy/dist/pypy/lang/prolog/builtin/formatting.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/formatting.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,144 @@
+import os
+import string
+
+from pypy.lang.prolog.interpreter.term import Term, Float, Number, Var, Atom
+from pypy.lang.prolog.interpreter import error, helper, parsing
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+class TermFormatter(object):
+    def __init__(self, engine, quoted=False, max_depth=0,
+                 ignore_ops=False):
+        self.engine = engine
+        self.quoted = quoted
+        self.max_depth = max_depth
+        self.ignore_ops = ignore_ops
+        self.curr_depth = 0
+        self._make_reverse_op_mapping()
+    
+    def from_option_list(engine, options):
+        # XXX add numbervars support
+        quoted = False
+        max_depth = 0
+        ignore_ops = False
+        number_vars = False
+        for option in options:
+            if (not isinstance(option, Term) or len(option.args) != 1):
+                error.throw_domain_error('write_option', option)
+            arg = option.args[0]
+            if option.name == "max_depth":
+                try:
+                    max_depth = helper.unwrap_int(arg)
+                except error.CatchableError:
+                    error.throw_domain_error('write_option', option)
+            elif (not isinstance(arg, Atom) or
+                (arg.name != "true" and arg.name != "false")):
+                error.throw_domain_error('write_option', option)
+                assert 0, "unreachable"
+            elif option.name == "quoted":
+                quoted = arg.name == "true"
+            elif option.name == "ignore_ops":
+                ignore_ops = arg.name == "true"
+        return TermFormatter(engine, quoted, max_depth, ignore_ops)
+    from_option_list = staticmethod(from_option_list)
+
+    def format(self, term):
+        self.curr_depth += 1
+        if self.max_depth > 0 and self.curr_depth > self.max_depth:
+            return "..."
+        if isinstance(term, Atom):
+            return self.format_atom(term.name)
+        elif isinstance(term, Number):
+            return self.format_number(term)
+        elif isinstance(term, Float):
+            return self.format_float(term)
+        elif isinstance(term, Term):
+            return self.format_term(term)
+        elif isinstance(term, Var):
+            return self.format_var(term)
+
+    def format_atom(self, s):
+        from algorithm.automaton.deterministic import LexerError
+        if self.quoted:
+            try:
+                tokens = parsing.lexer.tokenize(s)
+                if (len(tokens) == 1 and tokens[0][0] == 'ATOM' and
+                    tokens[0][1] == s):
+                    return s
+            except LexerError:
+                pass
+            return "'%s'" % (s, )
+        return s
+
+    def format_number(self, num):
+        return str(num.num)
+
+    def format_float(self, num):
+        return str(num.num)
+
+    def format_var(self, var):
+        return "_G%s" % (var.index, )
+
+
+    def format_term_normally(self, term):
+        return "%s(%s)" % (self.format_atom(term.name),
+                           ", ".join([self.format(a) for a in term.args]))
+
+    def format_term(self, term):
+        if self.ignore_ops:
+            return self.format_term_normally(term)
+        else:
+            return self.format_with_ops(term)[1]
+
+    def format_with_ops(self, term):
+        if not isinstance(term, Term):
+            return (0, self.format(term))
+        if term.signature == "./2":
+            result = ["["]
+            while isinstance(term, Term) and term.signature == "./2":
+                first = term.args[0]
+                second = term.args[1]
+                result.append(self.format(first))
+                result.append(", ")
+                term = second
+            if isinstance(term, Atom) and term.name == "[]":
+                result[-1] = "]"
+            else:
+                result[-1] = "|"
+                result.append(self.format(term))
+                result.append("]")
+            return (0, "".join(result))
+        if (len(term.args), term.name) not in self.op_mapping:
+            return (0, self.format_term_normally(term))
+        form, prec = self.op_mapping[(len(term.args), term.name)]
+        result = []
+        assert 0 <= len(term.args) <= 2
+        curr_index = 0
+        for c in form:
+            if c == "f":
+                result.append(self.format_atom(term.name))
+            else:
+                childprec, child = self.format_with_ops(term.args[curr_index])
+                parentheses = (c == "x" and childprec >= prec or
+                               c == "y" and childprec > prec)
+                if parentheses:
+                    result.append("(")
+                    result.append(child)
+                    result.append(")")
+                else:
+                    result.append(child)
+                curr_index += 1
+        assert curr_index == len(term.args)
+        return (prec, "".join(result))
+
+    def _make_reverse_op_mapping(self):
+        m = {}
+        for prec, allops in self.engine.getoperations():
+            for form, ops in allops:
+                for op in ops:
+                    m[len(form) - 1, op] = (form, prec)
+        self.op_mapping = m
+
+def impl_write_term(engine, term, options):
+    f = TermFormatter.from_option_list(engine, options)
+    os.write(1, f.format(term))
+expose_builtin(impl_write_term, "write_term", unwrap_spec=["concrete", "list"])

Added: pypy/dist/pypy/lang/prolog/builtin/metacall.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/metacall.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,21 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# meta-call predicates
+
+def impl_call(engine, call, continuation):
+    try:
+        return engine.call(call, continuation)
+    except error.CutException, e:
+        return e.continuation.call(engine)
+expose_builtin(impl_call, "call", unwrap_spec=["callable"],
+               handles_continuation=True)
+
+def impl_once(engine, clause, continuation):
+    engine.call(clause)
+    return continuation.call(engine)
+expose_builtin(impl_once, "once", unwrap_spec=["callable"],
+               handles_continuation=True)
+

Added: pypy/dist/pypy/lang/prolog/builtin/parseraccess.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/parseraccess.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,58 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# operators
+
+def impl_current_op(engine, precedence, typ, name, continuation):
+    for prec, allops in engine.getoperations():
+        for form, ops in allops:
+            for op in ops:
+                oldstate = engine.frame.branch()
+                try:
+                    precedence.unify(term.Number(prec), engine.frame)
+                    typ.unify(term.Atom(form), engine.frame)
+                    name.unify(term.Atom(op), engine.frame)
+                    return continuation.call(engine)
+                except error.UnificationFailed:
+                    engine.frame.revert(oldstate)
+    raise error.UnificationFailed()
+expose_builtin(impl_current_op, "current_op", unwrap_spec=["obj", "obj", "obj"],
+               handles_continuation=True)
+
+def impl_op(engine, precedence, typ, name):
+    from pypy.lang.prolog.interpreter import parsing
+    if engine.operations is None:
+        engine.operations = parsing.make_default_operations()
+    operations = engine.operations
+    precedence_to_ops = {}
+    for prec, allops in operations:
+        precedence_to_ops[prec] = allops
+        for form, ops in allops:
+            try:
+                index = ops.index(name)
+                del ops[index]
+            except ValueError:
+                pass
+    if precedence != 0:
+        if precedence in precedence_to_ops:
+            allops = precedence_to_ops[precedence]
+            for form, ops in allops:
+                if form == typ:
+                    ops.append(name)
+                    break
+            else:
+                allops.append((typ, [name]))
+        else:
+            for i in range(len(operations)):
+                (prec, allops) = operations[i]
+                if precedence > prec:
+                    operations.insert(i, (precedence, [(typ, [name])]))
+                    break
+            else:
+                operations.append((precedence, [(typ, [name])]))
+    engine.parser = parsing.make_parser_at_runtime(engine.operations)
+expose_builtin(impl_op, "op", unwrap_spec=["int", "atom", "atom"])
+
+

Added: pypy/dist/pypy/lang/prolog/builtin/register.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/register.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,72 @@
+import py
+from pypy.lang.prolog.interpreter import arithmetic
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin import builtins
+
+from pypy.rpython.objectmodel import we_are_translated
+
+def expose_builtin(func, name, unwrap_spec=None, handles_continuation=False,
+                   translatable=True):
+    if isinstance(name, list):
+        expose_as = name
+        name = name[0]
+    else:
+        expose_as = [name]
+    if not name.isalnum():
+        name = func.func_name
+    funcname = "wrap_%s_%s" % (name, len(unwrap_spec))
+    code = ["def %s(engine, query, continuation):" % (funcname, )]
+    if not translatable:
+        code.append("    if we_are_translated():")
+        code.append("        raise error.UncatchableError('does not work in translated version')")
+    subargs = ["engine"]
+    for i, spec in enumerate(unwrap_spec):
+        varname = "var%s" % (i, )
+        subargs.append(varname)
+        if spec in ("obj", "callable", "int", "atom", "arithmetic"):
+            code.append("    %s = query.args[%s].dereference(engine.frame)" %
+                        (varname, i))
+        elif spec in ("concrete", "list"):
+            code.append("    %s = query.args[%s].getvalue(engine.frame)" %
+                        (varname, i))
+        if spec in ("callable", "int", "atom", "arithmetic", "list"):
+            code.append(
+                "    if isinstance(%s, term.Var):" % (varname,))
+            code.append(
+                "        error.throw_instantiation_error()")
+        if spec == "obj":
+            pass
+        elif spec == "concrete":
+            pass
+        elif spec == "callable":
+            code.append(
+                "    if not isinstance(%s, term.Callable):" % (varname,))
+            code.append(
+                "        error.throw_type_error('callable', %s)" % (varname,))
+        elif spec == "raw":
+            code.append("    %s = query.args[%s]" % (varname, i))
+        elif spec == "int":
+            code.append("    %s = helper.unwrap_int(%s)" % (varname, varname))
+        elif spec == "atom":
+            code.append("    %s = helper.unwrap_atom(%s)" % (varname, varname))
+        elif spec == "arithmetic":
+            code.append("    %s = arithmetic.eval_arithmetic(engine, %s)" %
+                        (varname, varname))
+        elif spec == "list":
+            code.append("    %s = helper.unwrap_list(%s)" % (varname, varname))
+        else:
+            assert 0, "not implemented " + spec
+    if handles_continuation:
+        subargs.append("continuation")
+    call = "    result = %s(%s)" % (func.func_name, ", ".join(subargs))
+    code.append(call)
+    if not handles_continuation:
+        code.append("    return continuation.call(engine)")
+    miniglobals = globals().copy()
+    miniglobals[func.func_name] = func
+    exec py.code.Source("\n".join(code)).compile() in miniglobals
+    for name in expose_as:
+        signature = "%s/%s" % (name, len(unwrap_spec))
+        builtins[signature] = miniglobals[funcname]
+

Added: pypy/dist/pypy/lang/prolog/builtin/source.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/source.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,34 @@
+import py
+from pypy.lang.prolog.interpreter import arithmetic
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.interpreter.error import UnificationFailed, FunctionNotFound
+from pypy.rpython.objectmodel import we_are_translated
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+
+# ___________________________________________________________________
+# loading prolog source files
+
+def impl_consult(engine, var):
+    import os
+    if isinstance(var, term.Atom):
+        try:
+            fd = os.open(var.name, os.O_RDONLY, 0777)
+        except OSError, e:
+            error.throw_existence_error("source_sink", var)
+            assert 0, "unreachable" # make the flow space happy
+        try:
+            content = []
+            while 1:
+                s = os.read(fd, 4096)
+                if not s:
+                    break
+                content.append(s)
+            file_content = "".join(content)
+        finally:
+            os.close(fd)
+        engine.runstring(file_content)
+expose_builtin(impl_consult, "consult", unwrap_spec=["obj"])
+
+

Added: pypy/dist/pypy/lang/prolog/builtin/termconstruction.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/termconstruction.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,100 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# analysing and construction terms
+
+def impl_functor(engine, t, functor, arity):
+    if helper.is_atomic(t):
+        functor.unify(t, engine.frame)
+        arity.unify(term.Number(0), engine.frame)
+    elif isinstance(t, term.Term):
+        functor.unify(term.Atom(t.name), engine.frame)
+        arity.unify(term.Number(len(t.args)), engine.frame)
+    elif isinstance(t, term.Var):
+        if isinstance(functor, term.Var):
+            error.throw_instantiation_error()
+        elif isinstance(functor, term.Var):
+            error.throw_instantiation_error()
+        a = helper.unwrap_int(arity)
+        if a < 0:
+            error.throw_domain_error("not_less_than_zero", arity)
+        else:
+            functor = helper.ensure_atomic(functor)
+            if a == 0:
+                t.unify(helper.ensure_atomic(functor), engine.frame)
+            else:
+                name = helper.unwrap_atom(functor)
+                start = engine.frame.needed_vars
+                engine.frame.extend(a)
+                t.unify(
+                    term.Term(name,
+                              [term.Var(i) for i in range(start, start + a)]),
+                    engine.frame)
+expose_builtin(impl_functor, "functor", unwrap_spec=["obj", "obj", "obj"])
+
+def impl_arg(engine, first, second, third, continuation):
+    if isinstance(second, term.Var):
+        error.throw_instantiation_error()
+    if isinstance(second, term.Atom):
+        raise error.UnificationFailed()
+    if not isinstance(second, term.Term):
+        error.throw_type_error("compound", second)
+    if isinstance(first, term.Var):
+        for i in range(len(second.args)):
+            arg = second.args[i]
+            oldstate = engine.frame.branch()
+            try:
+                third.unify(arg, engine.frame)
+                first.unify(term.Number(i + 1), engine.frame)
+                return continuation.call(engine)
+            except error.UnificationFailed:
+                engine.frame.revert(oldstate)
+        raise error.UnificationFailed()
+    elif isinstance(first, term.Number):
+        num = first.num
+        if num == 0:
+            raise error.UnificationFailed
+        if num < 0:
+            error.throw_domain_error("not_less_than_zero", first)
+        if num > len(second.args):
+            raise error.UnificationFailed()
+        arg = second.args[num - 1]
+        third.unify(arg, engine.frame)
+    else:
+        error.throw_type_error("integer", first)
+    return continuation.call(engine)
+expose_builtin(impl_arg, "arg", unwrap_spec=["obj", "obj", "obj"],
+               handles_continuation=True)
+
+def impl_univ(engine, first, second):
+    if not isinstance(first, term.Var):
+        if isinstance(first, term.Term):
+            l = [term.Atom(first.name)] + first.args
+        else:
+            l = [first]
+        u1 = helper.wrap_list(l)
+        if not isinstance(second, term.Var):
+            u1.unify(second, engine.frame)
+        else:
+            u1.unify(second, engine.frame)
+    else:
+        if isinstance(second, term.Var):
+            error.throw_instantiation_error()
+        else:
+            l = helper.unwrap_list(second)
+            head = l[0]
+            if not isinstance(head, term.Atom):
+                error.throw_type_error("atom", head)
+            term.Term(head.name, l[1:]).unify(first, engine.frame)
+expose_builtin(impl_univ, "=..", unwrap_spec=["obj", "obj"])
+
+def impl_copy_term(engine, interm, outterm):
+    d = {}
+    copy = interm.clone_compress_vars(d, engine.frame.maxvar())
+    engine.frame.extend(len(d))
+    outterm.unify(copy, engine.frame)
+expose_builtin(impl_copy_term, "copy_term", unwrap_spec=["obj", "obj"])
+
+

Added: pypy/dist/pypy/lang/prolog/builtin/test/__init__.py
==============================================================================

Added: pypy/dist/pypy/lang/prolog/builtin/test/test_formatting.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/test/test_formatting.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,21 @@
+from pypy.lang.prolog.builtin import formatting
+from pypy.lang.prolog.interpreter.parsing import parse_query_term
+from pypy.lang.prolog.interpreter.engine import Engine
+
+def test_list():
+    f = formatting.TermFormatter(Engine(), quoted=False, ignore_ops=False)
+    t = parse_query_term("[1, 2, 3, 4, 5 | X].")
+    assert f.format(t) == "[1, 2, 3, 4, 5|_G0]"
+    t = parse_query_term("[a, b, 'A$%%$$'|[]].")
+    assert f.format(t) == "[a, b, A$%%$$]"
+    t = parse_query_term("'.'(a, b, c).")
+    assert f.format(t) == ".(a, b, c)"
+
+def test_op_formatting():
+    f = formatting.TermFormatter(Engine(), quoted=False, ignore_ops=False)
+    t = parse_query_term("'+'(1, 2).")
+    assert f.format(t) == "1+2"
+    t = parse_query_term("'+'(1, *(3, 2)).")
+    assert f.format(t) == "1+3*2"
+    t = parse_query_term("'*'(1, *(3, 2)).")
+    assert f.format(t) == "1*(3*2)"

Added: pypy/dist/pypy/lang/prolog/builtin/type.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/type.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,64 @@
+import py
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# type verifications
+
+def impl_nonvar(engine, var):
+    if isinstance(var, term.Var):
+        raise error.UnificationFailed()
+expose_builtin(impl_nonvar, "nonvar", unwrap_spec=["obj"])
+
+def impl_var(engine, var):
+    if not isinstance(var, term.Var):
+        raise error.UnificationFailed()
+expose_builtin(impl_var, "var", unwrap_spec=["obj"])
+
+def impl_integer(engine, var):
+    if isinstance(var, term.Var) or not isinstance(var, term.Number):
+        raise error.UnificationFailed()
+expose_builtin(impl_integer, "integer", unwrap_spec=["obj"])
+
+def impl_float(engine, var):
+    if isinstance(var, term.Var) or not isinstance(var, term.Float):
+        raise error.UnificationFailed()
+expose_builtin(impl_float, "float", unwrap_spec=["obj"])
+
+def impl_number(engine, var):
+    if (isinstance(var, term.Var) or
+        (not isinstance(var, term.Number) and not
+         isinstance(var, term.Float))):
+        raise error.UnificationFailed()
+expose_builtin(impl_number, "number", unwrap_spec=["obj"])
+
+def impl_atom(engine, var):
+    if isinstance(var, term.Var) or not isinstance(var, term.Atom):
+        raise error.UnificationFailed()
+expose_builtin(impl_atom, "atom", unwrap_spec=["obj"])
+
+def impl_atomic(engine, var):
+    if helper.is_atomic(var):
+        return
+    raise error.UnificationFailed()
+expose_builtin(impl_atomic, "atomic", unwrap_spec=["obj"])
+
+def impl_compound(engine, var):
+    if isinstance(var, term.Var) or not isinstance(var, term.Term):
+        raise error.UnificationFailed()
+expose_builtin(impl_compound, "compound", unwrap_spec=["obj"])
+
+def impl_callable(engine, var):
+    if not helper.is_callable(var, engine):
+        raise error.UnificationFailed()
+expose_builtin(impl_callable, "callable", unwrap_spec=["obj"])
+
+def impl_ground(engine, var):
+    if isinstance(var, term.Var):
+        raise error.UnificationFailed()
+    if isinstance(var, term.Term):
+        for arg in var.args:
+            impl_ground(engine, arg)
+expose_builtin(impl_ground, "ground", unwrap_spec=["concrete"])
+
+

Added: pypy/dist/pypy/lang/prolog/builtin/unify.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/builtin/unify.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,41 @@
+import py
+from pypy.lang.prolog.interpreter import arithmetic
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.builtin.register import expose_builtin
+
+# ___________________________________________________________________
+# comparison and unification of terms
+
+def impl_unify(engine, obj1, obj2):
+    obj1.unify(obj2, engine.frame)
+expose_builtin(impl_unify, "=", unwrap_spec=["raw", "raw"])
+
+def impl_unify_with_occurs_check(engine, obj1, obj2):
+    obj1.unify(obj2, engine.frame, occurs_check=True)
+expose_builtin(impl_unify_with_occurs_check, "unify_with_occurs_check",
+               unwrap_spec=["raw", "raw"])
+
+def impl_does_not_unify(engine, obj1, obj2):
+    try:
+        obj1.unify(obj2, engine.frame)
+    except error.UnificationFailed:
+        return
+    raise error.UnificationFailed()
+expose_builtin(impl_does_not_unify, "\\=", unwrap_spec=["raw", "raw"])
+
+
+for ext, prolog, python in [("eq", "==", "== 0"),
+                            ("ne", "\\==", "!= 0"),
+                            ("lt", "@<", "== -1"),
+                            ("le", "@=<", "!= 1"),
+                            ("gt", "@>", "== 1"),
+                            ("ge", "@>=", "!= -1")]:
+    exec py.code.Source("""
+def impl_standard_comparison_%s(engine, obj1, obj2):
+    c = term.cmp_standard_order(obj1, obj2, engine.frame)
+    if not c %s:
+        raise error.UnificationFailed()""" % (ext, python)).compile()
+    expose_builtin(globals()["impl_standard_comparison_%s" % (ext, )], prolog,
+                   unwrap_spec=["obj", "obj"])
+ 

Added: pypy/dist/pypy/lang/prolog/interpreter/__init__.py
==============================================================================

Added: pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,87 @@
+import py
+import math
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter import engine, helper, term, error
+from pypy.lang.prolog.interpreter.error import UnificationFailed, FunctionNotFound
+from pypy.rlib.rarithmetic import intmask
+
+arithmetic_functions = {}
+
+pattern_to_function = {}
+
+def wrap_builtin_operation(pattern, unwrap_spec, can_overflow):
+    code = ["def f(engine, query):"]
+    for i, spec in enumerate(unwrap_spec):
+        varname = "var%s" % (i, )
+        code.append(
+            "    %s = eval_arithmetic(engine, query.args[%s])" % (varname, i))
+        code.append(
+            "    v%s = 0" % (i, ))
+        code.append("    if isinstance(%s, term.Number):" % (varname, ))
+        code.append("        v%s = %s.num" % (i, varname))
+        if spec == "expr":
+            code.append("    elif isinstance(%s, term.Float):" % (varname, ))
+            code.append("        v%s = %s.num" % (i, varname))
+        code.append("    else:")
+        code.append("        error.throw_type_error('int', %s)" % (varname, ))
+    code.append("    return norm_float(%s)" % pattern)
+    miniglobals = globals().copy()
+    exec py.code.Source("\n".join(code)).compile() in miniglobals
+    return miniglobals['f']
+
+wrap_builtin_operation._annspecialcase_ = 'specialize:memo'
+
+def eval_arithmetic(engine, query):
+    query = query.getvalue(engine.frame)
+    if isinstance(query, term.Number):
+        return query
+    if isinstance(query, term.Float):
+        return norm_float(query.num)
+    if isinstance(query, term.Atom):
+        #XXX beautify that
+        if query.name == "pi":
+            return term.Float(math.pi)
+        if query.name == "e":
+            return term.Float(math.e)
+        raise error.UncatchableError("not implemented")
+    if isinstance(query, term.Term):
+        func = arithmetic_functions.get(query.signature, None)
+        if func is None:
+            error.throw_type_error("evaluable", query.get_prolog_signature())
+        return func(engine, query)
+    raise error.UncatchableError("not implemented")
+
+def norm_float(v):
+    if v == int(v):
+        return term.Number(int(v))
+    else:
+        return term.Float(v)
+
+simple_functions = [
+    ("+",                     ["expr", "expr"], "v0 + v1", True),
+    ("-",                     ["expr", "expr"], "v0 - v1", True),
+    ("*",                     ["expr", "expr"], "v0 * v1", True),
+    ("//",                    ["int",  "int"],  "v0 / v1", True),
+    ("**",                    ["expr", "expr"], "v0 ** v1", True),
+    (">>",                    ["int", "int"],   "v0 >> v1", False),
+    ("<<",                    ["int", "int"],   "intmask(v0 << v1)", False),
+    ("\\/",                   ["int", "int"],   "v0 | v1", False),
+    ("/\\",                   ["int", "int"],   "v0 & v1", False),
+    ("xor",                   ["int", "int"],   "v0 ^ v1", False),
+    ("mod",                   ["int", "int"],   "v0 % v1", False),
+    ("\\",                    ["int"],          "v0 ^ 0", False),
+    ("abs",                   ["expr"],         "abs(v0)", True),
+#    ("max",                   ["expr", "expr"], "max(v0, v1)", False),
+#    ("min",                   ["expr", "expr"], "min(v0, v1)", False),
+    ("round",                 ["expr"],         "int(v0 + 0.5)", False),
+    ("floor",                 ["expr"],         "math.floor(v0)", False),
+    ("ceiling",               ["expr"],         "math.ceil(v0)", False),
+    ("floor",                 ["expr"],         "math.floor(v0)", False),
+    ("float_fractional_part", ["expr"],         "v0 - int(v0)", False),
+    ("float_integer_part",    ["expr"],         "int(v0)", False),
+]
+
+for prolog_name, unwrap_spec, pattern, overflow in simple_functions:
+    f = wrap_builtin_operation(pattern, unwrap_spec, overflow)
+    signature = "%s/%s" % (prolog_name, len(unwrap_spec))
+    arithmetic_functions[signature] = f

Added: pypy/dist/pypy/lang/prolog/interpreter/choice.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/choice.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,102 @@
+import os
+import py
+
+from py.magic import greenlet
+from pypy.rpython.objectmodel import we_are_translated
+from pypy.rpython.rstack import yield_current_frame_to_caller
+from pypy.translator.c.test.test_stackless import StacklessTest
+
+from pypy.lang.prolog.interpreter.error import UnificationFailed, CutException
+
+def make_llframe(choice_point, func, args):
+    llframe = yield_current_frame_to_caller()
+    try:
+        choice_point.current = llframe
+        try:
+            func(*args)
+        except UnificationFailed:
+            choice_point.no_choice()
+        except Exception, e:
+            choice_point.exception = e
+        choice_point.switch_back()
+    except:
+        pass
+    os.write(0, "bad\n")
+    return llframe # will nexer be executed, help the translator
+make_llframe._annspecialcase_ = "specialize:arg(1)"
+
+class ChoicePoint(object):
+    def __init__(self, engine, continuation, stop_cut=False):
+        self._init_current()
+        self.engine = engine
+        self.oldstate = engine.frame.branch()
+        self.continuation = continuation
+        self.stop_cut = stop_cut
+        self.any_choice = True
+        self.exception = None
+
+    def _init_current(self):
+        if we_are_translated():
+            self.current = None
+        else:
+            self.current = greenlet.getcurrent()
+
+    def choose(self, last=False):
+        try:
+            self.do_continue()
+        except CutException, e:
+            if self.stop_cut:
+                self.continuation = e.continuation
+            else:
+                self.exception = e
+        except UnificationFailed:
+            self.engine.frame.revert(self.oldstate)
+            if last:
+                raise
+            return
+        self.switch_back()
+        assert 0
+
+    def chooselast(self):
+        self.do_continue()
+
+    def no_choice(self):
+        self.exception = UnificationFailed()
+
+    def switch(self, func, *args):
+        if we_are_translated():
+            llframe = make_llframe(self, func, args)
+            llframe.switch()
+        else:
+            g = greenlet(func)
+            try:
+                g.switch(*args)
+            except UnificationFailed:
+                self.no_choice()
+        if self.exception is not None:
+            raise self.exception
+    switch._annspecialcase_ = "specialize:arg(1)"
+
+    def switch_back(self):
+        self.current.switch()
+
+    def do_continue(self):
+        self.continuation.run(self.engine)
+
+class RuleChoicePoint(ChoicePoint):
+    def __init__(self, query, engine, continuation, stop_cut=False):
+        ChoicePoint.__init__(self, engine, continuation, stop_cut)
+        self.query = query
+        self.rule = None
+
+    def choose_rule(self, rule):
+        self.rule = rule
+        self.choose()
+
+    def choose_last_rule(self, rule):
+        self.rule = rule
+        self.chooselast()
+
+    def do_continue(self):
+        continuation = self.continuation
+        self.engine.try_rule(self.rule, self.query, continuation)

Added: pypy/dist/pypy/lang/prolog/interpreter/conftest.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/conftest.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,10 @@
+import py, sys
+
+rootdir = py.magic.autopath().dirpath()
+
+Option = py.test.Config.Option
+
+option = py.test.Config.addoptions("prolog options", 
+        Option('--slow', action="store_true", dest="slow", default=False,
+               help="view translation tests' flow graphs with Pygame"),
+    )

Added: pypy/dist/pypy/lang/prolog/interpreter/engine.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/engine.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,255 @@
+from pypy.lang.prolog.interpreter.term import Var, Term, Rule, Atom, debug_print, \
+    Callable
+from pypy.lang.prolog.interpreter.error import UnificationFailed, FunctionNotFound, \
+    CutException
+from pypy.lang.prolog.interpreter import error
+
+DEBUG = True
+
+class Continuation(object):
+    def call(self, engine):
+        pass
+
+DONOTHING = Continuation()
+
+class LimitedScopeContinuation(Continuation):
+    def __init__(self, continuation):
+        self.scope_active = True
+        self.continuation = continuation
+
+    def call(self, engine):
+        self.scope_active = False
+        return self.continuation.call(engine)
+
+START_NUMBER_OF_VARS = 4096
+
+
+class Frame(object):
+    def __init__(self):
+        self.vars = [None] * START_NUMBER_OF_VARS
+        self.trail = []
+        self.needed_vars = 0
+        self.last_branch = 0
+
+    def clear(self, length):
+        l = max(START_NUMBER_OF_VARS, length)
+        self.vars = [None] * l
+        self.needed_vars = length
+        self.last_branch = length
+        self.trail = []
+
+    def getvar(self, index):
+        return self.vars[index]
+
+    def setvar(self, index, val):
+        oldval = self.vars[index]
+        self.vars[index] = val
+        # only trail for variables that have a chance to get restored
+        # on the last choice point
+        if index < self.last_branch:
+            self.trail.append((index, oldval))
+
+    def branch(self):
+        old_last_branch = self.last_branch
+        self.last_branch = self.needed_vars
+        return len(self.trail), self.needed_vars, old_last_branch
+
+    def revert(self, state):
+        trails, length, old_last_branch = state
+        assert length == self.last_branch
+        for i in range(len(self.trail) - 1, trails - 1, -1):
+            index, val = self.trail[i]
+            if index >= length:
+                val = None
+            self.vars[index] = val
+        for i in range(length, self.needed_vars):
+            self.vars[i] = None
+        del self.trail[trails:]
+        self.needed_vars = length
+
+    def discard(self, state):
+        old_last_branch = state[2]
+        self.last_branch = old_last_branch
+
+    def extend(self, numvars):
+        if numvars:
+            self.needed_vars += numvars
+            newvars = max(0, numvars - (len(self.vars) - self.needed_vars))
+            if newvars == 0:
+                return
+            self.vars.extend([None] * (2 * newvars)) # allocate a bit more
+            assert self.needed_vars <= len(self.vars)
+
+    def maxvar(self):
+        return self.needed_vars
+
+class Engine(object):
+    def __init__(self):
+        self.frame = Frame()
+        self.signature2rules = {}
+        self.parser = None
+        self.operations = None
+    
+    def add_rule(self, rule, end=True):
+        from prolog import builtin
+        if DEBUG:
+            debug_print("add_rule", rule)
+        if isinstance(rule, Term):
+            if rule.name == ":-":
+                rule = Rule(rule.args[0], rule.args[1])
+            else:
+                rule = Rule(rule, None)
+            signature = rule.signature
+        elif isinstance(rule, Atom):
+            rule = Rule(rule, None)
+            signature = rule.signature
+        else:
+            error.throw_type_error("callable", rule)
+            assert 0, "unreachable" # XXX make annotator happy
+        if signature in builtin.builtins:
+            error.throw_permission_error(
+                "modify", "static_procedure", rule.head.get_prolog_signature())
+        # it's important to not update the list in place, because
+        # there might be references to it in the stack somewhere
+        rules = self.signature2rules.get(signature, [])
+        if end:
+            self.signature2rules[signature] = rules + [rule]
+        else:
+            self.signature2rules[signature] = [rule] + rules
+
+    def run(self, query, continuation=DONOTHING):
+        if not isinstance(query, Callable):
+            error.throw_type_error("callable", query)
+        vars = query.get_max_var() + 1
+        self.frame.clear(vars)
+        try:
+            return self.call(query, continuation)
+        except CutException, e:
+            self.continue_after_cut(e.continuation)
+
+    def _build_and_run(self, tree):
+        from pypy.lang.prolog.interpreter.parsing import TermBuilder
+        builder = TermBuilder()
+        term = builder.build_query(tree)
+        if isinstance(term, Term) and term.name == ":-" and len(term.args) == 1:
+            self.run(term.args[0])
+        else:
+            self.add_rule(term)
+        return self.parser
+
+    def runstring(self, s):
+        from pypy.lang.prolog.interpreter.parsing import parse_file
+        trees = parse_file(s, self.parser, Engine._build_and_run, self)
+
+    def call(self, query, continuation=DONOTHING):
+        assert isinstance(query, Callable)
+        from pypy.lang.prolog.builtin import builtins
+        if DEBUG:
+            debug_print("calling", query)
+        signature = query.signature
+        # check for builtins
+        builtin = builtins.get(signature, None)
+        if builtin is not None:
+            return builtin(self, query, continuation)
+        # do a real call
+        return self.user_call(query, continuation)
+
+    def user_call(self, query, continuation):
+        #import pdb; pdb.set_trace()
+        signature = query.signature
+        rules = self.signature2rules.get(signature, None)
+        if rules is None:
+            error.throw_existence_error(
+                "procedure", query.get_prolog_signature())
+        unify_hash = query.get_deeper_unify_hash(self.frame)
+        rule, i = self.find_applicable_rule(0, rules, query, unify_hash)
+        if rule is None:
+            # none of the rules apply
+            raise UnificationFailed()
+        oldstate = self.frame.branch()
+        while 1:
+            next, i = self.find_applicable_rule(i, rules, query, unify_hash)
+            if next is None:
+                self.frame.discard(oldstate)
+                break
+            if rule.contains_cut:
+                continuation = LimitedScopeContinuation(continuation)
+                try:
+                    result = self.try_rule(rule, query, continuation)
+                    self.frame.discard(oldstate)
+                    return result
+                except UnificationFailed:
+                    self.frame.revert(oldstate)
+                except CutException, e:
+                    if continuation.scope_active:
+                        return self.continue_after_cut(e.continuation,
+                                                       continuation)
+                    raise
+            else:
+                try:
+                    result = self.try_rule(rule, query, continuation)
+                    self.frame.discard(oldstate)
+                    return result
+                except UnificationFailed:
+                    self.frame.revert(oldstate)
+            rule = next
+        if rule.contains_cut:
+            continuation = LimitedScopeContinuation(continuation)
+            try:
+                return self.try_rule(rule, query, continuation)
+            except CutException, e:
+                if continuation.scope_active:
+                    self.continue_after_cut(e.continuation, continuation)
+                raise
+        return self.try_rule(rule, query, continuation)
+
+    def try_rule(self, rule, query, continuation=DONOTHING):
+        if DEBUG:
+            debug_print("trying rule", rule, query, self.frame.vars[:self.frame.needed_vars])
+        try:
+            # standardizing apart
+            nextcall = rule.clone_and_unify_head(self.frame, query)
+        except UnificationFailed:
+            if DEBUG:
+                debug_print("didn't work", rule, query, self.frame.vars[:self.frame.needed_vars])
+            raise
+        if DEBUG:
+            debug_print("worked", rule, query, self.frame.vars[:self.frame.needed_vars])
+        if nextcall is not None:
+            return self.call(nextcall, continuation)
+        return continuation.call(self)
+
+    def find_applicable_rule(self, startindex, rules, query, uh1):
+        i = startindex
+        while i < len(rules):
+            uh2 = rules[i].unify_hash
+            assert len(uh1) == len(uh2)
+            for j in range(len(uh1)):
+                if uh1[j] != 0 and uh2[j] != 0 and uh1[j] != uh2[j]:
+                    break
+            else:
+                return rules[i], i + 1
+            i += 1
+        return None, 0
+
+    def continue_after_cut(self, continuation, lsc=None):
+        while 1:
+            try:
+                return continuation.call(self)
+            except CutException, e:
+                if lsc is not None and not lsc.scope_active:
+                    raise
+                continuation = e.continuation
+
+    def parse(self, s):
+        from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder, lexer
+        builder = TermBuilder()
+        trees = parse_file(s, self.parser)
+        terms = builder.build_many(trees)
+        return terms, builder.var_to_pos
+
+    def getoperations(self):
+        from pypy.lang.prolog.interpreter.parsing import default_operations
+        if self.operations is None:
+            return default_operations
+        return self.operations

Added: pypy/dist/pypy/lang/prolog/interpreter/error.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/error.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,73 @@
+class PrologError(Exception):
+    pass
+
+class CatchableError(PrologError):
+    def __init__(self, errorterm):
+        from pypy.lang.prolog.interpreter import term
+        self.term = term.Term("error", [errorterm])
+
+class UserError(CatchableError):
+    def __init__(self, errorterm):
+        self.term = errorterm
+
+class UncatchableError(PrologError):
+    def __init__(self, message):
+        self.message = message
+
+class UnificationFailed(PrologError):
+    pass
+
+class FunctionNotFound(PrologError):
+    def __init__(self, signature):
+        self.signature = signature
+
+class CutException(PrologError):
+    def __init__(self, continuation):
+        self.continuation = continuation
+
+    pass
+
+def throw_instantiation_error():
+    from pypy.lang.prolog.interpreter import term
+    raise CatchableError(term.Atom("instantiation_error"))
+
+def throw_type_error(valid_type, obj):
+    from pypy.lang.prolog.interpreter import term
+    # valid types are:
+    # atom, atomic, byte, callable, character
+    # evaluable, in_byte, in_character, integer, list
+    # number, predicate_indicator, variable
+    from pypy.lang.prolog.interpreter import term
+    raise CatchableError(
+        term.Term("type_error", [term.Atom(valid_type), obj]))
+
+def throw_domain_error(valid_domain, obj):
+    from pypy.lang.prolog.interpreter import term
+    # valid domains are:
+    # character_code_list, close_option, flag_value, io_mode,
+    # not_empty_list, not_less_than_zero, operator_priority,
+    # operator_specifier, prolog_flag, read_option, source_sink,
+    # stream, stream_option, stream_or_alias, stream_position,
+    # stream_property, write_option
+    raise CatchableError(
+        term.Term("domain_error", [term.Atom(valid_domain), obj]))
+
+def throw_existence_error(object_type, obj):
+    from pypy.lang.prolog.interpreter import term
+    # valid types are:
+    # procedure, source_sink, stream
+    raise CatchableError(
+        term.Term("existence_error", [term.Atom(object_type), obj]))
+
+def throw_permission_error(operation, permission_type, obj):
+    from pypy.lang.prolog.interpreter import term
+    # valid operations are:
+    # access, create, input, modify, open, output, reposition 
+
+    # valid permission_types are:
+    # binary_stream, flag, operator, past_end_of_stream, private_procedure,
+    # static_procedure, source_sink, stream, text_stream. 
+    raise CatchableError(
+        term.Term("permission_error", [term.Atom(operation),
+                                       term.Atom(permission_type),
+                                       obj]))

Added: pypy/dist/pypy/lang/prolog/interpreter/helper.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/helper.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,76 @@
+""" Helper functions for dealing with prolog lists"""
+
+from pypy.lang.prolog.interpreter import term
+from pypy.lang.prolog.interpreter import error
+
+def wrap_list(python_list):
+    curr = term.Atom("[]")
+    for i in range(len(python_list) - 1, -1, -1):
+        curr = term.Term(".", [python_list[i], curr])
+    return curr
+
+def unwrap_list(prolog_list):
+    result = []
+    curr = prolog_list
+    while isinstance(curr, term.Term):
+        if not curr.name == ".":
+            error.throw_type_error("list", prolog_list)
+        result.append(curr.args[0])
+        curr = curr.args[1]
+    if isinstance(curr, term.Atom) and curr.name == "[]":
+        return result
+    error.throw_type_error("list", prolog_list)
+
+def is_callable(var, engine):
+    return isinstance(var, term.Callable)
+
+def ensure_callable(var):
+    if isinstance(var, term.Callable):
+        return var
+    error.throw_type_error("callable", var)
+
+def unwrap_int(obj):
+    if isinstance(obj, term.Number):
+        return obj.num
+    elif isinstance(obj, term.Float):
+        f = obj.num; i = int(f)
+        if f == i:
+            return i
+    error.throw_type_error('integer', obj)
+
+def unwrap_atom(obj):
+    if isinstance(obj, term.Atom):
+        return obj.name
+    error.throw_type_error('atom', obj)
+
+def unwrap_predicate_indicator(predicate):
+    if not isinstance(predicate, term.Term):
+        error.throw_type_error("predicate_indicator", predicate)
+        assert 0, "unreachable"
+    if not predicate.name == "/" or len(predicate.args) != 2:
+        error.throw_type_error("predicate_indicator", predicate)
+    name = unwrap_atom(predicate.args[0])
+    arity = unwrap_int(predicate.args[1])
+    return name, arity
+
+def ensure_atomic(obj):
+    if not is_atomic(obj):
+        error.throw_type_error('atomic', obj)
+    return obj
+
+def is_atomic(obj):
+    return (isinstance(obj, term.Atom) or isinstance(obj, term.Float) or 
+            isinstance(obj, term.Number))
+
+
+def convert_to_str(obj):
+    if isinstance(obj, term.Var):
+        error.throw_instantiation_error()
+    if isinstance(obj, term.Atom):
+        return obj.name
+    elif isinstance(obj, term.Number):
+        return str(obj.num)
+    elif isinstance(obj, term.Float):
+        return str(obj.num)
+    error.throw_type_error("atomic", obj)
+

Added: pypy/dist/pypy/lang/prolog/interpreter/main.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/main.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+import py
+import sys
+sys.path.append(str(py.magic.autopath().dirpath().dirpath()))
+
+from pypy.rlib.parsing.parsing import ParseError
+from pypy.rlib.parsing.deterministic import LexerError
+from pypy.lang.prolog.interpreter.parsing import parse_file, get_query_and_vars
+from pypy.lang.prolog.interpreter.parsing import get_engine
+from pypy.lang.prolog.interpreter.engine import Engine
+from pypy.lang.prolog.interpreter.engine import Continuation
+from pypy.lang.prolog.interpreter import error
+import pypy.lang.prolog.interpreter.term
+pypy.lang.prolog.interpreter.term.DEBUG = False
+
+import code
+
+helptext = """
+ ';':   redo
+ 'p':   print
+ 'h':   help
+ 
+"""
+
+class StopItNow(Exception):
+    pass
+
+class ContinueContinuation(Continuation):
+    def __init__(self, var_to_pos, write):
+        self.var_to_pos = var_to_pos
+        self.write = write
+
+    def call(self, engine):
+        self.write("yes\n")
+        var_representation(self.var_to_pos, engine, self.write)
+        while 1:
+            res = getch()
+            self.write(res+"\n")
+            if res in "\r\x04":
+                self.write("\n")
+                raise StopItNow()
+            if res in ";nr":
+                raise error.UnificationFailed
+            elif res in "h?":
+                self.write(helptext)
+            elif res in "p":
+                var_representation(self.var_to_pos, engine, self.write)
+            else:
+                self.write('unknown action. press "h" for help\n')
+
+def var_representation(var_to_pos, engine, write):
+    from pypy.lang.prolog.builtin.formatting import TermFormatter
+    f = TermFormatter(engine, quoted=True, max_depth=10)
+    vars = var_to_pos.items()
+    vars.sort()
+    frame = engine.frame
+    for var, real_var in vars:
+        if var.startswith("_"):
+            continue
+        val = real_var.getvalue(frame)
+        write("%s = %s\n" % (var, f.format(val)))
+
+class PrologConsole(code.InteractiveConsole):
+    def __init__(self, engine):
+        code.InteractiveConsole.__init__(self, {})
+        del self.__dict__['compile']
+        self.engine = engine
+
+    def compile(self, source, filename="<input>", symbol="single"):
+        try:
+            if not source.strip():
+                return None, None
+            return get_query_and_vars(source)
+        except ParseError, e:
+            #print e
+            # fake a Python syntax error :-)
+            absoffset = e.args[1][-1]
+            lines = source.split("\n")
+            curroffset = 0
+            for i, line in enumerate(lines):
+                if curroffset <= absoffset < curroffset + len(line) + 1:
+                    break
+                curroffset = curroffset + len(line) + 1
+            if source.strip().endswith("."):
+                raise SyntaxError(
+                    "syntax error",
+                    (filename, i+1, absoffset - curroffset, line))
+            return None
+        except LexerError, e:
+            # fake a Python syntax error
+            absoffset = e.index
+            lines = source.split("\n")
+            curroffset = 0
+            for i, line in enumerate(lines):
+                if curroffset <= absoffset < curroffset + len(line) + 1:
+                    break
+                curroffset = curroffset + len(line) + 1
+            raise SyntaxError(
+                "token error", (filename, i + 1, absoffset - curroffset, line))
+
+    def runcode(self, code):
+        try:
+            query, var_to_pos = code
+            if query is None:
+                return
+            self.engine.run(query, ContinueContinuation(var_to_pos, self.write))
+        except error.UnificationFailed:
+            self.write("no\n")
+        except error.CatchableError, e:
+            self.write("ERROR: ")
+            if e.term.args[0].name == "instantiation_error":
+                print e.term
+                self.write("arguments not sufficiently instantiated\n")
+            elif e.term.args[0].name == "existence_error":
+                print e.term
+                self.write("Undefined %s: %s\n" % (e.term.args[0].args[0],
+                                                   e.term.args[0].args[1]))
+            else:
+                self.write("of unknown type: %s\n" % (e.term, ))
+        except error.UncatchableError, e:
+            self.write("INTERNAL ERROR: %s\n" % (e.message, ))
+        except StopItNow:
+            self.write("yes\n")
+
+    def showtracebach(self):
+        self.write("traceback. boooring. nothing to see here")
+
+
+class _Getch(object):
+    """Gets a single character from standard input.  Does not echo to the
+screen."""
+    def __init__(self):
+        try:
+            import msvcrt
+            self.impl = self.get_windows
+        except ImportError:
+            try:
+                import tty, sys, termios
+	        self.impl = self.get_unix
+            except ImportError:
+                import Carbon, Carbon.Evt
+                self.impl = self.get_carbon
+
+    def __call__(self):
+        return self.impl()
+
+    def get_unix(self):
+        import sys, tty, termios
+        fd = sys.stdin.fileno()
+        old_settings = termios.tcgetattr(fd)
+        try:
+            tty.setraw(sys.stdin.fileno())
+            ch = sys.stdin.read(1)
+        finally:
+            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+        return ch
+
+    def get_windows(self):
+        import msvcrt
+        return msvcrt.getch()
+
+
+    def get_carbon(self):
+        """
+        A function which returns the current ASCII key that is down;
+        if no ASCII key is down, the null string is returned.  The
+        page http://www.mactech.com/macintosh-c/chap02-1.html was
+        very helpful in figuring out how to do this.
+        """
+        import Carbon
+        if Carbon.Evt.EventAvail(0x0008)[0]==0: # 0x0008 is the keyDownMask
+            return ''
+        else:
+            # The message (msg) contains the ASCII char which is
+            # extracted with the 0x000000FF charCodeMask; this
+            # number is converted to an ASCII character with chr() and
+            # returned
+            (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
+            return chr(msg & 0x000000FF)
+
+
+getch = _Getch()
+
+
+if __name__ == '__main__':
+    import readline
+    oldps1 = getattr(sys, "ps1", ">>> ")
+    oldps2 = getattr(sys, "ps2", "... ")
+    try:
+        sys.ps1 = ">?- "
+        sys.ps2 = "... "
+        if not len(sys.argv) == 2:
+            e = Engine()
+        else:
+            e = get_engine(py.path.local(sys.argv[1]).read())
+        c = PrologConsole(e)
+        c.interact("PyPy Prolog Console")
+    finally:
+        sys.ps1 = oldps1
+        sys.ps2 = oldps2
+    

Added: pypy/dist/pypy/lang/prolog/interpreter/parsing.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/parsing.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,3416 @@
+import py
+from pypy.rlib.parsing.ebnfparse import parse_ebnf
+from pypy.rlib.parsing.regexparse import parse_regex
+from pypy.rlib.parsing.lexer import Lexer, DummyLexer
+from pypy.rlib.parsing.deterministic import DFA
+from pypy.rlib.parsing.tree import Nonterminal, Symbol, RPythonVisitor
+from pypy.rlib.parsing.parsing import PackratParser, LazyParseTable, Rule
+from pypy.rlib.parsing.regex import StringExpression
+
+def make_regexes():
+    regexs = [
+        ("VAR", parse_regex("[A-Z_]([a-zA-Z0-9]|_)*|_")),
+        ("NUMBER", parse_regex("(0|[1-9][0-9]*)(\.[0-9]+)?")),
+        ("IGNORE", parse_regex(
+            "[ \\n\\t]|(/\\*[^\\*]*(\\*[^/][^\\*]*)*\\*/)|(%[^\\n]*)")),
+        ("ATOM", parse_regex("([a-z]([a-zA-Z0-9]|_)*)|('[^']*')|\[\]|!|\+|\-")),
+        ("(", parse_regex("\(")),
+        (")", parse_regex("\)")),
+        ("[", parse_regex("\[")),
+        ("]", parse_regex("\]")),
+        (".", parse_regex("\.")),
+        ("|", parse_regex("\|")),
+    ]
+    return zip(*regexs)
+
+basic_rules = [
+    Rule('query', [['toplevel_op_expr', '.', 'EOF']]),
+    Rule('fact', [['toplevel_op_expr', '.']]),
+    Rule('complexterm', [['ATOM', '(', 'toplevel_op_expr', ')'], ['expr']]),
+    Rule('expr',
+         [['VAR'],
+          ['NUMBER'],
+          ['+', 'NUMBER'],
+          ['-', 'NUMBER'],
+          ['ATOM'],
+          ['(', 'toplevel_op_expr', ')'],
+          ['listexpr'],
+          ]),
+    Rule('listexpr', [['[', 'listbody', ']']]),
+    Rule('listbody',
+         [['toplevel_op_expr', '|', 'toplevel_op_expr'],
+          ['toplevel_op_expr']])
+    ]
+
+# x: term with priority lower than f
+# y: term with priority lower or equal than f
+# possible types: xf yf xfx xfy yfx yfy fy fx
+# priorities: A > B
+#
+# binaryops
+# (1)  xfx:  A -> B f B | B
+# (2)  xfy:  A -> B f A | B
+# (3)  yfx:  A -> A f B | B
+# (4)  yfy:  A -> A f A | B
+#
+# unaryops
+# (5)  fx:   A -> f A | B
+# (6)  fy:   A -> f B | B
+# (7)  xf:   A -> B f | B
+# (8)  yf:   A -> A f | B
+
+def make_default_operations():
+    operations = [
+         (1200, [("xfx", ["-->", ":-"]),
+                 ("fx",  [":-", "?-"])]),
+         (1100, [("xfy", [";"])]),
+         (1050, [("xfy", ["->"])]),
+         (1000, [("xfy", [","])]),
+         (900,  [("fy",  ["\\+"]),
+                 ("fx",  ["~"])]),
+         (700,  [("xfx", ["<", "=", "=..", "=@=", "=:=", "=<", "==", "=\=", ">",
+                          ">=", "@<", "@=<", "@>", "@>=", "\=", "\==", "is"])]),
+         (600,  [("xfy", [":"])]),
+         (500,  [("yfx", ["+", "-", "/\\", "\\/", "xor"]),
+                 ( "fx", ["+", "-", "?", "\\"])]),
+         (400,  [("yfx", ["*", "/", "//", "<<", ">>", "mod", "rem"])]),
+         (200,  [("xfx", ["**"]), ("xfy", ["^"])]),
+         ]
+    return operations
+
+default_operations = make_default_operations()
+
+import sys
+sys.setrecursionlimit(10000)
+
+def make_from_form(form, op, x, y):
+    result = []
+    for c in form:
+        if c == 'x':
+            result.append(x)
+        if c == 'y':
+            result.append(y)
+        if c == 'f':
+            result.append(op)
+    return result
+
+def make_expansion(y, x, allops):
+    expansions = []
+    for form, ops in allops:
+        for op in ops:
+            expansion = make_from_form(form, op, x, y)
+            expansions.append(expansion)
+    expansions.append([x])
+    return expansions
+
+def eliminate_immediate_left_recursion(symbol, expansions):
+    newsymbol = "extra%s" % (symbol, )
+    newexpansions = []
+    with_recursion = [expansion for expansion in expansions
+                          if expansion[0] == symbol]
+    without_recursion = [expansion for expansion in expansions
+                              if expansion[0] != symbol]
+    expansions = [expansion + [newsymbol] for expansion in without_recursion]
+    newexpansions = [expansion[1:] + [newsymbol]
+                         for expansion in with_recursion]
+    newexpansions.append([])
+    return expansions, newexpansions, newsymbol
+
+def make_all_rules(standard_rules, operations=None):
+    if operations is None:
+        operations = default_operations
+    all_rules = standard_rules[:]
+    for i in range(len(operations)):
+        precedence, allops = operations[i]
+        if i == 0:
+            y = "toplevel_op_expr"
+        else:
+            y = "expr%s" % (precedence, )
+        if i != len(operations) - 1:
+            x = "expr%s" % (operations[i + 1][0], )
+        else:
+            x = "complexterm"
+        expansions = make_expansion(y, x, allops)
+        tup = eliminate_immediate_left_recursion(y, expansions)
+        expansions, extra_expansions, extra_symbol = tup
+        all_rules.append(Rule(extra_symbol, extra_expansions))
+        all_rules.append(Rule(y, expansions))
+    return all_rules
+
+def add_necessary_regexs(regexs, names, operations=None):
+    if operations is None:
+        operations = default_operations
+    regexs = regexs[:]
+    names = names[:]
+    for precedence, allops in operations:
+        for form, ops in allops:
+            for op in ops:
+                regexs.insert(-1, StringExpression(op))
+                names.insert(-1, "ATOM")
+    return regexs, names
+
+class PrologParseTable(LazyParseTable):
+    def terminal_equality(self, symbol, input):
+        if input[0] == "ATOM":
+            return symbol == "ATOM" or symbol == input[1]
+        return symbol == input[0]
+
+class PrologPackratParser(PackratParser):
+    def __init__(self, rules, startsymbol):
+        PackratParser.__init__(self, rules, startsymbol, PrologParseTable,
+                               check_for_left_recursion=False)
+
+def make_basic_rules():
+    names, regexs = make_regexes()
+    return basic_rules, names, regexs
+
+def make_parser(basic_rules, names, regexs):
+    real_rules = make_all_rules(basic_rules)
+#    for r in real_rules:
+#        print r
+    regexs, names = add_necessary_regexs(list(regexs), list(names))
+    lexer = Lexer(regexs, names, ignore=["IGNORE"])
+    parser_fact = PrologPackratParser(real_rules, "fact")
+    parser_query = PrologPackratParser(real_rules, "query")
+    return lexer, parser_fact, parser_query, basic_rules
+
+def make_all():
+    return make_parser(*make_basic_rules())
+
+def make_parser_at_runtime(operations):
+    real_rules = make_all_rules(basic_rules, operations)
+    parser_fact = PrologPackratParser(real_rules, "fact")
+    return parser_fact
+
+def _dummyfunc(arg, tree):
+    return parser_fact
+
+def parse_file(s, parser=None, callback=_dummyfunc, arg=None):
+    tokens = lexer.tokenize(s)
+    lines = []
+    line = []
+    for tok in tokens:
+        line.append(tok)
+        if tok[0] == ".":
+            lines.append(line)
+            line = []
+    if parser is None:
+        parser = parser_fact
+    trees = []
+    for line in lines:
+        tree = parser.parse(line, lazy=False)
+        if callback is not None:
+            # XXX ugh
+            parser = callback(arg, tree)
+            if parser is None:
+                parser = parser_fact
+        trees.append(tree)
+    return trees
+
+def parse_query(s):
+    tokens = lexer.tokenize(s, eof=True)
+    s = parser_query.parse(tokens, lazy=False)
+
+def parse_query_term(s):
+    return get_query_and_vars(s)[0]
+
+def get_query_and_vars(s):
+    tokens = lexer.tokenize(s, eof=True)
+    s = parser_query.parse(tokens, lazy=False)
+    builder = TermBuilder()
+    query = builder.build(s)
+    return query, builder.var_to_pos
+
+class OrderTransformer(object):
+    def transform(self, node):
+        if isinstance(node, Symbol):
+            return node
+        if isinstance(node, Nonterminal):
+            if len(node.children) == 1:
+                return Nonterminal(
+                    node.symbol, [self.transform(node.children[0])])
+            if len(node.children) == 2 or len(node.children) == 3:
+                left = node.children[-2]
+                right = node.children[-1]
+                if (isinstance(right, Nonterminal) and
+                    right.symbol.startswith("extraexpr")):
+                    if len(node.children) == 2:
+                        leftreplacement = self.transform(left)
+                    else:
+                        leftreplacement = Nonterminal(
+                            node.symbol,
+                            [self.transform(node.children[0]),
+                             self.transform(left)])
+                    children = [leftreplacement,
+                                self.transform(right.children[0]),
+                                self.transform(right.children[1])]
+
+                    newnode = Nonterminal(node.symbol, children)
+                    return self.transform_extra(right, newnode)
+            children = [self.transform(child) for child in node.children]
+            return Nonterminal(node.symbol, children)
+
+    def transform_extra(self, extranode, child):
+        symbol = extranode.symbol[5:]
+        if len(extranode.children) == 2:
+            return child
+        right = extranode.children[2]
+        assert isinstance(right, Nonterminal)
+        children = [child,
+                    self.transform(right.children[0]),
+                    self.transform(right.children[1])]
+        newnode = Nonterminal(symbol, children)
+        return self.transform_extra(right, newnode)
+
+class TermBuilder(RPythonVisitor):
+
+    def __init__(self):
+        self.var_to_pos = {}
+        self.freevar = 0
+
+    def build(self, s):
+        "NOT_RPYTHON"
+        if isinstance(s, list):
+            return self.build_many(s)
+        return self.build_query(s)
+
+    def build_many(self, trees):
+        ot = OrderTransformer()
+        facts = []
+        for tree in trees:
+            s = ot.transform(tree)
+            facts.append(self.build_fact(s))
+        return facts
+
+    def build_query(self, s):
+        ot = OrderTransformer()
+        s = ot.transform(s)
+        return self.visit(s.children[0])
+
+    def build_fact(self, node):
+        self.var_to_pos = {}
+        self.freevar = 0
+        return self.visit(node.children[0])
+
+    def visit(self, node):
+        node = self.find_first_interesting(node)
+        return self.dispatch(node)
+
+    def general_nonterminal_visit(self, node):
+        from pypy.lang.prolog.interpreter.term import Term, Number, Float
+        children = []
+        name = ""
+        for child in node.children:
+            if isinstance(child, Symbol):
+                name = self.general_symbol_visit(child).name
+            else:
+                children.append(child)
+        children = [self.visit(child) for child in children]
+        if len(children) == 1 and (name == "-" or name == "+"):
+            if name == "-":
+                factor = -1
+            else:
+                factor = 1
+            child = children[0]
+            if isinstance(child, Number):
+                return Number(factor * child.num)
+            if isinstance(child, Float):
+                return Float(factor * child.num)
+        return Term(name, children)
+
+    def build_list(self, node):
+        node = self.find_first_interesting(node)
+        if isinstance(node, Nonterminal):
+            child = node.children[1]
+            if (isinstance(child, Symbol) and
+                node.children[1].additional_info == ","):
+                element = self.visit(node.children[0])
+                l = self.build_list(node.children[2])
+                l.insert(0, element)
+                return l
+        return [self.visit(node)]
+
+    def find_first_interesting(self, node):
+        if isinstance(node, Nonterminal) and len(node.children) == 1:
+            return self.find_first_interesting(node.children[0])
+        return node
+
+    def general_symbol_visit(self, node):
+        from pypy.lang.prolog.interpreter.term import Atom
+        if node.additional_info.startswith("'"):
+            end = len(node.additional_info) - 1
+            assert end >= 0
+            name = unescape(node.additional_info[1:end])
+        else:
+            name = node.additional_info
+        return Atom(name)
+
+    def visit_VAR(self, node):
+        from pypy.lang.prolog.interpreter.term import Var
+        varname = node.additional_info
+        if varname == "_":
+            pos = self.freevar
+            self.freevar += 1
+            return Var(pos)
+        if varname in self.var_to_pos:
+            return self.var_to_pos[varname]
+        res = Var(self.freevar)
+        self.freevar += 1
+        self.var_to_pos[varname] = res
+        return res
+
+    def visit_NUMBER(self, node):
+        from pypy.lang.prolog.interpreter.term import Number, Float
+        s = node.additional_info
+        try:
+            return Number(int(s))
+        except ValueError:
+            # XXX float is not supported by the rtyper yet :-(
+            # return Float(float(s))
+            from pypy.objspace.std.strutil import break_up_float
+            from pypy.rlib.rarithmetic import parts_to_float
+            a, b, c, d = break_up_float(s)
+            return Float(parts_to_float(a, b, c, d))
+
+    def visit_complexterm(self, node):
+        from pypy.lang.prolog.interpreter.term import Term
+        name = self.general_symbol_visit(node.children[0]).name
+        children = self.build_list(node.children[2])
+        return Term(name, children)
+
+    def visit_expr(self, node):
+        from pypy.lang.prolog.interpreter.term import Number, Float
+        if node.children[0].additional_info == '-':
+            result = self.visit(node.children[1])
+            if isinstance(result, Number):
+                return Number(-result.num)
+            elif isinstance(result, Float):
+                return Float(-result.num)
+        return self.visit(node.children[1])
+
+    def visit_listexpr(self, node):
+        from pypy.lang.prolog.interpreter.term import Atom, Term
+        node = node.children[1]
+        if len(node.children) == 1:
+            l = self.build_list(node)
+            start = Atom("[]")
+        else:
+            l = self.build_list(node.children[0])
+            start = self.visit(node.children[2])
+        l.reverse()
+        curr = start
+        for elt in l:
+            curr = Term(".", [elt, curr])
+        return curr
+
+
+ESCAPES = {
+    "\\a": "\a",
+    "\\b": "\b",
+    "\\f": "\f",
+    "\\n": "\n",
+    "\\r": "\r",
+    "\\t": "\t",
+    "\\v": "\v",
+    "\\\\":  "\\"
+}
+
+
+def unescape(s):
+    if "\\" not in s:
+        return s
+    result = []
+    i = 0
+    escape = False
+    while i < len(s):
+        c = s[i]
+        if escape:
+            escape = False
+            f = "\\" + c
+            if f in ESCAPES:
+                result.append(ESCAPES[f])
+            else:
+                result.append(c)
+        elif c == "\\":
+            escape = True
+        else:
+            result.append(c)
+        i += 1
+    return "".join(result)
+
+def get_engine(source):
+    from pypy.lang.prolog.interpreter.engine import Engine
+    trees = parse_file(source)
+    builder = TermBuilder()
+    e = Engine()
+    for fact in builder.build_many(trees):
+        e.add_rule(fact)
+    return e
+
+# generated code between this line and its other occurence
+
+parser_fact = PrologPackratParser([Rule('query', [['toplevel_op_expr', '.', 'EOF']]),
+  Rule('fact', [['toplevel_op_expr', '.']]),
+  Rule('complexterm', [['ATOM', '(', 'toplevel_op_expr', ')'], ['expr']]),
+  Rule('expr', [['VAR'], ['NUMBER'], ['+', 'NUMBER'], ['-', 'NUMBER'], ['ATOM'], ['(', 'toplevel_op_expr', ')'], ['listexpr']]),
+  Rule('listexpr', [['[', 'listbody', ']']]),
+  Rule('listbody', [['toplevel_op_expr', '|', 'toplevel_op_expr'], ['toplevel_op_expr']]),
+  Rule('extratoplevel_op_expr', [[]]),
+  Rule('toplevel_op_expr', [['expr1100', '-->', 'expr1100', 'extratoplevel_op_expr'], ['expr1100', ':-', 'expr1100', 'extratoplevel_op_expr'], [':-', 'expr1100', 'extratoplevel_op_expr'], ['?-', 'expr1100', 'extratoplevel_op_expr'], ['expr1100', 'extratoplevel_op_expr']]),
+  Rule('extraexpr1100', [[]]),
+  Rule('expr1100', [['expr1050', ';', 'expr1100', 'extraexpr1100'], ['expr1050', 'extraexpr1100']]),
+  Rule('extraexpr1050', [[]]),
+  Rule('expr1050', [['expr1000', '->', 'expr1050', 'extraexpr1050'], ['expr1000', 'extraexpr1050']]),
+  Rule('extraexpr1000', [[]]),
+  Rule('expr1000', [['expr900', ',', 'expr1000', 'extraexpr1000'], ['expr900', 'extraexpr1000']]),
+  Rule('extraexpr900', [[]]),
+  Rule('expr900', [['\\+', 'expr900', 'extraexpr900'], ['~', 'expr700', 'extraexpr900'], ['expr700', 'extraexpr900']]),
+  Rule('extraexpr700', [[]]),
+  Rule('expr700', [['expr600', '<', 'expr600', 'extraexpr700'], ['expr600', '=', 'expr600', 'extraexpr700'], ['expr600', '=..', 'expr600', 'extraexpr700'], ['expr600', '=@=', 'expr600', 'extraexpr700'], ['expr600', '=:=', 'expr600', 'extraexpr700'], ['expr600', '=<', 'expr600', 'extraexpr700'], ['expr600', '==', 'expr600', 'extraexpr700'], ['expr600', '=\\=', 'expr600', 'extraexpr700'], ['expr600', '>', 'expr600', 'extraexpr700'], ['expr600', '>=', 'expr600', 'extraexpr700'], ['expr600', '@<', 'expr600', 'extraexpr700'], ['expr600', '@=<', 'expr600', 'extraexpr700'], ['expr600', '@>', 'expr600', 'extraexpr700'], ['expr600', '@>=', 'expr600', 'extraexpr700'], ['expr600', '\\=', 'expr600', 'extraexpr700'], ['expr600', '\\==', 'expr600', 'extraexpr700'], ['expr600', 'is', 'expr600', 'extraexpr700'], ['expr600', 'extraexpr700']]),
+  Rule('extraexpr600', [[]]),
+  Rule('expr600', [['expr500', ':', 'expr600', 'extraexpr600'], ['expr500', 'extraexpr600']]),
+  Rule('extraexpr500', [['+', 'expr400', 'extraexpr500'], ['-', 'expr400', 'extraexpr500'], ['/\\', 'expr400', 'extraexpr500'], ['\\/', 'expr400', 'extraexpr500'], ['xor', 'expr400', 'extraexpr500'], []]),
+  Rule('expr500', [['+', 'expr400', 'extraexpr500'], ['-', 'expr400', 'extraexpr500'], ['?', 'expr400', 'extraexpr500'], ['\\', 'expr400', 'extraexpr500'], ['expr400', 'extraexpr500']]),
+  Rule('extraexpr400', [['*', 'expr200', 'extraexpr400'], ['/', 'expr200', 'extraexpr400'], ['//', 'expr200', 'extraexpr400'], ['<<', 'expr200', 'extraexpr400'], ['>>', 'expr200', 'extraexpr400'], ['mod', 'expr200', 'extraexpr400'], ['rem', 'expr200', 'extraexpr400'], []]),
+  Rule('expr400', [['expr200', 'extraexpr400']]),
+  Rule('extraexpr200', [[]]),
+  Rule('expr200', [['complexterm', '**', 'complexterm', 'extraexpr200'], ['complexterm', '^', 'expr200', 'extraexpr200'], ['complexterm', 'extraexpr200']])],
+ 'fact')
+parser_query = PrologPackratParser([Rule('query', [['toplevel_op_expr', '.', 'EOF']]),
+  Rule('fact', [['toplevel_op_expr', '.']]),
+  Rule('complexterm', [['ATOM', '(', 'toplevel_op_expr', ')'], ['expr']]),
+  Rule('expr', [['VAR'], ['NUMBER'], ['+', 'NUMBER'], ['-', 'NUMBER'], ['ATOM'], ['(', 'toplevel_op_expr', ')'], ['listexpr']]),
+  Rule('listexpr', [['[', 'listbody', ']']]),
+  Rule('listbody', [['toplevel_op_expr', '|', 'toplevel_op_expr'], ['toplevel_op_expr']]),
+  Rule('extratoplevel_op_expr', [[]]),
+  Rule('toplevel_op_expr', [['expr1100', '-->', 'expr1100', 'extratoplevel_op_expr'], ['expr1100', ':-', 'expr1100', 'extratoplevel_op_expr'], [':-', 'expr1100', 'extratoplevel_op_expr'], ['?-', 'expr1100', 'extratoplevel_op_expr'], ['expr1100', 'extratoplevel_op_expr']]),
+  Rule('extraexpr1100', [[]]),
+  Rule('expr1100', [['expr1050', ';', 'expr1100', 'extraexpr1100'], ['expr1050', 'extraexpr1100']]),
+  Rule('extraexpr1050', [[]]),
+  Rule('expr1050', [['expr1000', '->', 'expr1050', 'extraexpr1050'], ['expr1000', 'extraexpr1050']]),
+  Rule('extraexpr1000', [[]]),
+  Rule('expr1000', [['expr900', ',', 'expr1000', 'extraexpr1000'], ['expr900', 'extraexpr1000']]),
+  Rule('extraexpr900', [[]]),
+  Rule('expr900', [['\\+', 'expr900', 'extraexpr900'], ['~', 'expr700', 'extraexpr900'], ['expr700', 'extraexpr900']]),
+  Rule('extraexpr700', [[]]),
+  Rule('expr700', [['expr600', '<', 'expr600', 'extraexpr700'], ['expr600', '=', 'expr600', 'extraexpr700'], ['expr600', '=..', 'expr600', 'extraexpr700'], ['expr600', '=@=', 'expr600', 'extraexpr700'], ['expr600', '=:=', 'expr600', 'extraexpr700'], ['expr600', '=<', 'expr600', 'extraexpr700'], ['expr600', '==', 'expr600', 'extraexpr700'], ['expr600', '=\\=', 'expr600', 'extraexpr700'], ['expr600', '>', 'expr600', 'extraexpr700'], ['expr600', '>=', 'expr600', 'extraexpr700'], ['expr600', '@<', 'expr600', 'extraexpr700'], ['expr600', '@=<', 'expr600', 'extraexpr700'], ['expr600', '@>', 'expr600', 'extraexpr700'], ['expr600', '@>=', 'expr600', 'extraexpr700'], ['expr600', '\\=', 'expr600', 'extraexpr700'], ['expr600', '\\==', 'expr600', 'extraexpr700'], ['expr600', 'is', 'expr600', 'extraexpr700'], ['expr600', 'extraexpr700']]),
+  Rule('extraexpr600', [[]]),
+  Rule('expr600', [['expr500', ':', 'expr600', 'extraexpr600'], ['expr500', 'extraexpr600']]),
+  Rule('extraexpr500', [['+', 'expr400', 'extraexpr500'], ['-', 'expr400', 'extraexpr500'], ['/\\', 'expr400', 'extraexpr500'], ['\\/', 'expr400', 'extraexpr500'], ['xor', 'expr400', 'extraexpr500'], []]),
+  Rule('expr500', [['+', 'expr400', 'extraexpr500'], ['-', 'expr400', 'extraexpr500'], ['?', 'expr400', 'extraexpr500'], ['\\', 'expr400', 'extraexpr500'], ['expr400', 'extraexpr500']]),
+  Rule('extraexpr400', [['*', 'expr200', 'extraexpr400'], ['/', 'expr200', 'extraexpr400'], ['//', 'expr200', 'extraexpr400'], ['<<', 'expr200', 'extraexpr400'], ['>>', 'expr200', 'extraexpr400'], ['mod', 'expr200', 'extraexpr400'], ['rem', 'expr200', 'extraexpr400'], []]),
+  Rule('expr400', [['expr200', 'extraexpr400']]),
+  Rule('extraexpr200', [[]]),
+  Rule('expr200', [['complexterm', '**', 'complexterm', 'extraexpr200'], ['complexterm', '^', 'expr200', 'extraexpr200'], ['complexterm', 'extraexpr200']])],
+ 'query')
+def recognize(runner, i):
+    assert i >= 0
+    input = runner.text
+    state = 0
+    while 1:
+        if state == 0:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 0
+                return ~i
+            if char == '\t':
+                state = 1
+            elif char == '\n':
+                state = 1
+            elif char == ' ':
+                state = 1
+            elif char == '(':
+                state = 2
+            elif char == ',':
+                state = 3
+            elif char == '0':
+                state = 4
+            elif '1' <= char <= '9':
+                state = 5
+            elif char == '<':
+                state = 6
+            elif char == '@':
+                state = 7
+            elif 'A' <= char <= 'Z':
+                state = 8
+            elif char == '_':
+                state = 8
+            elif char == '\\':
+                state = 9
+            elif 'a' <= char <= 'h':
+                state = 10
+            elif 'j' <= char <= 'l':
+                state = 10
+            elif 'n' <= char <= 'q':
+                state = 10
+            elif 's' <= char <= 'w':
+                state = 10
+            elif char == 'y':
+                state = 10
+            elif char == 'z':
+                state = 10
+            elif char == 'x':
+                state = 11
+            elif char == '|':
+                state = 12
+            elif char == "'":
+                state = 13
+            elif char == '+':
+                state = 14
+            elif char == '/':
+                state = 15
+            elif char == ';':
+                state = 16
+            elif char == '?':
+                state = 17
+            elif char == '[':
+                state = 18
+            elif char == '*':
+                state = 19
+            elif char == '.':
+                state = 20
+            elif char == ':':
+                state = 21
+            elif char == '>':
+                state = 22
+            elif char == '^':
+                state = 23
+            elif char == 'r':
+                state = 24
+            elif char == '~':
+                state = 25
+            elif char == '!':
+                state = 26
+            elif char == '%':
+                state = 27
+            elif char == ')':
+                state = 28
+            elif char == '-':
+                state = 29
+            elif char == '=':
+                state = 30
+            elif char == ']':
+                state = 31
+            elif char == 'i':
+                state = 32
+            elif char == 'm':
+                state = 33
+            else:
+                break
+        if state == 4:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 4
+                return i
+            if char == '.':
+                state = 73
+            else:
+                break
+        if state == 5:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 5
+                return i
+            if char == '.':
+                state = 73
+            elif '0' <= char <= '9':
+                state = 5
+                continue
+            else:
+                break
+        if state == 6:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 6
+                return i
+            if char == '<':
+                state = 72
+            else:
+                break
+        if state == 7:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 7
+                return ~i
+            if char == '=':
+                state = 67
+            elif char == '<':
+                state = 68
+            elif char == '>':
+                state = 69
+            else:
+                break
+        if state == 8:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 8
+                return i
+            if '0' <= char <= '9':
+                state = 8
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 8
+                continue
+            elif char == '_':
+                state = 8
+                continue
+            elif 'a' <= char <= 'z':
+                state = 8
+                continue
+            else:
+                break
+        if state == 9:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 9
+                return i
+            if char == '=':
+                state = 64
+            elif char == '/':
+                state = 65
+            elif char == '+':
+                state = 63
+            else:
+                break
+        if state == 10:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 10
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'z':
+                state = 10
+                continue
+            else:
+                break
+        if state == 11:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 11
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'n':
+                state = 10
+                continue
+            elif 'p' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 'o':
+                state = 61
+            else:
+                break
+        if state == 13:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 13
+                return ~i
+            if char == "'":
+                state = 26
+            elif '\x00' <= char <= '&':
+                state = 13
+                continue
+            elif '(' <= char <= '\xff':
+                state = 13
+                continue
+            else:
+                break
+        if state == 15:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 15
+                return i
+            if char == '*':
+                state = 57
+            elif char == '\\':
+                state = 58
+            elif char == '/':
+                state = 59
+            else:
+                break
+        if state == 17:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 17
+                return i
+            if char == '-':
+                state = 56
+            else:
+                break
+        if state == 18:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 18
+                return i
+            if char == ']':
+                state = 26
+            else:
+                break
+        if state == 19:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 19
+                return i
+            if char == '*':
+                state = 55
+            else:
+                break
+        if state == 21:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 21
+                return i
+            if char == '-':
+                state = 54
+            else:
+                break
+        if state == 22:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 22
+                return i
+            if char == '=':
+                state = 52
+            elif char == '>':
+                state = 53
+            else:
+                break
+        if state == 24:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 24
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'd':
+                state = 10
+                continue
+            elif 'f' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 'e':
+                state = 50
+            else:
+                break
+        if state == 27:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 27
+                return i
+            if '\x00' <= char <= '\t':
+                state = 27
+                continue
+            elif '\x0b' <= char <= '\xff':
+                state = 27
+                continue
+            else:
+                break
+        if state == 29:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 29
+                return i
+            if char == '>':
+                state = 48
+            elif char == '-':
+                state = 47
+            else:
+                break
+        if state == 30:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 30
+                return i
+            if char == '@':
+                state = 37
+            elif char == '<':
+                state = 38
+            elif char == '.':
+                state = 39
+            elif char == ':':
+                state = 40
+            elif char == '=':
+                state = 41
+            elif char == '\\':
+                state = 42
+            else:
+                break
+        if state == 32:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 32
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'r':
+                state = 10
+                continue
+            elif 't' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 's':
+                state = 36
+            else:
+                break
+        if state == 33:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 33
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'n':
+                state = 10
+                continue
+            elif 'p' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 'o':
+                state = 34
+            else:
+                break
+        if state == 34:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 34
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'c':
+                state = 10
+                continue
+            elif 'e' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 'd':
+                state = 35
+            else:
+                break
+        if state == 35:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 35
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'z':
+                state = 10
+                continue
+            else:
+                break
+        if state == 36:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 36
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'z':
+                state = 10
+                continue
+            else:
+                break
+        if state == 37:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 37
+                return ~i
+            if char == '=':
+                state = 46
+            else:
+                break
+        if state == 39:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 39
+                return ~i
+            if char == '.':
+                state = 45
+            else:
+                break
+        if state == 40:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 40
+                return ~i
+            if char == '=':
+                state = 44
+            else:
+                break
+        if state == 42:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 42
+                return ~i
+            if char == '=':
+                state = 43
+            else:
+                break
+        if state == 47:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 47
+                return ~i
+            if char == '>':
+                state = 49
+            else:
+                break
+        if state == 50:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 50
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'l':
+                state = 10
+                continue
+            elif 'n' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 'm':
+                state = 51
+            else:
+                break
+        if state == 51:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 51
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'z':
+                state = 10
+                continue
+            else:
+                break
+        if state == 57:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 57
+                return ~i
+            if '\x00' <= char <= ')':
+                state = 57
+                continue
+            elif '+' <= char <= '\xff':
+                state = 57
+                continue
+            elif char == '*':
+                state = 60
+            else:
+                break
+        if state == 60:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 60
+                return ~i
+            if '\x00' <= char <= '.':
+                state = 57
+                continue
+            elif '0' <= char <= '\xff':
+                state = 57
+                continue
+            elif char == '/':
+                state = 1
+            else:
+                break
+        if state == 61:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 61
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'q':
+                state = 10
+                continue
+            elif 's' <= char <= 'z':
+                state = 10
+                continue
+            elif char == 'r':
+                state = 62
+            else:
+                break
+        if state == 62:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 62
+                return i
+            if '0' <= char <= '9':
+                state = 10
+                continue
+            elif 'A' <= char <= 'Z':
+                state = 10
+                continue
+            elif char == '_':
+                state = 10
+                continue
+            elif 'a' <= char <= 'z':
+                state = 10
+                continue
+            else:
+                break
+        if state == 64:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 64
+                return i
+            if char == '=':
+                state = 66
+            else:
+                break
+        if state == 67:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 67
+                return ~i
+            if char == '<':
+                state = 71
+            else:
+                break
+        if state == 69:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 69
+                return i
+            if char == '=':
+                state = 70
+            else:
+                break
+        if state == 73:
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 73
+                return ~i
+            if '0' <= char <= '9':
+                state = 74
+            else:
+                break
+        if state == 74:
+            runner.last_matched_index = i - 1
+            runner.last_matched_state = state
+            if i < len(input):
+                char = input[i]
+                i += 1
+            else:
+                runner.state = 74
+                return i
+            if '0' <= char <= '9':
+                state = 74
+                continue
+            else:
+                break
+        runner.last_matched_state = state
+        runner.last_matched_index = i - 1
+        runner.state = state
+        if i == len(input):
+            return i
+        else:
+            return ~i
+        break
+    runner.state = state
+    return ~i
+lexer = DummyLexer(recognize, DFA(75,
+ {(0, '\t'): 1,
+  (0, '\n'): 1,
+  (0, ' '): 1,
+  (0, '!'): 26,
+  (0, '%'): 27,
+  (0, "'"): 13,
+  (0, '('): 2,
+  (0, ')'): 28,
+  (0, '*'): 19,
+  (0, '+'): 14,
+  (0, ','): 3,
+  (0, '-'): 29,
+  (0, '.'): 20,
+  (0, '/'): 15,
+  (0, '0'): 4,
+  (0, '1'): 5,
+  (0, '2'): 5,
+  (0, '3'): 5,
+  (0, '4'): 5,
+  (0, '5'): 5,
+  (0, '6'): 5,
+  (0, '7'): 5,
+  (0, '8'): 5,
+  (0, '9'): 5,
+  (0, ':'): 21,
+  (0, ';'): 16,
+  (0, '<'): 6,
+  (0, '='): 30,
+  (0, '>'): 22,
+  (0, '?'): 17,
+  (0, '@'): 7,
+  (0, 'A'): 8,
+  (0, 'B'): 8,
+  (0, 'C'): 8,
+  (0, 'D'): 8,
+  (0, 'E'): 8,
+  (0, 'F'): 8,
+  (0, 'G'): 8,
+  (0, 'H'): 8,
+  (0, 'I'): 8,
+  (0, 'J'): 8,
+  (0, 'K'): 8,
+  (0, 'L'): 8,
+  (0, 'M'): 8,
+  (0, 'N'): 8,
+  (0, 'O'): 8,
+  (0, 'P'): 8,
+  (0, 'Q'): 8,
+  (0, 'R'): 8,
+  (0, 'S'): 8,
+  (0, 'T'): 8,
+  (0, 'U'): 8,
+  (0, 'V'): 8,
+  (0, 'W'): 8,
+  (0, 'X'): 8,
+  (0, 'Y'): 8,
+  (0, 'Z'): 8,
+  (0, '['): 18,
+  (0, '\\'): 9,
+  (0, ']'): 31,
+  (0, '^'): 23,
+  (0, '_'): 8,
+  (0, 'a'): 10,
+  (0, 'b'): 10,
+  (0, 'c'): 10,
+  (0, 'd'): 10,
+  (0, 'e'): 10,
+  (0, 'f'): 10,
+  (0, 'g'): 10,
+  (0, 'h'): 10,
+  (0, 'i'): 32,
+  (0, 'j'): 10,
+  (0, 'k'): 10,
+  (0, 'l'): 10,
+  (0, 'm'): 33,
+  (0, 'n'): 10,
+  (0, 'o'): 10,
+  (0, 'p'): 10,
+  (0, 'q'): 10,
+  (0, 'r'): 24,
+  (0, 's'): 10,
+  (0, 't'): 10,
+  (0, 'u'): 10,
+  (0, 'v'): 10,
+  (0, 'w'): 10,
+  (0, 'x'): 11,
+  (0, 'y'): 10,
+  (0, 'z'): 10,
+  (0, '|'): 12,
+  (0, '~'): 25,
+  (4, '.'): 73,
+  (5, '.'): 73,
+  (5, '0'): 5,
+  (5, '1'): 5,
+  (5, '2'): 5,
+  (5, '3'): 5,
+  (5, '4'): 5,
+  (5, '5'): 5,
+  (5, '6'): 5,
+  (5, '7'): 5,
+  (5, '8'): 5,
+  (5, '9'): 5,
+  (6, '<'): 72,
+  (7, '<'): 68,
+  (7, '='): 67,
+  (7, '>'): 69,
+  (8, '0'): 8,
+  (8, '1'): 8,
+  (8, '2'): 8,
+  (8, '3'): 8,
+  (8, '4'): 8,
+  (8, '5'): 8,
+  (8, '6'): 8,
+  (8, '7'): 8,
+  (8, '8'): 8,
+  (8, '9'): 8,
+  (8, 'A'): 8,
+  (8, 'B'): 8,
+  (8, 'C'): 8,
+  (8, 'D'): 8,
+  (8, 'E'): 8,
+  (8, 'F'): 8,
+  (8, 'G'): 8,
+  (8, 'H'): 8,
+  (8, 'I'): 8,
+  (8, 'J'): 8,
+  (8, 'K'): 8,
+  (8, 'L'): 8,
+  (8, 'M'): 8,
+  (8, 'N'): 8,
+  (8, 'O'): 8,
+  (8, 'P'): 8,
+  (8, 'Q'): 8,
+  (8, 'R'): 8,
+  (8, 'S'): 8,
+  (8, 'T'): 8,
+  (8, 'U'): 8,
+  (8, 'V'): 8,
+  (8, 'W'): 8,
+  (8, 'X'): 8,
+  (8, 'Y'): 8,
+  (8, 'Z'): 8,
+  (8, '_'): 8,
+  (8, 'a'): 8,
+  (8, 'b'): 8,
+  (8, 'c'): 8,
+  (8, 'd'): 8,
+  (8, 'e'): 8,
+  (8, 'f'): 8,
+  (8, 'g'): 8,
+  (8, 'h'): 8,
+  (8, 'i'): 8,
+  (8, 'j'): 8,
+  (8, 'k'): 8,
+  (8, 'l'): 8,
+  (8, 'm'): 8,
+  (8, 'n'): 8,
+  (8, 'o'): 8,
+  (8, 'p'): 8,
+  (8, 'q'): 8,
+  (8, 'r'): 8,
+  (8, 's'): 8,
+  (8, 't'): 8,
+  (8, 'u'): 8,
+  (8, 'v'): 8,
+  (8, 'w'): 8,
+  (8, 'x'): 8,
+  (8, 'y'): 8,
+  (8, 'z'): 8,
+  (9, '+'): 63,
+  (9, '/'): 65,
+  (9, '='): 64,
+  (10, '0'): 10,
+  (10, '1'): 10,
+  (10, '2'): 10,
+  (10, '3'): 10,
+  (10, '4'): 10,
+  (10, '5'): 10,
+  (10, '6'): 10,
+  (10, '7'): 10,
+  (10, '8'): 10,
+  (10, '9'): 10,
+  (10, 'A'): 10,
+  (10, 'B'): 10,
+  (10, 'C'): 10,
+  (10, 'D'): 10,
+  (10, 'E'): 10,
+  (10, 'F'): 10,
+  (10, 'G'): 10,
+  (10, 'H'): 10,
+  (10, 'I'): 10,
+  (10, 'J'): 10,
+  (10, 'K'): 10,
+  (10, 'L'): 10,
+  (10, 'M'): 10,
+  (10, 'N'): 10,
+  (10, 'O'): 10,
+  (10, 'P'): 10,
+  (10, 'Q'): 10,
+  (10, 'R'): 10,
+  (10, 'S'): 10,
+  (10, 'T'): 10,
+  (10, 'U'): 10,
+  (10, 'V'): 10,
+  (10, 'W'): 10,
+  (10, 'X'): 10,
+  (10, 'Y'): 10,
+  (10, 'Z'): 10,
+  (10, '_'): 10,
+  (10, 'a'): 10,
+  (10, 'b'): 10,
+  (10, 'c'): 10,
+  (10, 'd'): 10,
+  (10, 'e'): 10,
+  (10, 'f'): 10,
+  (10, 'g'): 10,
+  (10, 'h'): 10,
+  (10, 'i'): 10,
+  (10, 'j'): 10,
+  (10, 'k'): 10,
+  (10, 'l'): 10,
+  (10, 'm'): 10,
+  (10, 'n'): 10,
+  (10, 'o'): 10,
+  (10, 'p'): 10,
+  (10, 'q'): 10,
+  (10, 'r'): 10,
+  (10, 's'): 10,
+  (10, 't'): 10,
+  (10, 'u'): 10,
+  (10, 'v'): 10,
+  (10, 'w'): 10,
+  (10, 'x'): 10,
+  (10, 'y'): 10,
+  (10, 'z'): 10,
+  (11, '0'): 10,
+  (11, '1'): 10,
+  (11, '2'): 10,
+  (11, '3'): 10,
+  (11, '4'): 10,
+  (11, '5'): 10,
+  (11, '6'): 10,
+  (11, '7'): 10,
+  (11, '8'): 10,
+  (11, '9'): 10,
+  (11, 'A'): 10,
+  (11, 'B'): 10,
+  (11, 'C'): 10,
+  (11, 'D'): 10,
+  (11, 'E'): 10,
+  (11, 'F'): 10,
+  (11, 'G'): 10,
+  (11, 'H'): 10,
+  (11, 'I'): 10,
+  (11, 'J'): 10,
+  (11, 'K'): 10,
+  (11, 'L'): 10,
+  (11, 'M'): 10,
+  (11, 'N'): 10,
+  (11, 'O'): 10,
+  (11, 'P'): 10,
+  (11, 'Q'): 10,
+  (11, 'R'): 10,
+  (11, 'S'): 10,
+  (11, 'T'): 10,
+  (11, 'U'): 10,
+  (11, 'V'): 10,
+  (11, 'W'): 10,
+  (11, 'X'): 10,
+  (11, 'Y'): 10,
+  (11, 'Z'): 10,
+  (11, '_'): 10,
+  (11, 'a'): 10,
+  (11, 'b'): 10,
+  (11, 'c'): 10,
+  (11, 'd'): 10,
+  (11, 'e'): 10,
+  (11, 'f'): 10,
+  (11, 'g'): 10,
+  (11, 'h'): 10,
+  (11, 'i'): 10,
+  (11, 'j'): 10,
+  (11, 'k'): 10,
+  (11, 'l'): 10,
+  (11, 'm'): 10,
+  (11, 'n'): 10,
+  (11, 'o'): 61,
+  (11, 'p'): 10,
+  (11, 'q'): 10,
+  (11, 'r'): 10,
+  (11, 's'): 10,
+  (11, 't'): 10,
+  (11, 'u'): 10,
+  (11, 'v'): 10,
+  (11, 'w'): 10,
+  (11, 'x'): 10,
+  (11, 'y'): 10,
+  (11, 'z'): 10,
+  (13, '\x00'): 13,
+  (13, '\x01'): 13,
+  (13, '\x02'): 13,
+  (13, '\x03'): 13,
+  (13, '\x04'): 13,
+  (13, '\x05'): 13,
+  (13, '\x06'): 13,
+  (13, '\x07'): 13,
+  (13, '\x08'): 13,
+  (13, '\t'): 13,
+  (13, '\n'): 13,
+  (13, '\x0b'): 13,
+  (13, '\x0c'): 13,
+  (13, '\r'): 13,
+  (13, '\x0e'): 13,
+  (13, '\x0f'): 13,
+  (13, '\x10'): 13,
+  (13, '\x11'): 13,
+  (13, '\x12'): 13,
+  (13, '\x13'): 13,
+  (13, '\x14'): 13,
+  (13, '\x15'): 13,
+  (13, '\x16'): 13,
+  (13, '\x17'): 13,
+  (13, '\x18'): 13,
+  (13, '\x19'): 13,
+  (13, '\x1a'): 13,
+  (13, '\x1b'): 13,
+  (13, '\x1c'): 13,
+  (13, '\x1d'): 13,
+  (13, '\x1e'): 13,
+  (13, '\x1f'): 13,
+  (13, ' '): 13,
+  (13, '!'): 13,
+  (13, '"'): 13,
+  (13, '#'): 13,
+  (13, '$'): 13,
+  (13, '%'): 13,
+  (13, '&'): 13,
+  (13, "'"): 26,
+  (13, '('): 13,
+  (13, ')'): 13,
+  (13, '*'): 13,
+  (13, '+'): 13,
+  (13, ','): 13,
+  (13, '-'): 13,
+  (13, '.'): 13,
+  (13, '/'): 13,
+  (13, '0'): 13,
+  (13, '1'): 13,
+  (13, '2'): 13,
+  (13, '3'): 13,
+  (13, '4'): 13,
+  (13, '5'): 13,
+  (13, '6'): 13,
+  (13, '7'): 13,
+  (13, '8'): 13,
+  (13, '9'): 13,
+  (13, ':'): 13,
+  (13, ';'): 13,
+  (13, '<'): 13,
+  (13, '='): 13,
+  (13, '>'): 13,
+  (13, '?'): 13,
+  (13, '@'): 13,
+  (13, 'A'): 13,
+  (13, 'B'): 13,
+  (13, 'C'): 13,
+  (13, 'D'): 13,
+  (13, 'E'): 13,
+  (13, 'F'): 13,
+  (13, 'G'): 13,
+  (13, 'H'): 13,
+  (13, 'I'): 13,
+  (13, 'J'): 13,
+  (13, 'K'): 13,
+  (13, 'L'): 13,
+  (13, 'M'): 13,
+  (13, 'N'): 13,
+  (13, 'O'): 13,
+  (13, 'P'): 13,
+  (13, 'Q'): 13,
+  (13, 'R'): 13,
+  (13, 'S'): 13,
+  (13, 'T'): 13,
+  (13, 'U'): 13,
+  (13, 'V'): 13,
+  (13, 'W'): 13,
+  (13, 'X'): 13,
+  (13, 'Y'): 13,
+  (13, 'Z'): 13,
+  (13, '['): 13,
+  (13, '\\'): 13,
+  (13, ']'): 13,
+  (13, '^'): 13,
+  (13, '_'): 13,
+  (13, '`'): 13,
+  (13, 'a'): 13,
+  (13, 'b'): 13,
+  (13, 'c'): 13,
+  (13, 'd'): 13,
+  (13, 'e'): 13,
+  (13, 'f'): 13,
+  (13, 'g'): 13,
+  (13, 'h'): 13,
+  (13, 'i'): 13,
+  (13, 'j'): 13,
+  (13, 'k'): 13,
+  (13, 'l'): 13,
+  (13, 'm'): 13,
+  (13, 'n'): 13,
+  (13, 'o'): 13,
+  (13, 'p'): 13,
+  (13, 'q'): 13,
+  (13, 'r'): 13,
+  (13, 's'): 13,
+  (13, 't'): 13,
+  (13, 'u'): 13,
+  (13, 'v'): 13,
+  (13, 'w'): 13,
+  (13, 'x'): 13,
+  (13, 'y'): 13,
+  (13, 'z'): 13,
+  (13, '{'): 13,
+  (13, '|'): 13,
+  (13, '}'): 13,
+  (13, '~'): 13,
+  (13, '\x7f'): 13,
+  (13, '\x80'): 13,
+  (13, '\x81'): 13,
+  (13, '\x82'): 13,
+  (13, '\x83'): 13,
+  (13, '\x84'): 13,
+  (13, '\x85'): 13,
+  (13, '\x86'): 13,
+  (13, '\x87'): 13,
+  (13, '\x88'): 13,
+  (13, '\x89'): 13,
+  (13, '\x8a'): 13,
+  (13, '\x8b'): 13,
+  (13, '\x8c'): 13,
+  (13, '\x8d'): 13,
+  (13, '\x8e'): 13,
+  (13, '\x8f'): 13,
+  (13, '\x90'): 13,
+  (13, '\x91'): 13,
+  (13, '\x92'): 13,
+  (13, '\x93'): 13,
+  (13, '\x94'): 13,
+  (13, '\x95'): 13,
+  (13, '\x96'): 13,
+  (13, '\x97'): 13,
+  (13, '\x98'): 13,
+  (13, '\x99'): 13,
+  (13, '\x9a'): 13,
+  (13, '\x9b'): 13,
+  (13, '\x9c'): 13,
+  (13, '\x9d'): 13,
+  (13, '\x9e'): 13,
+  (13, '\x9f'): 13,
+  (13, '\xa0'): 13,
+  (13, '\xa1'): 13,
+  (13, '\xa2'): 13,
+  (13, '\xa3'): 13,
+  (13, '\xa4'): 13,
+  (13, '\xa5'): 13,
+  (13, '\xa6'): 13,
+  (13, '\xa7'): 13,
+  (13, '\xa8'): 13,
+  (13, '\xa9'): 13,
+  (13, '\xaa'): 13,
+  (13, '\xab'): 13,
+  (13, '\xac'): 13,
+  (13, '\xad'): 13,
+  (13, '\xae'): 13,
+  (13, '\xaf'): 13,
+  (13, '\xb0'): 13,
+  (13, '\xb1'): 13,
+  (13, '\xb2'): 13,
+  (13, '\xb3'): 13,
+  (13, '\xb4'): 13,
+  (13, '\xb5'): 13,
+  (13, '\xb6'): 13,
+  (13, '\xb7'): 13,
+  (13, '\xb8'): 13,
+  (13, '\xb9'): 13,
+  (13, '\xba'): 13,
+  (13, '\xbb'): 13,
+  (13, '\xbc'): 13,
+  (13, '\xbd'): 13,
+  (13, '\xbe'): 13,
+  (13, '\xbf'): 13,
+  (13, '\xc0'): 13,
+  (13, '\xc1'): 13,
+  (13, '\xc2'): 13,
+  (13, '\xc3'): 13,
+  (13, '\xc4'): 13,
+  (13, '\xc5'): 13,
+  (13, '\xc6'): 13,
+  (13, '\xc7'): 13,
+  (13, '\xc8'): 13,
+  (13, '\xc9'): 13,
+  (13, '\xca'): 13,
+  (13, '\xcb'): 13,
+  (13, '\xcc'): 13,
+  (13, '\xcd'): 13,
+  (13, '\xce'): 13,
+  (13, '\xcf'): 13,
+  (13, '\xd0'): 13,
+  (13, '\xd1'): 13,
+  (13, '\xd2'): 13,
+  (13, '\xd3'): 13,
+  (13, '\xd4'): 13,
+  (13, '\xd5'): 13,
+  (13, '\xd6'): 13,
+  (13, '\xd7'): 13,
+  (13, '\xd8'): 13,
+  (13, '\xd9'): 13,
+  (13, '\xda'): 13,
+  (13, '\xdb'): 13,
+  (13, '\xdc'): 13,
+  (13, '\xdd'): 13,
+  (13, '\xde'): 13,
+  (13, '\xdf'): 13,
+  (13, '\xe0'): 13,
+  (13, '\xe1'): 13,
+  (13, '\xe2'): 13,
+  (13, '\xe3'): 13,
+  (13, '\xe4'): 13,
+  (13, '\xe5'): 13,
+  (13, '\xe6'): 13,
+  (13, '\xe7'): 13,
+  (13, '\xe8'): 13,
+  (13, '\xe9'): 13,
+  (13, '\xea'): 13,
+  (13, '\xeb'): 13,
+  (13, '\xec'): 13,
+  (13, '\xed'): 13,
+  (13, '\xee'): 13,
+  (13, '\xef'): 13,
+  (13, '\xf0'): 13,
+  (13, '\xf1'): 13,
+  (13, '\xf2'): 13,
+  (13, '\xf3'): 13,
+  (13, '\xf4'): 13,
+  (13, '\xf5'): 13,
+  (13, '\xf6'): 13,
+  (13, '\xf7'): 13,
+  (13, '\xf8'): 13,
+  (13, '\xf9'): 13,
+  (13, '\xfa'): 13,
+  (13, '\xfb'): 13,
+  (13, '\xfc'): 13,
+  (13, '\xfd'): 13,
+  (13, '\xfe'): 13,
+  (13, '\xff'): 13,
+  (15, '*'): 57,
+  (15, '/'): 59,
+  (15, '\\'): 58,
+  (17, '-'): 56,
+  (18, ']'): 26,
+  (19, '*'): 55,
+  (21, '-'): 54,
+  (22, '='): 52,
+  (22, '>'): 53,
+  (24, '0'): 10,
+  (24, '1'): 10,
+  (24, '2'): 10,
+  (24, '3'): 10,
+  (24, '4'): 10,
+  (24, '5'): 10,
+  (24, '6'): 10,
+  (24, '7'): 10,
+  (24, '8'): 10,
+  (24, '9'): 10,
+  (24, 'A'): 10,
+  (24, 'B'): 10,
+  (24, 'C'): 10,
+  (24, 'D'): 10,
+  (24, 'E'): 10,
+  (24, 'F'): 10,
+  (24, 'G'): 10,
+  (24, 'H'): 10,
+  (24, 'I'): 10,
+  (24, 'J'): 10,
+  (24, 'K'): 10,
+  (24, 'L'): 10,
+  (24, 'M'): 10,
+  (24, 'N'): 10,
+  (24, 'O'): 10,
+  (24, 'P'): 10,
+  (24, 'Q'): 10,
+  (24, 'R'): 10,
+  (24, 'S'): 10,
+  (24, 'T'): 10,
+  (24, 'U'): 10,
+  (24, 'V'): 10,
+  (24, 'W'): 10,
+  (24, 'X'): 10,
+  (24, 'Y'): 10,
+  (24, 'Z'): 10,
+  (24, '_'): 10,
+  (24, 'a'): 10,
+  (24, 'b'): 10,
+  (24, 'c'): 10,
+  (24, 'd'): 10,
+  (24, 'e'): 50,
+  (24, 'f'): 10,
+  (24, 'g'): 10,
+  (24, 'h'): 10,
+  (24, 'i'): 10,
+  (24, 'j'): 10,
+  (24, 'k'): 10,
+  (24, 'l'): 10,
+  (24, 'm'): 10,
+  (24, 'n'): 10,
+  (24, 'o'): 10,
+  (24, 'p'): 10,
+  (24, 'q'): 10,
+  (24, 'r'): 10,
+  (24, 's'): 10,
+  (24, 't'): 10,
+  (24, 'u'): 10,
+  (24, 'v'): 10,
+  (24, 'w'): 10,
+  (24, 'x'): 10,
+  (24, 'y'): 10,
+  (24, 'z'): 10,
+  (27, '\x00'): 27,
+  (27, '\x01'): 27,
+  (27, '\x02'): 27,
+  (27, '\x03'): 27,
+  (27, '\x04'): 27,
+  (27, '\x05'): 27,
+  (27, '\x06'): 27,
+  (27, '\x07'): 27,
+  (27, '\x08'): 27,
+  (27, '\t'): 27,
+  (27, '\x0b'): 27,
+  (27, '\x0c'): 27,
+  (27, '\r'): 27,
+  (27, '\x0e'): 27,
+  (27, '\x0f'): 27,
+  (27, '\x10'): 27,
+  (27, '\x11'): 27,
+  (27, '\x12'): 27,
+  (27, '\x13'): 27,
+  (27, '\x14'): 27,
+  (27, '\x15'): 27,
+  (27, '\x16'): 27,
+  (27, '\x17'): 27,
+  (27, '\x18'): 27,
+  (27, '\x19'): 27,
+  (27, '\x1a'): 27,
+  (27, '\x1b'): 27,
+  (27, '\x1c'): 27,
+  (27, '\x1d'): 27,
+  (27, '\x1e'): 27,
+  (27, '\x1f'): 27,
+  (27, ' '): 27,
+  (27, '!'): 27,
+  (27, '"'): 27,
+  (27, '#'): 27,
+  (27, '$'): 27,
+  (27, '%'): 27,
+  (27, '&'): 27,
+  (27, "'"): 27,
+  (27, '('): 27,
+  (27, ')'): 27,
+  (27, '*'): 27,
+  (27, '+'): 27,
+  (27, ','): 27,
+  (27, '-'): 27,
+  (27, '.'): 27,
+  (27, '/'): 27,
+  (27, '0'): 27,
+  (27, '1'): 27,
+  (27, '2'): 27,
+  (27, '3'): 27,
+  (27, '4'): 27,
+  (27, '5'): 27,
+  (27, '6'): 27,
+  (27, '7'): 27,
+  (27, '8'): 27,
+  (27, '9'): 27,
+  (27, ':'): 27,
+  (27, ';'): 27,
+  (27, '<'): 27,
+  (27, '='): 27,
+  (27, '>'): 27,
+  (27, '?'): 27,
+  (27, '@'): 27,
+  (27, 'A'): 27,
+  (27, 'B'): 27,
+  (27, 'C'): 27,
+  (27, 'D'): 27,
+  (27, 'E'): 27,
+  (27, 'F'): 27,
+  (27, 'G'): 27,
+  (27, 'H'): 27,
+  (27, 'I'): 27,
+  (27, 'J'): 27,
+  (27, 'K'): 27,
+  (27, 'L'): 27,
+  (27, 'M'): 27,
+  (27, 'N'): 27,
+  (27, 'O'): 27,
+  (27, 'P'): 27,
+  (27, 'Q'): 27,
+  (27, 'R'): 27,
+  (27, 'S'): 27,
+  (27, 'T'): 27,
+  (27, 'U'): 27,
+  (27, 'V'): 27,
+  (27, 'W'): 27,
+  (27, 'X'): 27,
+  (27, 'Y'): 27,
+  (27, 'Z'): 27,
+  (27, '['): 27,
+  (27, '\\'): 27,
+  (27, ']'): 27,
+  (27, '^'): 27,
+  (27, '_'): 27,
+  (27, '`'): 27,
+  (27, 'a'): 27,
+  (27, 'b'): 27,
+  (27, 'c'): 27,
+  (27, 'd'): 27,
+  (27, 'e'): 27,
+  (27, 'f'): 27,
+  (27, 'g'): 27,
+  (27, 'h'): 27,
+  (27, 'i'): 27,
+  (27, 'j'): 27,
+  (27, 'k'): 27,
+  (27, 'l'): 27,
+  (27, 'm'): 27,
+  (27, 'n'): 27,
+  (27, 'o'): 27,
+  (27, 'p'): 27,
+  (27, 'q'): 27,
+  (27, 'r'): 27,
+  (27, 's'): 27,
+  (27, 't'): 27,
+  (27, 'u'): 27,
+  (27, 'v'): 27,
+  (27, 'w'): 27,
+  (27, 'x'): 27,
+  (27, 'y'): 27,
+  (27, 'z'): 27,
+  (27, '{'): 27,
+  (27, '|'): 27,
+  (27, '}'): 27,
+  (27, '~'): 27,
+  (27, '\x7f'): 27,
+  (27, '\x80'): 27,
+  (27, '\x81'): 27,
+  (27, '\x82'): 27,
+  (27, '\x83'): 27,
+  (27, '\x84'): 27,
+  (27, '\x85'): 27,
+  (27, '\x86'): 27,
+  (27, '\x87'): 27,
+  (27, '\x88'): 27,
+  (27, '\x89'): 27,
+  (27, '\x8a'): 27,
+  (27, '\x8b'): 27,
+  (27, '\x8c'): 27,
+  (27, '\x8d'): 27,
+  (27, '\x8e'): 27,
+  (27, '\x8f'): 27,
+  (27, '\x90'): 27,
+  (27, '\x91'): 27,
+  (27, '\x92'): 27,
+  (27, '\x93'): 27,
+  (27, '\x94'): 27,
+  (27, '\x95'): 27,
+  (27, '\x96'): 27,
+  (27, '\x97'): 27,
+  (27, '\x98'): 27,
+  (27, '\x99'): 27,
+  (27, '\x9a'): 27,
+  (27, '\x9b'): 27,
+  (27, '\x9c'): 27,
+  (27, '\x9d'): 27,
+  (27, '\x9e'): 27,
+  (27, '\x9f'): 27,
+  (27, '\xa0'): 27,
+  (27, '\xa1'): 27,
+  (27, '\xa2'): 27,
+  (27, '\xa3'): 27,
+  (27, '\xa4'): 27,
+  (27, '\xa5'): 27,
+  (27, '\xa6'): 27,
+  (27, '\xa7'): 27,
+  (27, '\xa8'): 27,
+  (27, '\xa9'): 27,
+  (27, '\xaa'): 27,
+  (27, '\xab'): 27,
+  (27, '\xac'): 27,
+  (27, '\xad'): 27,
+  (27, '\xae'): 27,
+  (27, '\xaf'): 27,
+  (27, '\xb0'): 27,
+  (27, '\xb1'): 27,
+  (27, '\xb2'): 27,
+  (27, '\xb3'): 27,
+  (27, '\xb4'): 27,
+  (27, '\xb5'): 27,
+  (27, '\xb6'): 27,
+  (27, '\xb7'): 27,
+  (27, '\xb8'): 27,
+  (27, '\xb9'): 27,
+  (27, '\xba'): 27,
+  (27, '\xbb'): 27,
+  (27, '\xbc'): 27,
+  (27, '\xbd'): 27,
+  (27, '\xbe'): 27,
+  (27, '\xbf'): 27,
+  (27, '\xc0'): 27,
+  (27, '\xc1'): 27,
+  (27, '\xc2'): 27,
+  (27, '\xc3'): 27,
+  (27, '\xc4'): 27,
+  (27, '\xc5'): 27,
+  (27, '\xc6'): 27,
+  (27, '\xc7'): 27,
+  (27, '\xc8'): 27,
+  (27, '\xc9'): 27,
+  (27, '\xca'): 27,
+  (27, '\xcb'): 27,
+  (27, '\xcc'): 27,
+  (27, '\xcd'): 27,
+  (27, '\xce'): 27,
+  (27, '\xcf'): 27,
+  (27, '\xd0'): 27,
+  (27, '\xd1'): 27,
+  (27, '\xd2'): 27,
+  (27, '\xd3'): 27,
+  (27, '\xd4'): 27,
+  (27, '\xd5'): 27,
+  (27, '\xd6'): 27,
+  (27, '\xd7'): 27,
+  (27, '\xd8'): 27,
+  (27, '\xd9'): 27,
+  (27, '\xda'): 27,
+  (27, '\xdb'): 27,
+  (27, '\xdc'): 27,
+  (27, '\xdd'): 27,
+  (27, '\xde'): 27,
+  (27, '\xdf'): 27,
+  (27, '\xe0'): 27,
+  (27, '\xe1'): 27,
+  (27, '\xe2'): 27,
+  (27, '\xe3'): 27,
+  (27, '\xe4'): 27,
+  (27, '\xe5'): 27,
+  (27, '\xe6'): 27,
+  (27, '\xe7'): 27,
+  (27, '\xe8'): 27,
+  (27, '\xe9'): 27,
+  (27, '\xea'): 27,
+  (27, '\xeb'): 27,
+  (27, '\xec'): 27,
+  (27, '\xed'): 27,
+  (27, '\xee'): 27,
+  (27, '\xef'): 27,
+  (27, '\xf0'): 27,
+  (27, '\xf1'): 27,
+  (27, '\xf2'): 27,
+  (27, '\xf3'): 27,
+  (27, '\xf4'): 27,
+  (27, '\xf5'): 27,
+  (27, '\xf6'): 27,
+  (27, '\xf7'): 27,
+  (27, '\xf8'): 27,
+  (27, '\xf9'): 27,
+  (27, '\xfa'): 27,
+  (27, '\xfb'): 27,
+  (27, '\xfc'): 27,
+  (27, '\xfd'): 27,
+  (27, '\xfe'): 27,
+  (27, '\xff'): 27,
+  (29, '-'): 47,
+  (29, '>'): 48,
+  (30, '.'): 39,
+  (30, ':'): 40,
+  (30, '<'): 38,
+  (30, '='): 41,
+  (30, '@'): 37,
+  (30, '\\'): 42,
+  (32, '0'): 10,
+  (32, '1'): 10,
+  (32, '2'): 10,
+  (32, '3'): 10,
+  (32, '4'): 10,
+  (32, '5'): 10,
+  (32, '6'): 10,
+  (32, '7'): 10,
+  (32, '8'): 10,
+  (32, '9'): 10,
+  (32, 'A'): 10,
+  (32, 'B'): 10,
+  (32, 'C'): 10,
+  (32, 'D'): 10,
+  (32, 'E'): 10,
+  (32, 'F'): 10,
+  (32, 'G'): 10,
+  (32, 'H'): 10,
+  (32, 'I'): 10,
+  (32, 'J'): 10,
+  (32, 'K'): 10,
+  (32, 'L'): 10,
+  (32, 'M'): 10,
+  (32, 'N'): 10,
+  (32, 'O'): 10,
+  (32, 'P'): 10,
+  (32, 'Q'): 10,
+  (32, 'R'): 10,
+  (32, 'S'): 10,
+  (32, 'T'): 10,
+  (32, 'U'): 10,
+  (32, 'V'): 10,
+  (32, 'W'): 10,
+  (32, 'X'): 10,
+  (32, 'Y'): 10,
+  (32, 'Z'): 10,
+  (32, '_'): 10,
+  (32, 'a'): 10,
+  (32, 'b'): 10,
+  (32, 'c'): 10,
+  (32, 'd'): 10,
+  (32, 'e'): 10,
+  (32, 'f'): 10,
+  (32, 'g'): 10,
+  (32, 'h'): 10,
+  (32, 'i'): 10,
+  (32, 'j'): 10,
+  (32, 'k'): 10,
+  (32, 'l'): 10,
+  (32, 'm'): 10,
+  (32, 'n'): 10,
+  (32, 'o'): 10,
+  (32, 'p'): 10,
+  (32, 'q'): 10,
+  (32, 'r'): 10,
+  (32, 's'): 36,
+  (32, 't'): 10,
+  (32, 'u'): 10,
+  (32, 'v'): 10,
+  (32, 'w'): 10,
+  (32, 'x'): 10,
+  (32, 'y'): 10,
+  (32, 'z'): 10,
+  (33, '0'): 10,
+  (33, '1'): 10,
+  (33, '2'): 10,
+  (33, '3'): 10,
+  (33, '4'): 10,
+  (33, '5'): 10,
+  (33, '6'): 10,
+  (33, '7'): 10,
+  (33, '8'): 10,
+  (33, '9'): 10,
+  (33, 'A'): 10,
+  (33, 'B'): 10,
+  (33, 'C'): 10,
+  (33, 'D'): 10,
+  (33, 'E'): 10,
+  (33, 'F'): 10,
+  (33, 'G'): 10,
+  (33, 'H'): 10,
+  (33, 'I'): 10,
+  (33, 'J'): 10,
+  (33, 'K'): 10,
+  (33, 'L'): 10,
+  (33, 'M'): 10,
+  (33, 'N'): 10,
+  (33, 'O'): 10,
+  (33, 'P'): 10,
+  (33, 'Q'): 10,
+  (33, 'R'): 10,
+  (33, 'S'): 10,
+  (33, 'T'): 10,
+  (33, 'U'): 10,
+  (33, 'V'): 10,
+  (33, 'W'): 10,
+  (33, 'X'): 10,
+  (33, 'Y'): 10,
+  (33, 'Z'): 10,
+  (33, '_'): 10,
+  (33, 'a'): 10,
+  (33, 'b'): 10,
+  (33, 'c'): 10,
+  (33, 'd'): 10,
+  (33, 'e'): 10,
+  (33, 'f'): 10,
+  (33, 'g'): 10,
+  (33, 'h'): 10,
+  (33, 'i'): 10,
+  (33, 'j'): 10,
+  (33, 'k'): 10,
+  (33, 'l'): 10,
+  (33, 'm'): 10,
+  (33, 'n'): 10,
+  (33, 'o'): 34,
+  (33, 'p'): 10,
+  (33, 'q'): 10,
+  (33, 'r'): 10,
+  (33, 's'): 10,
+  (33, 't'): 10,
+  (33, 'u'): 10,
+  (33, 'v'): 10,
+  (33, 'w'): 10,
+  (33, 'x'): 10,
+  (33, 'y'): 10,
+  (33, 'z'): 10,
+  (34, '0'): 10,
+  (34, '1'): 10,
+  (34, '2'): 10,
+  (34, '3'): 10,
+  (34, '4'): 10,
+  (34, '5'): 10,
+  (34, '6'): 10,
+  (34, '7'): 10,
+  (34, '8'): 10,
+  (34, '9'): 10,
+  (34, 'A'): 10,
+  (34, 'B'): 10,
+  (34, 'C'): 10,
+  (34, 'D'): 10,
+  (34, 'E'): 10,
+  (34, 'F'): 10,
+  (34, 'G'): 10,
+  (34, 'H'): 10,
+  (34, 'I'): 10,
+  (34, 'J'): 10,
+  (34, 'K'): 10,
+  (34, 'L'): 10,
+  (34, 'M'): 10,
+  (34, 'N'): 10,
+  (34, 'O'): 10,
+  (34, 'P'): 10,
+  (34, 'Q'): 10,
+  (34, 'R'): 10,
+  (34, 'S'): 10,
+  (34, 'T'): 10,
+  (34, 'U'): 10,
+  (34, 'V'): 10,
+  (34, 'W'): 10,
+  (34, 'X'): 10,
+  (34, 'Y'): 10,
+  (34, 'Z'): 10,
+  (34, '_'): 10,
+  (34, 'a'): 10,
+  (34, 'b'): 10,
+  (34, 'c'): 10,
+  (34, 'd'): 35,
+  (34, 'e'): 10,
+  (34, 'f'): 10,
+  (34, 'g'): 10,
+  (34, 'h'): 10,
+  (34, 'i'): 10,
+  (34, 'j'): 10,
+  (34, 'k'): 10,
+  (34, 'l'): 10,
+  (34, 'm'): 10,
+  (34, 'n'): 10,
+  (34, 'o'): 10,
+  (34, 'p'): 10,
+  (34, 'q'): 10,
+  (34, 'r'): 10,
+  (34, 's'): 10,
+  (34, 't'): 10,
+  (34, 'u'): 10,
+  (34, 'v'): 10,
+  (34, 'w'): 10,
+  (34, 'x'): 10,
+  (34, 'y'): 10,
+  (34, 'z'): 10,
+  (35, '0'): 10,
+  (35, '1'): 10,
+  (35, '2'): 10,
+  (35, '3'): 10,
+  (35, '4'): 10,
+  (35, '5'): 10,
+  (35, '6'): 10,
+  (35, '7'): 10,
+  (35, '8'): 10,
+  (35, '9'): 10,
+  (35, 'A'): 10,
+  (35, 'B'): 10,
+  (35, 'C'): 10,
+  (35, 'D'): 10,
+  (35, 'E'): 10,
+  (35, 'F'): 10,
+  (35, 'G'): 10,
+  (35, 'H'): 10,
+  (35, 'I'): 10,
+  (35, 'J'): 10,
+  (35, 'K'): 10,
+  (35, 'L'): 10,
+  (35, 'M'): 10,
+  (35, 'N'): 10,
+  (35, 'O'): 10,
+  (35, 'P'): 10,
+  (35, 'Q'): 10,
+  (35, 'R'): 10,
+  (35, 'S'): 10,
+  (35, 'T'): 10,
+  (35, 'U'): 10,
+  (35, 'V'): 10,
+  (35, 'W'): 10,
+  (35, 'X'): 10,
+  (35, 'Y'): 10,
+  (35, 'Z'): 10,
+  (35, '_'): 10,
+  (35, 'a'): 10,
+  (35, 'b'): 10,
+  (35, 'c'): 10,
+  (35, 'd'): 10,
+  (35, 'e'): 10,
+  (35, 'f'): 10,
+  (35, 'g'): 10,
+  (35, 'h'): 10,
+  (35, 'i'): 10,
+  (35, 'j'): 10,
+  (35, 'k'): 10,
+  (35, 'l'): 10,
+  (35, 'm'): 10,
+  (35, 'n'): 10,
+  (35, 'o'): 10,
+  (35, 'p'): 10,
+  (35, 'q'): 10,
+  (35, 'r'): 10,
+  (35, 's'): 10,
+  (35, 't'): 10,
+  (35, 'u'): 10,
+  (35, 'v'): 10,
+  (35, 'w'): 10,
+  (35, 'x'): 10,
+  (35, 'y'): 10,
+  (35, 'z'): 10,
+  (36, '0'): 10,
+  (36, '1'): 10,
+  (36, '2'): 10,
+  (36, '3'): 10,
+  (36, '4'): 10,
+  (36, '5'): 10,
+  (36, '6'): 10,
+  (36, '7'): 10,
+  (36, '8'): 10,
+  (36, '9'): 10,
+  (36, 'A'): 10,
+  (36, 'B'): 10,
+  (36, 'C'): 10,
+  (36, 'D'): 10,
+  (36, 'E'): 10,
+  (36, 'F'): 10,
+  (36, 'G'): 10,
+  (36, 'H'): 10,
+  (36, 'I'): 10,
+  (36, 'J'): 10,
+  (36, 'K'): 10,
+  (36, 'L'): 10,
+  (36, 'M'): 10,
+  (36, 'N'): 10,
+  (36, 'O'): 10,
+  (36, 'P'): 10,
+  (36, 'Q'): 10,
+  (36, 'R'): 10,
+  (36, 'S'): 10,
+  (36, 'T'): 10,
+  (36, 'U'): 10,
+  (36, 'V'): 10,
+  (36, 'W'): 10,
+  (36, 'X'): 10,
+  (36, 'Y'): 10,
+  (36, 'Z'): 10,
+  (36, '_'): 10,
+  (36, 'a'): 10,
+  (36, 'b'): 10,
+  (36, 'c'): 10,
+  (36, 'd'): 10,
+  (36, 'e'): 10,
+  (36, 'f'): 10,
+  (36, 'g'): 10,
+  (36, 'h'): 10,
+  (36, 'i'): 10,
+  (36, 'j'): 10,
+  (36, 'k'): 10,
+  (36, 'l'): 10,
+  (36, 'm'): 10,
+  (36, 'n'): 10,
+  (36, 'o'): 10,
+  (36, 'p'): 10,
+  (36, 'q'): 10,
+  (36, 'r'): 10,
+  (36, 's'): 10,
+  (36, 't'): 10,
+  (36, 'u'): 10,
+  (36, 'v'): 10,
+  (36, 'w'): 10,
+  (36, 'x'): 10,
+  (36, 'y'): 10,
+  (36, 'z'): 10,
+  (37, '='): 46,
+  (39, '.'): 45,
+  (40, '='): 44,
+  (42, '='): 43,
+  (47, '>'): 49,
+  (50, '0'): 10,
+  (50, '1'): 10,
+  (50, '2'): 10,
+  (50, '3'): 10,
+  (50, '4'): 10,
+  (50, '5'): 10,
+  (50, '6'): 10,
+  (50, '7'): 10,
+  (50, '8'): 10,
+  (50, '9'): 10,
+  (50, 'A'): 10,
+  (50, 'B'): 10,
+  (50, 'C'): 10,
+  (50, 'D'): 10,
+  (50, 'E'): 10,
+  (50, 'F'): 10,
+  (50, 'G'): 10,
+  (50, 'H'): 10,
+  (50, 'I'): 10,
+  (50, 'J'): 10,
+  (50, 'K'): 10,
+  (50, 'L'): 10,
+  (50, 'M'): 10,
+  (50, 'N'): 10,
+  (50, 'O'): 10,
+  (50, 'P'): 10,
+  (50, 'Q'): 10,
+  (50, 'R'): 10,
+  (50, 'S'): 10,
+  (50, 'T'): 10,
+  (50, 'U'): 10,
+  (50, 'V'): 10,
+  (50, 'W'): 10,
+  (50, 'X'): 10,
+  (50, 'Y'): 10,
+  (50, 'Z'): 10,
+  (50, '_'): 10,
+  (50, 'a'): 10,
+  (50, 'b'): 10,
+  (50, 'c'): 10,
+  (50, 'd'): 10,
+  (50, 'e'): 10,
+  (50, 'f'): 10,
+  (50, 'g'): 10,
+  (50, 'h'): 10,
+  (50, 'i'): 10,
+  (50, 'j'): 10,
+  (50, 'k'): 10,
+  (50, 'l'): 10,
+  (50, 'm'): 51,
+  (50, 'n'): 10,
+  (50, 'o'): 10,
+  (50, 'p'): 10,
+  (50, 'q'): 10,
+  (50, 'r'): 10,
+  (50, 's'): 10,
+  (50, 't'): 10,
+  (50, 'u'): 10,
+  (50, 'v'): 10,
+  (50, 'w'): 10,
+  (50, 'x'): 10,
+  (50, 'y'): 10,
+  (50, 'z'): 10,
+  (51, '0'): 10,
+  (51, '1'): 10,
+  (51, '2'): 10,
+  (51, '3'): 10,
+  (51, '4'): 10,
+  (51, '5'): 10,
+  (51, '6'): 10,
+  (51, '7'): 10,
+  (51, '8'): 10,
+  (51, '9'): 10,
+  (51, 'A'): 10,
+  (51, 'B'): 10,
+  (51, 'C'): 10,
+  (51, 'D'): 10,
+  (51, 'E'): 10,
+  (51, 'F'): 10,
+  (51, 'G'): 10,
+  (51, 'H'): 10,
+  (51, 'I'): 10,
+  (51, 'J'): 10,
+  (51, 'K'): 10,
+  (51, 'L'): 10,
+  (51, 'M'): 10,
+  (51, 'N'): 10,
+  (51, 'O'): 10,
+  (51, 'P'): 10,
+  (51, 'Q'): 10,
+  (51, 'R'): 10,
+  (51, 'S'): 10,
+  (51, 'T'): 10,
+  (51, 'U'): 10,
+  (51, 'V'): 10,
+  (51, 'W'): 10,
+  (51, 'X'): 10,
+  (51, 'Y'): 10,
+  (51, 'Z'): 10,
+  (51, '_'): 10,
+  (51, 'a'): 10,
+  (51, 'b'): 10,
+  (51, 'c'): 10,
+  (51, 'd'): 10,
+  (51, 'e'): 10,
+  (51, 'f'): 10,
+  (51, 'g'): 10,
+  (51, 'h'): 10,
+  (51, 'i'): 10,
+  (51, 'j'): 10,
+  (51, 'k'): 10,
+  (51, 'l'): 10,
+  (51, 'm'): 10,
+  (51, 'n'): 10,
+  (51, 'o'): 10,
+  (51, 'p'): 10,
+  (51, 'q'): 10,
+  (51, 'r'): 10,
+  (51, 's'): 10,
+  (51, 't'): 10,
+  (51, 'u'): 10,
+  (51, 'v'): 10,
+  (51, 'w'): 10,
+  (51, 'x'): 10,
+  (51, 'y'): 10,
+  (51, 'z'): 10,
+  (57, '\x00'): 57,
+  (57, '\x01'): 57,
+  (57, '\x02'): 57,
+  (57, '\x03'): 57,
+  (57, '\x04'): 57,
+  (57, '\x05'): 57,
+  (57, '\x06'): 57,
+  (57, '\x07'): 57,
+  (57, '\x08'): 57,
+  (57, '\t'): 57,
+  (57, '\n'): 57,
+  (57, '\x0b'): 57,
+  (57, '\x0c'): 57,
+  (57, '\r'): 57,
+  (57, '\x0e'): 57,
+  (57, '\x0f'): 57,
+  (57, '\x10'): 57,
+  (57, '\x11'): 57,
+  (57, '\x12'): 57,
+  (57, '\x13'): 57,
+  (57, '\x14'): 57,
+  (57, '\x15'): 57,
+  (57, '\x16'): 57,
+  (57, '\x17'): 57,
+  (57, '\x18'): 57,
+  (57, '\x19'): 57,
+  (57, '\x1a'): 57,
+  (57, '\x1b'): 57,
+  (57, '\x1c'): 57,
+  (57, '\x1d'): 57,
+  (57, '\x1e'): 57,
+  (57, '\x1f'): 57,
+  (57, ' '): 57,
+  (57, '!'): 57,
+  (57, '"'): 57,
+  (57, '#'): 57,
+  (57, '$'): 57,
+  (57, '%'): 57,
+  (57, '&'): 57,
+  (57, "'"): 57,
+  (57, '('): 57,
+  (57, ')'): 57,
+  (57, '*'): 60,
+  (57, '+'): 57,
+  (57, ','): 57,
+  (57, '-'): 57,
+  (57, '.'): 57,
+  (57, '/'): 57,
+  (57, '0'): 57,
+  (57, '1'): 57,
+  (57, '2'): 57,
+  (57, '3'): 57,
+  (57, '4'): 57,
+  (57, '5'): 57,
+  (57, '6'): 57,
+  (57, '7'): 57,
+  (57, '8'): 57,
+  (57, '9'): 57,
+  (57, ':'): 57,
+  (57, ';'): 57,
+  (57, '<'): 57,
+  (57, '='): 57,
+  (57, '>'): 57,
+  (57, '?'): 57,
+  (57, '@'): 57,
+  (57, 'A'): 57,
+  (57, 'B'): 57,
+  (57, 'C'): 57,
+  (57, 'D'): 57,
+  (57, 'E'): 57,
+  (57, 'F'): 57,
+  (57, 'G'): 57,
+  (57, 'H'): 57,
+  (57, 'I'): 57,
+  (57, 'J'): 57,
+  (57, 'K'): 57,
+  (57, 'L'): 57,
+  (57, 'M'): 57,
+  (57, 'N'): 57,
+  (57, 'O'): 57,
+  (57, 'P'): 57,
+  (57, 'Q'): 57,
+  (57, 'R'): 57,
+  (57, 'S'): 57,
+  (57, 'T'): 57,
+  (57, 'U'): 57,
+  (57, 'V'): 57,
+  (57, 'W'): 57,
+  (57, 'X'): 57,
+  (57, 'Y'): 57,
+  (57, 'Z'): 57,
+  (57, '['): 57,
+  (57, '\\'): 57,
+  (57, ']'): 57,
+  (57, '^'): 57,
+  (57, '_'): 57,
+  (57, '`'): 57,
+  (57, 'a'): 57,
+  (57, 'b'): 57,
+  (57, 'c'): 57,
+  (57, 'd'): 57,
+  (57, 'e'): 57,
+  (57, 'f'): 57,
+  (57, 'g'): 57,
+  (57, 'h'): 57,
+  (57, 'i'): 57,
+  (57, 'j'): 57,
+  (57, 'k'): 57,
+  (57, 'l'): 57,
+  (57, 'm'): 57,
+  (57, 'n'): 57,
+  (57, 'o'): 57,
+  (57, 'p'): 57,
+  (57, 'q'): 57,
+  (57, 'r'): 57,
+  (57, 's'): 57,
+  (57, 't'): 57,
+  (57, 'u'): 57,
+  (57, 'v'): 57,
+  (57, 'w'): 57,
+  (57, 'x'): 57,
+  (57, 'y'): 57,
+  (57, 'z'): 57,
+  (57, '{'): 57,
+  (57, '|'): 57,
+  (57, '}'): 57,
+  (57, '~'): 57,
+  (57, '\x7f'): 57,
+  (57, '\x80'): 57,
+  (57, '\x81'): 57,
+  (57, '\x82'): 57,
+  (57, '\x83'): 57,
+  (57, '\x84'): 57,
+  (57, '\x85'): 57,
+  (57, '\x86'): 57,
+  (57, '\x87'): 57,
+  (57, '\x88'): 57,
+  (57, '\x89'): 57,
+  (57, '\x8a'): 57,
+  (57, '\x8b'): 57,
+  (57, '\x8c'): 57,
+  (57, '\x8d'): 57,
+  (57, '\x8e'): 57,
+  (57, '\x8f'): 57,
+  (57, '\x90'): 57,
+  (57, '\x91'): 57,
+  (57, '\x92'): 57,
+  (57, '\x93'): 57,
+  (57, '\x94'): 57,
+  (57, '\x95'): 57,
+  (57, '\x96'): 57,
+  (57, '\x97'): 57,
+  (57, '\x98'): 57,
+  (57, '\x99'): 57,
+  (57, '\x9a'): 57,
+  (57, '\x9b'): 57,
+  (57, '\x9c'): 57,
+  (57, '\x9d'): 57,
+  (57, '\x9e'): 57,
+  (57, '\x9f'): 57,
+  (57, '\xa0'): 57,
+  (57, '\xa1'): 57,
+  (57, '\xa2'): 57,
+  (57, '\xa3'): 57,
+  (57, '\xa4'): 57,
+  (57, '\xa5'): 57,
+  (57, '\xa6'): 57,
+  (57, '\xa7'): 57,
+  (57, '\xa8'): 57,
+  (57, '\xa9'): 57,
+  (57, '\xaa'): 57,
+  (57, '\xab'): 57,
+  (57, '\xac'): 57,
+  (57, '\xad'): 57,
+  (57, '\xae'): 57,
+  (57, '\xaf'): 57,
+  (57, '\xb0'): 57,
+  (57, '\xb1'): 57,
+  (57, '\xb2'): 57,
+  (57, '\xb3'): 57,
+  (57, '\xb4'): 57,
+  (57, '\xb5'): 57,
+  (57, '\xb6'): 57,
+  (57, '\xb7'): 57,
+  (57, '\xb8'): 57,
+  (57, '\xb9'): 57,
+  (57, '\xba'): 57,
+  (57, '\xbb'): 57,
+  (57, '\xbc'): 57,
+  (57, '\xbd'): 57,
+  (57, '\xbe'): 57,
+  (57, '\xbf'): 57,
+  (57, '\xc0'): 57,
+  (57, '\xc1'): 57,
+  (57, '\xc2'): 57,
+  (57, '\xc3'): 57,
+  (57, '\xc4'): 57,
+  (57, '\xc5'): 57,
+  (57, '\xc6'): 57,
+  (57, '\xc7'): 57,
+  (57, '\xc8'): 57,
+  (57, '\xc9'): 57,
+  (57, '\xca'): 57,
+  (57, '\xcb'): 57,
+  (57, '\xcc'): 57,
+  (57, '\xcd'): 57,
+  (57, '\xce'): 57,
+  (57, '\xcf'): 57,
+  (57, '\xd0'): 57,
+  (57, '\xd1'): 57,
+  (57, '\xd2'): 57,
+  (57, '\xd3'): 57,
+  (57, '\xd4'): 57,
+  (57, '\xd5'): 57,
+  (57, '\xd6'): 57,
+  (57, '\xd7'): 57,
+  (57, '\xd8'): 57,
+  (57, '\xd9'): 57,
+  (57, '\xda'): 57,
+  (57, '\xdb'): 57,
+  (57, '\xdc'): 57,
+  (57, '\xdd'): 57,
+  (57, '\xde'): 57,
+  (57, '\xdf'): 57,
+  (57, '\xe0'): 57,
+  (57, '\xe1'): 57,
+  (57, '\xe2'): 57,
+  (57, '\xe3'): 57,
+  (57, '\xe4'): 57,
+  (57, '\xe5'): 57,
+  (57, '\xe6'): 57,
+  (57, '\xe7'): 57,
+  (57, '\xe8'): 57,
+  (57, '\xe9'): 57,
+  (57, '\xea'): 57,
+  (57, '\xeb'): 57,
+  (57, '\xec'): 57,
+  (57, '\xed'): 57,
+  (57, '\xee'): 57,
+  (57, '\xef'): 57,
+  (57, '\xf0'): 57,
+  (57, '\xf1'): 57,
+  (57, '\xf2'): 57,
+  (57, '\xf3'): 57,
+  (57, '\xf4'): 57,
+  (57, '\xf5'): 57,
+  (57, '\xf6'): 57,
+  (57, '\xf7'): 57,
+  (57, '\xf8'): 57,
+  (57, '\xf9'): 57,
+  (57, '\xfa'): 57,
+  (57, '\xfb'): 57,
+  (57, '\xfc'): 57,
+  (57, '\xfd'): 57,
+  (57, '\xfe'): 57,
+  (57, '\xff'): 57,
+  (60, '\x00'): 57,
+  (60, '\x01'): 57,
+  (60, '\x02'): 57,
+  (60, '\x03'): 57,
+  (60, '\x04'): 57,
+  (60, '\x05'): 57,
+  (60, '\x06'): 57,
+  (60, '\x07'): 57,
+  (60, '\x08'): 57,
+  (60, '\t'): 57,
+  (60, '\n'): 57,
+  (60, '\x0b'): 57,
+  (60, '\x0c'): 57,
+  (60, '\r'): 57,
+  (60, '\x0e'): 57,
+  (60, '\x0f'): 57,
+  (60, '\x10'): 57,
+  (60, '\x11'): 57,
+  (60, '\x12'): 57,
+  (60, '\x13'): 57,
+  (60, '\x14'): 57,
+  (60, '\x15'): 57,
+  (60, '\x16'): 57,
+  (60, '\x17'): 57,
+  (60, '\x18'): 57,
+  (60, '\x19'): 57,
+  (60, '\x1a'): 57,
+  (60, '\x1b'): 57,
+  (60, '\x1c'): 57,
+  (60, '\x1d'): 57,
+  (60, '\x1e'): 57,
+  (60, '\x1f'): 57,
+  (60, ' '): 57,
+  (60, '!'): 57,
+  (60, '"'): 57,
+  (60, '#'): 57,
+  (60, '$'): 57,
+  (60, '%'): 57,
+  (60, '&'): 57,
+  (60, "'"): 57,
+  (60, '('): 57,
+  (60, ')'): 57,
+  (60, '*'): 57,
+  (60, '+'): 57,
+  (60, ','): 57,
+  (60, '-'): 57,
+  (60, '.'): 57,
+  (60, '/'): 1,
+  (60, '0'): 57,
+  (60, '1'): 57,
+  (60, '2'): 57,
+  (60, '3'): 57,
+  (60, '4'): 57,
+  (60, '5'): 57,
+  (60, '6'): 57,
+  (60, '7'): 57,
+  (60, '8'): 57,
+  (60, '9'): 57,
+  (60, ':'): 57,
+  (60, ';'): 57,
+  (60, '<'): 57,
+  (60, '='): 57,
+  (60, '>'): 57,
+  (60, '?'): 57,
+  (60, '@'): 57,
+  (60, 'A'): 57,
+  (60, 'B'): 57,
+  (60, 'C'): 57,
+  (60, 'D'): 57,
+  (60, 'E'): 57,
+  (60, 'F'): 57,
+  (60, 'G'): 57,
+  (60, 'H'): 57,
+  (60, 'I'): 57,
+  (60, 'J'): 57,
+  (60, 'K'): 57,
+  (60, 'L'): 57,
+  (60, 'M'): 57,
+  (60, 'N'): 57,
+  (60, 'O'): 57,
+  (60, 'P'): 57,
+  (60, 'Q'): 57,
+  (60, 'R'): 57,
+  (60, 'S'): 57,
+  (60, 'T'): 57,
+  (60, 'U'): 57,
+  (60, 'V'): 57,
+  (60, 'W'): 57,
+  (60, 'X'): 57,
+  (60, 'Y'): 57,
+  (60, 'Z'): 57,
+  (60, '['): 57,
+  (60, '\\'): 57,
+  (60, ']'): 57,
+  (60, '^'): 57,
+  (60, '_'): 57,
+  (60, '`'): 57,
+  (60, 'a'): 57,
+  (60, 'b'): 57,
+  (60, 'c'): 57,
+  (60, 'd'): 57,
+  (60, 'e'): 57,
+  (60, 'f'): 57,
+  (60, 'g'): 57,
+  (60, 'h'): 57,
+  (60, 'i'): 57,
+  (60, 'j'): 57,
+  (60, 'k'): 57,
+  (60, 'l'): 57,
+  (60, 'm'): 57,
+  (60, 'n'): 57,
+  (60, 'o'): 57,
+  (60, 'p'): 57,
+  (60, 'q'): 57,
+  (60, 'r'): 57,
+  (60, 's'): 57,
+  (60, 't'): 57,
+  (60, 'u'): 57,
+  (60, 'v'): 57,
+  (60, 'w'): 57,
+  (60, 'x'): 57,
+  (60, 'y'): 57,
+  (60, 'z'): 57,
+  (60, '{'): 57,
+  (60, '|'): 57,
+  (60, '}'): 57,
+  (60, '~'): 57,
+  (60, '\x7f'): 57,
+  (60, '\x80'): 57,
+  (60, '\x81'): 57,
+  (60, '\x82'): 57,
+  (60, '\x83'): 57,
+  (60, '\x84'): 57,
+  (60, '\x85'): 57,
+  (60, '\x86'): 57,
+  (60, '\x87'): 57,
+  (60, '\x88'): 57,
+  (60, '\x89'): 57,
+  (60, '\x8a'): 57,
+  (60, '\x8b'): 57,
+  (60, '\x8c'): 57,
+  (60, '\x8d'): 57,
+  (60, '\x8e'): 57,
+  (60, '\x8f'): 57,
+  (60, '\x90'): 57,
+  (60, '\x91'): 57,
+  (60, '\x92'): 57,
+  (60, '\x93'): 57,
+  (60, '\x94'): 57,
+  (60, '\x95'): 57,
+  (60, '\x96'): 57,
+  (60, '\x97'): 57,
+  (60, '\x98'): 57,
+  (60, '\x99'): 57,
+  (60, '\x9a'): 57,
+  (60, '\x9b'): 57,
+  (60, '\x9c'): 57,
+  (60, '\x9d'): 57,
+  (60, '\x9e'): 57,
+  (60, '\x9f'): 57,
+  (60, '\xa0'): 57,
+  (60, '\xa1'): 57,
+  (60, '\xa2'): 57,
+  (60, '\xa3'): 57,
+  (60, '\xa4'): 57,
+  (60, '\xa5'): 57,
+  (60, '\xa6'): 57,
+  (60, '\xa7'): 57,
+  (60, '\xa8'): 57,
+  (60, '\xa9'): 57,
+  (60, '\xaa'): 57,
+  (60, '\xab'): 57,
+  (60, '\xac'): 57,
+  (60, '\xad'): 57,
+  (60, '\xae'): 57,
+  (60, '\xaf'): 57,
+  (60, '\xb0'): 57,
+  (60, '\xb1'): 57,
+  (60, '\xb2'): 57,
+  (60, '\xb3'): 57,
+  (60, '\xb4'): 57,
+  (60, '\xb5'): 57,
+  (60, '\xb6'): 57,
+  (60, '\xb7'): 57,
+  (60, '\xb8'): 57,
+  (60, '\xb9'): 57,
+  (60, '\xba'): 57,
+  (60, '\xbb'): 57,
+  (60, '\xbc'): 57,
+  (60, '\xbd'): 57,
+  (60, '\xbe'): 57,
+  (60, '\xbf'): 57,
+  (60, '\xc0'): 57,
+  (60, '\xc1'): 57,
+  (60, '\xc2'): 57,
+  (60, '\xc3'): 57,
+  (60, '\xc4'): 57,
+  (60, '\xc5'): 57,
+  (60, '\xc6'): 57,
+  (60, '\xc7'): 57,
+  (60, '\xc8'): 57,
+  (60, '\xc9'): 57,
+  (60, '\xca'): 57,
+  (60, '\xcb'): 57,
+  (60, '\xcc'): 57,
+  (60, '\xcd'): 57,
+  (60, '\xce'): 57,
+  (60, '\xcf'): 57,
+  (60, '\xd0'): 57,
+  (60, '\xd1'): 57,
+  (60, '\xd2'): 57,
+  (60, '\xd3'): 57,
+  (60, '\xd4'): 57,
+  (60, '\xd5'): 57,
+  (60, '\xd6'): 57,
+  (60, '\xd7'): 57,
+  (60, '\xd8'): 57,
+  (60, '\xd9'): 57,
+  (60, '\xda'): 57,
+  (60, '\xdb'): 57,
+  (60, '\xdc'): 57,
+  (60, '\xdd'): 57,
+  (60, '\xde'): 57,
+  (60, '\xdf'): 57,
+  (60, '\xe0'): 57,
+  (60, '\xe1'): 57,
+  (60, '\xe2'): 57,
+  (60, '\xe3'): 57,
+  (60, '\xe4'): 57,
+  (60, '\xe5'): 57,
+  (60, '\xe6'): 57,
+  (60, '\xe7'): 57,
+  (60, '\xe8'): 57,
+  (60, '\xe9'): 57,
+  (60, '\xea'): 57,
+  (60, '\xeb'): 57,
+  (60, '\xec'): 57,
+  (60, '\xed'): 57,
+  (60, '\xee'): 57,
+  (60, '\xef'): 57,
+  (60, '\xf0'): 57,
+  (60, '\xf1'): 57,
+  (60, '\xf2'): 57,
+  (60, '\xf3'): 57,
+  (60, '\xf4'): 57,
+  (60, '\xf5'): 57,
+  (60, '\xf6'): 57,
+  (60, '\xf7'): 57,
+  (60, '\xf8'): 57,
+  (60, '\xf9'): 57,
+  (60, '\xfa'): 57,
+  (60, '\xfb'): 57,
+  (60, '\xfc'): 57,
+  (60, '\xfd'): 57,
+  (60, '\xfe'): 57,
+  (60, '\xff'): 57,
+  (61, '0'): 10,
+  (61, '1'): 10,
+  (61, '2'): 10,
+  (61, '3'): 10,
+  (61, '4'): 10,
+  (61, '5'): 10,
+  (61, '6'): 10,
+  (61, '7'): 10,
+  (61, '8'): 10,
+  (61, '9'): 10,
+  (61, 'A'): 10,
+  (61, 'B'): 10,
+  (61, 'C'): 10,
+  (61, 'D'): 10,
+  (61, 'E'): 10,
+  (61, 'F'): 10,
+  (61, 'G'): 10,
+  (61, 'H'): 10,
+  (61, 'I'): 10,
+  (61, 'J'): 10,
+  (61, 'K'): 10,
+  (61, 'L'): 10,
+  (61, 'M'): 10,
+  (61, 'N'): 10,
+  (61, 'O'): 10,
+  (61, 'P'): 10,
+  (61, 'Q'): 10,
+  (61, 'R'): 10,
+  (61, 'S'): 10,
+  (61, 'T'): 10,
+  (61, 'U'): 10,
+  (61, 'V'): 10,
+  (61, 'W'): 10,
+  (61, 'X'): 10,
+  (61, 'Y'): 10,
+  (61, 'Z'): 10,
+  (61, '_'): 10,
+  (61, 'a'): 10,
+  (61, 'b'): 10,
+  (61, 'c'): 10,
+  (61, 'd'): 10,
+  (61, 'e'): 10,
+  (61, 'f'): 10,
+  (61, 'g'): 10,
+  (61, 'h'): 10,
+  (61, 'i'): 10,
+  (61, 'j'): 10,
+  (61, 'k'): 10,
+  (61, 'l'): 10,
+  (61, 'm'): 10,
+  (61, 'n'): 10,
+  (61, 'o'): 10,
+  (61, 'p'): 10,
+  (61, 'q'): 10,
+  (61, 'r'): 62,
+  (61, 's'): 10,
+  (61, 't'): 10,
+  (61, 'u'): 10,
+  (61, 'v'): 10,
+  (61, 'w'): 10,
+  (61, 'x'): 10,
+  (61, 'y'): 10,
+  (61, 'z'): 10,
+  (62, '0'): 10,
+  (62, '1'): 10,
+  (62, '2'): 10,
+  (62, '3'): 10,
+  (62, '4'): 10,
+  (62, '5'): 10,
+  (62, '6'): 10,
+  (62, '7'): 10,
+  (62, '8'): 10,
+  (62, '9'): 10,
+  (62, 'A'): 10,
+  (62, 'B'): 10,
+  (62, 'C'): 10,
+  (62, 'D'): 10,
+  (62, 'E'): 10,
+  (62, 'F'): 10,
+  (62, 'G'): 10,
+  (62, 'H'): 10,
+  (62, 'I'): 10,
+  (62, 'J'): 10,
+  (62, 'K'): 10,
+  (62, 'L'): 10,
+  (62, 'M'): 10,
+  (62, 'N'): 10,
+  (62, 'O'): 10,
+  (62, 'P'): 10,
+  (62, 'Q'): 10,
+  (62, 'R'): 10,
+  (62, 'S'): 10,
+  (62, 'T'): 10,
+  (62, 'U'): 10,
+  (62, 'V'): 10,
+  (62, 'W'): 10,
+  (62, 'X'): 10,
+  (62, 'Y'): 10,
+  (62, 'Z'): 10,
+  (62, '_'): 10,
+  (62, 'a'): 10,
+  (62, 'b'): 10,
+  (62, 'c'): 10,
+  (62, 'd'): 10,
+  (62, 'e'): 10,
+  (62, 'f'): 10,
+  (62, 'g'): 10,
+  (62, 'h'): 10,
+  (62, 'i'): 10,
+  (62, 'j'): 10,
+  (62, 'k'): 10,
+  (62, 'l'): 10,
+  (62, 'm'): 10,
+  (62, 'n'): 10,
+  (62, 'o'): 10,
+  (62, 'p'): 10,
+  (62, 'q'): 10,
+  (62, 'r'): 10,
+  (62, 's'): 10,
+  (62, 't'): 10,
+  (62, 'u'): 10,
+  (62, 'v'): 10,
+  (62, 'w'): 10,
+  (62, 'x'): 10,
+  (62, 'y'): 10,
+  (62, 'z'): 10,
+  (64, '='): 66,
+  (67, '<'): 71,
+  (69, '='): 70,
+  (73, '0'): 74,
+  (73, '1'): 74,
+  (73, '2'): 74,
+  (73, '3'): 74,
+  (73, '4'): 74,
+  (73, '5'): 74,
+  (73, '6'): 74,
+  (73, '7'): 74,
+  (73, '8'): 74,
+  (73, '9'): 74,
+  (74, '0'): 74,
+  (74, '1'): 74,
+  (74, '2'): 74,
+  (74, '3'): 74,
+  (74, '4'): 74,
+  (74, '5'): 74,
+  (74, '6'): 74,
+  (74, '7'): 74,
+  (74, '8'): 74,
+  (74, '9'): 74},
+ set([1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 41, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 74]),
+ set([1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 41, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 74]),
+ ['0, start|, 0, start|, 0, 0, 0, 0, 0, start|, 0, 0, 0, start|, 0, start|, 0, start|, 0, 0, 0, 0, start|, 0, start|, 0, start|, 0, start|, 0, start|, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0',
+  'IGNORE',
+  '(',
+  'ATOM',
+  'NUMBER',
+  'NUMBER',
+  'ATOM',
+  '1, 1, 1, 1',
+  'VAR',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  '|',
+  '0, 1, 0, start|, 0, final*, start*, 0, 0, 1, final|, start|, 0, final*, start*, 0, 0, final|, start|, 0, 1, final*, start*',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  '[',
+  'ATOM',
+  '.',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'IGNORE',
+  ')',
+  'ATOM',
+  'ATOM',
+  ']',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  '2',
+  'ATOM',
+  '2',
+  '2',
+  'ATOM',
+  '2',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  '2',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'final*, start*, 1, 0, 0, start|, 0, final*, start*, 0, final*, start*, 0, 0, 1, final|, start|, 0, final*, start*, 0, final*, start*, 0, 0, final|, start|, 0, 1, final*, start*, 0, final*, 0, start|, 0, final*, start*, final*, start*, 0, 0, final*, 1, final|, final*, 0, start|, 0, final*, start*, final*, start*, 0, 0, final*, final|, 1, final*, 0, 1, final|, start|, 0, final*, start*, final*, start*, 0, 0, final*, final*, 0, final|, start|, 0, 1, final*, start*, final*, start*, 0, 0, final*',
+  'ATOM',
+  'ATOM',
+  '1, 0, 1, 0, start|',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  '2',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  'ATOM',
+  '1, 0',
+  'NUMBER']), {'IGNORE': None})
+basic_rules = [Rule('query', [['toplevel_op_expr', '.', 'EOF']]), Rule('fact', [['toplevel_op_expr', '.']]), Rule('complexterm', [['ATOM', '(', 'toplevel_op_expr', ')'], ['expr']]), Rule('expr', [['VAR'], ['NUMBER'], ['+', 'NUMBER'], ['-', 'NUMBER'], ['ATOM'], ['(', 'toplevel_op_expr', ')'], ['listexpr']]), Rule('listexpr', [['[', 'listbody', ']']]), Rule('listbody', [['toplevel_op_expr', '|', 'toplevel_op_expr'], ['toplevel_op_expr']])]
+# generated code between this line and its other occurence
+ 
+if __name__ == '__main__':
+    f = py.magic.autopath()
+    oldcontent = f.read()
+    s = "# GENERATED CODE BETWEEN THIS LINE AND ITS OTHER OCCURENCE\n".lower()
+    pre, gen, after = oldcontent.split(s)
+
+    lexer, parser_fact, parser_query, basic_rules = make_all()
+    newcontent = ("%s%s\nparser_fact = %r\nparser_query = %r\n%s\n"
+                  "basic_rules = %r\n%s%s") % (
+            pre, s, parser_fact, parser_query, lexer.get_dummy_repr(),
+            basic_rules, s, after)
+    print newcontent
+    f.write(newcontent)

Added: pypy/dist/pypy/lang/prolog/interpreter/term.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/term.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,591 @@
+import math
+from pypy.rpython.objectmodel import we_are_translated, UnboxedValue
+from pypy.rlib.rarithmetic import intmask
+from pypy.lang.prolog.interpreter.error import UnificationFailed, UncatchableError
+
+DEBUG = True
+
+TAGBITS = 3
+CURR_TAG = 1
+def tag():
+    global CURR_TAG
+    CURR_TAG += 1
+    assert CURR_TAG <= 2 ** TAGBITS
+    return CURR_TAG
+
+def debug_print(*args):
+    if DEBUG and not we_are_translated():
+        print " ".join([str(a) for a in args])
+
+class PrologObject(object):
+    __slots__ = ()
+    def getvalue(self, frame):
+        return self
+
+    def dereference(self, frame):
+        return self
+
+    def get_max_var(self):
+        return -1
+
+    def clone(self, offset):
+        return self
+
+    def clone_compress_vars(self, vars_new_indexes, offset):
+        return self
+
+    def make_template(self, vars_new_indexes):
+        return self
+
+    def instantiate_template(self, template_frame):
+        return self
+
+    def get_unify_hash(self, frame=None):
+        # if two non-var objects return two different numbers
+        # they must not be unifiable
+        raise NotImplementedError("abstract base class")
+
+    def get_deeper_unify_hash(self, frame=None):
+        return [self.get_unify_hash(frame)]
+
+    def unify(self, other, frame, occurs_check=False):
+        pass
+    unify._annspecialcase_ = "specialize:arg(3)"
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        raise NotImplementedError("abstract base class")
+
+    def contains_var(self, var, frame):
+        return False
+
+    def __eq__(self, other):
+        # for testing
+        return self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+
+
+class Var(PrologObject, UnboxedValue):
+    TAG = 0
+    STANDARD_ORDER = 0
+
+    __slots__ = ('index', )
+
+    def unify(self, other, frame, occurs_check=False):
+        #debug_print("unify", self, other, frame.vars)
+        self, val = self.get_last_var_in_chain_and_val(frame)
+        if val is not None:
+            other.unify(val, frame, occurs_check)
+        elif isinstance(other, Var):
+            other, val = other.get_last_var_in_chain_and_val(frame)
+            if val is None:
+                if other.index != self.index:
+                    frame.setvar(self.index, other)
+            else:
+                self.unify(val, frame, occurs_check)
+        else:
+            if occurs_check and other.contains_var(self, frame):
+                raise UnificationFailed()
+            frame.setvar(self.index, other)
+    unify._annspecialcase_ = "specialize:arg(3)"
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        self, val = self.get_last_var_in_chain_and_val(frame)
+        if val is not None:
+            return val.unify_with_template(other, frame, template_frame,
+                                           to_instantiate)
+        if isinstance(other, Var):
+            other, otherval = other.get_last_var_in_chain_and_val(frame)
+            if otherval is None:
+                if other.index != self.index:
+                    return frame.setvar(self.index, other)
+            else:
+                return self.unify_with_template(otherval, frame,
+                                                template_frame, to_instantiate)
+        else:
+            if isinstance(other, TemplateVar):
+                return other.unify_with_template(self, frame, template_frame,
+                                                 to_instantiate)
+            if isinstance(other, Term):
+                to_instantiate.append((self.index, other))
+            frame.setvar(self.index, other)
+
+    def getvalue(self, frame):
+        var, res = self.get_last_var_in_chain_and_val(frame)
+        if res is not None:
+            return res.getvalue(frame)
+        return var
+
+    def dereference(self, frame):
+        var, res = self.get_last_var_in_chain_and_val(frame)
+        if res is not None:
+            return res
+        return var
+
+    def get_last_var_in_chain_and_val(self, frame):
+        next = frame.getvar(self.index)
+        if next is None or not isinstance(next, Var):
+            return self, next
+        # do path compression
+        last, val = next.get_last_var_in_chain_and_val(frame)
+        if val is None:
+            frame.setvar(self.index, last)
+        else:
+            frame.setvar(self.index, val)
+        return last, val
+
+    def get_max_var(self):
+        return self.index
+
+    def clone(self, offset):
+        return Var(self.index + offset)
+
+    def clone_compress_vars(self, vars_new_indexes, offset):
+        if self.index in vars_new_indexes:
+            return Var(vars_new_indexes[self.index])
+        index = len(vars_new_indexes) + offset
+        vars_new_indexes[self.index] = index
+        return Var(index)
+    
+    def make_template(self, vars_new_indexes):
+        if self.index in vars_new_indexes:
+            return TemplateVar(vars_new_indexes[self.index])
+        index = len(vars_new_indexes)
+        vars_new_indexes[self.index] = index
+        return TemplateVar(index)
+
+    def get_unify_hash(self, frame=None):
+        if frame is None:
+            return 0
+        self = self.dereference(frame)
+        if isinstance(self, Var):
+            return 0
+        return self.get_unify_hash(frame)
+
+    def contains_var(self, var, frame):
+        self = self.dereference(frame)
+        if self is var:
+            return True
+        if not isinstance(self, Var):
+            return self.contains_var(var, frame)
+        return False
+
+    def __repr__(self):
+        return "Var(%s)" % (self.index, )
+
+
+class TemplateVar(PrologObject):
+    TAG = 0
+    STANDARD_ORDER = 0
+    __slots__ = 'index'
+
+    def __init__(self, index):
+        self.index = index
+
+    def unify(self, other, frame, occurs_check=False):
+        raise UncatchableError("TemplateVar in wrong place")
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        val = template_frame[self.index]
+        if val is None:
+            template_frame[self.index] = other
+        else:
+            val.unify_with_template(other, frame, template_frame, to_instantiate)
+
+    def getvalue(self, frame):
+        raise UncatchableError("TemplateVar in wrong place")
+
+    def dereference(self, frame):
+        raise UncatchableError("TemplateVar in wrong place")
+
+    def get_max_var(self):
+        return self.index
+
+    def clone(self, offset):
+        return TemplateVar(self.index + offset)
+
+    def clone_compress_vars(self, vars_new_indexes, offset):
+        raise UncatchableError("TemplateVar in wrong place")
+
+    def make_template(self, vars_new_indexes):
+        raise UncatchableError("TemplateVar in wrong place")
+
+    def instantiate_template(self, template_frame):
+        return template_frame[self.index]
+
+    def get_unify_hash(self, frame=None):
+        return 0
+
+    def contains_var(self, var, frame):
+        raise UncatchableError("TemplateVar in wrong place")
+
+    def __repr__(self):
+        return "TemplateVar(%s)" % (self.index, )
+
+
+class Callable(PrologObject):
+    name = ""
+    signature = ""
+
+    def get_prolog_signature(self):
+        raise NotImplementedError("abstract base")
+
+class Atom(Callable):
+    TAG = tag()
+    STANDARD_ORDER = 1
+    def __init__(self, name):
+        self.name = name
+        self.signature = self.name + "/0"
+
+    def __str__(self):
+        return self.name
+
+    def __repr__(self):
+        return "Atom(%r)" % (self.name,)
+
+    def unify(self, other, frame, occurs_check=False):
+        #debug_print("unify", self, other, type(other))
+        if isinstance(other, Var):
+            return other.unify(self, frame, occurs_check)
+        elif isinstance(other, Atom):
+            if other.name != self.name:
+                raise UnificationFailed
+            return
+        raise UnificationFailed
+    unify._annspecialcase_ = "specialize:arg(3)"
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        if isinstance(other, Var):
+            return other.unify_with_template(self, frame, template_frame, to_instantiate)
+        elif isinstance(other, TemplateVar):
+            return other.unify_with_template(self, frame, template_frame, to_instantiate)
+        elif isinstance(other, Atom):
+            if other.name != self.name:
+                raise UnificationFailed
+            return
+        raise UnificationFailed
+
+    def get_unify_hash(self, frame=None):
+        return intmask(hash(self.name) << TAGBITS | self.TAG)
+
+    def get_prolog_signature(self):
+        return Term("/", [self, Number(0)])
+
+class Number(PrologObject):
+    TAG = tag()
+    STANDARD_ORDER = 2
+    def __init__(self, num):
+        self.num = num
+ 
+    def unify(self, other, frame, occurs_check=False):
+        #debug_print("unify", self, other, type(other))
+        if isinstance(other, Var):
+            return other.unify(self, frame, occurs_check)
+        elif isinstance(other, Number):
+            if other.num != self.num:
+                raise UnificationFailed
+            return
+        raise UnificationFailed
+    unify._annspecialcase_ = "specialize:arg(3)"
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        if isinstance(other, Var):
+            return other.unify_with_template(self, frame, template_frame, to_instantiate)
+        elif isinstance(other, TemplateVar):
+            return other.unify_with_template(self, frame, template_frame, to_instantiate)
+        elif isinstance(other, Number):
+            if other.num != self.num:
+                raise UnificationFailed
+            return
+        raise UnificationFailed
+
+    def __str__(self):
+        return repr(self.num)
+
+    def __repr__(self):
+        return "Number(%r)" % (self.num, )
+
+    def get_unify_hash(self, frame=None):
+        return intmask(self.num << TAGBITS | self.TAG)
+
+
+class Float(PrologObject):
+    TAG = tag()
+    STANDARD_ORDER = 2
+    def __init__(self, num):
+        self.num = num
+
+    def unify(self, other, frame, occurs_check=False):
+        if isinstance(other, Var):
+            return other.unify(self, frame, occurs_check)
+        elif isinstance(other, Float):
+            if other.num != self.num:
+                raise UnificationFailed
+            return
+        raise UnificationFailed
+    unify._annspecialcase_ = "specialize:arg(3)"
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        if isinstance(other, Var):
+            return other.unify_with_template(self, frame, template_frame, to_instantiate)
+        elif isinstance(other, TemplateVar):
+            return other.unify_with_template(self, frame, template_frame, to_instantiate)
+        elif isinstance(other, Float):
+            if other.num != self.num:
+                raise UnificationFailed
+            return
+        raise UnificationFailed
+
+    def get_unify_hash(self, frame=None):
+        #XXX no clue whether this is a good idea...
+        m, e = math.frexp(self.num)
+        m = intmask(int(m / 2 * 2 ** (32 - TAGBITS)))
+        return intmask(m << TAGBITS | self.TAG)
+
+    def __str__(self):
+        return repr(self.num)
+
+    def __repr__(self):
+        return "Float(%r)" % (self.num, )
+
+
+# helper functions for various Term methods
+
+def _clone(obj, offset):
+    return obj.clone(offset)
+
+def _clone_compress_vars(obj, vars_new_indexes, offset):
+    return obj.clone_compress_vars(vars_new_indexes, offset)
+
+def _make_template(obj, vars_new_indexes):
+    return obj.make_template(vars_new_indexes)
+
+def _instantiate_template(obj, template_frame):
+    return obj.instantiate_template(template_frame)
+
+def _getvalue(obj, frame):
+    return obj.getvalue(frame)
+
+class Term(Callable):
+    TAG = tag()
+    STANDARD_ORDER = 3
+    def __init__(self, name, args, signature=None):
+        self.name = name
+        self.args = args
+        if signature is None:
+            self.signature = name + "/" + str(len(args))
+        else:
+            self.signature = signature
+
+    def __repr__(self):
+        return "Term(%r, %r)" % (self.name, self.args)
+
+    def __str__(self):
+        return "%s(%s)" % (self.name, ", ".join([str(a) for a in self.args]))
+
+    def unify(self, other, frame, occurs_check=False):
+        if not isinstance(other, Term):
+            if isinstance(other, Var):
+                return other.unify(self, frame, occurs_check)
+            raise UnificationFailed
+        if (hash(self.name) != hash(other.name) or 
+            self.name != other.name or len(self.args) != len(other.args)):
+            raise UnificationFailed
+        for i in range(len(self.args)):
+            self.args[i].unify(other.args[i], frame, occurs_check)
+    unify._annspecialcase_ = "specialize:arg(3)"
+
+    def unify_with_template(self, other, frame, template_frame, to_instantiate):
+        if not isinstance(other, Term):
+            if isinstance(other, Var):
+                return other.unify_with_template(self, frame, template_frame, to_instantiate)
+            if isinstance(other, TemplateVar):
+                return other.unify_with_template(self, frame, template_frame, to_instantiate)
+            raise UnificationFailed
+        if (hash(self.name) != hash(other.name) or 
+            self.name != other.name or len(self.args) != len(other.args)):
+            raise UnificationFailed
+        for i in range(len(self.args)):
+            self.args[i].unify_with_template(other.args[i], frame,
+                                             template_frame, to_instantiate)
+
+    def get_max_var(self):
+        result = -1
+        for subterm in self.args:
+            result = max(result, subterm.get_max_var())
+        return result
+    
+    def clone(self, offset):
+        return self._copy_term(_clone, offset)
+
+    def clone_compress_vars(self, vars_new_indexes, offset):
+        return self._copy_term(_clone_compress_vars, vars_new_indexes, offset)
+
+    def make_template(self, vars_new_indexes):
+        return self._copy_term(_make_template, vars_new_indexes)
+
+    def instantiate_template(self, template_frame):
+        return self._copy_term(_instantiate_template, template_frame)
+
+    def getvalue(self, frame):
+        return self._copy_term(_getvalue, frame)
+
+    def _copy_term(self, copy_individual, *extraargs):
+        args = [None] * len(self.args)
+        newinstance = False
+        for i in range(len(self.args)):
+            arg = self.args[i]
+            cloned = copy_individual(arg, *extraargs)
+            if cloned is not arg:
+                newinstance = True
+            args[i] = cloned
+        if newinstance:
+            return Term(self.name, args, self.signature)
+        else:
+            return self
+    _copy_term._annspecialcase_ = "specialize:arg(1)"
+
+    def get_unify_hash(self, frame=None):
+        return intmask(hash(self.signature) << TAGBITS | self.TAG)
+
+    def get_deeper_unify_hash(self, frame=None):
+        result = [0] * len(self.args)
+        for i in range(len(self.args)):
+            result[i] = self.args[i].get_unify_hash(frame)
+        return result
+
+    def get_prolog_signature(self):
+        return Term("/", [Atom(self.name), Number(len(self.args))])
+    
+    def contains_var(self, var, frame):
+        for arg in self.args:
+            if arg.contains_var(var, frame):
+                return True
+        return False
+        
+
+class Rule(object):
+    def __init__(self, head, body):
+        from pypy.lang.prolog.interpreter import helper
+        d = {}
+        head = head.make_template(d)
+        assert isinstance(head, Callable)
+        self.head = head
+        if body is not None:
+            body = helper.ensure_callable(body)
+            self.body = body.make_template(d)
+        else:
+            self.body = None
+        self.numvars = len(d)
+        self.signature = self.head.signature
+        self.unify_hash = self.head.get_deeper_unify_hash()
+        self._does_contain_cut()
+
+    def _does_contain_cut(self):
+        if self.body is None:
+            self.contains_cut = False
+            return
+        stack = [self.body]
+        while stack:
+            current = stack.pop()
+            if isinstance(current, Atom):
+                if current.name == "!":
+                    self.contains_cut = True
+                    return
+            elif isinstance(current, Term):
+                stack.extend(current.args)
+        self.contains_cut = False
+
+    def clone(self, offset):
+        if self.body is None:
+            body = None
+        else:
+            body = self.body.clone(offset)
+        return Rule(self.head.clone(offset), body)
+
+    def clone_and_unify_head(self, frame, head):
+        template_frame = [None] * self.numvars
+        if isinstance(head, Term):
+            to_instantiate = []
+            h2 = self.head
+            assert isinstance(h2, Term)
+            for i in range(len(h2.args)):
+                arg1 = h2.args[i]
+                arg2 = head.args[i]
+                if (isinstance(arg1, Term) or
+                    isinstance(arg1, TemplateVar)):
+                    h2.args[i].unify_with_template(
+                        head.args[i], frame, template_frame, to_instantiate)
+                else:
+                    h2.args[i].unify(head.args[i], frame)
+            extend_and_normalize_template_frame(template_frame, frame)
+            for index, obj in to_instantiate:
+                frame.vars[index] = obj.instantiate_template(template_frame)
+        body = self.body
+        if body is None:
+            return None
+        return body.instantiate_template(template_frame)
+
+    def __repr__(self):
+        if self.body is None:
+            return "%s." % (self.head, )
+        return "%s :- %s." % (self.head, self.body)
+
+
+def extend_and_normalize_template_frame(template_frame, frame):
+    next_free = frame.maxvar()
+    for i in range(len(template_frame)):
+        val = template_frame[i]
+        if val is None:
+            template_frame[i] = Var(next_free)
+            next_free += 1
+        elif isinstance(val, TemplateVar):
+            template_frame[i] = template_frame[val.index]
+    frame.extend(next_free - frame.maxvar())
+
+def rcmp(a, b): # RPython does not support cmp...
+    if a == b:
+        return 0
+    if a < b:
+        return -1
+    return 1
+rcmp._annspecialcase_ = "specialize:argtype(0)"
+
+def cmp_standard_order(obj1, obj2, frame):
+    c = rcmp(obj1.STANDARD_ORDER, obj2.STANDARD_ORDER)
+    if c != 0:
+        return c
+    if isinstance(obj1, Var):
+        assert isinstance(obj2, Var)
+        return rcmp(obj1.index, obj2.index)
+    if isinstance(obj1, Atom):
+        assert isinstance(obj2, Atom)
+        return rcmp(obj1.name, obj2.name)
+    if isinstance(obj1, Term):
+        assert isinstance(obj2, Term)
+        c = rcmp(len(obj1.args), len(obj2.args))
+        if c != 0:
+            return c
+        c = rcmp(obj1.name, obj2.name)
+        if c != 0:
+            return c
+        for i in range(len(obj1.args)):
+            a1 = obj1.args[i].dereference(frame)
+            a2 = obj2.args[i].dereference(frame)
+            c = cmp_standard_order(a1, a2, frame)
+            if c != 0:
+                return c
+        return 0
+    # XXX hum
+    if isinstance(obj1, Number):
+        if isinstance(obj2, Number):
+            return rcmp(obj1.num, obj2.num)
+        elif isinstance(obj2, Float):
+            return rcmp(obj1.num, obj2.num)
+    if isinstance(obj1, Float):
+        if isinstance(obj2, Number):
+            return rcmp(obj1.num, obj2.num)
+        elif isinstance(obj2, Float):
+            return rcmp(obj1.num, obj2.num)
+    assert 0

Added: pypy/dist/pypy/lang/prolog/interpreter/test/__init__.py
==============================================================================

Added: pypy/dist/pypy/lang/prolog/interpreter/test/dont_test_translate.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/dont_test_translate.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,51 @@
+from pypy.translator.interactive import Translation
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.lang.prolog.interpreter import parsing
+from pypy.lang.prolog.interpreter.term import Atom
+from pypy.lang.prolog.interpreter.test.tool import *
+
+from pypy.lang.prolog.interpreter.conftest import option
+if not option.slow:
+    py.test.skip("slow tests")
+
+def test_parser():
+    def f(x):
+        if x:
+            s = "a(X, Y, Z)."
+        else:
+            s = "f(a, X, _, _, X, f(X, 2.455))."
+        term = parsing.parse_file(s)
+        assert isinstance(term, parsing.Nonterminal)
+        return term.symbol
+    assert f(True) == "file"
+    assert f(True) == "file"
+    t = Translation(f)
+    t.annotate([bool])
+    t.rtype()
+    t.backendopt()
+    func = t.compile_c()
+    assert func(True) == "file"
+    assert func(False) == "file"
+
+def test_engine():
+    e = get_engine("""
+        g(a, a).
+        g(a, b).
+        g(b, c).
+        f(X, Z) :- g(X, Y), g(Y, Z).
+    """)
+    t1 = parse_query_term("f(a, c).")
+    t2 = parse_query_term("f(X, c).")
+    def run():
+        e.run(t1)
+        e.run(t2)
+        v0 = e.frame.getvar(0)
+        if isinstance(v0, Atom):
+            return v0.name
+        return "no!"
+    assert run() == "a"
+    t = Translation(run)
+    t.annotate()
+    t.rtype()
+    func = t.compile_c()
+    assert func() == "a"

Added: pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,24 @@
+import py
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine
+from pypy.lang.prolog.interpreter.error import UnificationFailed, CutException
+from pypy.lang.prolog.interpreter.engine import Frame, Engine
+from pypy.lang.prolog.interpreter import error
+from pypy.lang.prolog.interpreter.test.tool import collect_all, assert_false, assert_true
+
+def test_simple():
+    assert_true("X is 1 + 2, X = 3.")
+    assert_true("X is 1.2 + 2.8, X = 4.")
+    assert_false("X is 1.1 + 2.8, X = 4.0.")
+    assert_true("X is 2 * -2, X = -4.")
+    assert_true("X is 2 + -2, X = 0.")
+    assert_true("X is 2 // -2, X = -1.")
+
+def test_comparison():
+    assert_true("1 =:= 1.0.")
+    assert_true("1 + 1 > 1.")
+    assert_true("1 + 0.001 >= 1 + 0.001.")
+    assert_true("1 + 0.001 =< 1 + 0.001.")
+    assert_false("1 > 1.")
+    assert_false("1 =\\= 1.0.")
+    assert_true("1 =\\= 32.")

Added: pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,341 @@
+import py
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine
+from pypy.lang.prolog.interpreter.error import UnificationFailed
+from pypy.lang.prolog.interpreter.engine import Frame, Engine
+from pypy.lang.prolog.interpreter import error
+from pypy.lang.prolog.interpreter.test.tool import collect_all, assert_false, assert_true
+from pypy.lang.prolog.interpreter.test.tool import prolog_raises
+
+def test_fail():
+    e = get_engine("""
+        g(a).
+        f(X) :- g(X), fail.
+        f(a).
+    """)
+    frames = collect_all(e, "f(X).")
+    assert len(frames) == 1
+
+def test_not():
+    e = get_engine("""
+        g(a, a).
+        g(b, a).
+        g(b, b).
+
+        m(o, a).
+        m(o, b).
+        m(o, c).
+        same(X, X).
+
+        sibling(X, Y) :- m(Z, X), m(Z, Y), \\+same(X, Y).
+    """)
+    assert_true("not((!, fail)).", e)
+    assert_true("not(g(b, c)).", e)
+    assert_false("not(g(a, a)).", e)
+    assert_true("\\+(g(b, c)).", e)
+    assert_false("\\+(g(a, a)).", e)
+    assert_false("not(!).", e)
+
+    frames = collect_all(e, "sibling(a, X).")
+    assert len(frames) == 2
+
+def test_and():
+    assert_false("fail, X.")
+    prolog_raises("type_error(callable, 1)", "(fail, 1)")
+
+def test_nonvar():
+    e = get_engine("""
+        g(X) :- nonvar(X).
+        g(x, X) :- nonvar(x), nonvar(X).
+        f(X, Y) :- nonvar(X), nonvar(Y).
+    """)
+    assert_true("g(a).", e)
+    assert_false("g(X).", e)
+    assert_true("g(x).", e)
+    assert_true("g(x, a).", e)
+    assert_true("g(X, X).", e)
+    assert_false("f(X, X).", e)
+
+def test_consult():
+    p = py.test.ensuretemp("prolog")
+    f = p.join("test.pl")
+    f.write("g(a, a). g(a, b).")
+    e = get_engine("g(c, c).")
+    assert_true("g(c, c).", e)
+    assert_true("consult('%s')." % (f, ), e)
+    assert_true("g(c, c).", e)
+    assert_true("g(a, a).", e)
+    assert_true("g(a, b).", e)
+    py.test.raises(
+        error.CatchableError,
+        assert_true, "consult('/hopefully/does/not/exist').")
+
+def test_assert_retract():
+    e = get_engine("g(b, b).")
+    assert_true("g(B, B).", e)
+    assert_true("assert(g(c, d)).", e)
+    assert_true("assert(g(a, b)).", e)
+    assert_true("assert(g(a, b)).", e) # assert the same rule multiple times
+    assert_true("g(B, B).", e)
+    assert_true("g(a, b).", e)
+    assert_true("g(c, d).", e)
+    assert_true("retract(g(B, B)).", e)
+    assert_false("g(B, B).", e)
+    assert_true("retract(g(a, b)).", e)
+    assert_true("g(a, b).", e)
+    assert_true("retract(g(a, b)).", e)
+    assert_false("retract(g(a, b)).", e)
+    assert_false("g(a, b).", e)
+    assert_true("g(c, d).", e)
+    e = get_engine("""
+        g(b, b).
+        f(X) :- g(X, b).
+        f(a).
+    """)
+    assert_true("f(b).", e)
+    assert_true("f(a).", e)
+    assert_true("retract(f(X) :- g(X, Y)), Y == b.", e)
+    assert_false("f(b).", e)
+    assert_true("f(a).", e)
+    prolog_raises("permission_error(X, Y, Z)", "retract(atom(X))")
+
+def test_assert_at_right_end():
+    e = get_engine("g(b, b). f(b, b). h(b, b).")
+    assert_true("assert(g(a, a)).", e)
+    assert_true("assertz(f(a, a)).", e)
+    assert_true("A = a, asserta(h(A, A)).", e)
+    f = assert_true("g(B, B).", e)
+    assert f.vars[0].name == "b"
+    f = assert_true("f(B, B).", e)
+    assert f.vars[0].name == "b"
+    assert_false("h(c, c).", e)
+    f = assert_true("h(B, B).", e)
+    assert f.vars[0].name == "a"
+
+def test_assert_logical_update_view():
+    e = get_engine("""
+        g(a).
+        g(c) :- assertz(g(d)).
+        g(b).
+    """)
+    frames = collect_all(e, "g(X).")
+    assert len(frames) == 3
+
+def test_abolish():
+    e = get_engine("g(b, b). g(c, c). g(a). f(b, b). h(b, b).")
+    assert_true("abolish(g/2).", e)
+    assert_true("g(a).", e)
+    prolog_raises("existence_error(X, Y)", "g(A, B)", e)
+    prolog_raises("type_error(predicate_indicator, a)", "abolish(a)", e)
+
+def test_unify():
+    assert_true("g(b, B) = g(b, b).")
+    assert_true("X = Y.")
+    assert_true("X = f(X).")
+    assert_false("g(b, B) \\= g(b, b).")
+    assert_false("X \\= Y.")
+    assert_false("X \\= f(X).")
+    assert_true("x \\= y.")
+    assert_true("unify_with_occurs_check(X, Y).")
+    assert_true("unify_with_occurs_check(X, X).")
+    assert_false("unify_with_occurs_check(X, f(X)).")
+    assert_false("unify_with_occurs_check(X, f(g(h(a, b, c, d(X, e), e)))).")
+    assert_false("unify_with_occurs_check(g(X), X).")
+    assert_false("X = Y, unify_with_occurs_check(X, f(d(Y), Y)).")
+
+def test_call():
+    e = get_engine("g(b, b).")
+    assert_true("call(g(X, X)).", e)
+    assert_true("X =.. [g, b, b], call(X).", e)
+    e = get_engine("""
+        g(X) :- call(f(X)).
+        g(a).
+        g(b).
+        f(X) :- !, h(X).
+        f(a).
+        f(b).
+        h(X) :- fail.
+        withcut(X) :- call(!), fail.
+        withcut(a).
+        """)
+    frames = collect_all(e, "g(X).")
+    assert len(frames) == 2
+    assert_true("withcut(a).", e)
+    assert_true("call((!, true)).")
+
+def test_or_with_cut():
+    assert_false("((X = 1, !); X = 2), X = 2.")
+    assert_true("((X = 1, !); X = 2), X = 1.")
+
+def test_cut():
+    e = get_engine("""
+        f(0).
+        f(X) :- Y is X - 1, !, f(Y).
+        f(X) :- Y is X - 2, !, f(Y).
+    """)
+    assert_true("f(20).", e)
+
+def test_term_construction():
+    assert_true("g(a, b, c) =.. [G, A, B, C].")
+    assert_true("g(a, b, c) =.. [g, a, b, c].")
+    assert_true("X =.. [g, a, b, c], X = g(a, b, c).")
+    assert_true("arg(1, g(a, b, c), a).")
+    assert_true("arg(2, g(a, b, c), b).")
+    assert_true("arg(3, g(a, b, c), c).")
+    assert_false("arg(3, g(a, b, c), d).")
+    assert_false("arg(0, g(a, b, c), X).")
+    assert_false("arg(10, g(a, b, c), X).")
+    assert_true("arg(1, g(a, b, c), X), X = a.")
+    assert_true("arg(2, f(a, b, c), X), X = b.")
+    assert_true("arg(3, h(a, b, c), X), X = c.")
+    e = get_engine("""
+        f(1, a).
+        f(2, b).
+        f(3, c).
+    """)
+    frames = collect_all(e, "arg(X, g(a, b, c), A), f(X, A).")
+    assert len(frames) == 3
+    assert_true("arg(X, h(a, b, c), b), X = 2.")
+    assert_true("arg(X, h(a, b, g(X, b)), g(3, B)), X = 3, B = b.")
+    assert_true("copy_term(X, Y), X = 1, Y = 2.")
+    assert_true("copy_term(a, a).")
+    assert_false("copy_term(f(X), g(X)).")
+    assert_true("copy_term(f(X), f(a)), X = b.")
+
+def test_type_checks():
+    assert_true("integer(123).")
+    assert_false("integer(a).")
+    assert_false("integer(X).")
+    assert_true("float(123.12).")
+    assert_false("float(a).")
+    assert_false("float(12).")
+    assert_true("number(123).")
+    assert_true("number(42.42).")
+    assert_false("integer(a).")
+    assert_false("integer(X).")
+    assert_true("var(X).")
+    assert_false("X = a, var(X).")
+    assert_true("compound(g(a)).")
+    assert_false("compound(gxx).")
+    assert_false("compound(123).")
+    assert_false("compound([]).")
+    assert_false("compound(X).")
+    assert_true("atom(a).")
+    assert_true("atom('asdf').")
+    assert_false("atom(12).")
+    assert_false("atom(X).")
+    assert_true("atomic('asdf').")
+    assert_true("atomic(12.5).")
+    assert_false("atomic(f(1, 2, 3)).")
+    assert_false("atomic(X).")
+    assert_false("callable(X).")
+    assert_false("callable(1).")
+    assert_true("callable(asdf).")
+    assert_true("callable(asdf(a, b, c, d, e, f)).")
+    assert_true("ground(a).")
+    assert_true("ground(t(a, b, f(a, b, g(a, b)))).")
+    assert_false("ground(t(a, b, f(a, b, g(a, X)))).")
+    assert_true("X = 13, ground(t(a, b, f(a, b, g(a, X)))).")
+    assert_false("ground(X).")
+
+def test_repeat():
+    assert_true("repeat, true.")
+    py.test.raises(UnificationFailed,
+        Engine().run, parse_query_term("repeat, !, fail."))
+    # hard to test repeat differently
+
+def test_exception_handling():
+    assert_true("catch(f, E, true).")
+    assert_true("catch(throw(error), E, true).")
+    py.test.raises(error.CatchableError,
+                   assert_true, "catch(true, E, fail), f.")
+    py.test.raises(error.CatchableError,
+                   assert_true, "catch(throw(error), failure, fail).")
+    assert_true("catch(catch(throw(error), failure, fail), error, true).")
+
+def test_between():
+    assert_true("between(12, 15, 12).")
+    assert_true("between(-5, 15, 0).")
+    assert_false("between(12, 15, 6).")
+    assert_false("between(12, 15, 16).")
+    frames = collect_all(Engine(), "between(1, 4, X).")
+    assert len(frames) == 4
+    assert frames[0].vars[0].num == 1
+
+def test_is():
+    assert_true("5 is 1 + 1 + 1 + 1 + 1.")
+
+def test_parser_access():
+    assert_true("current_op(200, xfx, **).")
+    f = collect_all(Engine(), "current_op(200, Form, X).")
+    assert len(f) == 2
+    e = get_engine("""
+        foo(a, b).
+    """)
+    assert_true("op(450, xfy, foo).", e)
+    assert_true("a foo b.", e)
+    assert_true("op(0, xfy, foo).", e)
+    # XXX really a ParseError
+    py.test.raises(Exception, assert_false, "a foo b.", e) 
+    # change precedence of + for funny results :-)
+    assert_true("14 is 2 + 3 * 4.", e)
+    assert_true("op(350, xfy, +).", e)
+    assert_true("20 is 2 + 3 * 4.", e)
+    assert_true("op(500, xfy, +).", e)
+
+def test_functor():
+    assert_true("functor(f(a, b, c), f, 3).")
+    assert_true("functor(f(a, b, c), X, Y), X=f, Y=3.")
+    assert_true("functor(f, X, Y), X=f, Y=0.")
+    assert_true("functor(1, X, Y), X=1, Y=0.")
+    assert_true("functor(F, a, 0), F=a.")
+    assert_true("functor(F, 12, 0), F=12.")
+    assert_true("functor(F, 12.5, 0), F=12.5.")
+    assert_true("functor(F, f, 4), F=f(1, 2, 3, 4).")
+    assert_true("functor(F, g, 1), F=g(asdf).")
+    assert_true("functor(F, g, 3), F=g(X, Y, 1), X = 12, Y = 34, ground(F).")
+
+def test_standard_comparison():
+    assert_true("X = Y, f(X, Y, X, Y) == f(X, X, Y, Y).")
+    assert_true("X = Y, f(X, Y, X, Z) \\== f(X, X, Y, Y).")
+    assert_true("X @< Y, X @=< X, X @=< Y, Y @> X.")
+    assert_true("'\\\\=='(f(X, Y), 12).")
+    assert_true("X = f(a), Y = f(b), Y @> X.")
+
+def test_atom_length():
+    assert_true("atom_length('abc', 3).")
+    assert_true("atom_length('\\\\', 1).")
+    assert_true("atom_length('abc', X), X = 3.")
+
+def test_atom_concat():
+    assert_true("atom_concat(ab, cdef, abcdef).")
+    assert_true("atom_concat(ab, cdef, X), X = abcdef.")
+    assert_true("atom_concat(ab, X, abcdef), X = cdef.")
+    assert_true("atom_concat(X, cdef, abcdef), X = ab.")
+    assert_true("atom_concat(1, Y, '1def'), Y = def.")
+    frames = collect_all(
+        Engine(),
+        "atom_concat(X, Y, abcd), atom(X), atom(Y).")
+    assert len(frames) == 5
+
+def test_sub_atom():
+    assert_true("sub_atom(abc, B, L, A, bc), B=1, L=2, A=0.")
+
+def test_findall():
+    assert_true("findall(X, (X = a; X = b; X = c), L), L = [a, b, c].")
+    assert_true("findall(X + Y, (X = 1), L), L = [1+_].")
+
+def test_ifthenelse():
+    e = get_engine("f(x). f(y). f(z).")
+    assert_false("f(c) -> true.", e)
+    assert_true("f(X) -> X \\= x; f(z).", e)
+    assert_false("true -> fail.", e)
+
+def test_once():
+    assert_true("once(repeat).")
+
+def test_write_term():
+    prolog_raises("domain_error(write_option, E)",
+                  "write_term(a, [quoted(af)])")
+    prolog_raises("type_error(list, E)",
+                  "write_term(a, asdf)")

Added: pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,243 @@
+import py
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine
+from pypy.lang.prolog.interpreter.error import UnificationFailed, CatchableError
+from pypy.lang.prolog.interpreter.test.tool import collect_all, assert_true, assert_false
+from pypy.lang.prolog.interpreter.test.tool import prolog_raises
+
+def test_and():
+    e = get_engine("""
+        g(a, a).
+        g(a, b).
+        g(b, c).
+        f(X, Z) :- g(X, Y), g(Y, Z).
+    """)
+    e.run(parse_query_term("f(a, c)."))
+    e.run(parse_query_term("f(X, c)."))
+    print e.frame.vars
+    assert e.frame.getvar(0).name == "a"
+
+def test_and_long():
+    e = get_engine("""
+        f(x). f(y). f(z).
+        g(a). g(b). g(c).
+        h(d). h(e). h(f).
+        f(X, Y, Z) :- f(X), g(Y), h(Z).
+    """)
+    frames = collect_all(e, "f(X, Y, Z).")
+    assert len(frames) == 27  
+
+def test_numeral():
+    e = get_engine("""
+        num(0).
+        num(succ(X)) :- num(X).
+        add(X, 0, X).
+        add(X, succ(Y), Z) :- add(succ(X), Y, Z).
+        mul(X, 0, 0).
+        mul(X, succ(0), X).
+        mul(X, succ(Y), Z) :- mul(X, Y, A), add(A, X, Z).
+        factorial(0, succ(0)).
+        factorial(succ(X), Y) :- factorial(X, Z), mul(Z, succ(X), Y).
+    """)
+    def nstr(n):
+        if n == 0:
+            return "0"
+        return "succ(%s)" % nstr(n - 1)
+    e.run(parse_query_term("num(0)."))
+    e.run(parse_query_term("num(succ(0))."))
+    e.run(parse_query_term("num(X)."))
+    assert e.frame.getvar(0).num == 0
+    e.run(parse_query_term("add(0, 0, 0)."))
+    py.test.raises(UnificationFailed, e.run, parse_query_term("""
+        add(0, 0, succ(0))."""))
+    e.run(parse_query_term("add(succ(0), succ(0), succ(succ(0)))."))
+    e.run(parse_query_term("mul(succ(0), 0, 0)."))
+    e.run(parse_query_term("mul(succ(succ(0)), succ(0), succ(succ(0)))."))
+    e.run(parse_query_term("mul(succ(succ(0)), succ(succ(0)), succ(succ(succ(succ(0)))))."))
+    e.run(parse_query_term("factorial(0, succ(0))."))
+    e.run(parse_query_term("factorial(succ(0), succ(0))."))
+    e.run(parse_query_term("factorial(%s, %s)." % (nstr(5), nstr(120))))
+
+def test_or():
+    e = get_engine("""
+        g(a, b).
+        g(b, a).
+        f(X, Y) :- g(X, b); g(a, Y).
+        """)
+    e.run(parse_query_term("f(a, c)."))
+    e.run(parse_query_term("f(d, b)."))
+    prolog_raises("ERROR", "foo(X); X = 1")
+
+
+def test_or_and_call_with_cut():
+    assert_false("(!, fail); true.")
+    assert_true("(call(!), fail); true.")
+
+def test_or_backtrack():
+    e = get_engine("""
+        a(a).
+        b(b).
+        g(a, b).
+        g(a, a).
+        f(X, Y, Z) :- (g(X, Z); g(X, Z); g(Z, Y)), a(Z).
+        """)
+    e.run(parse_query_term("f(a, b, Z)."))
+    assert e.frame.getvar(0).name == "a"
+    f = collect_all(e, "X = 1; X = 2.")
+    assert len(f) == 2
+
+def test_backtrack_to_same_choice_point():
+    e = get_engine("""
+        a(a).
+        b(b).
+        start(Z) :- Z = X, f(X, b), X == b, Z == b.
+        f(X, Y) :- a(Y).
+        f(X, Y) :- X = a, a(Y).
+        f(X, Y) :- X = b, b(Y).
+    """)
+    assert_true("start(Z).", e)
+
+def test_equivalent_with_quotes():
+    e = get_engine("""
+        g('a', X).
+        g('b', 'c').
+    """)
+    e.run(parse_query_term("g(a, b)."))
+    e.run(parse_query_term("g(b, c)."))
+
+def test_error_unknown_function():
+    e = get_engine("""
+        g(a).
+        f(X) :- g(X), h(X).
+    """)
+    prolog_raises("existence_error(procedure, h/1)", "f(X)", e)
+    
+def test_collect_all():
+    e = get_engine("""
+        g(a).
+        g(b).
+        g(c).
+    """)
+    frames = collect_all(e, "g(X).")
+    assert len(frames) == 3
+    assert frames[0].getvar(0).name == "a"
+    assert frames[1].getvar(0).name == "b"
+    assert frames[2].getvar(0).name == "c"
+
+def test_cut():
+    e = get_engine("""
+        g(a).
+        g(b).
+        a(a).
+        b(b).
+        f(X) :- g(X),!,b(X).
+        f(x).
+        f(y).
+    """)
+    frames = collect_all(e, "f(X).")
+    assert len(frames) == 0
+    assert_true("!.")
+
+def test_cut2():
+    e = get_engine("""
+        g(a).
+        g(b).
+        h(a, x).
+        h(a, y).
+        f(X, Y) :- g(X), !, !, !, !, !, h(X, Y).
+    """)
+    frames = collect_all(e, "f(X, Y).")
+    assert len(frames) == 2
+
+def test_cut3():
+    e = get_engine("""
+        member(H, [H | _]).
+        member(H, [_ | T]) :- member(H, T).
+
+        s(a, L) :- !, fail.
+        s(b, L).
+        s(X, L) :-
+            member(Y, L),
+            L = [_| S],
+            s(Y, S).
+    """)
+    #    import pdb; pdb.set_trace()
+    assert_true("s(d, [a, b]).", e)
+
+def test_rule_with_cut_calling_rule_with_cut():
+    e = get_engine("""
+        f(b) :- !.
+        f(c).
+        g(X) :- f(X), !.
+        g(a).
+    """)
+    frames = collect_all(e, "g(X).")
+    assert len(frames) == 1
+
+def test_not_with_cut():
+    e = get_engine("""
+    p1 :- \\+ q1.
+    q1 :- fail.
+    q1 :- true.
+    
+    p2:- \\+ q2.
+    q2 :- !, fail.
+    q2 :- true.
+    """)
+    assert_false("p1.", e)
+    assert_true("p2.", e)
+
+def test_numbers():
+    e = get_engine("""
+        g(1, 2).
+        g(X, Y) :- g(1, X), g(1, Y).
+    """)
+    e.run(parse_query_term("g(2, 2)."))
+
+def test_lists():
+    e = get_engine("""
+        nrev([],[]).
+        nrev([X|Y],Z) :- nrev(Y,Z1),
+                         append(Z1,[X],Z).
+
+        append([],L,L).
+        append([X|Y],L,[X|Z]) :- append(Y,L,Z).
+    """)
+    e.run(parse_query_term("nrev(%s, X)." % (range(15), )))
+    e.run(parse_query_term("nrev(%s, %s)." % (range(8), range(7, -1, -1))))
+
+def test_indexing():
+    # this test is quite a lot faster if indexing works properly. hrmrm
+    e = get_engine("g(a, b, c, d, e, f, g, h, i, j, k, l). " +
+            "".join(["f(%s, g(%s)) :- g(A, B, C, D, E, F, G, H, I ,J, K, l). "
+                      % (chr(i), chr(i + 1))
+                                for i in range(97, 122)]))
+    t = parse_query_term("f(x, g(y)).")
+    for i in range(200):
+        e.run(t)
+    t = parse_query_term("f(x, g(y, a)).")
+    for i in range(200):
+        py.test.raises(UnificationFailed, e.run, t)
+
+def test_indexing2():
+    e = get_engine("""
+        mother(o, j).
+        mother(o, m).
+        mother(o, b).
+
+        sibling(X, Y) :- mother(Z, X), mother(Z, Y).
+    """)
+    frames = collect_all(e, "sibling(m, X).")
+    assert len(frames) == 3
+
+def test_runstring():
+    e = get_engine("foo(a, c).")
+    e.runstring("""
+        :- op(450, xfy, foo).
+        a foo b.
+        b foo X :- a foo X.
+    """)
+    assert_true("foo(a, b).", e)
+
+def test_handle_non_callable():
+    py.test.raises(CatchableError, assert_true, "1.")

Added: pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,110 @@
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder, OrderTransformer
+from pypy.lang.prolog.interpreter.parsing import parse_query_term
+
+
+def test_simple():
+    t = parse_file("""
+h(X, Y, Z) :- -Y = Z.
+""")
+    builder = TermBuilder()
+    facts = builder.build(t)
+    assert len(facts) == 1
+
+def test_numeral():
+    from pypy.lang.prolog.interpreter.term import Term, Atom, Var
+    from pypy.lang.prolog.interpreter.engine import Engine
+    t = parse_file("""
+numeral(null). % end of line comment
+numeral(succ(X)) :- numeral(X). % another one
+
+add_numeral(X, null, X).
+add_numeral(X, succ(Y), Z) :- add_numeral(succ(X), Y, Z).
+
+greater_than(succ(null), null).
+greater_than(succ(X), null) :- greater_than(X, null).
+greater_than(succ(X), succ(Y)) :- greater_than(X, Y).
+""")
+    builder = TermBuilder()
+    facts = builder.build(t)
+    e = Engine()
+    for fact in facts:
+        print fact
+        e.add_rule(fact)
+    assert e.signature2rules["add_numeral/3"][0].head.args[1].name == "null"
+    four = Term("succ", [Term("succ", [Term("succ",
+                [Term("succ", [Atom("null")])])])])
+    e.run(parse_query_term("numeral(succ(succ(null)))."))
+    term = parse_query_term(
+        """add_numeral(succ(succ(null)), succ(succ(null)), X).""")
+    e.run(term)
+    var = Var(0).getvalue(e.frame)
+    print var, e.frame
+    # does not raise
+    var.unify(four, e.frame)
+    term = parse_query_term(
+        """greater_than(succ(succ(succ(null))), succ(succ(null))).""")
+    e.run(term)
+
+def test_quoted_atoms():
+    t = parse_file("""
+        g('ASa0%!!231@~!@#%', a, []). /* /* /* * * * / a mean comment */
+    """)
+    builder = TermBuilder()
+    facts = builder.build(t)
+
+def test_parenthesis():
+    t = parse_file("""
+        g(X, Y) :- (g(x, y); g(a, b)), /* this too is a comment
+*/ g(x, z).
+    """)
+    builder = TermBuilder()
+    facts = builder.build(t)
+
+def test_cut():
+    t = parse_file("""
+        g(X, /* this is some comment */
+        Y) :- g(X), !, h(Y).
+    """)
+    builder = TermBuilder()
+    facts = builder.build(t)
+  
+def test_noparam():
+    t = parse_file("""
+        test.
+    """)
+    builder = TermBuilder()
+    facts = builder.build(t)
+
+def test_list():
+    t = parse_file("""
+        W = [].
+        X = [a, b, c, d, e, f, g, h].
+        Y = [a|T].
+        Z = [a,b,c|T].
+    """)
+    builder = TermBuilder()
+    facts = builder.build(t)
+
+def test_number():
+    t = parse_file("""
+        X = -1.
+        Y = -1.345.
+    """)
+    builder = TermBuilder()
+    facts = builder.build(t)
+    assert len(facts) == 2
+    assert facts[0].args[1].num == -1
+    assert facts[1].args[1].num == -1.345
+    t = parse_file("""
+        X = -1.
+        arg(X, h(a, b, c), b), X = 2.
+        arg(X, h(a, b, g(X, b)), g(3, B)), X = 3, B = b.
+    """)
+
+def test_chaining():
+    t = parse_file("f(X) = X + X + 1 + 2.")
+    builder = TermBuilder()
+    facts = builder.build(t)
+    t = parse_file("f(X) = X + X * 1 + 23 / 13.")
+    facts = builder.build(t)
+    t = parse_file("-X + 1.")

Added: pypy/dist/pypy/lang/prolog/interpreter/test/test_standard.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_standard.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,13 @@
+# some tests stolen from the standard test suite
+# XXX find a way to more systematically test these test suites
+import py
+from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
+from pypy.lang.prolog.interpreter.test.tool import collect_all, assert_true, assert_false
+
+class TestSec78(object):
+    def test_common(self):
+        assert_false('fail.')
+        assert_true('true.')
+
+    def DONOTtest_cut(self):
+        assert_true('!.')

Added: pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,64 @@
+import py
+from pypy.lang.prolog.interpreter.error import UnificationFailed
+from pypy.lang.prolog.interpreter.term import Atom, Var, Number, Term, Rule
+from pypy.lang.prolog.interpreter.engine import Frame, Engine
+
+def test_atom():
+    a = Atom("hallo")
+    b = Atom("hallo")
+    # does not raise
+    a.unify(b, None)
+    py.test.raises(UnificationFailed, "a.unify(Atom('xxx'), None)")
+
+def test_var():
+    b = Var(0)
+    frame = Frame()
+    frame.clear(1)
+    b.unify(Atom("hallo"), frame)
+    assert b.getvalue(frame).name == "hallo"
+    a = Var(0)
+    b = Var(1)
+    frame.clear(2)
+    a.unify(b, frame)
+    a.unify(Atom("hallo"), frame)
+    assert a.getvalue(frame).name == "hallo"
+    assert b.getvalue(frame).name == "hallo"
+
+def test_unify_var():
+    b = Var(0)
+    frame = Frame()
+    frame.clear(1)
+    b.unify(b, frame)
+    b.unify(Atom("hallo"), frame)
+    py.test.raises(UnificationFailed, b.unify, Atom("bye"), frame)
+
+def test_recursive():
+    b = Var(0)
+    frame = Frame()
+    frame.clear(1)
+    b.unify(Term("hallo", [b]), frame)
+    
+
+def test_term():
+    X = Var(0)
+    Y = Var(1)
+    t1 = Term("f", [Atom("hallo"), X])
+    t2 = Term("f", [Y, Atom("HALLO")])
+    frame = Frame()
+    frame.clear(2)
+    print t1, t2
+    t1.unify(t2, frame)
+    assert X.getvalue(frame).name == "HALLO"
+    assert Y.getvalue(frame).name == "hallo"
+
+def test_run():
+    e = Engine()
+    e.add_rule(Term("f", [Atom("a"), Atom("b")]))
+    e.add_rule(Term("f", [Var(0), Var(0)]))
+    e.add_rule(Term(":-", [Term("f", [Var(0), Var(1)]),
+                           Term("f", [Var(1), Var(0)])]))
+    assert e.run(Term("f", [Atom("b"), Var(0)])) is None
+    assert e.frame.getvar(0).name == "b"
+    assert e.run(Term("f", [Atom("b"), Atom("a")])) is None
+
+

Added: pypy/dist/pypy/lang/prolog/interpreter/test/tool.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/tool.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,43 @@
+import py
+from pypy.lang.prolog.interpreter.error import UnificationFailed, FunctionNotFound
+from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine
+from pypy.lang.prolog.interpreter.engine import Continuation, Frame, Engine
+
+def assert_true(query, e=None):
+    if e is None:
+        e = Engine()
+    term = e.parse(query)[0][0]
+    e.run(term)
+    f = Frame()
+    f.vars = e.frame.vars[:]
+    return f
+
+def assert_false(query, e=None):
+    if e is None:
+        e = Engine()
+    term = e.parse(query)[0][0]
+    py.test.raises(UnificationFailed, e.run, term)
+
+def prolog_raises(exc, query, e=None):
+    return assert_true("catch(((%s), fail), error(%s), true)." %
+                       (query, exc), e)
+
+class CollectAllContinuation(Continuation):
+    def __init__(self):
+        self.frames = []
+
+    def call(self, engine):
+        f = Frame()
+        f.vars = engine.frame.vars[:]
+        self.frames.append(f)
+#        import pdb; pdb.set_trace()
+        print "restarting computation"
+        raise UnificationFailed
+
+def collect_all(engine, s):
+    collector = CollectAllContinuation()
+    term = engine.parse(s)[0][0]
+    py.test.raises(UnificationFailed, engine.run, term,
+                   collector)
+    return collector.frames
+

Added: pypy/dist/pypy/lang/prolog/interpreter/translatedmain.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/translatedmain.py	Sun Nov 12 22:16:10 2006
@@ -0,0 +1,144 @@
+import os, sys
+from pypy.rlib.parsing.parsing import ParseError
+from pypy.rlib.parsing.deterministic import LexerError
+from pypy.lang.prolog.interpreter.main import helptext
+from pypy.lang.prolog.interpreter.parsing import parse_file, get_query_and_vars
+from pypy.lang.prolog.interpreter.parsing import get_engine
+from pypy.lang.prolog.interpreter.engine import Engine
+from pypy.lang.prolog.interpreter.engine import Continuation
+from pypy.lang.prolog.interpreter import error, term
+import pypy.lang.prolog.interpreter.term
+pypy.lang.prolog.interpreter.term.DEBUG = False
+
+
+class StopItNow(Exception):
+    pass
+
+class ContinueContinuation(Continuation):
+    def __init__(self, var_to_pos, write):
+        self.var_to_pos = var_to_pos
+        self.write = write
+
+    def call(self, engine):
+        self.write("yes\n")
+        var_representation(self.var_to_pos, engine, self.write)
+        while 1:
+            res = getch()
+            #self.write(res+"\n")
+            if res in "\r\x04\n":
+                self.write("\n")
+                raise StopItNow()
+            if res in ";nr":
+                raise error.UnificationFailed
+            elif res in "h?":
+                self.write(helptext)
+            elif res in "p":
+                var_representation(self.var_to_pos, engine, self.write)
+            else:
+                self.write('unknown action. press "h" for help\n')
+
+def var_representation(var_to_pos, engine, write):
+    from pypy.lang.prolog.builtin import formatting
+    f = formatting.TermFormatter(engine, quoted=True, max_depth=20)
+    for var, real_var in var_to_pos.iteritems():
+        if var.startswith("_"):
+            continue
+        val = f.format(real_var.getvalue(engine.frame))
+        write("%s = %s\n" % (var, val))
+
+def getch():
+    line = readline()
+    return line[0]
+
+def debug(msg):
+    os.write(2, "debug: " + msg + '\n')
+
+def printmessage(msg):
+    os.write(1, msg)
+
+def readline():
+    result = []
+    while 1:
+        s = os.read(0, 1)
+        result.append(s)
+        if s == "\n":
+            break
+        if s == '':
+            if len(result) > 1:
+                break
+            raise SystemExit
+    return "".join(result)
+
+def run(goal, var_to_pos, e):
+    from pypy.lang.prolog.interpreter.error import UnificationFailed, CatchableError
+    from pypy.lang.prolog.interpreter.error import UncatchableError, UserError
+    from pypy.lang.prolog.builtin import formatting
+    f = formatting.TermFormatter(e, quoted=True, max_depth=20)
+    try:
+        e.run(goal, ContinueContinuation(var_to_pos, printmessage))
+    except UnificationFailed:
+        printmessage("no\n")
+    except UncatchableError, e:
+        printmessage("INTERNAL ERROR: %s\n" % (e.message, ))
+    except UserError, e:
+        printmessage("ERROR: ")
+        f._make_reverse_op_mapping()
+        printmessage("Unhandled exception: ")
+        printmessage(f.format(e.term))
+    except CatchableError, e:
+        f._make_reverse_op_mapping()
+        printmessage("ERROR: ")
+        t = e.term
+        if isinstance(t, term.Term):
+            errorterm = t.args[0]
+            if isinstance(errorterm, term.Callable):
+                if errorterm.name == "instantiation_error":
+                    printmessage("arguments not sufficiently instantiated\n")
+                    return
+                elif errorterm.name == "existence_error":
+                    if isinstance(errorterm, term.Term):
+                        printmessage("Undefined %s: %s\n" % (
+                            f.format(errorterm.args[0]),
+                            f.format(errorterm.args[1])))
+                        return
+                elif errorterm.name == "domain_error":
+                    if isinstance(errorterm, term.Term):
+                        printmessage(
+                            "Domain error: '%s' expected, found '%s'\n" % (
+                            f.format(errorterm.args[0]),
+                            f.format(errorterm.args[1])))
+                        return
+                elif errorterm.name == "type_error":
+                    if isinstance(errorterm, term.Term):
+                        printmessage(
+                            "Type error: '%s' expected, found '%s'\n" % (
+                            f.format(errorterm.args[0]),
+                            f.format(errorterm.args[1])))
+                        return
+        printmessage(" (but I cannot tell you which one)\n")
+    except StopItNow:
+        pass
+    else:
+        printmessage("yes\n")
+
+def repl(e):
+    printmessage("welcome!\n")
+    while 1:
+        printmessage(">?- ")
+        line = readline()
+        if line == "halt.\n":
+            break
+        try:
+            goals, var_to_pos = e.parse(line)
+        except ParseError:
+            printmessage("parse error\n")
+            continue
+        for goal in goals:
+            run(goal, var_to_pos, e)
+ 
+def execute(e, filename):
+    e.run(term.Term("consult", [term.Atom(filename)]))
+
+if __name__ == '__main__':
+    e = Engine()
+    repl(e)



More information about the Pypy-commit mailing list