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

cfbolz at codespeak.net cfbolz at codespeak.net
Fri May 25 18:11:45 CEST 2007


Author: cfbolz
Date: Fri May 25 18:11:45 2007
New Revision: 43640

Modified:
   pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py
   pypy/dist/pypy/lang/prolog/builtin/formatting.py
   pypy/dist/pypy/lang/prolog/builtin/register.py
   pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py
   pypy/dist/pypy/lang/prolog/interpreter/engine.py
   pypy/dist/pypy/lang/prolog/interpreter/helper.py
   pypy/dist/pypy/lang/prolog/interpreter/portal.py
   pypy/dist/pypy/lang/prolog/interpreter/term.py
   pypy/dist/pypy/lang/prolog/interpreter/test/test_jit.py
Log:
attempt to jit some of the integer arithmetic functions. requires some
rewriting.


Modified: pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py	(original)
+++ pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py	Fri May 25 18:11:45 2007
@@ -27,6 +27,7 @@
 
 def impl_is(engine, var, num):
     var.unify(num, engine.heap)
+impl_is._look_inside_me_ = True
 expose_builtin(impl_is, "is", unwrap_spec=["raw", "arithmetic"])
 
 for ext, prolog, python in [("eq", "=:=", "=="),
@@ -43,7 +44,7 @@
             eq = num1.num %s num2.num
     elif isinstance(num1, term.Float):
         if isinstance(num2, term.Float):
-            eq = num1.num %s num2.num
+            eq = num1.floatval %s num2.floatval
     if not eq:
         raise error.UnificationFailed()""" % (ext, python, python)).compile()
     expose_builtin(globals()["impl_arith_%s" % (ext, )], prolog,

Modified: pypy/dist/pypy/lang/prolog/builtin/formatting.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/builtin/formatting.py	(original)
+++ pypy/dist/pypy/lang/prolog/builtin/formatting.py	Fri May 25 18:11:45 2007
@@ -73,7 +73,7 @@
         return str(num.num)
 
     def format_float(self, num):
-        return str(num.num)
+        return str(num.floatval)
 
     def format_var(self, var):
         return "_G%s" % (var.index, )

Modified: pypy/dist/pypy/lang/prolog/builtin/register.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/builtin/register.py	(original)
+++ pypy/dist/pypy/lang/prolog/builtin/register.py	Fri May 25 18:11:45 2007
@@ -87,7 +87,7 @@
         signature = "%s/%s" % (name, len(unwrap_spec))
         b = Builtin(miniglobals[funcname])
         builtins[signature] = b
-        if signature == ",/2":
+        if signature in [",/2", "is/2"]:
             builtins_list.insert(0, (signature, b))
         else:
             builtins_list.append((signature, b))

Modified: pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py	(original)
+++ pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py	Fri May 25 18:11:45 2007
@@ -4,10 +4,12 @@
 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
+from pypy.rlib.jit import we_are_jitted, hint
+from pypy.rlib.unroll import unrolling_iterable
 
 arithmetic_functions = {}
+arithmetic_functions_list = []
 
-pattern_to_function = {}
 
 class CodeCollector(object):
     def __init__(self):
@@ -85,29 +87,15 @@
     code.end_block("def")
     miniglobals = globals().copy()
     exec py.code.Source(code.tostring()).compile() in miniglobals
-    return miniglobals["prolog_" + name]
+    result = miniglobals["prolog_" + name]
+    result._look_inside_me_ = True
+    return result
 
 wrap_builtin_operation._annspecialcase_ = 'specialize:memo'
 
 def eval_arithmetic(engine, query):
-    query = query.getvalue(engine.heap)
-    if isinstance(query, term.Number):
-        return query
-    if isinstance(query, term.Float):
-        return norm_float(query)
-    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)
-        error.throw_type_error("evaluable", query.get_prolog_signature())
-    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")
+    return query.eval_arithmetic(engine)
+eval_arithmetic._look_inside_me_ = True
 
 def norm_float(obj):
     v = obj.floatval
@@ -121,7 +109,7 @@
     ("-",                     ["expr", "expr"], "v0 - v1", True, True),
     ("*",                     ["expr", "expr"], "v0 * v1", True, True),
     ("//",                    ["int",  "int"],  "v0 / v1", True, False),
-    ("**",                    ["expr", "expr"], "v0 ** v1", True, True),
+    ("**",                    ["expr", "expr"], "float(v0) ** float(v1)", True, False),
     (">>",                    ["int", "int"],   "v0 >> v1", False, False),
     ("<<",                    ["int", "int"],   "intmask(v0 << v1)", False,
                                                                      False),
@@ -134,9 +122,9 @@
     ("max",                   ["expr", "expr"], "max(v0, v1)", False, True),
     ("min",                   ["expr", "expr"], "min(v0, v1)", False, True),
     ("round",                 ["expr"],         "int(v0 + 0.5)", False, False),
-    ("floor",                 ["expr"],         "math.floor(v0)", False, True), #XXX
-    ("ceiling",               ["expr"],         "math.ceil(v0)", False, True), #XXX
-    ("float_fractional_part", ["expr"],         "v0 - int(v0)", False, True), #XXX
+    ("floor",                 ["expr"],         "math.floor(v0)", False, False), #XXX
+    ("ceiling",               ["expr"],         "math.ceil(v0)", False, False), #XXX
+    ("float_fractional_part", ["expr"],         "v0 - int(v0)", False, False), #XXX
     ("float_integer_part",    ["expr"],         "int(v0)", False, True),
 ]
 
@@ -151,3 +139,6 @@
                                intversion)
     signature = "%s/%s" % (prolog_name, len(unwrap_spec))
     arithmetic_functions[signature] = f
+    arithmetic_functions_list.append((signature, f))
+
+arithmetic_functions_list = unrolling_iterable(arithmetic_functions_list)

Modified: pypy/dist/pypy/lang/prolog/interpreter/engine.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/engine.py	(original)
+++ pypy/dist/pypy/lang/prolog/interpreter/engine.py	Fri May 25 18:11:45 2007
@@ -334,7 +334,7 @@
                                                        continuation)
                     raise
             else:
-                inline = False #XXX rule.body is None # inline facts
+                inline = rule.body is None # inline facts
                 try:
                     # for the last rule (rulechain is None), this will always
                     # return, because choice_point is False

Modified: pypy/dist/pypy/lang/prolog/interpreter/helper.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/helper.py	(original)
+++ pypy/dist/pypy/lang/prolog/interpreter/helper.py	Fri May 25 18:11:45 2007
@@ -3,8 +3,10 @@
 from pypy.lang.prolog.interpreter import term
 from pypy.lang.prolog.interpreter import error
 
+emptylist = term.Atom.newatom("[]")
+
 def wrap_list(python_list):
-    curr = term.Atom.newatom("[]")
+    curr = emptylist
     for i in range(len(python_list) - 1, -1, -1):
         curr = term.Term(".", [python_list[i], curr])
     return curr
@@ -23,6 +25,7 @@
 
 def is_callable(var, engine):
     return isinstance(var, term.Callable)
+is_callable._look_inside_me_ = True
 
 def ensure_callable(var):
     if isinstance(var, term.Var):
@@ -31,6 +34,7 @@
         return var
     else:
         error.throw_type_error("callable", var)
+ensure_callable._look_inside_me_ = True
 
 def unwrap_int(obj):
     if isinstance(obj, term.Number):
@@ -45,6 +49,7 @@
     if isinstance(obj, term.Atom):
         return obj.name
     error.throw_type_error('atom', obj)
+unwrap_atom._look_inside_me_ = True
 
 def unwrap_predicate_indicator(predicate):
     if not isinstance(predicate, term.Term):

Modified: pypy/dist/pypy/lang/prolog/interpreter/portal.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/portal.py	(original)
+++ pypy/dist/pypy/lang/prolog/interpreter/portal.py	Fri May 25 18:11:45 2007
@@ -1,5 +1,5 @@
 from pypy.jit.hintannotator.policy import ManualGraphPolicy
-from pypy.lang.prolog.interpreter import term, engine
+from pypy.lang.prolog.interpreter import term, engine, helper
 from pypy.translator.translator import graphof
 from pypy.annotation.specialize import getuniquenondirectgraph
 
@@ -27,7 +27,7 @@
 
     def fill_timeshift_graphs(self, t, portal_graph):
         import pypy
-        for cls in [term.Var, term.Term, term.Number, term.Float, term.Atom]:
+        for cls in [term.Var, term.Term, term.Number, term.Atom]:
             self.seegraph(cls.copy)
             self.seegraph(cls.__init__)
             self.seegraph(cls.copy_and_unify)
@@ -37,6 +37,7 @@
             self.seegraph(cls.copy_and_basic_unify)
         for cls in [term.Var, term.Term, term.Number, term.Atom]:
             self.seegraph(cls.get_unify_hash)
+            self.seegraph(cls.eval_arithmetic)
         for cls in [term.Callable, term.Atom, term.Term]:
             self.seegraph(cls.get_prolog_signature)
             self.seegraph(cls.unify_hash_of_children)
@@ -58,6 +59,8 @@
         for cls in [engine.Continuation, engine.LimitedScopeContinuation,
                     pypy.lang.prolog.builtin.control.AndContinuation]:
             self.seegraph(cls._call)
+        for function in "".split():
+            self.seegraph(getattr(helper, function))
 
 def get_portal(drv):
     t = drv.translator

Modified: pypy/dist/pypy/lang/prolog/interpreter/term.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/term.py	(original)
+++ pypy/dist/pypy/lang/prolog/interpreter/term.py	Fri May 25 18:11:45 2007
@@ -2,8 +2,10 @@
 from pypy.rlib.objectmodel import we_are_translated, UnboxedValue
 from pypy.rlib.rarithmetic import intmask
 from pypy.lang.prolog.interpreter.error import UnificationFailed, UncatchableError
+from pypy.lang.prolog.interpreter import error
 from pypy.rlib.jit import hint
 from pypy.rlib.objectmodel import specialize
+from pypy.rlib.jit import we_are_jitted, hint, purefunction
 
 DEBUG = False
 
@@ -71,6 +73,8 @@
         # for testing
         return not (self == other)
 
+    def eval_arithmetic(self, engine):
+        error.throw_type_error("evaluable", self)
 
 class Var(PrologObject):
     TAG = 0
@@ -169,13 +173,20 @@
         return (self.__class__ == other.__class__ and
                 self.index == other.index)
 
+    @staticmethod
+    @purefunction
     def newvar(index):
         result = Var.cache.get(index, None)
         if result is not None:
             return result
         Var.cache[index] = result = Var(index)
         return result
-    newvar = staticmethod(newvar)
+
+    def eval_arithmetic(self, engine):
+        self = self.dereference(engine.heap)
+        if isinstance(self, Var):
+            error.throw_instantiation_error()
+        return self.eval_arithmetic(engine)
 
 
 class NonVar(PrologObject):
@@ -271,13 +282,22 @@
     def get_prolog_signature(self):
         return Term("/", [self, NUMBER_0])
 
+    @staticmethod
+    @purefunction
     def newatom(name):
         result = Atom.cache.get(name, None)
         if result is not None:
             return result
         Atom.cache[name] = result = Atom(name)
         return result
-    newatom = staticmethod(newatom)
+
+    def eval_arithmetic(self, engine):
+        #XXX beautify that
+        if self.name == "pi":
+            return Float.pi
+        if self.name == "e":
+            return Float.e
+        error.throw_type_error("evaluable", self.get_prolog_signature())
 
 
 class Number(NonVar):
@@ -312,6 +332,9 @@
     def get_unify_hash(self, heap):
         return intmask(self.num << TAGBITS | self.TAG)
 
+    def eval_arithmetic(self, engine):
+        return self
+
 NUMBER_0 = Number(0)
 
 class Float(NonVar):
@@ -349,6 +372,14 @@
     def __repr__(self):
         return "Float(%r)" % (self.floatval, )
 
+    def eval_arithmetic(self, engine):
+        from pypy.lang.prolog.interpreter.arithmetic import norm_float
+        return norm_float(self)
+
+Float.e = Float(math.e)
+Float.pi = Float(math.pi)
+
+
 class BlackBox(NonVar):
     # meant to be subclassed
     TAG = tag()
@@ -376,6 +407,7 @@
         return intmask(id(self) << TAGBITS | self.TAG)
 
 
+
 # helper functions for various Term methods
 
 def _clone(obj, offset):
@@ -490,6 +522,20 @@
                 return True
         return False
         
+    def eval_arithmetic(self, engine):
+        from pypy.lang.prolog.interpreter.arithmetic import arithmetic_functions
+        from pypy.lang.prolog.interpreter.arithmetic import arithmetic_functions_list
+        if we_are_jitted():
+            signature = hint(self.signature, promote=True)
+            func = None
+            for sig, func in arithmetic_functions_list:
+                if sig == signature:
+                    break
+        else:
+            func = arithmetic_functions.get(self.signature, None)
+        if func is None:
+            error.throw_type_error("evaluable", self.get_prolog_signature())
+        return func(engine, self)
 
 class Rule(object):
     _immutable_ = True

Modified: pypy/dist/pypy/lang/prolog/interpreter/test/test_jit.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/test/test_jit.py	(original)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_jit.py	Fri May 25 18:11:45 2007
@@ -133,23 +133,26 @@
 
     def test_loop(self):
         e = get_engine("""
-            f(X) :- h(X).
-            f(a).
-            h(X) :- h(X).
+            f(X) :- h(X, _).
+            f(50).
+            h(0, _).
+            h(X, Y) :- Y is X - 1, h(Y, _).
         """)
-        X = e.heap.newvar()
+        num = term.Number(50)
 
         def main(n):
             e.heap.reset()
             if n == 0:
-                e.call(term.Term("f", [X]))
-                return isinstance(X.dereference(e.heap), term.Atom)
+                e.call(term.Term("f", [num]))
+                return True
             else:
                 return False
 
+        res = main(0)
+        assert res
         res = self.timeshift_from_portal(main, portal.PORTAL,
                                          [0], policy=POLICY,
                                          backendoptimize=True, 
                                          inline=0.0)
-        assert res == True
+        assert res
 



More information about the Pypy-commit mailing list