Commits

David Schneider  committed 95c243c

Provide an interface to access term arguments to avoid accessing the internal array directly

  • Participants
  • Parent commits a97f0b7
  • Branches continuation-based

Comments (0)

Files changed (16)

File prolog/builtin/control.py

         scont = fcont = continuation.CutDelimiter(engine, scont, fcont)
         fcont = OrContinuation(engine, scont, heap, fcont, call2)
         newscont, fcont, heap = impl_if(
-                engine, heap, helper.ensure_callable(call1.args[0]),
-                call1.args[1], scont, fcont, insert_cutdelimiter=False)
+                engine, heap, helper.ensure_callable(call1.argument_at(0)),
+                call1.argument_at(1), scont, fcont, insert_cutdelimiter=False)
         return newscont, fcont, heap.branch()
     else:
         fcont = OrContinuation(engine, scont, heap, fcont, call2)

File prolog/builtin/database.py

 def impl_retract(engine, heap, pattern):
     from 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])
+        head = helper.ensure_callable(pattern.argument_at(0))
+        body = helper.ensure_callable(pattern.argument_at(1))
     else:
         head = pattern
         body = None

File prolog/builtin/formatting.py

         ignore_ops = False
         number_vars = False
         for option in options:
-            if (not isinstance(option, Term) or len(option.args) != 1):
+            if (not isinstance(option, Term) or len(option.argument_count()) != 1):
                 error.throw_domain_error('write_option', option)
-            arg = option.args[0]
+            arg = option.argument_at(0)
             if option.name == "max_depth":
                 try:
                     max_depth = helper.unwrap_int(arg)
 
     def format_term_normally(self, term):
         return "%s(%s)" % (self.format_atom(term.name),
-                           ", ".join([self.format(a) for a in term.args]))
+                           ", ".join([self.format(a) for a in term.arguments()]))
 
     def format_term(self, term):
         if self.ignore_ops:
         if term.signature == "./2":
             result = ["["]
             while isinstance(term, Term) and term.signature == "./2":
-                first = term.args[0]
-                second = term.args[1]
+                first = term.argument_at(0)
+                second = term.argument_at(1)
                 result.append(self.format(first))
                 result.append(", ")
                 term = second
                 result.append(self.format(term))
                 result.append("]")
             return (0, "".join(result))
-        if (len(term.args), term.name) not in self.op_mapping:
+        if (term.argument_count(), term.name) not in self.op_mapping:
             return (0, self.format_term_normally(term))
-        form, prec = self.op_mapping[(len(term.args), term.name)]
+        form, prec = self.op_mapping[(term.argument_count(), term.name)]
         result = []
-        assert 0 <= len(term.args) <= 2
+        assert 0 <= term.argument_count() <= 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])
+                childprec, child = self.format_with_ops(term.argument_at(curr_index))
                 parentheses = (c == "x" and childprec >= prec or
                                c == "y" and childprec > prec)
                 if parentheses:
                 else:
                     result.append(child)
                 curr_index += 1
-        assert curr_index == len(term.args)
+        assert curr_index == term.argument_count()
         return (prec, "".join(result))
 
     def _make_reverse_op_mapping(self):

File prolog/builtin/register.py

         varname = "var%s" % (i, )
         subargs.append(varname)
         if spec in ("obj", "callable", "int", "atom", "arithmetic"):
