1. Carl Friedrich Bolz
  2. Pyrolog

Commits

Carl Friedrich Bolz  committed 3722068

add term/arity and atom specialization

  • Participants
  • Parent commits 08f3f15
  • Branches minimal-specialization

Comments (0)

Files changed (2)

File prolog/interpreter/specialterm.py

View file
 from prolog.interpreter import term
 from prolog.interpreter import signature
 
-from pypy.rlib import jit, objectmodel, rarithmetic, rerased
+from pypy.rlib import jit, objectmodel, rarithmetic, rerased, unroll
 from pypy.rlib.objectmodel import specialize
 
 erase, unerase = rerased.new_erasing_pair("pyrolog-shape")
         assert isinstance(obj, term.BindingVar)
         return obj.dereference(heap)
 
+    def read_argument(self, i, obj):
+        res = unerase(obj._raw_argument_at(i))
+        jit.record_known_class(res, term.BindingVar)
+        return res
+
+class AtomArgumentDescr(ArgumentDescr):
+    def compatible_with(self, obj):
+        return isinstance(obj, term.Atom)
+
+    def dereference_with_known_type(self, obj, heap):
+        return obj
+
+    def read_argument(self, i, obj):
+        res = unerase(obj._raw_argument_at(i))
+        jit.record_known_class(res, term.Atom)
+        return res
 
 class NumberArgumentDescr(ArgumentDescr):
     def compatible_with(self, obj):
         obj._raw_set_argument_at(i, res)
 
 ANY_ARGUMENT = AnyArgumentDescr()
-VAR_ARGUMENT = VarArgumentDescr()
-NUMBER_ARGUMENT = NumberArgumentDescr()
+all_argument_descrs = [VarArgumentDescr(),
+                       NumberArgumentDescr(),
+                       AtomArgumentDescr()]
 
 class Shape(object):
     _immutable_fields_ = ["signature", "args[*]"]
     shape = get_base_shape(signature)
     for i in range(len(args)):
         arg = args[i]
-        if VAR_ARGUMENT.compatible_with(arg):
-            argshape = VAR_ARGUMENT
-        elif NUMBER_ARGUMENT.compatible_with(arg):
-            argshape = NUMBER_ARGUMENT
+        for descr in all_argument_descrs:
+            if descr.compatible_with(arg):
+                argshape = descr
+                break
         else:
             continue
         shape = shape.replace(i, argshape)
     generic_callable.__name__ = 'SpecializedGeneric'+str(n_args)
     return generic_callable
 
+def make_specialized_argument_descr(termcls):
+    class cls(ArgumentDescr):
+        def compatible_with(self, obj):
+            return isinstance(obj, termcls)
+
+        def dereference_with_known_type(self, obj, heap):
+            return obj
+
+        def read_argument(self, i, obj):
+            res = unerase(obj._raw_argument_at(i))
+            jit.record_known_class(res, termcls)
+            return res
+    cls.__name__ = termcls.__name__ + "ArgumentDescr"
+    return cls()
+
 specialized_term_classes = [make_specialized_term_cls(i) for i in range(1, 10)]
+all_argument_descrs.extend([make_specialized_argument_descr(cls)
+            for cls in specialized_term_classes])
+
+all_argument_descrs = unroll.unrolling_iterable(all_argument_descrs)

File prolog/interpreter/test/test_specialized_terms.py

View file
     s3 = a3.get_shape()
     assert s1 is not s3
 
+def test_specialize_atom():
+    h = Heap()
+    sig = signature.Signature.getsignature("foo", 2)
+    bar = Callable.build("bar")
+    a1 = specialterm.build(sig, [bar, Number(0)])
+    assert a1.argument_at(0) is bar
+    s1 = a1.get_shape()
+    a2 = specialterm.build(sig, [bar, Number(1)])
+    s2 = a2.get_shape()
+    assert s1 is s2
+
+    a3 = specialterm.build(sig, [Float(0.1), Number(1)])
+    s3 = a3.get_shape()
+    assert s1 is not s3
+
+def test_specialize_term():
+    h = Heap()
+    sig = signature.Signature.getsignature("foo", 2)
+    bar = Callable.build("bar", [Number(0), Number(1)])
+    a1 = specialterm.build(sig, [bar, Number(0)])
+    assert a1.argument_at(0) is bar
+    s1 = a1.get_shape()
+    a2 = specialterm.build(sig, [bar, Number(1)])
+    s2 = a2.get_shape()
+    assert s1 is s2
+
+    bar1 = Callable.build("bar", [Number(0)])
+    a3 = specialterm.build(sig, [bar1, Number(1)])
+    s3 = a3.get_shape()
+    assert s1 is not s3