enable backtracking on partial strings
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -86,8 +86,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prolog_parser"
|
name = "prolog_parser"
|
||||||
version = "0.7.15"
|
version = "0.7.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num 0.2.0 (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)",
|
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -113,7 +112,7 @@ dependencies = [
|
|||||||
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"prolog_parser 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"prolog_parser 0.7.16",
|
||||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -152,7 +151,6 @@ 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.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 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 ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f"
|
||||||
"checksum prolog_parser 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "11f378539616d1cd7b8fc006f309b5a4b483b82cbab76e898a9f1c99318b4dfa"
|
|
||||||
"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
|
"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 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"
|
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
|
|||||||
downcast = "0.9.1"
|
downcast = "0.9.1"
|
||||||
num = "0.2"
|
num = "0.2"
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = "0.7.15"
|
prolog_parser = "0.7.16"
|
||||||
|
|
||||||
[dependencies.termion]
|
[dependencies.termion]
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -249,7 +249,8 @@ pub struct MachineState {
|
|||||||
pub(super) or_stack: OrStack,
|
pub(super) or_stack: OrStack,
|
||||||
pub(super) registers: Registers,
|
pub(super) registers: Registers,
|
||||||
pub(super) trail: Vec<Ref>,
|
pub(super) trail: Vec<Ref>,
|
||||||
pub(super) partial_string_trail: Vec<(StringList, usize)>,
|
pub(super) pstr_trail: Vec<(usize, StringList, usize)>, // b, String, trunc_pt
|
||||||
|
pub(super) pstr_tr: usize,
|
||||||
pub(super) tr: usize,
|
pub(super) tr: usize,
|
||||||
pub(super) hb: usize,
|
pub(super) hb: usize,
|
||||||
pub(super) block: usize, // an offset into the OR stack.
|
pub(super) block: usize, // an offset into the OR stack.
|
||||||
@@ -298,6 +299,15 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st.tr = machine_st.or_stack[b].tr;
|
machine_st.tr = machine_st.or_stack[b].tr;
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
|
machine_st.pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
|
||||||
|
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
|
||||||
|
|
||||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h;
|
machine_st.hb = machine_st.heap.h;
|
||||||
@@ -327,6 +337,15 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st.tr = machine_st.or_stack[b].tr;
|
machine_st.tr = machine_st.or_stack[b].tr;
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
|
machine_st.pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
|
||||||
|
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
|
||||||
|
|
||||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h;
|
machine_st.hb = machine_st.heap.h;
|
||||||
@@ -351,10 +370,18 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr);
|
machine_st.unwind_trail(old_tr, curr_tr);
|
||||||
|
|
||||||
machine_st.tr = machine_st.or_stack[b].tr;
|
machine_st.tr = machine_st.or_stack[b].tr;
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
|
machine_st.pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
|
||||||
|
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
|
||||||
|
|
||||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||||
machine_st.b = machine_st.or_stack[b].b;
|
machine_st.b = machine_st.or_stack[b].b;
|
||||||
|
|
||||||
@@ -382,10 +409,18 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr);
|
machine_st.unwind_trail(old_tr, curr_tr);
|
||||||
|
|
||||||
machine_st.tr = machine_st.or_stack[b].tr;
|
machine_st.tr = machine_st.or_stack[b].tr;
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
|
machine_st.pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
|
|
||||||
|
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
|
||||||
|
|
||||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||||
|
|
||||||
machine_st.b = machine_st.or_stack[b].b;
|
machine_st.b = machine_st.or_stack[b].b;
|
||||||
@@ -842,6 +877,7 @@ fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
|
|||||||
if b > b0 {
|
if b > b0 {
|
||||||
machine_st.b = b0;
|
machine_st.b = b0;
|
||||||
machine_st.tidy_trail();
|
machine_st.tidy_trail();
|
||||||
|
machine_st.tidy_pstr_trail();
|
||||||
machine_st.or_stack.truncate(machine_st.b);
|
machine_st.or_stack.truncate(machine_st.b);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -923,6 +959,7 @@ impl CutPolicy for SCCCutPolicy {
|
|||||||
if b > b0 {
|
if b > b0 {
|
||||||
machine_st.b = b0;
|
machine_st.b = b0;
|
||||||
machine_st.tidy_trail();
|
machine_st.tidy_trail();
|
||||||
|
machine_st.tidy_pstr_trail();
|
||||||
machine_st.or_stack.truncate(machine_st.b);
|
machine_st.or_stack.truncate(machine_st.b);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ impl MachineState {
|
|||||||
or_stack: OrStack::new(),
|
or_stack: OrStack::new(),
|
||||||
registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used.
|
registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used.
|
||||||
trail: vec![],
|
trail: vec![],
|
||||||
partial_string_trail: vec![],
|
pstr_trail: vec![],
|
||||||
|
pstr_tr: 0,
|
||||||
tr: 0,
|
tr: 0,
|
||||||
hb: 0,
|
hb: 0,
|
||||||
block: 0,
|
block: 0,
|
||||||
@@ -162,6 +163,51 @@ impl MachineState {
|
|||||||
printer.print(addr)
|
printer.print(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn unify_string(&mut self, pdl: &mut Vec<Addr>, s1: &mut StringList, s2: &mut StringList) -> bool
|
||||||
|
{
|
||||||
|
if let Some(c1) = s1.head() {
|
||||||
|
if let Some(c2) = s2.head() {
|
||||||
|
if c1 == c2 {
|
||||||
|
pdl.push(Addr::Con(Constant::String(s1.tail())));
|
||||||
|
pdl.push(Addr::Con(Constant::String(s2.tail())));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if s2.is_expandable() {
|
||||||
|
self.pstr_trail(s2.clone());
|
||||||
|
|
||||||
|
pdl.push(Addr::Con(Constant::String(s2.push_char(c1))));
|
||||||
|
pdl.push(Addr::Con(Constant::String(s1.tail())));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if s1.is_expandable() {
|
||||||
|
if let Some(c) = s2.head() {
|
||||||
|
self.pstr_trail(s1.clone());
|
||||||
|
|
||||||
|
pdl.push(Addr::Con(Constant::String(s1.push_char(c))));
|
||||||
|
pdl.push(Addr::Con(Constant::String(s2.tail())));
|
||||||
|
} else if s2.is_expandable() {
|
||||||
|
return s1 == s2;
|
||||||
|
} else {
|
||||||
|
self.pstr_trail(s1.clone());
|
||||||
|
s1.set_non_expandable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if s2.head().is_none() {
|
||||||
|
if s2.is_expandable() {
|
||||||
|
self.pstr_trail(s2.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
s2.set_non_expandable();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn unify(&mut self, a1: Addr, a2: Addr) {
|
pub(super) fn unify(&mut self, a1: Addr, a2: Addr) {
|
||||||
let mut pdl = vec![a1, a2];
|
let mut pdl = vec![a1, a2];
|
||||||
|
|
||||||
@@ -208,6 +254,8 @@ impl MachineState {
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else if s.is_expandable() {
|
} else if s.is_expandable() {
|
||||||
|
let prev_s = s.clone();
|
||||||
|
|
||||||
let mut stepper = |c| {
|
let mut stepper = |c| {
|
||||||
let new_s = s.push_char(c);
|
let new_s = s.push_char(c);
|
||||||
|
|
||||||
@@ -217,12 +265,14 @@ impl MachineState {
|
|||||||
|
|
||||||
match self.heap[a1].clone() {
|
match self.heap[a1].clone() {
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::Char(c))) => {
|
HeapCellValue::Addr(Addr::Con(Constant::Char(c))) => {
|
||||||
|
self.pstr_trail(prev_s);
|
||||||
stepper(c);
|
stepper(c);
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::Atom(ref a, _))) =>
|
HeapCellValue::Addr(Addr::Con(Constant::Atom(ref a, _))) =>
|
||||||
if let Some(c) = a.as_str().chars().next() {
|
if let Some(c) = a.as_str().chars().next() {
|
||||||
if c.len_utf8() == a.as_str().len() {
|
if c.len_utf8() == a.as_str().len() {
|
||||||
|
self.pstr_trail(prev_s);
|
||||||
stepper(c);
|
stepper(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -237,6 +287,7 @@ impl MachineState {
|
|||||||
| (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 self.flags.double_quotes.is_chars() => {
|
||||||
if s.is_expandable() && s.is_empty() {
|
if s.is_expandable() && s.is_empty() {
|
||||||
|
self.pstr_trail(s.clone());
|
||||||
s.set_non_expandable();
|
s.set_non_expandable();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -251,43 +302,9 @@ impl MachineState {
|
|||||||
pdl.push(Addr::HeapCell(a2 + 1));
|
pdl.push(Addr::HeapCell(a2 + 1));
|
||||||
},
|
},
|
||||||
(Addr::Con(Constant::String(ref mut s1)),
|
(Addr::Con(Constant::String(ref mut s1)),
|
||||||
Addr::Con(Constant::String(ref mut s2))) => {
|
Addr::Con(Constant::String(ref mut s2))) =>
|
||||||
let mut stepper = |s1: &mut StringList, s2: &mut StringList| -> bool {
|
self.fail = !(self.unify_string(&mut pdl, s1, s2)
|
||||||
if let Some(c1) = s1.head() {
|
|| self.unify_string(&mut pdl, s2, s1)),
|
||||||
if let Some(c2) = s2.head() {
|
|
||||||
if c1 == c2 {
|
|
||||||
pdl.push(Addr::Con(Constant::String(s1.tail())));
|
|
||||||
pdl.push(Addr::Con(Constant::String(s2.tail())));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if s2.is_expandable() {
|
|
||||||
pdl.push(Addr::Con(Constant::String(s2.push_char(c1))));
|
|
||||||
pdl.push(Addr::Con(Constant::String(s1.tail())));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if s1.is_expandable() {
|
|
||||||
if let Some(c) = s2.head() {
|
|
||||||
pdl.push(Addr::Con(Constant::String(s1.push_char(c))));
|
|
||||||
pdl.push(Addr::Con(Constant::String(s2.tail())));
|
|
||||||
} else if s2.is_expandable() {
|
|
||||||
return s1 == s2;
|
|
||||||
} else {
|
|
||||||
s1.set_non_expandable();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else if s2.head().is_none() {
|
|
||||||
s2.set_non_expandable();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
self.fail = !(stepper(s1, s2) || stepper(s2, s1));
|
|
||||||
},
|
|
||||||
(Addr::Con(ref c1), Addr::Con(ref c2)) =>
|
(Addr::Con(ref c1), Addr::Con(ref c2)) =>
|
||||||
if c1 != c2 {
|
if c1 != c2 {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
@@ -317,6 +334,19 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pstr_trail(&mut self, s: StringList) {
|
||||||
|
if let Some((prev_b, prev_s, _)) = self.pstr_trail.last().cloned() {
|
||||||
|
if prev_b == self.b && prev_s == s {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = s.len();
|
||||||
|
self.pstr_trail.push((self.b, s, len));
|
||||||
|
self.pstr_tr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
fn trail(&mut self, r: Ref) {
|
fn trail(&mut self, r: Ref) {
|
||||||
match r {
|
match r {
|
||||||
Ref::HeapCell(hc) =>
|
Ref::HeapCell(hc) =>
|
||||||
@@ -356,6 +386,35 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn unwind_pstr_trail(&mut self, a1: usize, a2: usize) {
|
||||||
|
for i in a1 .. a2 {
|
||||||
|
let (_, mut s, end) = self.pstr_trail[i].clone();
|
||||||
|
s.truncate(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn tidy_pstr_trail(&mut self) {
|
||||||
|
if self.b == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = self.b - 1;
|
||||||
|
let mut i = self.or_stack[b].pstr_tr;
|
||||||
|
|
||||||
|
while i < self.pstr_tr {
|
||||||
|
let str_b = self.pstr_trail[i].0;
|
||||||
|
|
||||||
|
if b < str_b {
|
||||||
|
let pstr_tr = self.pstr_tr;
|
||||||
|
let val = self.pstr_trail[pstr_tr - 1].clone();
|
||||||
|
self.pstr_trail[i] = val;
|
||||||
|
self.pstr_tr -= 1;
|
||||||
|
} else {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn tidy_trail(&mut self) {
|
pub(super) fn tidy_trail(&mut self) {
|
||||||
if self.b == 0 {
|
if self.b == 0 {
|
||||||
return;
|
return;
|
||||||
@@ -402,6 +461,8 @@ impl MachineState {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write_char_to_string(&mut self, s: &mut StringList, c: char) -> bool {
|
fn write_char_to_string(&mut self, s: &mut StringList, c: char) -> bool {
|
||||||
|
self.pstr_trail(s.clone());
|
||||||
|
|
||||||
let new_s = s.push_char(c);
|
let new_s = s.push_char(c);
|
||||||
self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::String(new_s))));
|
self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::String(new_s))));
|
||||||
false
|
false
|
||||||
@@ -422,6 +483,7 @@ impl MachineState {
|
|||||||
Constant::EmptyList if self.flags.double_quotes.is_chars() =>
|
Constant::EmptyList if self.flags.double_quotes.is_chars() =>
|
||||||
!s.is_empty(),
|
!s.is_empty(),
|
||||||
Constant::String(ref s2) if s.is_empty() && s.is_expandable() => {
|
Constant::String(ref s2) if s.is_empty() && s.is_expandable() => {
|
||||||
|
self.pstr_trail(s.clone());
|
||||||
s.append(s2);
|
s.append(s2);
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
@@ -2140,6 +2202,7 @@ impl MachineState {
|
|||||||
self.b,
|
self.b,
|
||||||
self.p.clone() + 1,
|
self.p.clone() + 1,
|
||||||
self.tr,
|
self.tr,
|
||||||
|
self.pstr_tr,
|
||||||
self.heap.h,
|
self.heap.h,
|
||||||
self.b0,
|
self.b0,
|
||||||
self.num_of_args);
|
self.num_of_args);
|
||||||
@@ -2175,6 +2238,7 @@ impl MachineState {
|
|||||||
self.b,
|
self.b,
|
||||||
self.p.clone() + offset,
|
self.p.clone() + offset,
|
||||||
self.tr,
|
self.tr,
|
||||||
|
self.pstr_tr,
|
||||||
self.heap.h,
|
self.heap.h,
|
||||||
self.b0,
|
self.b0,
|
||||||
self.num_of_args);
|
self.num_of_args);
|
||||||
@@ -2246,13 +2310,14 @@ impl MachineState {
|
|||||||
self.b0 = 0;
|
self.b0 = 0;
|
||||||
self.s = 0;
|
self.s = 0;
|
||||||
self.tr = 0;
|
self.tr = 0;
|
||||||
|
self.pstr_tr = 0;
|
||||||
self.p = CodePtr::default();
|
self.p = CodePtr::default();
|
||||||
self.cp = LocalCodePtr::default();
|
self.cp = LocalCodePtr::default();
|
||||||
self.num_of_args = 0;
|
self.num_of_args = 0;
|
||||||
|
|
||||||
self.fail = false;
|
self.fail = false;
|
||||||
self.trail.clear();
|
self.trail.clear();
|
||||||
self.partial_string_trail.clear();
|
self.pstr_trail.clear();
|
||||||
self.heap.clear();
|
self.heap.clear();
|
||||||
self.mode = MachineMode::Write;
|
self.mode = MachineMode::Write;
|
||||||
self.and_stack.clear();
|
self.and_stack.clear();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub struct Frame {
|
|||||||
pub b: usize,
|
pub b: usize,
|
||||||
pub bp: CodePtr,
|
pub bp: CodePtr,
|
||||||
pub tr: usize,
|
pub tr: usize,
|
||||||
|
pub pstr_tr: usize,
|
||||||
pub h: usize,
|
pub h: usize,
|
||||||
pub b0: usize,
|
pub b0: usize,
|
||||||
args: Vec<Addr>
|
args: Vec<Addr>
|
||||||
@@ -22,20 +23,22 @@ impl Frame {
|
|||||||
b: usize,
|
b: usize,
|
||||||
bp: CodePtr,
|
bp: CodePtr,
|
||||||
tr: usize,
|
tr: usize,
|
||||||
|
pstr_tr: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
b0: usize,
|
b0: usize,
|
||||||
n: usize)
|
n: usize)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
Frame {
|
Frame {
|
||||||
global_index: global_index,
|
global_index,
|
||||||
e: e,
|
e,
|
||||||
cp: cp,
|
cp,
|
||||||
b: b,
|
b,
|
||||||
bp: bp,
|
bp,
|
||||||
tr: tr,
|
tr,
|
||||||
h: h,
|
pstr_tr,
|
||||||
b0: b0,
|
h,
|
||||||
|
b0,
|
||||||
args: vec![Addr::HeapCell(0); n]
|
args: vec![Addr::HeapCell(0); n]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,11 +62,12 @@ impl OrStack {
|
|||||||
b: usize,
|
b: usize,
|
||||||
bp: CodePtr,
|
bp: CodePtr,
|
||||||
tr: usize,
|
tr: usize,
|
||||||
|
pstr_tr: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
b0: usize,
|
b0: usize,
|
||||||
n: usize)
|
n: usize)
|
||||||
{
|
{
|
||||||
self.0.push(Frame::new(global_index, e, cp, b, bp, tr, h, b0, n));
|
self.0.push(Frame::new(global_index, e, cp, b, bp, tr, pstr_tr, h, b0, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
|
|||||||
37
src/tests.rs
37
src/tests.rs
@@ -1982,4 +1982,41 @@ fn test_queries_on_string_lists()
|
|||||||
[["X = [a, b, c | _]", "Y = _"]]);
|
[["X = [a, b, c | _]", "Y = _"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), Y = \"def\".",
|
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]"]]);
|
[["X = [a, b, c, d, e, f]", "Y = [d, e, f]"]]);
|
||||||
|
|
||||||
|
submit(&mut wam, "matcher([a,b,c|X], X).
|
||||||
|
matcher([a,b,d|X], X).");
|
||||||
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- partial_string(\"ab\", X), matcher(X, Y).",
|
||||||
|
[["X = [a, b, c | _]", "Y = _"],
|
||||||
|
["X = [a, b, d | _]", "Y = _"]]);
|
||||||
|
|
||||||
|
submit(&mut wam, "matcher([a,b,c,d|X], X).
|
||||||
|
matcher([a,c,d|X], X).");
|
||||||
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- partial_string(\"ab\", X), matcher(X, Y).",
|
||||||
|
[["X = [a, b, c, d | _]", "Y = _"]]);
|
||||||
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).",
|
||||||
|
[["X = [a, b, c, d | _]", "Y = _"],
|
||||||
|
["X = [a, c, d | _]", "Y = _"]]);
|
||||||
|
|
||||||
|
submit(&mut wam, "matcher([a,b,c,d|X], X).
|
||||||
|
matcher([a,c,d|X], X).
|
||||||
|
matcher([a,e,f|X], X).");
|
||||||
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).",
|
||||||
|
[["X = [a, b, c, d | _]", "Y = _"],
|
||||||
|
["X = [a, c, d | _]", "Y = _"],
|
||||||
|
["X = [a, e, f | _]", "Y = _"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), Y = \" t\".",
|
||||||
|
[["X = [a, b, c, d, ' ', t]", "Y = [' ', t]"],
|
||||||
|
["X = [a, c, d, ' ', t]", "Y = [' ', t]"],
|
||||||
|
["X = [a, e, f, ' ', t]", "Y = [' ', t]"]]);
|
||||||
|
|
||||||
|
submit(&mut wam, "matcher([a,b,c|X], X) :- X = [].
|
||||||
|
matcher([a,b,c|X], X).");
|
||||||
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y).",
|
||||||
|
[["X = [a, b, c]", "Y = []"],
|
||||||
|
["X = [a, b, c | _]", "Y = _"]]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user