-            code.append("    %s = query.args[%s].dereference(heap)" %
+            code.append("    %s = query.argument_at(%s).dereference(heap)" %
                         (varname, i))
         elif spec in ("concrete", "list"):
-            code.append("    %s = query.args[%s].getvalue(heap)" %
+            code.append("    %s = query.argument_at(%s).getvalue(heap)" %
                         (varname, i))
         if spec in ("int", "atom", "arithmetic", "list"):
             code.append(
             code.append(
                 "        error.throw_type_error('callable', %s)" % (varname,))
         elif spec == "raw":
-            code.append("    %s = query.args[%s]" % (varname, i))
+            code.append("    %s = query.argument_at(%s)" % (varname, i))
         elif spec == "int":
             code.append("    %s = helper.unwrap_int(%s)" % (varname, varname))
         elif spec == "atom":

File prolog/builtin/termconstruction.py

         arity.unify(term.Number(0), heap)
     elif isinstance(t, term.Term):
         functor.unify(term.Atom(t.name), heap)
-        arity.unify(term.Number(len(t.args)), heap)
+        arity.unify(term.Number(t.argument_count()), heap)
     elif isinstance(t, term.Var):
         if isinstance(functor, term.Var):
             error.throw_instantiation_error()
         error.throw_type_error("compound", second)
     if isinstance(first, term.Var):
         oldstate = heap.branch()
-        for i in range(len(second.args)):
-            arg = second.args[i]
+        for i in range(second.argument_count()):
+            arg = second.argument_at(i)
             try:
                 third.unify(arg, heap)
                 first.unify(term.Number(i + 1), heap)
             raise error.UnificationFailed
         if num < 0:
             error.throw_domain_error("not_less_than_zero", first)
-        if num > len(second.args):
+        if num > second.argument_count():
             raise error.UnificationFailed()
-        arg = second.args[num - 1]
+        arg = second.argument_at(num - 1)
         third.unify(arg, heap)
     else:
         error.throw_type_error("integer", first)
 def impl_univ(engine, heap, first, second):
     if not isinstance(first, term.Var):
         if isinstance(first, term.Term):
-            l = [term.Atom(first.name)] + first.args
+            l = [term.Atom(first.name)] + first.arguments()
         else:
             l = [first]
         u1 = helper.wrap_list(l)

File prolog/builtin/type.py

     if isinstance(var, term.Var):
         raise error.UnificationFailed()
     if isinstance(var, term.Term):
-        for arg in var.args:
+        for arg in var.arguments():
             impl_ground(engine, heap, arg)
 
 

File prolog/interpreter/arithmetic.py

     code.start_block("def prolog_%s(engine, query):" % name)
     for i, spec in enumerate(unwrap_spec):
         varname = "var%s" % (i, )
-        code.emit("%s = eval_arithmetic(engine, query.args[%s])" %
+        code.emit("%s = eval_arithmetic(engine, query.argument_at(%s))" %
                   (varname, i))
     for i, spec in enumerate(unwrap_spec):
         varname = "var%s" % (i, )

File prolog/interpreter/continuation.py

         from prolog import builtin
         if isinstance(rule, Term):
             if rule.name == ":-":
-                rule = Rule(rule.args[0], rule.args[1])
+                rule = Rule(rule.argument_at(0), rule.argument_at(1))
             else:
                 rule = Rule(rule, None)
         elif isinstance(rule, Atom):
         builder = TermBuilder()
         term = builder.build_query(tree)
         if isinstance(term, Term) and term.signature == ":-/1":
-            self.run(term.args[0])
+            self.run(term.argument_at(0))
         else:
             self.add_rule(term)
         return self.parser

File prolog/interpreter/function.py

         memo = {}
         self.head = h = head.enumerate_vars(memo)
         if isinstance(h, Term):
-            self.headargs = h.args
+            self.headargs = h.arguments()
         else:
             self.headargs = None
         if body is not None:
                     self.contains_cut = True
                     return
             elif isinstance(current, Term):
-                stack.extend(current.args)
+                stack.extend(current.arguments())
         self.contains_cut = False
 
     @jit.unroll_safe
             assert isinstance(head, Term)
             for i in range(len(self.headargs)):
                 arg2 = self.headargs[i]
-                arg1 = head.args[i]
+                arg1 = head.argument_at(i)
                 arg2.unify_and_standardize_apart(arg1, heap, env)
         body = self.body
         if body is None:

File prolog/interpreter/helper.py

     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]
+        result.append(curr.argument_at(0))
+        curr = curr.argument_at(1)
     if isinstance(curr, term.Atom) and curr.name == "[]":
         return result
     error.throw_type_error("list", prolog_list)
     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:
+    if not predicate.name == "/" or predicate.argument_count() != 2:
         error.throw_type_error("predicate_indicator", predicate)
-    name = unwrap_atom(predicate.args[0])
-    arity = unwrap_int(predicate.args[1])
+    name = unwrap_atom(predicate.argument_at(0))
+    arity = unwrap_int(predicate.argument_at(1))
     return name, arity
 
 def ensure_atomic(obj):

File prolog/interpreter/interactive.py

             self.write("no\n")
         except error.CatchableError, e:
             self.write("ERROR: ")
-            if e.term.args[0].name == "instantiation_error":
+            if e.term.argument_at(0).name == "instantiation_error":
                 print e.term
                 self.write("arguments not sufficiently instantiated\n")
-            elif e.term.args[0].name == "existence_error":
+            elif e.term.argument_at(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]))
+                self.write("Undefined %s: %s\n" % (e.term.argument_at(0).argument_at(0),
+                                                   e.term.argument_at(0).argument_at(1)))
             else:
                 self.write("of unknown type: %s\n" % (e.term, ))
         except error.UncatchableError, e:

File prolog/interpreter/term.py

 
     def __eq__(self, other):
         # for testing
+        # XXX delete
         return self is other
 
     def eval_arithmetic(self, engine):
 
     def get_prolog_signature(self):
         raise NotImplementedError("abstract base")
+        
+    def arguments(self):
+        raise NotImplementedError("abstract base")
+        
+    def argument_at(self, i):
+        raise NotImplementedError("abstract base")
 
-
+    def argument_count(self):
+        raise NotImplementedError("abstract base")
+        
 class Atom(Callable):
     TYPE_STANDARD_ORDER = 1
 
         if self.name == "e":
             return Float.e
         error.throw_type_error("evaluable", self.get_prolog_signature())
+        
+    def arguments(self):
+        return []
+
+    def argument_at(self, i):
+        raise IndexError
+    
+    def argument_count(self):
+        return 0
 
 
 class Number(NonVar): #, UnboxedValue):
     return obj.getvalue(heap)
 
 def _term_unify_and_standardize_apart(obj, i, other, heap, memo):
-    obj.unify_and_standardize_apart(other.args[i], heap, memo)
+    obj.unify_and_standardize_apart(other.argument_at(i), heap, memo)
 
 class Term(Callable):
     TYPE_STANDARD_ORDER = 3
     _immutable_ = True
-    _immutable_fields_ = ["args[*]"]
+    _immutable_fields_ = ["_args[*]"]
 
     def __init__(self, name, args, signature=None):
+
         self.name = name
-        self.args = make_sure_not_resized(args)
+        self._args = make_sure_not_resized(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)
+        return "Term(%r, %r)" % (self.name, self.arguments())
 
     def __str__(self):
-        return "%s(%s)" % (self.name, ", ".join([str(a) for a in self.args]))
+        return "%s(%s)" % (self.name, ", ".join([str(a) for a in self.arguments()]))
 
     @specialize.arg(3)
     def basic_unify(self, other, heap, occurs_check=False):
         if (isinstance(other, Term) and
             self.name == other.name and
-            len(self.args) == len(other.args)):
-            for i in range(len(self.args)):
-                self.args[i].unify(other.args[i], heap, occurs_check)
+            self.argument_count() == other.argument_count()):
+            for i in range(self.argument_count()):
+                self.argument_at(i).unify(other.argument_at(i), heap, occurs_check)
         else:
             raise UnificationFailed
 
     @specialize.arg(1)
     @jit.unroll_safe
     def _copy_term(self, copy_individual, *extraargs):
