1. Carl Friedrich Bolz
  2. Pyrolog

Commits

David Schneider  committed 1548b7b

(cfbolz, david) Implemented repeat

  • Participants
  • Parent commits e2fd032
  • Branches continuation-based

Comments (0)

Files changed (2)

File prolog/builtin/control.py

View file
 def impl_true(engine, heap):
     return
 
-#@expose_builtin("repeat", unwrap_spec=[], handles_continuation=True)
-def impl_repeat(engine, heap, continuation):
-    while 1:
-        try:
-            return continuation.call(engine, choice_point=True)
-        except error.UnificationFailed:
-            pass
+@expose_builtin("repeat", unwrap_spec=[], handles_continuation=True)
+def impl_repeat(engine, heap, scont, fcont):
+    return scont, RepeatContinuation(engine, scont, fcont, heap), heap.branch()
 
+class RepeatContinuation(continuation.FailureContinuation):
+    def __init__(self, engine, scont, fcont, heap):
+        continuation.FailureContinuation.__init__(self, engine, scont)
+        self.fcont = fcont
+        self.undoheap = heap
+        
+    def activate(self, fcont, heap):
+        assert 0, "Unreachable"
+        
+    def fail(self, heap):
+        heap = heap.revert_upto(self.undoheap)
+        return self.nextcont, self, heap
+    
+    def cut(self):
+        if self.fcont is not None:
+            return self.fcont.cut()
+        return None
+        
 @expose_builtin("!", unwrap_spec=[], handles_continuation=True)
 def impl_cut(engine, heap, scont, fcont):
     if fcont:
 
 class OrContinuation(continuation.FailureContinuation):
     def __init__(self, engine, nextcont, undoheap, orig_fcont, altcall):
-        continuation.Continuation.__init__(self, engine, nextcont)
+        continuation.FailureContinuation.__init__(self, engine, nextcont)
         self.altcall = altcall
         self.undoheap = undoheap
         self.orig_fcont = orig_fcont

File prolog/interpreter/test/test_builtin.py

View file
     py.test.raises(UnificationFailed,
         Engine().run, parse_query_term("repeat, !, fail."))
     # hard to test repeat differently
+    e = get_engine('f :- repeat, !, fail.')
+    assert_false('f.', e)
+    assert_true('f; true.', e)
+    
 
 def test_exception_handling():
     assert_true("catch(f, E, true).")