]> Repositorios git - scryer-prolog.git/commitdiff
distinguish eq from structural_eq on strings
authorMark Thom <[email protected]>
Mon, 3 Sep 2018 06:06:01 +0000 (00:06 -0600)
committerMark Thom <[email protected]>
Mon, 3 Sep 2018 06:06:01 +0000 (00:06 -0600)
src/prolog/compile.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/parser
src/prolog/read.rs
src/prolog/string_list.rs
src/prolog/toplevel.rs
src/tests.rs

index 5c014117407174f049166b67d8c7989eb140a474..f0bb298660a859b1e4fc0ef9965ccfc7a1ef54c0 100644 (file)
@@ -39,7 +39,6 @@ fn print_code(code: &Code) {
 pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result<TopLevelPacket, ParserError>
 {
     let atom_tbl = wam.atom_tbl();
-    let string_tbl = wam.string_tbl();
     let flags = wam.machine_flags();
 
     let index = MachineCodeIndices {
@@ -47,8 +46,7 @@ pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result<TopLevelPacket, Par
         op_dir: &mut wam.op_dir,
     };
 
-    let mut worker = TopLevelWorker::new(buffer.as_bytes(), atom_tbl, string_tbl,
-                                         flags, index);
+    let mut worker = TopLevelWorker::new(buffer.as_bytes(), atom_tbl, flags, index);
     worker.parse_code()
 }
 
@@ -245,8 +243,7 @@ fn use_qualified_module(module: &mut Option<Module>, submodule: &Module, exports
 pub
 fn compile_listing(wam: &mut Machine, src_str: &str, mut indices: MachineCodeIndices) -> EvalSession
 {
-    let mut worker   = TopLevelBatchWorker::new(src_str.as_bytes(), wam.atom_tbl(), wam.string_tbl(),
-                                                wam.machine_flags());
+    let mut worker = TopLevelBatchWorker::new(src_str.as_bytes(), wam.atom_tbl(), wam.machine_flags());
     let mut compiler = ListingCompiler::new(wam);
 
     while let Some(decl) = try_eval_session!(worker.consume(&mut indices)) {
index 5b01914601271e31dd3b9b21a3019811e0a24727..f7c4c1cde30de016e7506cc7dfdd41dc3f5c3431 100644 (file)
@@ -6,7 +6,6 @@ use prolog::machine::machine_errors::*;
 use prolog::num::{BigInt, BigUint, Zero, One};
 use prolog::or_stack::*;
 use prolog::read::*;
-use prolog::string_list::*;
 use prolog::tabled_rc::*;
 
 use downcast::Any;
@@ -299,7 +298,6 @@ impl Default for MachineFlags {
 
 pub struct MachineState {
     pub(crate) atom_tbl: TabledData<Atom>,
-    pub(crate) string_tbl: TabledData<StringListWrapper>,
     pub(super) s: usize,
     pub(super) p: CodePtr,
     pub(super) b: usize,
@@ -626,15 +624,7 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::Eq => {
-                let a1 = machine_st[temp_v!(1)].clone();
-                let a2 = machine_st[temp_v!(2)].clone();
-
-                machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
-                    false
-                } else {
-                    true
-                };
-
+                machine_st.fail = machine_st.eq_test();
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::Ground => {
index b9a411aebcb8684dda3961001874fd0570d803ce..2e223b6e96aea60f13b80dfa733fadb20b429074 100644 (file)
@@ -32,7 +32,6 @@ impl MachineState {
     pub(super) fn new() -> Self {
         MachineState {
             atom_tbl: Rc::new(RefCell::new(HashSet::new())),
-            string_tbl: Rc::new(RefCell::new(HashSet::new())),
             s: 0,
             p: CodePtr::default(),
             b: 0,
@@ -1420,6 +1419,33 @@ impl MachineState {
         };
     }
 
+    // returns true on failure.
+    pub(super) fn eq_test(&self) -> bool
+    {
+        let a1 = self[temp_v!(1)].clone();
+        let a2 = self[temp_v!(2)].clone();
+
+        let iter = self.zipped_acyclic_pre_order_iter(a1, a2);
+
+        for (v1, v2) in iter {
+            match (v1, v2) {
+                (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
+                    if ar1 != ar2 || n1 != n2 {
+                        return true;
+                    },
+                (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
+                    continue,
+                (HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) =>
+                    if a1 != a2 {
+                        return true;
+                    },
+                _ => return true
+            }
+        }
+
+        false
+    }
+    
     pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Ordering {
         let iter = self.zipped_acyclic_pre_order_iter(a1.clone(), a2.clone());
 
@@ -1500,10 +1526,8 @@ impl MachineState {
                  HeapCellValue::Addr(Addr::Con(Constant::Number(_)))) =>
                     return Ordering::Greater,
                 (HeapCellValue::Addr(Addr::Con(Constant::String(s1))),
-                 HeapCellValue::Addr(Addr::Con(Constant::String(s2)))) =>
-                    if s1 != s2 {
-                        return s1.cmp(&s2);
-                    },
+                 HeapCellValue::Addr(Addr::Con(Constant::String(s2)))) =>                    
+                    return s1.cmp(&s2),
                 (HeapCellValue::Addr(Addr::Con(Constant::String(_))), _) =>
                     return Ordering::Less,
                 (HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
index a5a8cd23713c21b188c44cacd4bc80de2523afd8..508eb9049c9dbb1ed21475bbf26fb17a49e94f4e 100644 (file)
@@ -1,7 +1,6 @@
 use prolog::ast::*;
 use prolog::compile::*;
 use prolog::heap_print::*;
-use prolog::string_list::StringListWrapper;
 use prolog::tabled_rc::*;
 
 mod machine_errors;
@@ -174,17 +173,15 @@ impl Machine {
         }
     }
 
+    #[inline]
     pub fn failed(&self) -> bool {
         self.ms.fail
     }
 
+    #[inline]
     pub fn atom_tbl(&self) -> TabledData<Atom> {
         self.ms.atom_tbl.clone()
     }
-
-    pub fn string_tbl(&self) -> TabledData<StringListWrapper> {
-        self.ms.string_tbl.clone()
-    }
     
     pub fn use_qualified_module_in_toplevel(&mut self, name: ClauseName, exports: Vec<PredicateKey>)
                                             -> EvalSession
index cd2fdbb463a36a2743042206f56020b5bf0359cf..b663bce82dc7543c2bc01b557f7b0926ef29f07c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cd2fdbb463a36a2743042206f56020b5bf0359cf
+Subproject commit b663bce82dc7543c2bc01b557f7b0926ef29f07c
index 2390d1536b81c0751de591a6ba27b62bdc42aca5..b6e942a43ccdec1f1a93294719bc78f4e9067082 100644 (file)
@@ -34,13 +34,12 @@ impl<'a> Reader<'a> {
         let flags = self.machine_st.machine_flags();
 
         loop {
-            let mut append_buf = String::new();            
+            let mut append_buf = String::new();
             stdin.read_line(&mut append_buf).unwrap();
 
             buffer += append_buf.as_str();
-            
-            let mut parser = Parser::new(buffer.as_bytes(), self.machine_st.atom_tbl.clone(),
-                                         self.machine_st.string_tbl.clone(), flags);
+
+            let mut parser = Parser::new(buffer.as_bytes(), self.machine_st.atom_tbl.clone(), flags);
 
             match parser.read_term(op_dir) {
                 Err(ParserError::UnexpectedEOF) => continue,
@@ -49,7 +48,7 @@ impl<'a> Reader<'a> {
             };
         }
     }
-    
+
     fn push_stub_addr(&mut self) {
         let h = self.machine_st.heap.h;
         self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
index 9a7262a4ce2e4d7c69757f03f3660a56a30b605d..dd021a7bba4484e0826786d120076d27eb64cfe0 100644 (file)
@@ -1,5 +1,3 @@
-use prolog::tabled_rc::*;
-
 use std::cell::{Cell, Ref, RefCell};
 use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
@@ -17,25 +15,28 @@ impl Hash for StringListWrapper {
 // cursor is ignored if the double_quotes flag is set to atom
 #[derive(Clone)]
 pub struct StringList {
-    body: TabledRc<StringListWrapper>,
+    body: Rc<StringListWrapper>,
     cursor: usize, // use this to generate a chars() iterator on the fly,
                    // and skip over the first cursor chars.
     expandable: Rc<Cell<bool>>
 }
 
 impl Hash for StringList {
+    #[inline]    
     fn hash<H: Hasher>(&self, state: &mut H) {
         (self.borrow().as_str(), self.cursor, self.expandable.get()).hash(state);
     }
 }
 
 impl PartialOrd for StringList {
+    #[inline]    
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(self.body.cmp(&other.body))
     }
 }
 
 impl Ord for StringList {
+    #[inline]
     fn cmp(&self, other: &Self) -> Ordering {
         if self.expandable.get() && !self.expandable.get() {
             Ordering::Greater
@@ -48,8 +49,9 @@ impl Ord for StringList {
 }
 
 impl PartialEq for StringList {
+    #[inline]
     fn eq(&self, other: &Self) -> bool {
-        self.borrow()[self.cursor ..] == other.borrow()[other.cursor ..] && self.expandable == other.expandable
+        Rc::ptr_eq(&self.body, &other.body)
     }
 }
 
@@ -57,8 +59,8 @@ impl Eq for StringList {}
 
 impl StringList {
     #[inline]
-    pub fn new(s: String, expandable: bool, string_tbl: TabledData<StringListWrapper>) -> Self {
-        let body = TabledRc::new(StringListWrapper(RefCell::new(s)), string_tbl);
+    pub fn new(s: String, expandable: bool) -> Self {
+        let body = Rc::new(StringListWrapper(RefCell::new(s)));
 
         StringList {
             cursor: 0,
@@ -76,12 +78,12 @@ impl StringList {
     pub fn set_expandable(&self) {
         self.expandable.set(true);
     }
-    
+
     #[inline]
     pub fn set_non_expandable(&self) {
         self.expandable.set(false);
     }
-    
+
     #[inline]
     pub fn push_char(&mut self, c: char) -> Self {
         if self.expandable.get() {
@@ -101,12 +103,12 @@ impl StringList {
         self.body.0.borrow_mut().extend(s.borrow()[s.cursor ..].chars());
         self.expandable.set(s.expandable.get());
     }
-    
+
     #[inline]
     pub fn cursor(&self) -> usize {
         self.cursor
-    }        
-    
+    }
+
     #[inline]
     pub fn head(&self) -> Option<char> {
         self.borrow()[self.cursor ..].chars().next()
@@ -127,7 +129,7 @@ impl StringList {
     pub fn is_empty(&self) -> bool {
         self.borrow().len() == self.cursor
     }
-    
+
     #[inline]
     pub fn borrow(&self) -> Ref<String> {
         self.body.0.borrow()
index 49969e407db0ff2d30881583d93a3fd999ce7dfa..1f3919c4d74589a884e0cda7530593d84d87495a 100644 (file)
@@ -3,7 +3,6 @@ use prolog::machine::*;
 use prolog::machine::machine_state::MachineFlags;
 use prolog::num::*;
 use prolog::parser::parser::*;
-use prolog::string_list::*;
 use prolog::tabled_rc::*;
 
 use std::collections::{HashSet, VecDeque};
@@ -620,11 +619,11 @@ pub struct TopLevelWorker<'a, R: Read> {
 }
 
 impl<'a, R: Read> TopLevelWorker<'a, R> {
-    pub fn new(inner: R, atom_tbl: TabledData<Atom>, string_tbl: TabledData<StringListWrapper>,
-               flags: MachineFlags, indices: MachineCodeIndices<'a>)
+    pub fn new(inner: R, atom_tbl: TabledData<Atom>, flags: MachineFlags,
+               indices: MachineCodeIndices<'a>)
                -> Self
     {
-        TopLevelWorker { parser: Parser::new(inner, atom_tbl, string_tbl, flags), indices }
+        TopLevelWorker { parser: Parser::new(inner, atom_tbl, flags), indices }
     }
 
     pub fn parse_code(&mut self) -> Result<TopLevelPacket, ParserError>
@@ -653,11 +652,9 @@ pub struct TopLevelBatchWorker<R: Read> {
 }
 
 impl<R: Read> TopLevelBatchWorker<R> {
-    pub fn new(inner: R, atom_tbl: TabledData<Atom>, string_tbl: TabledData<StringListWrapper>,
-               flags: MachineFlags)
-               -> Self
+    pub fn new(inner: R, atom_tbl: TabledData<Atom>, flags: MachineFlags) -> Self
     {
-        TopLevelBatchWorker { parser: Parser::new(inner, atom_tbl, string_tbl, flags),
+        TopLevelBatchWorker { parser: Parser::new(inner, atom_tbl, flags),
                               rel_worker: RelationWorker::new(),
                               source_mod: clause_name!("user"),
                               results: vec![] }
index 6d60213747ea3f992e1433d22a0f1183e9026b19..f165c0ab0e1efab2c4534deeaf5b28dec9ad5db8 100644 (file)
@@ -1811,14 +1811,20 @@ fn test_queries_on_string_lists()
     let mut wam = Machine::new();
 
     // double_quotes is chars by default.
-    assert_prolog_success!(&mut wam, "?- \"\" == [].");
+    assert_prolog_success!(&mut wam, "?- \"\" =@= [].");
+    assert_prolog_failure!(&mut wam, "?- \"\" == [].");
     assert_prolog_failure!(&mut wam, "?- \"abc\" == [].");
-    assert_prolog_success!(&mut wam, "?- \"abc\" == ['a', 'b', 'c'].");
-    assert_prolog_success!(&mut wam, "?- \"abc\" == ['a', 'b', c].");
-    assert_prolog_success!(&mut wam, "?- \"abc\" == ['a', b, 'c'].");
-    assert_prolog_success!(&mut wam, "?- \"abc\" == [a, 'b', 'c'].");
-    assert_prolog_success!(&mut wam, "?- \"abc\" == [a, 'b', c].");
-    assert_prolog_success!(&mut wam, "?- \"koen\" == [k, o, e, n].");
+    assert_prolog_success!(&mut wam, "?- \"abc\" =@= ['a', 'b', 'c'].");
+    assert_prolog_success!(&mut wam, "?- \"abc\" =@= ['a', 'b', c].");
+    assert_prolog_success!(&mut wam, "?- \"abc\" =@= ['a', b, 'c'].");
+    assert_prolog_success!(&mut wam, "?- \"abc\" =@= [a, 'b', 'c'].");
+    assert_prolog_success!(&mut wam, "?- \"abc\" =@= [a, 'b', c].");
+    assert_prolog_failure!(&mut wam, "?- \"abc\" == ['a', 'b', 'c'].");
+    assert_prolog_failure!(&mut wam, "?- \"abc\" == ['a', 'b', c].");
+    assert_prolog_failure!(&mut wam, "?- \"abc\" == ['a', b, 'c'].");
+    assert_prolog_failure!(&mut wam, "?- \"abc\" == [a, 'b', 'c'].");
+    assert_prolog_failure!(&mut wam, "?- \"abc\" == [a, 'b', c].");
+    assert_prolog_failure!(&mut wam, "?- \"koen\" == [k, o, e, n].");
     assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o, e, n].");
     assert_prolog_success!(&mut wam, "?- \"koen\" =@= [k, o, e, n].");
     assert_prolog_success!(&mut wam, "?- \"koen\" =@= \"koen\".");
@@ -1826,11 +1832,16 @@ fn test_queries_on_string_lists()
                            [["X = [e, n]"]]);
     assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o | X], X = \"en\".",
                            [["X = [e, n]"]]);
-    assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o | X], X == \"en\".",
-                           [["X = [e, n]"]]);
+    assert_prolog_failure!(&mut wam, "?- \"koen\" = [k, o | X], X == \"en\".");
     assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o | X], X =@= \"en\".",
                            [["X = [e, n]"]]);
 
+    assert_prolog_failure!(&mut wam, "?- X = \"abc\", Y = \"abc\", X == Y.");
+    assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abc\", Y), X == Y.");
+
+    assert_prolog_success!(&mut wam, "?- X = \"abc\", Y = \"abc\", X =@= Y.");
+    assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abc\", Y), X =@= Y.");
+    
     submit(&mut wam, "matcher([a,b,c|X], ['d','e','f'|X]).");
 
     assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", \"defdef\").");
@@ -1842,9 +1853,9 @@ fn test_queries_on_string_lists()
 
     submit(&mut wam, "matcher([a,b,c|X], X).");
 
-    assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", X), X = [d,e,f|Y], Y == [], X = \"def\".",
+    assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X = \"def\".",
                            [["X = [d, e, f]", "Y = []"]]);
-    assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", X), X = [d,e,f|Y], Y == [], X == \"def\".",
+    assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X =@= \"def\".",
                            [["X = [d, e, f]", "Y = []"]]);
     assert_prolog_success!(&mut wam, "?- X = ['a', 'b', 'c' | \"def\"].",
                            [["X = [a, b, c, d, e, f]"]]);