-        args = [None] * len(self.args)
+        args = [None] * self.argument_count()
         newinstance = False
         i = 0
-        while i < len(self.args):
-            arg = self.args[i]
+        while i < self.argument_count():
+            arg = self.argument_at(i)
             cloned = copy_individual(arg, i, *extraargs)
             newinstance = newinstance or cloned is not arg
             args[i] = cloned
             return self
 
     def get_prolog_signature(self):
-        return Term("/", [Atom.newatom(self.name), Number(len(self.args))])
+        return Term("/", [Atom.newatom(self.name),
+                                                Number(self.argument_count())])
     
     def contains_var(self, var, heap):
-        for arg in self.args:
+        for arg in self.arguments():
             if arg.contains_var(var, heap):
                 return True
         return False
         if func is None:
             error.throw_type_error("evaluable", self.get_prolog_signature())
         return func(engine, self)
+    
+    def arguments(self):
+        return self._args
 
-
+    def argument_at(self, i):
+        return self._args[i]
+        
+    def argument_count(self):
+        return len(self._args)
 @specialize.argtype(0)
 def rcmp(a, b): # RPython does not support cmp...
     if a == b:
         return rcmp(obj1.name, obj2.name)
     if isinstance(obj1, Term):
         assert isinstance(obj2, Term)
-        c = rcmp(len(obj1.args), len(obj2.args))
+        c = rcmp(obj1.argument_count(), obj2.argument_count())
         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(heap)
