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

@@ -4,7 +4,6 @@ use prolog_parser::tabled_rc::TabledData;
use crate::prolog::forms::*;
use crate::prolog::iterators::*;
use crate::prolog::machine::heap::Heap;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::MachineState;
use crate::prolog::machine::streams::Stream;
@@ -13,25 +12,6 @@ use std::collections::VecDeque;
type SubtermDeque = VecDeque<(usize, usize)>;
impl<'a> TermRef<'a> {
fn as_addr(&self, heap: &mut Heap, h: usize) -> Addr {
match self {
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
Addr::HeapCell(h)
}
&TermRef::Cons(..) => {
Addr::HeapCell(h)
}
&TermRef::Constant(_, _, c) => {
heap.put_constant(c.clone())
}
&TermRef::Clause(..) => {
Addr::Str(h)
}
}
}
}
pub type PrologStream = ParsingStream<Stream>;
pub mod readline {
@@ -102,7 +82,6 @@ pub mod readline {
result => {
result
}
}
}
}
@@ -128,24 +107,17 @@ impl MachineState {
}
}
fn push_stub_addr(machine_st: &mut MachineState) {
let h = machine_st.heap.h();
machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
#[inline]
pub(crate)
fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
let term_writer = TermWriter::new(machine_st);
term_writer.write_term_to_heap(term)
}
fn modify_head_of_queue(
machine_st: &mut MachineState,
queue: &mut SubtermDeque,
term: TermRef,
h: usize,
) {
if let Some((arity, site_h)) = queue.pop_front() {
machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
if arity > 1 {
queue.push_front((arity - 1, site_h + 1));
}
}
struct TermWriter<'a> {
machine_st: &'a mut MachineState,
queue: SubtermDeque,
var_dict: HeapVarDict,
}
pub struct TermWriteResult {
@@ -153,79 +125,168 @@ pub struct TermWriteResult {
pub(crate) var_dict: HeapVarDict,
}
pub(crate)
fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
let heap_loc = machine_st.heap.h();
let mut queue = SubtermDeque::new();
let mut var_dict = HeapVarDict::new();
for term in breadth_first_iter(term, true) {
let h = machine_st.heap.h();
match &term {
&TermRef::Cons(lvl, ..) => {
queue.push_back((2, h + 1));
machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
push_stub_addr(machine_st);
push_stub_addr(machine_st);
if let Level::Root = lvl {
continue;
}
}
&TermRef::Clause(lvl, _, ref ct, subterms) => {
queue.push_back((subterms.len(), h + 1));
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
machine_st.heap.push(named);
for _ in 0..subterms.len() {
push_stub_addr(machine_st);
}
if let Level::Root = lvl {
continue;
}
}
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..)
| &TermRef::Var(Level::Root, ..) => {
let addr = term.as_addr(&mut machine_st.heap, h);
if !addr.is_heap_bound() {
machine_st.heap.push(HeapCellValue::Addr(addr));
}
}
&TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = queue.pop_front() {
if arity > 1 {
queue.push_front((arity - 1, site_h + 1));
}
}
continue;
}
&TermRef::Var(_, _, ref var) => {
if let Some((arity, site_h)) = queue.pop_front() {
if let Some(addr) = var_dict.get(var).cloned() {
machine_st.heap[site_h] = HeapCellValue::Addr(addr);
} else {
var_dict.insert(var.clone(), Addr::HeapCell(site_h));
}
if arity > 1 {
queue.push_front((arity - 1, site_h + 1));
}
}
continue;
}
_ => {}
};
modify_head_of_queue(machine_st, &mut queue, term, h);
impl<'a> TermWriter<'a> {
#[inline]
fn new(machine_st: &'a mut MachineState) -> Self {
TermWriter {
machine_st,
queue: SubtermDeque::new(),
var_dict: HeapVarDict::new(),
}
}
TermWriteResult { heap_loc, var_dict }
#[inline]
fn modify_head_of_queue(&mut self, term: &TermRef<'a>, h: usize) {
if let Some((arity, site_h)) = self.queue.pop_front() {
self.machine_st.heap[site_h] =
HeapCellValue::Addr(self.term_as_addr(term, h));
if arity > 1 {
self.queue.push_front((arity - 1, site_h + 1));
}
}
}
#[inline]
fn push_stub_addr(&mut self) {
let h = self.machine_st.heap.h();
self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
}
fn term_as_addr(&mut self, term: &TermRef<'a>, h: usize) -> Addr {
match term {
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
Addr::HeapCell(h)
}
&TermRef::Cons(..) => {
Addr::HeapCell(h)
}
&TermRef::Constant(_, _, c) => {
self.machine_st.heap.put_constant(c.clone())
}
&TermRef::Clause(..) => {
Addr::Str(h)
}
&TermRef::PartialString(..) => {//_, _, ref pstr, tail) => {
Addr::PStrLocation(h, 0)
/*
match tail {
Term::AnonVar => {
let h = self.machine_st.heap.h();
self.machine_st.heap.allocate_pstr(pstr);
Addr::PStrLocation(h, 0)
}
Term::Constant(_, Constant::EmptyList) => {
self.machine_st.heap.put_complete_string(pstr)
}
Term::Var(_, ref var) => {
let h = self.machine_st.heap.h();
self.machine_st.heap.allocate_pstr(pstr);
let tail_h = self.machine_st.heap.h() - 1;
if let Some(addr) = self.var_dict.get(var) {
self.machine_st.heap[tail_h] = HeapCellValue::Addr(*addr);
} else {
self.var_dict.insert(var.clone(), Addr::HeapCell(tail_h));
}
Addr::PStrLocation(h, 0)
}
_ => {
unreachable!()
}
}
*/
}
}
}
fn write_term_to_heap(mut self, term: &'a Term) -> TermWriteResult {
let heap_loc = self.machine_st.heap.h();
for term in breadth_first_iter(term, true) {
let h = self.machine_st.heap.h();
match &term {
&TermRef::Cons(lvl, ..) => {
self.queue.push_back((2, h + 1));
self.machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
self.push_stub_addr();
self.push_stub_addr();
if let Level::Root = lvl {
continue;
}
}
&TermRef::Clause(lvl, _, ref ct, subterms) => {
self.queue.push_back((subterms.len(), h + 1));
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
self.machine_st.heap.push(named);
for _ in 0..subterms.len() {
self.push_stub_addr();
}
if let Level::Root = lvl {
continue;
}
}
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) |
&TermRef::Var(Level::Root, ..) => {
let addr = self.term_as_addr(&term, h);
if !addr.is_heap_bound() {
self.machine_st.heap.push(HeapCellValue::Addr(addr));
}
}
&TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = self.queue.pop_front() {
if arity > 1 {
self.queue.push_front((arity - 1, site_h + 1));
}
}
continue;
}
&TermRef::PartialString(lvl, _, ref pstr, tail) => {
if tail.is_some() {
self.machine_st.heap.allocate_pstr(&pstr);
} else {
self.machine_st.heap.put_complete_string(&pstr);
}
if let Level::Root = lvl {
} else if tail.is_some() {
let h = self.machine_st.heap.h();
self.queue.push_back((1, h - 1));
}
}
&TermRef::Var(_, _, ref var) => {
if let Some((arity, site_h)) = self.queue.pop_front() {
if let Some(addr) = self.var_dict.get(var).cloned() {
self.machine_st.heap[site_h] = HeapCellValue::Addr(addr);
} else {
self.var_dict.insert(var.clone(), Addr::HeapCell(site_h));
}
if arity > 1 {
self.queue.push_front((arity - 1, site_h + 1));
}
}
continue;
}
_ => {
}
};
self.modify_head_of_queue(&term, h);
}
TermWriteResult { heap_loc, var_dict: self.var_dict }
}
}