# Path: prolog/interpreter/term.py
# class BindingVar(Var):
#     __slots__ = ("binding", "created_after_choice_point")
# 
#     def __init__(self):
#         Var.__init__(self)
#         self.binding = None
# 
#     def getbinding(self):
#         return self.binding
# 
#     def setvalue(self, value, heap):
#         heap.add_trail(self)
#         self.binding = value
# 
#     @specialize.arg(4)
#     def _unify_potential_recursion(self, next, other, heap, occurs_check):
#         assert isinstance(next, NonVar)
#         if next is not other:
#             if isinstance(other, NonVar):
#                 self.setvalue(other, heap)
#             next._unify_derefed(other, heap, occurs_check)
# 
# class AttVar(BindingVar):
#     attmap = AttMap()
# 
#     def __init__(self):
#         BindingVar.__init__(self)
#         self.value_list = debug.make_sure_not_resized([])
# 
#     @specialize.arg(3)
#     def _unify_derefed(self, other, heap, occurs_check=False):
#         if isinstance(other, AttVar):
#             if other is not self:
#                 self.setvalue(other, heap)
#             return
#         if isinstance(other, Var):
#             return other._unify_derefed(self, heap, occurs_check)
#         return self.setvalue(other, heap)
# 
#     def setvalue(self, value, heap):
#         if self.value_list is not None:
#             heap.add_hook(self)
#         BindingVar.setvalue(self, value, heap)
# 
#     def __repr__(self):
#         attrs = []
#         attmap = jit.hint(self.attmap, promote=True)
#         if self.value_list is not None:
#             for key, index in attmap.indexes.iteritems():
#                 value = self.value_list[index]
#                 if value is not None:
#                     attrs.append("%s" % (key, ))
#         return "AttVar(%s, %s)" % (self.getbinding(), "[" + ", ".join(attrs) + "]")
# 
#     def copy(self, heap, memo):
#         self = self.dereference(None)
#         if isinstance(self, AttVar):
#             res = memo.get(self)
#             if res is not None:
#                 return res
#             newvar = heap.new_attvar()
#             own_list = self.value_list
#             newvar.attmap = self.attmap
#             if own_list is None:
#                 newvar.value_list = None
#             else:
#                 length = len(own_list)
#                 new_values = [None] * length
#                 for i in range(length):
#                     if own_list[i] is None:
#                         new_values[i] = None
#                     else:
#                         new_values[i] = own_list[i].copy(heap, memo)
#                 newvar.value_list = new_values
# 
#             memo.set(self, newvar)
#             return newvar
#         return self.copy(heap, memo)
# 
#     def add_attribute(self, attname, attribute):
#         attmap = jit.hint(self.attmap, promote=True)
#         index = attmap.get_index(attname)
#         if index != -1:
#             self.value_list[index] = attribute
#             return
#         self.attmap = attmap.with_extra_attribute(attname)
#         self.value_list = self.value_list + [attribute]
# 
#     def del_attribute(self, attname):
#         attmap = jit.hint(self.attmap, promote=True)
#         index = attmap.get_index(attname)
#         if self.value_list is not None:
#             self.value_list[index] = None
# 
#     def get_attribute(self, attname):
#         if self.value_list is None:
#             return None, -1
#         attmap = jit.hint(self.attmap, promote=True)
#         index = attmap.get_index(attname)
#         if index == -1:
#             return None, -1
#         return self.value_list[index], index
# 
#     def reset_field(self, index, value):
#         if self.value_list is None:
#             self.value_list = [None] * (index + 1)
#         else:
#             self.value_list = self.value_list + [None] * (
#                     index - len(self.value_list) + 1)
#         self.value_list[index] = value
# 
#     def get_attribute_index(self, attname):
#         attmap = jit.hint(self.attmap, promote=True)
#         return attmap.get_index(attname)
# 
#     def is_empty(self):
#         if self.value_list is None:
#             return True
#         for elem in self.value_list:
#             if elem is not None:
#                 return False
#         return True


from rpython.rlib import debug
from prolog.interpreter.term import BindingVar, AttVar
from rpython.rlib import jit
        from prolog.interpreter.term import var_in_term_classes
        self.trail_var[i] = var
        self.trail_binding[i] = var.binding
        self.i = i + 1

    def _is_created_in_self(self, var):
        created_in = var.created_after_choice_point
        if self is created_in: # fast path
            return True
        if created_in is not None and created_in.discarded:
            # unroll _find_not_discarded once for better jittability
            created_in = created_in.prev
            if created_in is not None and created_in.discarded:
                created_in = created_in._find_not_discarded()
            var.created_after_choice_point = created_in
        return self is created_in

    def _double_size(self):
        l = len(self.trail_var)
        if l == 0:
            self.trail_var = [None, None]
            self.trail_binding = [None, None]
        elif l == 1:
            assert 0, "cannot happen"
        else:
            self.trail_var = self.trail_var + [None] * l
            self.trail_binding = self.trail_binding + [None] * l

    def newvar(self):
        """ Make a new variable. Should return a Var instance, possibly with
        interesting attributes set that e.g. add_trail can inspect."""