-            a2 = obj2.args[i].dereference(heap)
+        for i in range(obj1.argument_count()):
+            a1 = obj1.argument_at(i).dereference(heap)
+            a2 = obj2.argument_at(i).dereference(heap)
             c = cmp_standard_order(a1, a2, heap)
             if c != 0:
                 return c

File prolog/interpreter/test/test_continuation.py

     query = Term(",", [Term("f", [Var()]), Term("g", [Var()])])
     py.test.raises(error.UnificationFailed,
                    e.run_query, query, CollectContinuation())
-    assert all[0].args[0].args[0].name == "x"
-    assert all[0].args[1].args[0].name == "a"
-    assert all[1].args[0].args[0].name == "x"
-    assert all[1].args[1].args[0].name == "b"
-    assert all[2].args[0].args[0].name == "y"
-    assert all[2].args[1].args[0].name == "a"
-    assert all[3].args[0].args[0].name == "y"
-    assert all[3].args[1].args[0].name == "b"
+    assert all[0].argument_at(0).argument_at(0).name == "x"
+    assert all[0].argument_at(1).argument_at(0).name == "a"
+    assert all[1].argument_at(0).argument_at(0).name == "x"
+    assert all[1].argument_at(1).argument_at(0).name == "b"
+    assert all[2].argument_at(0).argument_at(0).name == "y"
+    assert all[2].argument_at(1).argument_at(0).name == "a"
+    assert all[3].argument_at(0).argument_at(0).name == "y"
+    assert all[3].argument_at(1).argument_at(0).name == "b"
 
 # ___________________________________________________________________
 # integration tests

File prolog/interpreter/test/test_parsing.py

     for fact in facts:
         print fact
         e.add_rule(fact)
-    assert e.signature2function["add_numeral/3"].rulechain.head.args[1].name == "null"
+    assert e.signature2function["add_numeral/3"].rulechain.head.argument_at(1).name == "null"
     four = Term("succ", [Term("succ", [Term("succ",
                 [Term("succ", [Atom("null")])])])])
     e.run(parse_query_term("numeral(succ(succ(null)))."))
     """)
     builder = TermBuilder()
     fact, = builder.build(t)
-    assert fact.args[0].name == 'ASa0%!!231@~!@#%'
-    assert fact.args[1].name == 'a'
-    assert fact.args[2].name == '[]'
+    assert fact.argument_at(0).name == 'ASa0%!!231@~!@#%'
+    assert fact.argument_at(1).name == 'a'
+    assert fact.argument_at(2).name == '[]'
     t = parse_file("""
         'a'.
         a.
     builder = TermBuilder()
     facts = builder.build(t)
     assert len(facts) == 2
-    assert facts[0].args[1].num == -1
-    assert facts[1].args[1].floatval == -1.345
+    assert facts[0].argument_at(1).num == -1
+    assert facts[1].argument_at(1).floatval == -1.345
     t = parse_file("""
         X = -1.
         arg(X, h(a, b, c), b), X = 2.

File prolog/interpreter/test/test_unification.py

     t2 = t1.enumerate_vars({})
     assert isinstance(t2, Term)
     assert t2.signature == t1.signature
-    assert t2.args[0] is t2.args[1]
-    assert t2.args[0].num == 0
-    assert t2.args[2].args[1].num == 0
+    assert t2.argument_at(0) is t2.argument_at(1)
+    assert t2.argument_at(0).num == 0
+    assert t2.argument_at(2).argument_at(1).num == 0
 
 def test_copy_and_unify():
     heap = Heap()

File prolog/interpreter/translatedmain.py

         printmessage("ERROR: ")
         t = e.term
         if isinstance(t, term.Term):
-            errorterm = t.args[0]
+            errorterm = t.argument_at(0)
             if isinstance(errorterm, term.Callable):
                 if errorterm.name == "instantiation_error":
                     printmessage("arguments not sufficiently instantiated\n")
                 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])))
+                            f.format(errorterm.argument_at(0)),
+                            f.format(errorterm.argument_at(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])))
+                            f.format(errorterm.argument_at(0)),
+                            f.format(errorterm.argument_at(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])))
+                            f.format(errorterm.argument_at(0)),
+                            f.format(errorterm.argument_at(1))))
                         return
     # except error.UncatchableError, e:
     #     printmessage("INTERNAL ERROR: %s\n" % (e.message, ))