From c5fd13dfa00682d55204c2fe1537864072e4ca1e Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 3 Sep 2018 00:06:01 -0600 Subject: [PATCH] distinguish eq from structural_eq on strings --- src/prolog/compile.rs | 7 ++--- src/prolog/machine/machine_state.rs | 12 +-------- src/prolog/machine/machine_state_impl.rs | 34 ++++++++++++++++++++---- src/prolog/machine/mod.rs | 7 ++--- src/prolog/parser | 2 +- src/prolog/read.rs | 9 +++---- src/prolog/string_list.rs | 26 +++++++++--------- src/prolog/toplevel.rs | 13 ++++----- src/tests.rs | 33 +++++++++++++++-------- 9 files changed, 80 insertions(+), 63 deletions(-) diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index 5c014117..f0bb2986 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -39,7 +39,6 @@ fn print_code(code: &Code) { pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result { 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, 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)) { diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 5b019146..f7c4c1cd 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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, - pub(crate) string_tbl: TabledData, 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 => { diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index b9a411ae..2e223b6e 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -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(..))), diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index a5a8cd23..508eb904 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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 { self.ms.atom_tbl.clone() } - - pub fn string_tbl(&self) -> TabledData { - self.ms.string_tbl.clone() - } pub fn use_qualified_module_in_toplevel(&mut self, name: ClauseName, exports: Vec) -> EvalSession diff --git a/src/prolog/parser b/src/prolog/parser index cd2fdbb4..b663bce8 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit cd2fdbb463a36a2743042206f56020b5bf0359cf +Subproject commit b663bce82dc7543c2bc01b557f7b0926ef29f07c diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 2390d153..b6e942a4 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -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))); diff --git a/src/prolog/string_list.rs b/src/prolog/string_list.rs index 9a7262a4..dd021a7b 100644 --- a/src/prolog/string_list.rs +++ b/src/prolog/string_list.rs @@ -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, + body: Rc, cursor: usize, // use this to generate a chars() iterator on the fly, // and skip over the first cursor chars. expandable: Rc> } impl Hash for StringList { + #[inline] fn hash(&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 { 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) -> 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 { 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 { self.body.0.borrow() diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 49969e40..1f3919c4 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -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, string_tbl: TabledData, - flags: MachineFlags, indices: MachineCodeIndices<'a>) + pub fn new(inner: R, atom_tbl: TabledData, 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 @@ -653,11 +652,9 @@ pub struct TopLevelBatchWorker { } impl TopLevelBatchWorker { - pub fn new(inner: R, atom_tbl: TabledData, string_tbl: TabledData, - flags: MachineFlags) - -> Self + pub fn new(inner: R, atom_tbl: TabledData, 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![] } diff --git a/src/tests.rs b/src/tests.rs index 6d602137..f165c0ab 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -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]"]]); -- 2.54.0