Commits

Carl Friedrich Bolz committed e497a06

cache indicators

Comments (0)

Files changed (3)

prolog/interpreter/shape.py

     def replace(self, i, shape):
         assert 0, "cannot happen"
 
-    def get_path(self, i):
-        assert 0, "cannot happen"
-
     def __repr__(self):
         return "%s(%r)" % (self.__class__.__name__, self.w_obj)
 
         assert i == 0
         return shape
 
-    def get_path(self, index):
-        assert index == 0
-        return []
-
     def __repr__(self):
         return self.__class__.__name__ + "()"
 
     return x
 
 class SharingShape(Shape):
-    _immutable_fields_ = ["signature", "children[*]", "_num_storage_vars"]
+    _immutable_fields_ = ["signature", "children[*]", "_num_storage_vars", "paths[*]"]
     _cache = objectmodel.r_dict(shape_eq, shape_hash)
     _transitions = None
 
         self.children = children
         children = debug.make_sure_not_resized(children)
         _num_storage_vars = 0
-        for child in self.children:
+        paths = []
+        for i in range(len(children)):
+            child = children[i]
             _num_storage_vars += child.num_storage_vars()
+            if isinstance(child, InStorageShape):
+                paths.append(term.VarInTermPath([i]))
+            elif isinstance(child, SharingShape):
+                for subpath in child.paths:
+                    if subpath is not None:
+                        paths.append(term.VarInTermPath([i] + subpath.path))
         self._num_storage_vars = _num_storage_vars
+        assert len(paths) == _num_storage_vars
+        self.paths = paths[:]
 
     @staticmethod
     def build(signature, children):
         return self.children[i].resolve(shaped_callable, index)
 
     def get_path(self, index):
-        for j in range(len(self.children)):
-            child = self.children[j]
-            num = child.num_storage_vars()
-            if index < num:
-                return [j] + child.get_path(index)
-            else:
-                index -= num
-        assert 0, "cannot happen"
+        return self.paths[index]
 
     @staticmethod
     def build_potentially_wrap(signature, children):
                 self = self._make_mutable()
                 if deref is None:
                     child.parent = self
-                    child.indicator = term.VarInTermIndex(i + index)
+                    child.indicator = term.VarInTermIndex.build(i + index)
                 else:
                     newstorage[i + index] = deref
 
                 indicator = child.indicator
                 if (isinstance(indicator, term.VarInTermIndex) and
                         indicator.index == i):
-                    child.indicator = term.VarInTermIndex(i + offset)
+                    child.indicator = term.VarInTermIndex.build(i + offset)
         self.storage = newstorage
         self.shape = new_shape
         return self
                 if deref is None:
                     self = self._make_mutable()
                     old_child.parent = self
-                    old_child.indicator = term.VarInTermIndex(newi)
+                    old_child.indicator = term.VarInTermIndex.build(newi)
                 else:
                     self.set_storage(newi, deref)
             newi += 1

prolog/interpreter/term.py

         from prolog.interpreter.shape import ShapedCallableMutable
         assert isinstance(parent, ShapedCallableMutable)
         self.parent = parent
-        self.indicator = VarInTermIndex(index)
+        self.indicator = VarInTermIndex.build(index)
 
     def getbinding(self):
         val = self.indicator.get(self.parent)
             obj.storage[index] = value
         else:
             assert newobj is obj
-        self.indicator = VarInTermPath(path)
+        self.indicator = path
 
     def __repr__(self):
         if self.getbinding():
 class VarInTermIndicator(object):
     pass
 
-class VarInTermIndex(VarInTermIndicator): # XXX cache
+class VarInTermIndex(VarInTermIndicator):
     _immutable_fields_ = ["index"]
 
     def __init__(self, index):
     def get(self, obj):
         return obj.get_storage(self.index)
 
-class VarInTermPath(VarInTermIndicator): # XXX cache
+    @staticmethod
+    def build(index):
+        if index < OPTIMIZED_TERM_SIZE_MAX:
+            return VarInTermIndex._instances[index]
+        return VarInTermIndex(index)
+
+VarInTermIndex._instances = [VarInTermIndex(i) for i in range(OPTIMIZED_TERM_SIZE_MAX)]
+
+class VarInTermPath(VarInTermIndicator):
     _immutable_fields_ = ["path[*]"]
 
     def __init__(self, path):

prolog/interpreter/test/test_shape.py

     X = shape.InStorageShape.build()
     s1 = build(sig, [X, X])
     s2 = build(sig, [X, s1])
-    p = s2.get_path(0)
+    p = s2.get_path(0).path
     assert p == [0]
-    p = s2.get_path(1)
+    p = s2.get_path(1).path
     assert p == [1, 0]
-    p = s2.get_path(2)
+    p = s2.get_path(2).path
     assert p == [1, 1]