From 56ec5500314243ee41b1f6e95bfc1229c5c6661d Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 23 Dec 2018 12:14:03 -0700 Subject: [PATCH] fix unification on string lists. --- Cargo.lock | 6 +-- Cargo.toml | 2 +- src/prolog/machine/machine_state.rs | 4 +- src/prolog/machine/machine_state_impl.rs | 49 ++++++++++++++++-------- src/tests.rs | 19 ++++++++- 5 files changed, 56 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4228369c..3b053f79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,7 +86,7 @@ dependencies = [ [[package]] name = "prolog_parser" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -113,7 +113,7 @@ dependencies = [ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prolog_parser 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", + "prolog_parser 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -152,7 +152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" -"checksum prolog_parser 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "fc54110ca6a70b5b509f14826af44b97fa6d7a0832d97229e7de3b73224d2c33" +"checksum prolog_parser 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "121df281a26fc692c1b8089bfdc0ba010a4af06379dec213446297c0c357713a" "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" diff --git a/Cargo.toml b/Cargo.toml index 77018d32..d992eeaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ license = "BSD-3-Clause" downcast = "0.9.1" num = "0.2" ordered-float = "0.5.0" -prolog_parser = "0.7.18" +prolog_parser = "0.7.19" [dependencies.termion] version = "1.4.0" \ No newline at end of file diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 9c9bbc40..d6aa9786 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -271,7 +271,7 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize, } else { let stub = MachineError::functor_stub(name.clone(), arity); let h = machine_st.heap.h; - + Err(machine_st.error_form(MachineError::existence_error(h, name, arity), stub)) } @@ -601,7 +601,7 @@ pub(crate) trait CallPolicy: Any { let a2 = machine_st[temp_v!(2)].clone(); if let Addr::Con(Constant::String(s)) = a1 { - s.set_expandable(); + s.set_expandable(true); machine_st.write_constant_to_var(a2, Constant::String(s)); } else { machine_st.fail = true; diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index d479d2e0..16881958 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -185,7 +185,7 @@ impl MachineState { return s1 == s2; } else { self.pstr_trail(s1.clone()); - s1.set_non_expandable(); + s1.set_expandable(false); } return true; @@ -194,7 +194,7 @@ impl MachineState { self.pstr_trail(s2.clone()); } - s2.set_non_expandable(); + s2.set_expandable(false); return true; } @@ -281,7 +281,7 @@ impl MachineState { if self.flags.double_quotes.is_chars() => { if s.is_expandable() && s.is_empty() { self.pstr_trail(s.clone()); - s.set_non_expandable(); + s.set_expandable(false); continue; } @@ -335,8 +335,8 @@ impl MachineState { } } - let len = s.len(); - self.pstr_trail.push((self.b, s, len)); + let truncate_end = s.len() + s.cursor(); + self.pstr_trail.push((self.b, s, truncate_end)); self.pstr_tr += 1; } @@ -477,24 +477,39 @@ impl MachineState { self.fail = match c { Constant::EmptyList if self.flags.double_quotes.is_chars() => !s.is_empty(), - Constant::String(ref s2) if s.is_empty() && s.is_expandable() => { - self.pstr_trail(s.clone()); - s.append(s2); - false - }, + Constant::String(ref s2) + if s.is_expandable() && s2.starts_with(s) => { + self.pstr_trail(s.clone()); + s.append_suffix(s2); + s.set_expandable(s2.is_expandable()); + 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) + Constant::Atom(ref a, _) + if a.as_str().starts_with(&s.borrow()[s.cursor() ..]) => + if let Some(c) = a.as_str().chars().next() { + if c.len_utf8() == a.as_str().len() { + // detect chars masquerading as atoms. + if s.is_empty() { + self.write_char_to_string(s, c); + } + + false + } else { + true + } } else { true - } + }, + Constant::Char(ref c) if s.is_empty() && s.is_expandable() => + self.write_char_to_string(s, *c), + Constant::Char(ref c) => + if s.borrow().chars().next() == Some(*c) && c.len_utf8() == s.len() { + s.set_expandable(false); + false } else { true }, - Constant::Char(ref c) if s.is_empty() && s.is_expandable() => - self.write_char_to_string(s, *c), _ => true }, Addr::Con(c1) => diff --git a/src/tests.rs b/src/tests.rs index a7ae5558..e4e21c17 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1988,6 +1988,9 @@ fn test_queries_on_string_lists() assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), \"def\" = Y.", [["X = [a, b, c, d, e, f]", "Y = [d, e, f]"]]); + assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y).", + [["X = [a, b, c, d, e, f | _]", + "Y = [d, e, f | _]"]]); assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y), Y = \"defghijkl\".", [["X = [a, b, c, d, e, f, g, h, i, j, k, l]", @@ -1996,7 +1999,7 @@ fn test_queries_on_string_lists() \"defghijkl\" = Y.", [["X = [a, b, c, d, e, f, g, h, i, j, k, l]", "Y = [d, e, f, g, h, i, j, k, l]"]]); - + assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G].", [["X = [a, b, c, d, e, f | _]", "Y = [d, e, f | _]", "G = _"]]); assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), [d, e, f | G] = Y.", @@ -2091,4 +2094,18 @@ fn test_queries_on_string_lists() ["X = [b, d | _]", "Y = [d | _]"]]); assert_prolog_success!(&mut wam, "?- partial_string(\"bc\", X), matcher(X, Y).", [["X = [b, c | _]", "Y = [c | _]"]]); + + submit(&mut wam, "f(\"appendy jones\"). + f(\"appendy smithers jones\"). + f(\"appendy o'toole\")."); + + assert_prolog_success!(&mut wam, "?- partial_string(\"appendy\", X), f(X).", + [["X = [a, p, p, e, n, d, y, ' ', j, o, n, e, s]"], + ["X = [a, p, p, e, n, d, y, ' ', s, m, i, t, h, e, r, s, ' ', j, o, n, e, s]"], + ["X = [a, p, p, e, n, d, y, ' ', o, ''', t, o, o, l, e]"]]); + + assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abcdef\", X).", + [["X = [a, b, c, d, e, f | _]"]]); + assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abcdef\", X), X = \"abcdef\".", + [["X = [a, b, c, d, e, f]"]]); } -- 2.54.0