match on partial strings through get_list

This commit is contained in:
Mark Thom
2018-09-24 19:53:51 -06:00
parent bf84edce59
commit 23eed192e9
3 changed files with 46 additions and 16 deletions

View File

@@ -1,4 +1,5 @@
use prolog_parser::ast::*; use prolog_parser::ast::*;
use prolog_parser::string_list::*;
use prolog_parser::tabled_rc::*; use prolog_parser::tabled_rc::*;
use prolog::instructions::*; use prolog::instructions::*;
@@ -248,6 +249,7 @@ 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) 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.
@@ -299,7 +301,6 @@ pub(crate) trait CallPolicy: Any {
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;
machine_st.p += 1; machine_st.p += 1;
Ok(()) Ok(())
@@ -329,7 +330,6 @@ pub(crate) trait CallPolicy: Any {
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;
machine_st.p += offset; machine_st.p += offset;
Ok(()) Ok(())

View File

@@ -48,7 +48,8 @@ impl MachineState {
and_stack: AndStack::new(), and_stack: AndStack::new(),
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::new(), trail: vec![],
partial_string_trail: vec![],
tr: 0, tr: 0,
hb: 0, hb: 0,
block: 0, block: 0,
@@ -249,7 +250,8 @@ impl MachineState {
pdl.push(Addr::HeapCell(a1 + 1)); pdl.push(Addr::HeapCell(a1 + 1));
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 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 { let mut stepper = |s1: &mut StringList, s2: &mut StringList| -> bool {
if let Some(c1) = s1.head() { if let Some(c1) = s1.head() {
if let Some(c2) = s2.head() { if let Some(c2) = s2.head() {
@@ -368,7 +370,7 @@ impl MachineState {
match tr_i { match tr_i {
Ref::HeapCell(tr_i) => Ref::HeapCell(tr_i) =>
if tr_i < hb { //|| ((h < tr_i) && tr_i < b) { if tr_i < hb {
i += 1; i += 1;
} else { } else {
let tr = self.tr; 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) { pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: Constant) {
match self.store(self.deref(addr)) { match self.store(self.deref(addr)) {
Addr::HeapCell(hc) => { Addr::HeapCell(hc) => {
@@ -417,12 +426,23 @@ impl MachineState {
false false
}, },
Constant::String(s2) => *s != s2, 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 _ => true
}, },
Addr::Con(c1) => { Addr::Con(c1) =>
if c1 != c { if c1 != c {
self.fail = true; self.fail = true;
}
}, },
_ => self.fail = true _ => self.fail = true
}; };
@@ -2207,7 +2227,6 @@ impl MachineState {
self.p += 1; self.p += 1;
}, },
&CutInstruction::GetLevelAndUnify(r) => { &CutInstruction::GetLevelAndUnify(r) => {
// let b0 = Addr::Con(Constant::Usize(self.b0));
let b0 = self[perm_v!(1)].clone(); let b0 = self[perm_v!(1)].clone();
let a = self[r].clone(); let a = self[r].clone();
@@ -2233,6 +2252,7 @@ impl MachineState {
self.fail = false; self.fail = false;
self.trail.clear(); self.trail.clear();
self.partial_string_trail.clear();
self.heap.clear(); self.heap.clear();
self.mode = MachineMode::Write; self.mode = MachineMode::Write;
self.and_stack.clear(); self.and_stack.clear();

View File

@@ -1972,4 +1972,14 @@ fn test_queries_on_string_lists()
assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), X @> \"abc\"."); 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_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]"]]);
} }