]> Repositorios git - scryer-prolog.git/commitdiff
use copy_term/3 to print residual goals (#254)
authorMark Thom <[email protected]>
Sun, 5 Apr 2020 00:44:16 +0000 (18:44 -0600)
committerMark Thom <[email protected]>
Sun, 5 Apr 2020 08:55:04 +0000 (02:55 -0600)
src/prolog/machine/copier.rs

index 10b67d4e47f2995d4a88e25986077b95e9971102..baa1f2b92abe8fe75a2c8ceb4f551d94f28dc2fe 100644 (file)
@@ -53,13 +53,27 @@ impl<T: CopierTarget> CopyTermState<T> {
         &mut self.target[scan]
     }
 
+    fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
+        let trail_item = mem::replace(
+            &mut self.target[addr],
+            HeapCellValue::Addr(Addr::Lis(threshold)),
+        );
+
+        self.trail.push((
+            Ref::HeapCell(addr),
+            trail_item,
+        ));
+    }
+
     fn copy_list(&mut self, addr: usize) {
-        if let Addr::Lis(h) = self.target[addr + 1].as_addr(addr + 1) {
-            if h >= self.old_h {
-                *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h));
-                self.scan += 1;
+        for offset in 0 .. 2 {
+            if let Addr::Lis(h) = self.target[addr + offset].as_addr(addr + offset) {
+                if h >= self.old_h {
+                    *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h));
+                    self.scan += 1;
 
-                return;
+                    return;
+                }
             }
         }
 
@@ -74,15 +88,14 @@ impl<T: CopierTarget> CopyTermState<T> {
 
         let cdr = self.target.store(self.target.deref(Addr::HeapCell(addr + 1)));
 
-        if let Addr::Lis(_) = cdr {
-            let tail_addr = self.target[addr + 1].as_addr(addr + 1);
-
-            self.trail.push((
-                Ref::HeapCell(addr + 1),
-                HeapCellValue::Addr(tail_addr),
-            ));
+        if !cdr.is_ref() {
+            self.trail_list_cell(addr + 1, threshold);
+        } else {
+            let car = self.target.store(self.target.deref(Addr::HeapCell(addr)));
 
-            self.target[addr + 1] = HeapCellValue::Addr(Addr::Lis(threshold));
+            if !car.is_ref() {
+                self.trail_list_cell(addr, threshold);
+            }
         }
 
         self.scan += 1;
@@ -163,7 +176,7 @@ impl<T: CopierTarget> CopyTermState<T> {
                 };
 
                 self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold));
-                self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
+                self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
 
                 self.trail.push((
                     Ref::AttrVar(h),
@@ -271,6 +284,9 @@ impl<T: CopierTarget> CopyTermState<T> {
                                 *self.value_at_scan() = HeapCellValue::Addr(addr);
                             }
                         }
+                        Addr::Lis(h) if h >= self.old_h => {
+                            self.scan += 1;
+                        }
                         Addr::Lis(h) => {
                             self.copy_list(h);
                         }