match on partial strings through get_list
This commit is contained in:
@@ -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(())
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -135,7 +136,7 @@ impl MachineState {
|
|||||||
let mut output = printer.print(addr);
|
let mut output = printer.print(addr);
|
||||||
|
|
||||||
let bad_ending = format!("= {}", &var);
|
let bad_ending = format!("= {}", &var);
|
||||||
|
|
||||||
if output.ends_with(&bad_ending) {
|
if output.ends_with(&bad_ending) {
|
||||||
output.truncate(orig_len);
|
output.truncate(orig_len);
|
||||||
}
|
}
|
||||||
@@ -196,7 +197,7 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
},
|
},
|
||||||
(Addr::Lis(a1), Addr::Con(Constant::String(ref mut s)))
|
(Addr::Lis(a1), Addr::Con(Constant::String(ref mut s)))
|
||||||
| (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1))
|
| (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1))
|
||||||
if self.flags.double_quotes.is_chars() => {
|
if self.flags.double_quotes.is_chars() => {
|
||||||
if let Some(c) = s.head() {
|
if let Some(c) = s.head() {
|
||||||
pdl.push(Addr::Con(Constant::String(s.tail())));
|
pdl.push(Addr::Con(Constant::String(s.tail())));
|
||||||
@@ -233,7 +234,7 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
},
|
},
|
||||||
(Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s)))
|
(Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s)))
|
||||||
| (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() {
|
||||||
s.set_non_expandable();
|
s.set_non_expandable();
|
||||||
@@ -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() {
|
||||||
@@ -314,7 +316,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trail(&mut self, r: Ref) {
|
fn trail(&mut self, r: Ref) {
|
||||||
match r {
|
match r {
|
||||||
Ref::HeapCell(hc) =>
|
Ref::HeapCell(hc) =>
|
||||||
@@ -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,13 +426,24 @@ 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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1529,7 +1549,7 @@ impl MachineState {
|
|||||||
return Ordering::Greater,
|
return Ordering::Greater,
|
||||||
(HeapCellValue::Addr(Addr::Con(Constant::String(_))),
|
(HeapCellValue::Addr(Addr::Con(Constant::String(_))),
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::Number(_)))) =>
|
HeapCellValue::Addr(Addr::Con(Constant::Number(_)))) =>
|
||||||
return Ordering::Greater,
|
return Ordering::Greater,
|
||||||
(HeapCellValue::Addr(Addr::Con(Constant::String(s1))),
|
(HeapCellValue::Addr(Addr::Con(Constant::String(s1))),
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::String(s2)))) =>
|
HeapCellValue::Addr(Addr::Con(Constant::String(s2)))) =>
|
||||||
return if s1.is_expandable() {
|
return if s1.is_expandable() {
|
||||||
@@ -2045,7 +2065,7 @@ impl MachineState {
|
|||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_call_clause<'a>(&mut self, indices: MachineCodeIndices<'a>,
|
fn handle_call_clause<'a>(&mut self, indices: MachineCodeIndices<'a>,
|
||||||
call_policy: &mut Box<CallPolicy>,
|
call_policy: &mut Box<CallPolicy>,
|
||||||
cut_policy: &mut Box<CutPolicy>,
|
cut_policy: &mut Box<CutPolicy>,
|
||||||
@@ -2089,7 +2109,7 @@ impl MachineState {
|
|||||||
&ControlInstruction::Allocate(num_cells) =>
|
&ControlInstruction::Allocate(num_cells) =>
|
||||||
self.allocate(num_cells),
|
self.allocate(num_cells),
|
||||||
&ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) =>
|
&ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) =>
|
||||||
self.handle_call_clause(indices, call_policy, cut_policy,
|
self.handle_call_clause(indices, call_policy, cut_policy,
|
||||||
ct, arity, lco, use_default_cp),
|
ct, arity, lco, use_default_cp),
|
||||||
&ControlInstruction::Deallocate => self.deallocate(),
|
&ControlInstruction::Deallocate => self.deallocate(),
|
||||||
&ControlInstruction::JmpBy(arity, offset, _, lco) => {
|
&ControlInstruction::JmpBy(arity, offset, _, lco) => {
|
||||||
@@ -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();
|
||||||
|
|||||||
10
src/tests.rs
10
src/tests.rs
@@ -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]"]]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user