[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