compile special instructions for partial strings when recognized

This commit is contained in:
Mark Thom
2020-04-11 21:53:28 -06:00
parent 92d8642133
commit 6e4b76a3b4
16 changed files with 737 additions and 302 deletions

View File

@@ -89,7 +89,7 @@ impl CodeRepo {
_ => {
in_situ_code_dir.insert((name, arity), p);
}
}
}
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
let mut decl_code = cg.compile_predicate(&decl.0)?;

View File

@@ -179,12 +179,23 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
}
#[inline]
fn pop(&mut self) {
pub(crate)
fn put_complete_string(&mut self, s: &str) -> Addr {
let addr = self.allocate_pstr(s);
self.pop();
let h = self.h();
if h > 0 {
self.truncate(h - 1);
match &mut self[h - 1] {
&mut HeapCellValue::PartialString(_, ref mut has_tail) => {
*has_tail = false;
}
_ => {
unreachable!()
}
}
addr
}
#[inline]
@@ -219,21 +230,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
if s.is_empty() {
Addr::EmptyList
} else {
let addr = self.allocate_pstr(&s);
self.pop();
let h = self.h();
match &mut self[h - 1] {
&mut HeapCellValue::PartialString(_, ref mut has_tail) => {
*has_tail = false;
}
_ => {
unreachable!()
}
}
addr
self.put_complete_string(&s)
}
}
Constant::Usize(n) => {
@@ -242,6 +239,16 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
}
}
#[inline]
pub(crate)
fn pop(&mut self) {
let h = self.h();
if h > 0 {
self.truncate(h - 1);
}
}
#[inline]
pub(crate)
fn push(&mut self, val: HeapCellValue) -> usize {

View File

@@ -274,16 +274,10 @@ impl Addr {
let mut heap_pstr_iter =
machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
let mut buf = String::new();
let buf = heap_pstr_iter.to_string();
let end_addr = heap_pstr_iter.focus();
while let Some(Some(c)) = heap_pstr_iter.next() {
buf.push(c);
}
let end_addr =
machine_st.store(machine_st.deref(heap_pstr_iter.focus()));
if let Addr::EmptyList = end_addr {
if end_addr == Addr::EmptyList {
Some(Constant::String(Rc::new(buf)))
} else {
None

View File

@@ -21,8 +21,7 @@ use std::io::Write;
use std::mem;
use std::ops::{Index, IndexMut};
pub(crate)
struct HeapPStrIter<'a> {
pub(crate) struct HeapPStrIter<'a> {
focus: Addr,
machine_st: &'a MachineState,
seen: IndexSet<Addr>,
@@ -41,12 +40,44 @@ impl<'a> HeapPStrIter<'a> {
#[inline]
pub(crate)
fn focus(&'a self) -> Addr {
self.focus
self.machine_st.store(self.machine_st.deref(self.focus))
}
#[inline]
pub(crate)
fn to_string(&mut self) -> String {
let mut buf = String::new();
while let Some(iteratee) = self.next() {
match iteratee {
PStrIteratee::Char(c) => {
buf.push(c);
}
PStrIteratee::PStrSegment(h, n) => {
match &self.machine_st.heap[h] {
HeapCellValue::PartialString(ref pstr, _) => {
buf += pstr.as_str_from(n);
}
_ => {
unreachable!()
}
}
}
}
}
buf
}
}
#[derive(Clone, Copy)]
pub(crate) enum PStrIteratee {
Char(char),
PStrSegment(usize, usize),
}
impl<'a> Iterator for HeapPStrIter<'a> {
type Item = Option<char>;
type Item = PStrIteratee;
fn next(&mut self) -> Option<Self::Item> {
let addr = self.machine_st.store(self.machine_st.deref(self.focus));
@@ -59,13 +90,14 @@ impl<'a> Iterator for HeapPStrIter<'a> {
match addr {
Addr::PStrLocation(h, n) => {
if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
if let Some(c) = pstr.range_from(n ..).next() {
self.focus = Addr::PStrLocation(h, n + c.len_utf8());
return Some(Some(c));
if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
self.focus = if has_tail {
Addr::HeapCell(h + 1)
} else {
unreachable!()
}
Addr::EmptyList
};
return Some(PStrIteratee::PStrSegment(h, n));
} else {
unreachable!()
}
@@ -73,16 +105,36 @@ impl<'a> Iterator for HeapPStrIter<'a> {
Addr::Lis(l) => {
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
if let Addr::Char(c) = addr {
let opt_c = match addr {
Addr::Con(h) if self.machine_st.heap.atom_at(h) => {
if let HeapCellValue::Atom(ref atom, _) = &self.machine_st.heap[h] {
if atom.is_char() {
Some(atom.as_str().chars().next().unwrap())
} else {
None
}
} else {
unreachable!()
}
}
Addr::Char(c) => {
Some(c)
}
_ => {
None
}
};
if let Some(c) = opt_c {
self.focus = Addr::HeapCell(l + 1);
return Some(Some(c));
return Some(PStrIteratee::Char(c));
} else {
return None;
}
}
Addr::EmptyList => {
self.focus = Addr::EmptyList;
return Some(None);
return None;
}
_ => {
return None;
@@ -93,24 +145,51 @@ impl<'a> Iterator for HeapPStrIter<'a> {
#[inline]
pub(super)
fn compare_pstr<'a>(
pstr_iter: HeapPStrIter<'a>,
mut c_iter: impl Iterator<Item = char>,
) -> bool {
for opt_c in pstr_iter {
match opt_c {
Some(_) => {
if opt_c != c_iter.next() {
return false;
fn compare_pstr_to_string<'a>(
heap_pstr_iter: &mut HeapPStrIter<'a>,
s: &String,
) -> Option<usize> {
let mut s_offset = 0;
while let Some(iteratee) = heap_pstr_iter.next() {
match iteratee {
PStrIteratee::Char(c1) => {
if let Some(c2) = s[s_offset ..].chars().next() {
if c1 != c2 {
return None;
} else {
s_offset += c1.len_utf8();
}
} else {
return None;
}
}
None => {
return c_iter.next().is_none();
PStrIteratee::PStrSegment(h, n) => {
match heap_pstr_iter.machine_st.heap[h] {
HeapCellValue::PartialString(ref pstr, _) => {
let t = pstr.as_str_from(n);
if s[s_offset ..].starts_with(t) {
s_offset += t.len();
} else if t.starts_with(&s[s_offset ..]) {
heap_pstr_iter.focus =
Addr::PStrLocation(h, n + s[s_offset ..].len());
s_offset += s[s_offset ..].len();
return Some(s_offset);
} else {
return None;
}
}
_ => {
unreachable!()
}
}
}
}
}
false
Some(s_offset)
}
pub struct Ball {

View File

@@ -688,8 +688,8 @@ impl MachineState {
HeapPtr::HeapCell(ref mut h) => {
*h += rhs;
}
&mut HeapPtr::PStrChar(h, ref mut n)
| &mut HeapPtr::PStrLocation(h, ref mut n) => {
&mut HeapPtr::PStrChar(h, ref mut n) |
&mut HeapPtr::PStrLocation(h, ref mut n) => {
match &self.heap[h] {
HeapCellValue::PartialString(ref pstr, _) => {
for c in pstr.range_from(*n ..).take(rhs) {
@@ -768,13 +768,94 @@ impl MachineState {
self.trail.truncate(self.tr);
}
pub(super)
fn match_partial_string(&mut self, addr: Addr, string: &String, has_tail: bool) {
let mut heap_pstr_iter = self.heap_pstr_iter(addr);
match compare_pstr_to_string(&mut heap_pstr_iter, string) {
Some(prefix_len) if prefix_len == string.len() => {
let focus = heap_pstr_iter.focus();
match focus {
Addr::PStrLocation(h, n) => {
if has_tail {
self.s = HeapPtr::PStrLocation(h, n);
self.mode = MachineMode::Read;
} else {
self.fail = true;
}
}
addr => {
if has_tail {
let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self.bind(Ref::HeapCell(h), addr);
self.s = HeapPtr::HeapCell(h);
self.mode = MachineMode::Read;
} else {
if let Some(var) = addr.as_var() {
self.bind(var, Addr::EmptyList);
} else {
self.fail = true;
}
}
}
}
}
Some(prefix_len) => {
match heap_pstr_iter.focus() {
addr @ Addr::AttrVar(_) |
addr @ Addr::StackCell(..) |
addr @ Addr::HeapCell(_) => {
let h = self.heap.h();
let pstr_addr =
if has_tail {
self.s = HeapPtr::HeapCell(h+1);
self.mode = MachineMode::Read;
self.heap.allocate_pstr(&string[prefix_len ..])
} else {
self.heap.put_complete_string(&string[prefix_len ..])
};
self.bind(addr.as_var().unwrap(), pstr_addr);
}
Addr::Lis(l) if !self.flags.double_quotes.is_atom() => {
let h = self.heap.h();
let pstr_addr =
if has_tail {
self.s = HeapPtr::HeapCell(h+1);
self.mode = MachineMode::Read;
self.heap.allocate_pstr(&string[prefix_len ..])
} else {
self.heap.put_complete_string(&string[prefix_len ..])
};
self.unify(Addr::Lis(l), pstr_addr);
}
_ => {
self.fail = true;
}
}
}
None => {
self.fail = true;
}
}
}
pub(super)
fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) {
match self.store(self.deref(addr)) {
Addr::Con(c1) => {
self.fail = match &self.heap[c1] {
match &self.heap[c1] {
HeapCellValue::Atom(ref n1, _) => {
match c {
self.fail = match c {
Constant::Atom(ref n2, _) => {
n1 != n2
}
@@ -784,10 +865,10 @@ impl MachineState {
_ => {
true
}
}
};
}
HeapCellValue::Integer(ref n1) => {
match c {
self.fail = match c {
Constant::Fixnum(n2) => {
n1.to_isize() != Some(*n2)
}
@@ -800,10 +881,10 @@ impl MachineState {
_ => {
true
}
}
};
}
HeapCellValue::Rational(ref r1) => {
if let Constant::Rational(ref r2) = c {
self.fail = if let Constant::Rational(ref r2) = c {
r1 != r2
} else {
true
@@ -811,10 +892,13 @@ impl MachineState {
}
HeapCellValue::PartialString(..) => {
if let Constant::String(ref s2) = c {
let iter = self.heap_pstr_iter(Addr::PStrLocation(c1, 0));
!compare_pstr(iter, s2.chars())
self.match_partial_string(
Addr::PStrLocation(c1, 0),
&s2,
false,
);
} else {
true
self.fail = true;
}
}
_ => {
@@ -846,11 +930,14 @@ impl MachineState {
self.unify(Addr::Lis(l), addr);
}
Addr::PStrLocation(h, n) => {
self.fail = if let Constant::String(ref s2) = c {
let iter = self.heap_pstr_iter(Addr::PStrLocation(h, n));
!compare_pstr(iter, s2.chars())
if let Constant::String(ref s2) = c {
self.match_partial_string(
Addr::PStrLocation(h, n),
&s2,
false,
)
} else {
true
self.fail = true;
};
}
Addr::Stream(_) => {
@@ -1154,9 +1241,9 @@ impl MachineState {
self.s = HeapPtr::PStrChar(h, n);
self.mode = MachineMode::Read;
}
addr @ Addr::AttrVar(_)
| addr @ Addr::StackCell(..)
| addr @ Addr::HeapCell(_) => {
addr @ Addr::AttrVar(_) |
addr @ Addr::StackCell(..) |
addr @ Addr::HeapCell(_) => {
let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
@@ -1168,9 +1255,15 @@ impl MachineState {
self.s = HeapPtr::HeapCell(a);
self.mode = MachineMode::Read;
}
_ => self.fail = true,
_ => {
self.fail = true;
}
};
}
&FactInstruction::GetPartialString(_, ref string, reg, has_tail) => {
let addr = self.store(self.deref(self[reg]));
self.match_partial_string(addr, string, has_tail);
}
&FactInstruction::GetStructure(ref ct, arity, reg) => {
let addr = self.deref(self[reg]);
@@ -1191,14 +1284,15 @@ impl MachineState {
let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
self.heap
.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
self.mode = MachineMode::Write;
}
_ => self.fail = true,
_ => {
self.fail = true;
}
};
}
&FactInstruction::GetVariable(norm, arg) => {
@@ -1214,7 +1308,9 @@ impl MachineState {
match self.mode {
MachineMode::Read => {
let addr = self.s.read(&self.heap);
self.write_constant_to_var(addr, c);
self.increment_s_ptr(1);
}
MachineMode::Write => {
let addr = self.heap.put_constant(c.clone());
@@ -1224,12 +1320,13 @@ impl MachineState {
}
}
};
self.increment_s_ptr(1);
}
&FactInstruction::UnifyVariable(reg) => {
match self.mode {
MachineMode::Read => self[reg] = self.s.read(&self.heap),
MachineMode::Read => {
self[reg] = self.s.read(&self.heap);
self.increment_s_ptr(1);
}
MachineMode::Write => {
let h = self.heap.h();
@@ -1237,14 +1334,14 @@ impl MachineState {
self[reg] = Addr::HeapCell(h);
}
};
self.increment_s_ptr(1);
}
&FactInstruction::UnifyLocalValue(reg) => {
match self.mode {
MachineMode::Read => {
let reg_addr = self[reg];
self.unify(reg_addr, self.s.read(&self.heap));
self.increment_s_ptr(1);
}
MachineMode::Write => {
let addr = self.deref(self[reg]);
@@ -1265,26 +1362,26 @@ impl MachineState {
self.bind(Ref::HeapCell(h), addr);
}
};
self.increment_s_ptr(1);
}
&FactInstruction::UnifyValue(reg) => {
match self.mode {
MachineMode::Read => {
let reg_addr = self[reg];
self.unify(reg_addr, self.s.read(&self.heap));
self.increment_s_ptr(1);
}
MachineMode::Write => {
let heap_val = self.store(self[reg]);
self.heap.push(HeapCellValue::Addr(heap_val));
}
};
self.increment_s_ptr(1);
}
&FactInstruction::UnifyVoid(n) => {
match self.mode {
MachineMode::Read => self.increment_s_ptr(n),
MachineMode::Read => {
self.increment_s_ptr(n);
}
MachineMode::Write => {
let h = self.heap.h();
@@ -1394,6 +1491,18 @@ impl MachineState {
&QueryInstruction::PutList(_, reg) => {
self[reg] = Addr::Lis(self.heap.h());
}
&QueryInstruction::PutPartialString(_, ref string, reg, has_tail) => {
let pstr_addr =
if has_tail {
let pstr_addr = self.heap.allocate_pstr(&string);
self.heap.pop(); // the tail will be added by the next instruction.
pstr_addr
} else {
self.heap.put_complete_string(&string)
};
self[reg] = pstr_addr;
}
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
let h = self.heap.h();
@@ -1466,7 +1575,7 @@ impl MachineState {
&QueryInstruction::SetVoid(n) => {
let h = self.heap.h();
for i in h..h + n {
for i in h .. h + n {
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(i)));
}
}

View File

@@ -840,27 +840,33 @@ impl MachineState {
current_output_stream: &mut Stream,
) {
match instr {
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
&Line::Arithmetic(ref arith_instr) => {
self.execute_arith_instr(arith_instr)
}
&Line::Choice(ref choice_instr) => {
self.execute_choice_instr(choice_instr, &mut policies.call_policy)
}
&Line::Cut(ref cut_instr) => {
self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
}
&Line::Control(ref control_instr) => self.execute_ctrl_instr(
indices,
code_repo,
&mut policies.call_policy,
&mut policies.cut_policy,
current_input_stream,
current_output_stream,
control_instr,
),
&Line::Control(ref control_instr) => {
self.execute_ctrl_instr(
indices,
code_repo,
&mut policies.call_policy,
&mut policies.cut_policy,
current_input_stream,
current_output_stream,
control_instr,
)
}
&Line::Fact(ref fact_instr) => {
self.execute_fact_instr(&fact_instr);
self.p += 1;
}
&Line::Indexing(ref indexing_instr) => self.execute_indexing_instr(&indexing_instr),
&Line::Indexing(ref indexing_instr) => {
self.execute_indexing_instr(&indexing_instr)
}
&Line::IndexedChoice(ref choice_instr) => {
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
}

View File

@@ -164,7 +164,12 @@ impl PartialString {
pub(super)
fn clone_from_offset(&self, n: usize) -> Self {
let len = if self.len > n { self.len - n } else { 0 };
let len =
if self.len - '\u{0}'.len_utf8() > n {
self.len - n - '\u{0}'.len_utf8()
} else {
0
};
let mut pstr = PartialString {
buf: ptr::null_mut(),
@@ -216,4 +221,18 @@ impl PartialString {
ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
}
}
#[inline]
pub fn as_str_from(&self, n: usize) -> &str {
unsafe {
let slice = slice::from_raw_parts(
self.buf,
self.len - '\u{0}'.len_utf8(),
);
let s = str::from_utf8(slice).unwrap();
&s[n ..]
}
}
}

View File

@@ -1093,8 +1093,9 @@ impl RelationWorker {
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
}
}
term =>
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num)),
term => {
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
}
}
}
@@ -1132,8 +1133,7 @@ impl RelationWorker {
fn absorb(&mut self, other: RelationWorker) {
self.queue.extend(other.queue.into_iter());
self.dynamic_clauses
.extend(other.dynamic_clauses.into_iter());
self.dynamic_clauses.extend(other.dynamic_clauses.into_iter());
}
}