]> Repositorios git - scryer-prolog.git/commitdiff
match on partial strings through get_list
authorMark Thom <[email protected]>
Tue, 25 Sep 2018 01:53:51 +0000 (19:53 -0600)
committerMark Thom <[email protected]>
Tue, 25 Sep 2018 01:53:51 +0000 (19:53 -0600)
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/tests.rs

index 9a7ec66825dca44cab7452efba6bdf8fd4443170..7a8efc85ed45928ff24133bc5e84468ae1b1a590 100644 (file)
@@ -1,4 +1,5 @@
 use prolog_parser::ast::*;
+use prolog_parser::string_list::*;
 use prolog_parser::tabled_rc::*;
 
 use prolog::instructions::*;
@@ -248,6 +249,7 @@ pub struct MachineState {
     pub(super) or_stack: OrStack,
     pub(super) registers: Registers,
     pub(super) trail: Vec<Ref>,
+    pub(super) partial_string_trail: Vec<(StringList, usize)>,
     pub(super) tr: usize,
     pub(super) hb: usize,
     pub(super) block: usize, // an offset into the OR stack.
@@ -299,7 +301,6 @@ pub(crate) trait CallPolicy: Any {
         machine_st.heap.truncate(machine_st.or_stack[b].h);
 
         machine_st.hb = machine_st.heap.h;
-
         machine_st.p += 1;
 
         Ok(())
@@ -329,7 +330,6 @@ pub(crate) trait CallPolicy: Any {
         machine_st.heap.truncate(machine_st.or_stack[b].h);
 
         machine_st.hb = machine_st.heap.h;
-
         machine_st.p += offset;
 
         Ok(())
index 62db2efa5ae09828d923e0a5f64c90c0f9b92b87..03dcdf59bafeadb543c82c7979160cfc198881fc 100644 (file)
@@ -48,7 +48,8 @@ impl MachineState {
             and_stack: AndStack::new(),
             or_stack: OrStack::new(),
             registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used.
-            trail: Vec::new(),
+            trail: vec![],
+            partial_string_trail: vec![],
             tr: 0,
             hb: 0,
             block: 0,
@@ -135,7 +136,7 @@ impl MachineState {
         let mut output = printer.print(addr);
 
         let bad_ending = format!("= {}", &var);
-        
+
         if output.ends_with(&bad_ending) {
             output.truncate(orig_len);
         }
@@ -196,7 +197,7 @@ impl MachineState {
                         self.fail = true;
                     },
                     (Addr::Lis(a1), Addr::Con(Constant::String(ref mut s)))
-                        | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1))
+                  | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1))
                         if self.flags.double_quotes.is_chars() => {
                             if let Some(c) = s.head() {
                                 pdl.push(Addr::Con(Constant::String(s.tail())));
@@ -233,7 +234,7 @@ impl MachineState {
                             self.fail = true;
                         },
                     (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s)))
-                        | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList))
+                  | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList))
                         if self.flags.double_quotes.is_chars() => {
                             if s.is_expandable() && s.is_empty() {
                                 s.set_non_expandable();
@@ -249,7 +250,8 @@ impl MachineState {
                         pdl.push(Addr::HeapCell(a1 + 1));
                         pdl.push(Addr::HeapCell(a2 + 1));
                     },
-                    (Addr::Con(Constant::String(ref mut s1)), Addr::Con(Constant::String(ref mut s2))) => {
+                    (Addr::Con(Constant::String(ref mut s1)),
+                     Addr::Con(Constant::String(ref mut s2))) => {
                         let mut stepper = |s1: &mut StringList, s2: &mut StringList| -> bool {
                             if let Some(c1) = s1.head() {
                                 if let Some(c2) = s2.head() {
@@ -314,7 +316,7 @@ impl MachineState {
             }
         }
     }
-    
+
     fn trail(&mut self, r: Ref) {
         match r {
             Ref::HeapCell(hc) =>
@@ -368,7 +370,7 @@ impl MachineState {
 
             match tr_i {
                 Ref::HeapCell(tr_i) =>
-                    if tr_i < hb { //|| ((h < tr_i) && tr_i < b) {
+                    if tr_i < hb {
                         i += 1;
                     } else {
                         let tr = self.tr;
@@ -398,6 +400,13 @@ impl MachineState {
         }
     }
 
+    #[inline]
+    fn write_char_to_string(&mut self, s: &mut StringList, c: char) -> bool {
+        let new_s = s.push_char(c);
+        self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::String(new_s))));
+        false
+    }
+
     pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: Constant) {
         match self.store(self.deref(addr)) {
             Addr::HeapCell(hc) => {
@@ -417,13 +426,24 @@ impl MachineState {
                         false
                     },
                     Constant::String(s2) => *s != s2,
+                    Constant::Atom(ref a, _) if s.is_empty() && s.is_expandable() =>
+                        if let Some(c) = a.as_str().chars().next() {
+                            if c.len_utf8() == a.as_str().len() {
+                                self.write_char_to_string(s, c)
+                            } else {
+                                true
+                            }
+                        } else {
+                            true
+                        },
+                    Constant::Char(ref c) if s.is_empty() && s.is_expandable() =>
+                        self.write_char_to_string(s, *c),
                     _ => true
                 },
-            Addr::Con(c1) => {
+            Addr::Con(c1) =>
                 if c1 != c {
                     self.fail = true;
-                }
-            },
+                },
             _ => self.fail = true
         };
     }
@@ -1529,7 +1549,7 @@ impl MachineState {
                     return Ordering::Greater,
                 (HeapCellValue::Addr(Addr::Con(Constant::String(_))),
                  HeapCellValue::Addr(Addr::Con(Constant::Number(_)))) =>
-                    return Ordering::Greater,                
+                    return Ordering::Greater,
                 (HeapCellValue::Addr(Addr::Con(Constant::String(s1))),
                  HeapCellValue::Addr(Addr::Con(Constant::String(s2)))) =>
                     return if s1.is_expandable() {
@@ -2045,7 +2065,7 @@ impl MachineState {
 
         self.p += 1;
     }
-    
+
     fn handle_call_clause<'a>(&mut self, indices: MachineCodeIndices<'a>,
                               call_policy: &mut Box<CallPolicy>,
                               cut_policy:  &mut Box<CutPolicy>,
@@ -2089,7 +2109,7 @@ impl MachineState {
             &ControlInstruction::Allocate(num_cells) =>
                 self.allocate(num_cells),
             &ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) =>
-                self.handle_call_clause(indices, call_policy, cut_policy, 
+                self.handle_call_clause(indices, call_policy, cut_policy,
                                         ct, arity, lco, use_default_cp),
             &ControlInstruction::Deallocate => self.deallocate(),
             &ControlInstruction::JmpBy(arity, offset, _, lco) => {
@@ -2207,7 +2227,6 @@ impl MachineState {
                 self.p += 1;
             },
             &CutInstruction::GetLevelAndUnify(r) => {
-                // let b0 = Addr::Con(Constant::Usize(self.b0));
                 let b0 = self[perm_v!(1)].clone();
                 let a  = self[r].clone();
 
@@ -2233,6 +2252,7 @@ impl MachineState {
 
         self.fail = false;
         self.trail.clear();
+        self.partial_string_trail.clear();
         self.heap.clear();
         self.mode = MachineMode::Write;
         self.and_stack.clear();
index c2a139ea60f2b25eaf52585a8820016744e78cf4..3af70b0772c8146ef1ea31c93a9799c0ed23c9fa 100644 (file)
@@ -1972,4 +1972,14 @@ fn test_queries_on_string_lists()
     assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), X @> \"abc\".");
     assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), X \\=@= \"abc\".");
     assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), X @< \"abc\".");
+
+    assert_prolog_success!(&mut wam, "?- partial_string(\"ab\", X), matcher(X, Y), Y = [a,b|V], 
+                                         matcher(Y, Z), is_partial_string(Y).",
+                           [["V = [c | _]", "X = [a, b, c, a, b, c | _]", "Y = [a, b, c | _]", "Z = _"]]);
+    assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).",
+                           [["X = [a, b, c | _]", "Y = _"]]);
+    assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), is_partial_string(Y).",
+                           [["X = [a, b, c | _]", "Y = _"]]);
+    assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), Y = \"def\".",
+                           [["X = [a, b, c, d, e, f]", "Y = [d, e, f]"]]);
 }