]> Repositorios git - scryer-prolog.git/commitdiff
support comparison and unification of cyclic partial strings
authorMark Thom <[email protected]>
Thu, 18 Nov 2021 06:29:23 +0000 (23:29 -0700)
committerMark Thom <[email protected]>
Fri, 7 Jan 2022 04:44:41 +0000 (21:44 -0700)
src/machine/machine_state_impl.rs
src/machine/partial_string.rs
src/machine/system_calls.rs

index 89dd42697c7e57681176b3c65d268d1f95405651..1caa8a96ad730fe4ddb88ba56b05952d1b987877 100644 (file)
@@ -343,6 +343,13 @@ impl MachineState {
             (HeapCellValueTag::CStr, cstr_atom) => {
                 self.fail = atom != cstr_atom;
             }
+            (HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
+                self.unify_partial_string(atom_as_cstr_cell!(atom), value);
+
+                if !self.pdl.is_empty() {
+                    self.unify();
+                }
+            }
             _ => {
                 self.fail = true;
             }
@@ -367,12 +374,20 @@ impl MachineState {
         match compare_pstr_prefixes(&mut pstr_iter1, &mut pstr_iter2) {
             PStrCmpResult::Ordered(Ordering::Equal) => {}
             PStrCmpResult::Ordered(Ordering::Less) => {
-                self.pdl.push(empty_list_as_cell!());
-                self.pdl.push(pstr_iter2.focus);
+                if pstr_iter2.focus.as_var().is_none() {
+                    self.fail = true;
+                } else {
+                    self.pdl.push(empty_list_as_cell!());
+                    self.pdl.push(pstr_iter2.focus);
+                }
             }
             PStrCmpResult::Ordered(Ordering::Greater) => {
-                self.pdl.push(empty_list_as_cell!());
-                self.pdl.push(pstr_iter1.focus);
+                if pstr_iter1.focus.as_var().is_none() {
+                    self.fail = true;
+                } else {
+                    self.pdl.push(empty_list_as_cell!());
+                    self.pdl.push(pstr_iter1.focus);
+                }
             }
             continuable @ PStrCmpResult::FirstIterContinuable(iteratee) |
             continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
@@ -1014,12 +1029,20 @@ impl MachineState {
         match compare_pstr_prefixes(&mut pstr_iter1, &mut pstr_iter2) {
             PStrCmpResult::Ordered(Ordering::Equal) => {}
             PStrCmpResult::Ordered(Ordering::Less) => {
-                self.pdl.push(empty_list_as_cell!());
-                self.pdl.push(pstr_iter2.focus);
+                if pstr_iter2.focus.as_var().is_none() {
+                    self.fail = true;
+                } else {
+                    self.pdl.push(empty_list_as_cell!());
+                    self.pdl.push(pstr_iter2.focus);
+                }
             }
             PStrCmpResult::Ordered(Ordering::Greater) => {
-                self.pdl.push(empty_list_as_cell!());
-                self.pdl.push(pstr_iter1.focus);
+                if pstr_iter1.focus.as_var().is_none() {
+                    self.fail = true;
+                } else {
+                    self.pdl.push(empty_list_as_cell!());
+                    self.pdl.push(pstr_iter1.focus);
+                }
             }
             continuable @ PStrCmpResult::FirstIterContinuable(iteratee) |
             continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
index da32db4f910b94642909a3b149e2d19a8fe81b02..87256d04d8f59711ad4c09087f82a79c85b6be2e 100644 (file)
@@ -539,18 +539,33 @@ pub fn compare_pstr_prefixes<'a>(
     i2: &mut HeapPStrIter<'a>,
 ) -> PStrCmpResult {
     #[inline(always)]
-    fn consolidate_step(iter: &mut HeapPStrIter, step: &PStrIterStep) -> bool {
-        iter.focus = iter.heap[step.next_hare];
+    fn step(iter: &mut HeapPStrIter, hare: usize) -> Option<PStrIterStep> {
+        let result = iter.step(hare);
+
+        iter.focus = iter.heap[hare];
 
         if iter.focus.is_string_terminator(iter.heap) {
             iter.focus = empty_list_as_cell!();
         }
 
-        !iter.brent_st.step(step.next_hare).is_some()
+        result
+    }
+
+    #[inline(always)]
+    fn cycle_detection_step(i1: &mut HeapPStrIter, i2: &HeapPStrIter, step: &PStrIterStep) -> bool {
+        if i1.cycle_detected() {
+            i1.brent_st.hare = step.next_hare;
+            i2.cycle_detected()
+        } else if i1.brent_st.step(step.next_hare).is_some() {
+            i1.stepper = HeapPStrIter::post_cycle_discovery_stepper;
+            i2.cycle_detected()
+        } else {
+            false
+        }
     }
 
-    let mut r1 = i1.step(i1.brent_st.hare);
-    let mut r2 = i2.step(i2.brent_st.hare);
+    let mut r1 = step(i1, i1.brent_st.hare);
+    let mut r2 = step(i2, i2.brent_st.hare);
 
     loop {
         if let Some(step_1) = r1.as_mut() {
@@ -561,21 +576,14 @@ pub fn compare_pstr_prefixes<'a>(
                             return PStrCmpResult::Ordered(c1.cmp(&c2));
                         }
 
-                        let c1_result = consolidate_step(i1, &step_1);
-                        let c2_result = consolidate_step(i2, &step_2);
+                        cycle_detection_step(i1, i2, &step_1);
+                        let both_cyclic = cycle_detection_step(i2, i1, &step_2);
 
-                        if c1_result {
-                            r1 = i1.step(i1.brent_st.hare);
-                        }
-
-                        if c2_result {
-                            r2 = i2.step(i2.brent_st.hare);
-                        }
+                        r1 = step(i1, i1.brent_st.hare);
+                        r2 = step(i2, i2.brent_st.hare);
 
-                        if c1_result && c2_result {
+                        if !both_cyclic {
                             continue;
-                        } else {
-                            break;
                         }
                     }
                     (PStrIteratee::Char(_, c1), PStrIteratee::PStrSegment(f2, pstr_atom, n)) => {
@@ -591,36 +599,29 @@ pub fn compare_pstr_prefixes<'a>(
                             if n1 < pstr_atom.len() {
                                 step_2.iteratee = PStrIteratee::PStrSegment(f2, pstr_atom, n1);
 
-                                if consolidate_step(i1, &step_1) {
-                                    r1 = i1.step(step_1.next_hare);
+                                let c1_result = cycle_detection_step(i1, i2, &step_1);
+                                r1 = step(i1, i1.brent_st.hare);
+
+                                if !c1_result {
                                     continue;
-                                } else {
-                                    break;
                                 }
                             } else {
-                                let c1_result = consolidate_step(i1, &step_1);
-                                let c2_result = consolidate_step(i2, &step_2);
-
-                                if c1_result {
-                                    r1 = i1.step(i1.brent_st.hare);
-                                }
+                                cycle_detection_step(i1, i2, &step_1);
+                                let both_cyclic = cycle_detection_step(i2, i1, &step_2);
 
-                                if c2_result {
-                                    r2 = i2.step(i2.brent_st.hare);
-                                }
+                                r1 = step(i1, i1.brent_st.hare);
+                                r2 = step(i2, i2.brent_st.hare);
 
-                                if c1_result && c2_result {
+                                if !both_cyclic {
                                     continue;
-                                } else {
-                                    break;
                                 }
                             }
                         } else {
-                            if consolidate_step(i2, &step_2) {
-                                r2 = i2.step(step_2.next_hare);
+                            let c2_result = cycle_detection_step(i2, i1, &step_2);
+                            r2 = step(i2, i2.brent_st.hare);
+
+                            if !c2_result {
                                 continue;
-                            } else {
-                                break;
                             }
                         }
                     }
@@ -637,54 +638,42 @@ pub fn compare_pstr_prefixes<'a>(
                             if n1 < pstr_atom.len() {
                                 step_1.iteratee = PStrIteratee::PStrSegment(f1, pstr_atom, n1);
 
-                                if consolidate_step(i2, &step_2) {
-                                    r2 = i2.step(step_2.next_hare);
+                                let c2_result = cycle_detection_step(i2, i1, &step_2);
+                                r2 = step(i2, step_2.next_hare);
+
+                                if !c2_result {
                                     continue;
-                                } else {
-                                    break;
                                 }
                             } else {
-                                let c1_result = consolidate_step(i1, &step_1);
-                                let c2_result = consolidate_step(i2, &step_2);
-
-                                if c1_result {
-                                    r1 = i1.step(i1.brent_st.hare);
-                                }
+                                cycle_detection_step(i1, i2, &step_1);
+                                let both_cyclic = cycle_detection_step(i2, i1, &step_2);
 
-                                if c2_result {
-                                    r2 = i2.step(i2.brent_st.hare);
-                                }
+                                r1 = step(i1, i1.brent_st.hare);
+                                r2 = step(i2, i2.brent_st.hare);
 
-                                if c1_result && c2_result {
+                                if !both_cyclic {
                                     continue;
-                                } else {
-                                    break;
                                 }
                             }
                         } else {
-                            if consolidate_step(i1, &step_1) {
-                                r1 = i1.step(step_1.next_hare);
+                            let c1_result = cycle_detection_step(i1, i2, &step_1);
+                            r1 = step(i1, i1.brent_st.hare);
+
+                            if !c1_result {
                                 continue;
-                            } else {
-                                break;
                             }
                         }
                     }
                     (PStrIteratee::PStrSegment(f1, pstr1_atom, n1),
                      PStrIteratee::PStrSegment(f2, pstr2_atom, n2)) => {
                         if pstr1_atom == pstr2_atom && n1 == n2 {
-                            let c_result1 = consolidate_step(i1, &step_1);
-                            let c_result2 = consolidate_step(i2, &step_2);
-
-                            if c_result1 {
-                                r1 = i1.step(step_1.next_hare);
-                            }
+                            cycle_detection_step(i1, i2, &step_1);
+                            let both_cyclic = cycle_detection_step(i2, i1, &step_2);
 
-                            if c_result2 {
-                                r2 = i2.step(step_2.next_hare);
-                            }
+                            r1 = step(i1, i1.brent_st.hare);
+                            r2 = step(i2, i2.brent_st.hare);
 
-                            if c_result1 && c_result2 {
+                            if !both_cyclic {
                                 continue;
                             }
 
@@ -699,41 +688,32 @@ pub fn compare_pstr_prefixes<'a>(
 
                         match str1.len().cmp(&str2.len()) {
                             Ordering::Equal if str1 == str2 => {
-                                let c_result1 = consolidate_step(i1, &step_1);
-                                let c_result2 = consolidate_step(i2, &step_2);
+                                cycle_detection_step(i1, i2, &step_1);
+                                let both_cyclic = cycle_detection_step(i2, i1, &step_2);
 
-                                if c_result1 {
-                                    r1 = i1.step(step_1.next_hare);
-                                }
-
-                                if c_result2 {
-                                    r2 = i2.step(step_2.next_hare);
-                                }
+                                r1 = step(i1, i1.brent_st.hare);
+                                r2 = step(i2, i2.brent_st.hare);
 
-                                if c_result1 && c_result2 {
+                                if !both_cyclic {
                                     continue;
                                 }
-
-                                break;
                             }
                             Ordering::Less if str2.starts_with(str1) => {
                                 step_2.iteratee = PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len());
+                                let c1_result = cycle_detection_step(i1, i2, &step_1);
+                                r1 = step(i1, i1.brent_st.hare);
 
-                                if consolidate_step(i1, &step_1) {
-                                    r1 = i1.step(step_1.next_hare);
+                                if !c1_result {
                                     continue;
-                                } else {
-                                    break;
                                 }
                             }
                             Ordering::Greater if str1.starts_with(str2) => {
                                 step_1.iteratee = PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len());
+                                let c2_result = cycle_detection_step(i2, i1, &step_2);
+                                r2 = step(i2, i2.brent_st.hare);
 
-                                if consolidate_step(i2, &step_2) {
-                                    r2 = i2.step(step_2.next_hare);
+                                if !c2_result {
                                     continue;
-                                } else {
-                                    break;
                                 }
                             }
                             _ => {
@@ -757,22 +737,33 @@ pub fn compare_pstr_prefixes<'a>(
     // and thus matched by the compare_pstr_prefixes loop previously,
     // so here it suffices to check if they are both continuable.
 
-    if i1.focus == i2.focus {
-        PStrCmpResult::Ordered(Ordering::Equal)
-    } else if i1.focus == empty_list_as_cell!() {
-        PStrCmpResult::Ordered(Ordering::Less)
-    } else if i2.focus == empty_list_as_cell!() {
-        PStrCmpResult::Ordered(Ordering::Greater)
-    } else if i1.is_continuable() {
-        if i2.is_continuable() {
-            return PStrCmpResult::Ordered(Ordering::Equal);
-        }
+    let r1_at_end = r1.is_none();
+    let r2_at_end = r2.is_none();
 
-        PStrCmpResult::FirstIterContinuable(r1.unwrap().iteratee)
-    } else if i2.is_continuable() {
-        PStrCmpResult::SecondIterContinuable(r2.unwrap().iteratee)
+    if r1_at_end && r2_at_end {
+        if i1.focus == i2.focus {
+            PStrCmpResult::Ordered(Ordering::Equal)
+        } else {
+            PStrCmpResult::Unordered
+        }
+    } else if r1_at_end {
+        if i1.focus == empty_list_as_cell!() {
+            PStrCmpResult::Ordered(Ordering::Less)
+        } else {
+            PStrCmpResult::SecondIterContinuable(r2.unwrap().iteratee)
+        }
+    } else if r2_at_end {
+        if i2.focus == empty_list_as_cell!() {
+            PStrCmpResult::Ordered(Ordering::Greater)
+        } else {
+            PStrCmpResult::FirstIterContinuable(r1.unwrap().iteratee)
+        }
     } else {
-        PStrCmpResult::Unordered
+        if i1.is_continuable() && i2.is_continuable() {
+            PStrCmpResult::Ordered(Ordering::Equal)
+        } else {
+            PStrCmpResult::Unordered
+        }
     }
 }
 
index 7b85f2c4f5d6fd6b6d555516d1b2333d2ba7c13a..dd3858011c2d23e53e0d233913ddb396dd8bf833 100644 (file)
@@ -113,6 +113,15 @@ impl BrentAlgState {
         }
     }
 
+    #[inline(always)]
+    pub fn teleport_tortoise(&mut self) {
+        if self.lam == self.power {
+            self.tortoise = self.hare;
+            self.power <<= 1;
+            self.lam = 0;
+        }
+    }
+
     #[inline(always)]
     pub fn step(&mut self, hare: usize) -> Option<CycleSearchResult> {
         self.hare = hare;
@@ -120,10 +129,8 @@ impl BrentAlgState {
 
         if self.tortoise == self.hare {
             return Some(CycleSearchResult::NotList);
-        } else if self.lam == self.power {
-            self.tortoise = self.hare;
-            self.power <<= 1;
-            self.lam = 0;
+        } else {
+            self.teleport_tortoise();
         }
 
         None