# Path: prolog/interpreter/term.py
# class BindingVar(Var):
#     __slots__ = ("binding", "created_after_choice_point")
# 
#     def __init__(self):
#         Var.__init__(self)
#         self.binding = None
# 
#     def getbinding(self):
#         return self.binding
# 
#     def setvalue(self, value, heap):
#         heap.add_trail(self)
#         self.binding = value
# 
#     @specialize.arg(4)
#     def _unify_potential_recursion(self, next, other, heap, occurs_check):
#         assert isinstance(next, NonVar)
#         if next is not other:
#             if isinstance(other, NonVar):
#                 self.setvalue(other, heap)
#             next._unify_derefed(other, heap, occurs_check)
# 
# class AttVar(BindingVar):
#     attmap = AttMap()
# 
#     def __init__(self):
#         BindingVar.__init__(self)
#         self.value_list = debug.make_sure_not_resized([])
# 
#     @specialize.arg(3)
#     def _unify_derefed(self, other, heap, occurs_check=False):
#         if isinstance(other, AttVar):
#             if other is not self:
#                 self.setvalue(other, heap)
#             return
#         if isinstance(other, Var):
#             return other._unify_derefed(self, heap, occurs_check)
#         return self.setvalue(other, heap)
# 
#     def setvalue(self, value, heap):
#         if self.value_list is not None:
#             heap.add_hook(self)
#         BindingVar.setvalue(self, value, heap)
# 
#     def __repr__(self):
#         attrs = []
#         attmap = jit.hint(self.attmap, promote=True)
#         if self.value_list is not None:
#             for key, index in attmap.indexes.iteritems():
#                 value = self.value_list[index]
#                 if value is not None:
#                     attrs.append("%s" % (key, ))
#         return "AttVar(%s, %s)" % (self.getbinding(), "[" + ", ".join(attrs) + "]")
# 
#     def copy(self, heap, memo):
#         self = self.dereference(None)
#         if isinstance(self, AttVar):
#             res = memo.get(self)
#             if res is not None:
#                 return res
#             newvar = heap.new_attvar()
#             own_list = self.value_list
#             newvar.attmap = self.attmap
#             if own_list is None:
#                 newvar.value_list = None
#             else:
#                 length = len(own_list)
#                 new_values = [None] * length
#                 for i in range(length):
#                     if own_list[i] is None:
#                         new_values[i] = None
#                     else:
#                         new_values[i] = own_list[i].copy(heap, memo)
#                 newvar.value_list = new_values
# 
#             memo.set(self, newvar)
#             return newvar
#         return self.copy(heap, memo)
# 
#     def add_attribute(self, attname, attribute):
#         attmap = jit.hint(self.attmap, promote=True)
#         index = attmap.get_index(attname)
#         if index != -1:
#             self.value_list[index] = attribute
#             return
#         self.attmap = attmap.with_extra_attribute(attname)
#         self.value_list = self.value_list + [attribute]
# 
#     def del_attribute(self, attname):
#         attmap = jit.hint(self.attmap, promote=True)
#         index = attmap.get_index(attname)
#         if self.value_list is not None:
#             self.value_list[index] = None
# 
#     def get_attribute(self, attname):
#         if self.value_list is None:
#             return None, -1
#         attmap = jit.hint(self.attmap, promote=True)
#         index = attmap.get_index(attname)
#         if index == -1:
#             return None, -1
#         return self.value_list[index], index
# 
#     def reset_field(self, index, value):
#         if self.value_list is None:
#             self.value_list = [None] * (index + 1)
#         else:
#             self.value_list = self.value_list + [None] * (
#                     index - len(self.value_list) + 1)
#         self.value_list[index] = value
# 
#     def get_attribute_index(self, attname):
#         attmap = jit.hint(self.attmap, promote=True)
#         return attmap.get_index(attname)
# 
#     def is_empty(self):
#         if self.value_list is None:
#             return True
#         for elem in self.value_list:
#             if elem is not None:
#                 return False
#         return True


# Path: prolog/interpreter/heap.py
from rpython.rlib import debug
from prolog.interpreter.term import BindingVar, AttVar
from rpython.rlib import jit
        from prolog.interpreter.term import var_in_term_classes

        self.trail_var[i] = var
        self.trail_binding[i] = var.binding
        self.i = i + 1

    def _is_created_in_self(self, var):
        created_in = var.created_after_choice_point
        if self is created_in: # fast path
            return True
        if created_in is not None and created_in.discarded:
            # unroll _find_not_discarded once for better jittability
            created_in = created_in.prev
            if created_in is not None and created_in.discarded:
                created_in = created_in._find_not_discarded()
            var.created_after_choice_point = created_in
        return self is created_in

    def _double_size(self):
        l = len(self.trail_var)
        if l == 0:
            self.trail_var = [None, None]
            self.trail_binding = [None, None]
        elif l == 1:
            assert 0, "cannot happen"
        else:
            self.trail_var = self.trail_var + [None] * l
            self.trail_binding = self.trail_binding + [None] * l

    def newvar(self):
        """ Make a new variable. Should return a Var instance, possibly with
        interesting attributes set that e.g. add_trail can inspect."""

        result = BindingVar()