use new heap term representation
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,15 @@
|
||||
use crate::heap_iter::*;
|
||||
use crate::machine::*;
|
||||
use prolog_parser::temp_v;
|
||||
use crate::parser::ast::*;
|
||||
use crate::temp_v;
|
||||
use crate::types::*;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::vec::IntoIter;
|
||||
|
||||
pub(super) type Bindings = Vec<(usize, Addr)>;
|
||||
pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AttrVarInitializer {
|
||||
@@ -37,7 +39,7 @@ impl AttrVarInitializer {
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
|
||||
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: HeapCellValue) {
|
||||
if self.attr_var_init.bindings.is_empty() {
|
||||
self.attr_var_init.instigating_p = self.p.local();
|
||||
|
||||
@@ -53,28 +55,24 @@ impl MachineState {
|
||||
self.attr_var_init.bindings.push((h, addr));
|
||||
}
|
||||
|
||||
fn populate_var_and_value_lists(&mut self) -> (Addr, Addr) {
|
||||
fn populate_var_and_value_lists(&mut self) -> (HeapCellValue, HeapCellValue) {
|
||||
let iter = self
|
||||
.attr_var_init
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|(ref h, _)| HeapCellValue::Addr(Addr::AttrVar(*h)));
|
||||
.map(|(ref h, _)| attr_var_as_cell!(*h));
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
let var_list_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, iter));
|
||||
|
||||
let iter = self
|
||||
.attr_var_init
|
||||
.bindings
|
||||
.drain(0..)
|
||||
.map(|(_, addr)| HeapCellValue::Addr(addr));
|
||||
let iter = self.attr_var_init.bindings.drain(0..).map(|(_, ref v)| *v);
|
||||
|
||||
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
let value_list_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, iter));
|
||||
(var_list_addr, value_list_addr)
|
||||
}
|
||||
|
||||
fn verify_attributes(&mut self) {
|
||||
for (h, _) in &self.attr_var_init.bindings {
|
||||
self.heap[*h] = HeapCellValue::Addr(Addr::AttrVar(*h));
|
||||
self.heap[*h] = attr_var_as_cell!(*h);
|
||||
}
|
||||
|
||||
let (var_list_addr, value_list_addr) = self.populate_var_and_value_lists();
|
||||
@@ -83,19 +81,26 @@ impl MachineState {
|
||||
self[temp_v!(2)] = value_list_addr;
|
||||
}
|
||||
|
||||
pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
|
||||
pub(super) fn gather_attr_vars_created_since(&mut self, b: usize) -> IntoIter<HeapCellValue> {
|
||||
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
|
||||
.iter()
|
||||
.filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
|
||||
Addr::AttrVar(h) => Some(Addr::AttrVar(h)),
|
||||
_ => None,
|
||||
.filter_map(|h| {
|
||||
read_heap_cell!(self.store(self.deref(heap_loc_as_cell!(*h))), //Addr::HeapCell(*h))) {
|
||||
(HeapCellValueTag::AttrVar, h) => {
|
||||
Some(attr_var_as_cell!(h))
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
attr_vars
|
||||
.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2).unwrap_or(Ordering::Less));
|
||||
attr_vars.sort_unstable_by(|a1, a2| {
|
||||
compare_term_test!(self, *a1, *a2).unwrap_or(Ordering::Less)
|
||||
});
|
||||
|
||||
self.term_dedup(&mut attr_vars);
|
||||
attr_vars.dedup();
|
||||
attr_vars.into_iter()
|
||||
}
|
||||
|
||||
@@ -109,8 +114,10 @@ impl MachineState {
|
||||
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)];
|
||||
}
|
||||
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = Addr::CutPoint(self.b0);
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] = Addr::Usize(self.num_of_args);
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
||||
fixnum_as_cell!(Fixnum::build_with(self.b0 as i64));
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
|
||||
fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
|
||||
|
||||
self.verify_attributes();
|
||||
|
||||
@@ -119,33 +126,51 @@ impl MachineState {
|
||||
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
|
||||
}
|
||||
|
||||
pub(super) fn attr_vars_of_term(&self, addr: Addr) -> Vec<Addr> {
|
||||
pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> {
|
||||
let mut seen_set = IndexSet::new();
|
||||
let mut seen_vars = vec![];
|
||||
|
||||
let mut iter = self.acyclic_pre_order_iter(addr);
|
||||
let mut iter = stackful_preorder_iter(&mut self.heap, cell);
|
||||
|
||||
while let Some(addr) = iter.next() {
|
||||
if let HeapCellValue::Addr(Addr::AttrVar(h)) = self.heap.index_addr(&addr).as_ref() {
|
||||
if seen_set.contains(h) {
|
||||
continue;
|
||||
while let Some(value) = iter.next() {
|
||||
read_heap_cell!(value,
|
||||
(HeapCellValueTag::AttrVar, h) => {
|
||||
if seen_set.contains(&h) {
|
||||
continue;
|
||||
}
|
||||
|
||||
seen_vars.push(value);
|
||||
seen_set.insert(h);
|
||||
|
||||
let mut l = h + 1;
|
||||
// let mut list_elements = vec![];
|
||||
// let iter_stack_len = iter.stack_len();
|
||||
|
||||
loop {
|
||||
read_heap_cell!(iter.heap[l],
|
||||
(HeapCellValueTag::Lis) => {
|
||||
iter.push_stack(l);
|
||||
// l = elem + 1;
|
||||
break;
|
||||
}
|
||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
|
||||
if h == l {
|
||||
break;
|
||||
} else {
|
||||
l = h;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// iter.stack_slice_from(iter_stack_len ..).reverse();
|
||||
}
|
||||
|
||||
seen_vars.push(addr);
|
||||
seen_set.insert(*h);
|
||||
|
||||
let mut l = h + 1;
|
||||
let mut list_elements = vec![];
|
||||
|
||||
while let Addr::Lis(elem) = self.store(self.deref(Addr::HeapCell(l))) {
|
||||
list_elements.push(self.heap[elem].as_addr(elem));
|
||||
l = elem + 1;
|
||||
_ => {
|
||||
}
|
||||
|
||||
for element in list_elements.into_iter().rev() {
|
||||
iter.stack().push(element);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
seen_vars
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::instructions::*;
|
||||
use crate::machine::machine_indices::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CodeRepo {
|
||||
pub struct CodeRepo {
|
||||
pub(super) code: Code,
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
use crate::machine::machine_indices::*;
|
||||
use crate::atom_table::*;
|
||||
use crate::machine::stack::*;
|
||||
use crate::types::*;
|
||||
|
||||
use std::mem;
|
||||
use std::ops::IndexMut;
|
||||
@@ -7,20 +8,24 @@ use std::ops::IndexMut;
|
||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum AttrVarPolicy {
|
||||
pub enum AttrVarPolicy {
|
||||
DeepCopy,
|
||||
StripAttributes,
|
||||
}
|
||||
|
||||
pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||
fn deref(&self, val: Addr) -> Addr;
|
||||
fn push(&mut self, val: HeapCellValue);
|
||||
pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||
fn store(&self, value: HeapCellValue) -> HeapCellValue;
|
||||
fn deref(&self, value: HeapCellValue) -> HeapCellValue;
|
||||
fn push(&mut self, value: HeapCellValue);
|
||||
fn stack(&mut self) -> &mut Stack;
|
||||
fn store(&self, val: Addr) -> Addr;
|
||||
fn threshold(&self) -> usize;
|
||||
}
|
||||
|
||||
pub(crate) fn copy_term<T: CopierTarget>(target: T, addr: Addr, attr_var_policy: AttrVarPolicy) {
|
||||
pub(crate) fn copy_term<T: CopierTarget>(
|
||||
target: T,
|
||||
addr: HeapCellValue,
|
||||
attr_var_policy: AttrVarPolicy,
|
||||
) {
|
||||
let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
|
||||
copy_term_state.copy_term_impl(addr);
|
||||
}
|
||||
@@ -47,50 +52,51 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
|
||||
#[inline]
|
||||
fn value_at_scan(&mut self) -> &mut HeapCellValue {
|
||||
let scan = self.scan;
|
||||
&mut self.target[scan]
|
||||
&mut self.target[self.scan]
|
||||
}
|
||||
|
||||
fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
|
||||
let trail_item = mem::replace(
|
||||
&mut self.target[addr],
|
||||
HeapCellValue::Addr(Addr::Lis(threshold)),
|
||||
);
|
||||
|
||||
self.trail.push((Ref::HeapCell(addr), trail_item));
|
||||
let trail_item = mem::replace(&mut self.target[addr], list_loc_as_cell!(threshold));
|
||||
self.trail.push((Ref::heap_cell(addr), trail_item));
|
||||
}
|
||||
|
||||
fn copy_list(&mut self, addr: usize) {
|
||||
for offset in 0..2 {
|
||||
if let Addr::Lis(h) = self.target[addr + offset].as_addr(addr + offset) {
|
||||
if h >= self.old_h {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h));
|
||||
self.scan += 1;
|
||||
read_heap_cell!(self.target[addr + offset],
|
||||
(HeapCellValueTag::Lis, h) => {
|
||||
if h >= self.old_h {
|
||||
*self.value_at_scan() = list_loc_as_cell!(h);
|
||||
self.scan += 1;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let threshold = self.target.threshold();
|
||||
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
|
||||
*self.value_at_scan() = list_loc_as_cell!(threshold);
|
||||
|
||||
for i in 0..2 {
|
||||
let hcv = self.target[addr + i].context_free_clone();
|
||||
let hcv = self.target[addr + i];
|
||||
self.target.push(hcv);
|
||||
}
|
||||
|
||||
let cdr = self
|
||||
.target
|
||||
.store(self.target.deref(Addr::HeapCell(addr + 1)));
|
||||
.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
|
||||
|
||||
if !cdr.is_ref() {
|
||||
if !cdr.is_var() {
|
||||
self.trail_list_cell(addr + 1, threshold);
|
||||
} else {
|
||||
let car = self.target.store(self.target.deref(Addr::HeapCell(addr)));
|
||||
let car = self
|
||||
.target
|
||||
.store(self.target.deref(heap_loc_as_cell!(addr)));
|
||||
|
||||
if !car.is_ref() {
|
||||
if !car.is_var() {
|
||||
self.trail_list_cell(addr, threshold);
|
||||
}
|
||||
}
|
||||
@@ -98,187 +104,208 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
self.scan += 1;
|
||||
}
|
||||
|
||||
fn copy_partial_string(&mut self, addr: usize, n: usize) {
|
||||
if let &HeapCellValue::Addr(Addr::PStrLocation(h, _)) = &self.target[addr] {
|
||||
if h >= self.old_h {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(h, n));
|
||||
self.scan += 1;
|
||||
fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) {
|
||||
read_heap_cell!(self.target[pstr_loc],
|
||||
(HeapCellValueTag::PStrLoc, h) => {
|
||||
if h >= self.old_h {
|
||||
*self.value_at_scan() = match scan_tag {
|
||||
HeapCellValueTag::PStrLoc => {
|
||||
pstr_loc_as_cell!(h)
|
||||
}
|
||||
tag => {
|
||||
debug_assert!(tag == HeapCellValueTag::PStrOffset);
|
||||
pstr_offset_as_cell!(h)
|
||||
}
|
||||
};
|
||||
|
||||
return;
|
||||
self.scan += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
);
|
||||
|
||||
let threshold = self.target.threshold();
|
||||
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(threshold, n));
|
||||
|
||||
*self.value_at_scan() = pstr_loc_as_cell!(threshold);
|
||||
self.scan += 1;
|
||||
|
||||
let (pstr, has_tail) = match &self.target[addr] {
|
||||
&HeapCellValue::PartialString(ref pstr, has_tail) => {
|
||||
(pstr.clone_from_offset(0), has_tail)
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
self.target.push(self.target[pstr_loc]);
|
||||
|
||||
self.target
|
||||
.push(HeapCellValue::PartialString(pstr, has_tail));
|
||||
let replacement = pstr_loc_as_cell!(threshold);
|
||||
let trail_item = mem::replace(&mut self.target[pstr_loc], replacement);
|
||||
|
||||
let replacement = HeapCellValue::Addr(Addr::PStrLocation(threshold, n));
|
||||
|
||||
let trail_item = mem::replace(&mut self.target[addr], replacement);
|
||||
|
||||
self.trail.push((Ref::HeapCell(addr), trail_item));
|
||||
|
||||
if has_tail {
|
||||
let tail_addr = self.target[addr + 1].as_addr(addr + 1);
|
||||
self.target.push(HeapCellValue::Addr(tail_addr));
|
||||
}
|
||||
self.trail.push((Ref::heap_cell(pstr_loc), trail_item));
|
||||
self.target.push(self.target[pstr_loc + 1]);
|
||||
}
|
||||
|
||||
fn reinstantiate_var(&mut self, addr: Addr, frontier: usize) {
|
||||
match addr {
|
||||
Addr::HeapCell(h) => {
|
||||
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
||||
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
||||
fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) {
|
||||
read_heap_cell!(addr,
|
||||
(HeapCellValueTag::Var, h) => {
|
||||
self.target[frontier] = heap_loc_as_cell!(frontier);
|
||||
self.target[h] = heap_loc_as_cell!(frontier);
|
||||
|
||||
self.trail
|
||||
.push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h))));
|
||||
self.trail.push((Ref::heap_cell(h), heap_loc_as_cell!(h)));
|
||||
}
|
||||
Addr::StackCell(fr, sc) => {
|
||||
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
||||
self.target.stack().index_and_frame_mut(fr)[sc] = Addr::HeapCell(frontier);
|
||||
(HeapCellValueTag::StackVar, s) => {
|
||||
self.target[frontier] = heap_loc_as_cell!(frontier);
|
||||
self.target.stack()[s] = heap_loc_as_cell!(frontier);
|
||||
|
||||
self.trail.push((
|
||||
Ref::StackCell(fr, sc),
|
||||
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
|
||||
));
|
||||
self.trail.push((Ref::stack_cell(s), stack_loc_as_cell!(s)));
|
||||
}
|
||||
Addr::AttrVar(h) => {
|
||||
(HeapCellValueTag::AttrVar, h) => {
|
||||
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||
self.target.threshold()
|
||||
} else {
|
||||
frontier
|
||||
};
|
||||
|
||||
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||
self.target[frontier] = heap_loc_as_cell!(threshold);
|
||||
self.target[h] = heap_loc_as_cell!(threshold);
|
||||
|
||||
self.trail
|
||||
.push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h))));
|
||||
self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
|
||||
|
||||
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||
self.target
|
||||
.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
||||
.push(attr_var_as_cell!(threshold));
|
||||
|
||||
let list_val = self.target[h + 1].context_free_clone();
|
||||
let list_val = self.target[h + 1];
|
||||
self.target.push(list_val);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn copy_var(&mut self, addr: HeapCellValue) {
|
||||
let rd = self.target.deref(addr);
|
||||
let ra = self.target.store(rd);
|
||||
|
||||
read_heap_cell!(ra,
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
if h >= self.old_h {
|
||||
*self.value_at_scan() = rd;
|
||||
self.scan += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
);
|
||||
|
||||
if addr == ra {
|
||||
self.reinstantiate_var(addr, self.scan);
|
||||
self.scan += 1;
|
||||
} else {
|
||||
*self.value_at_scan() = ra;
|
||||
// self.copy_compound(rd, ra);
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_var(&mut self, addr: Addr) {
|
||||
let rd = self.target.store(self.target.deref(addr));
|
||||
/*
|
||||
fn copy_compound(&mut self, rd: HeapCellValue, ra: HeapCellValue) {
|
||||
let h = rd.get_value();
|
||||
let trail_item = self.target[h];
|
||||
let threshold = self.target.threshold();
|
||||
|
||||
match rd {
|
||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
||||
self.scan += 1;
|
||||
self.trail.push((Ref::heap_cell(h), trail_item));
|
||||
self.target[self.scan].set_value(threshold);
|
||||
|
||||
read_heap_cell!(ra,
|
||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||
self.target.push(ra);
|
||||
|
||||
for i in 0..arity {
|
||||
self.target.push(self.target[h + 1 + i]);
|
||||
}
|
||||
|
||||
self.target[h] = str_loc_as_cell!(self.scan + 1);
|
||||
}
|
||||
_ if addr == rd => {
|
||||
self.reinstantiate_var(addr, self.scan);
|
||||
self.scan += 1;
|
||||
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
|
||||
self.target.push(ra);
|
||||
self.target.push(self.target[h + 1]);
|
||||
|
||||
self.target[h] = pstr_loc_as_cell!(self.scan + 1);
|
||||
}
|
||||
(HeapCellValueTag::CStr, cstr_atom) => {
|
||||
self.target[h] = atom_as_cstr_cell!(cstr_atom);
|
||||
}
|
||||
(HeapCellValueTag::Str, s) => {
|
||||
self.copy_structure(s);
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
||||
*self.value_at_scan() = rd;
|
||||
self.trail.pop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
self.scan += 1;
|
||||
}
|
||||
*/
|
||||
|
||||
fn copy_structure(&mut self, addr: usize) {
|
||||
match self.target[addr].context_free_clone() {
|
||||
HeapCellValue::NamedStr(arity, name, fixity) => {
|
||||
read_heap_cell!(self.target[addr],
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
let threshold = self.target.threshold();
|
||||
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
|
||||
*self.value_at_scan() = str_loc_as_cell!(threshold);
|
||||
|
||||
let trail_item = mem::replace(
|
||||
&mut self.target[addr],
|
||||
HeapCellValue::Addr(Addr::Str(threshold)),
|
||||
str_loc_as_cell!(threshold),
|
||||
);
|
||||
|
||||
self.trail.push((Ref::HeapCell(addr), trail_item));
|
||||
|
||||
self.target
|
||||
.push(HeapCellValue::NamedStr(arity, name, fixity));
|
||||
self.trail.push((Ref::heap_cell(addr), trail_item));
|
||||
self.target.push(atom_as_cell!(name, arity));
|
||||
|
||||
for i in 0..arity {
|
||||
let hcv = self.target[addr + 1 + i].context_free_clone();
|
||||
let hcv = self.target[addr + 1 + i];
|
||||
self.target.push(hcv);
|
||||
}
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Str(addr)) => {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
|
||||
(HeapCellValueTag::Str, h) => {
|
||||
*self.value_at_scan() = str_loc_as_cell!(h);
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
self.scan += 1;
|
||||
}
|
||||
|
||||
fn copy_term_impl(&mut self, addr: Addr) {
|
||||
fn copy_term_impl(&mut self, addr: HeapCellValue) {
|
||||
self.scan = self.target.threshold();
|
||||
self.target.push(HeapCellValue::Addr(addr));
|
||||
self.target.push(addr);
|
||||
|
||||
while self.scan < self.target.threshold() {
|
||||
match self.value_at_scan() {
|
||||
&mut HeapCellValue::Addr(addr) => match addr {
|
||||
Addr::Con(h) => {
|
||||
let addr = self.target[h].as_addr(h);
|
||||
let addr = *self.value_at_scan();
|
||||
|
||||
if addr == Addr::Con(h) {
|
||||
*self.value_at_scan() = self.target[h].context_free_clone();
|
||||
} else {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(addr);
|
||||
}
|
||||
}
|
||||
Addr::Lis(h) => {
|
||||
if h >= self.old_h {
|
||||
self.scan += 1;
|
||||
} else {
|
||||
self.copy_list(h);
|
||||
}
|
||||
}
|
||||
addr @ Addr::AttrVar(_)
|
||||
| addr @ Addr::HeapCell(_)
|
||||
| addr @ Addr::StackCell(..) => {
|
||||
self.copy_var(addr);
|
||||
}
|
||||
Addr::Str(addr) => {
|
||||
self.copy_structure(addr);
|
||||
}
|
||||
Addr::PStrLocation(addr, n) => {
|
||||
self.copy_partial_string(addr, n);
|
||||
}
|
||||
Addr::Stream(h) => {
|
||||
*self.value_at_scan() = self.target[h].context_free_clone();
|
||||
}
|
||||
_ => {
|
||||
read_heap_cell!(addr,
|
||||
(HeapCellValueTag::Lis, h) => {
|
||||
if h >= self.old_h {
|
||||
self.scan += 1;
|
||||
} else {
|
||||
self.copy_list(h);
|
||||
}
|
||||
},
|
||||
}
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var) => {
|
||||
self.copy_var(addr);
|
||||
}
|
||||
(HeapCellValueTag::Str, h) => {
|
||||
self.copy_structure(h);
|
||||
}
|
||||
(HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrOffset, pstr_loc) => {
|
||||
self.copy_partial_string(addr.get_tag(), pstr_loc);
|
||||
}
|
||||
_ => {
|
||||
self.scan += 1;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
self.unwind_trail();
|
||||
@@ -286,12 +313,117 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
|
||||
fn unwind_trail(&mut self) {
|
||||
for (r, value) in self.trail.drain(0..) {
|
||||
match r {
|
||||
Ref::AttrVar(h) | Ref::HeapCell(h) => self.target[h] = value,
|
||||
Ref::StackCell(fr, sc) => {
|
||||
self.target.stack().index_and_frame_mut(fr)[sc] = value.as_addr(0)
|
||||
}
|
||||
let index = r.get_value() as usize;
|
||||
|
||||
match r.get_tag() {
|
||||
RefTag::AttrVar | RefTag::HeapCell => self.target[index] = value,
|
||||
RefTag::StackCell => self.target.stack()[index] = value,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
fn copier_tests() {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
let f_atom = atom!("f");
|
||||
let a_atom = atom!("a");
|
||||
let b_atom = atom!("b");
|
||||
|
||||
wam.machine_st.heap
|
||||
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[2], atom_as_cell!(b_atom));
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy);
|
||||
}
|
||||
|
||||
// check that the original heap state is still intact.
|
||||
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[2], atom_as_cell!(b_atom));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[3], str_loc_as_cell!(4));
|
||||
assert_eq!(wam.machine_st.heap[4], atom_as_cell!(f_atom, 2));
|
||||
assert_eq!(wam.machine_st.heap[5], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[6], atom_as_cell!(b_atom));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl);
|
||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||
|
||||
wam.machine_st.heap.pop();
|
||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||
|
||||
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl);
|
||||
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||
|
||||
wam.machine_st.heap.pop();
|
||||
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
|
||||
|
||||
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
|
||||
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy);
|
||||
}
|
||||
|
||||
print_heap_terms(wam.machine_st.heap[6..].iter(), 6);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], pstr_cell);
|
||||
assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(2));
|
||||
assert_eq!(wam.machine_st.heap[2], pstr_second_cell);
|
||||
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(4));
|
||||
assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
|
||||
assert_eq!(wam.machine_st.heap[5], fixnum_as_cell!(Fixnum::build_with(0i64)));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[7], pstr_cell);
|
||||
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(9));
|
||||
assert_eq!(wam.machine_st.heap[9], pstr_second_cell);
|
||||
assert_eq!(wam.machine_st.heap[10], pstr_loc_as_cell!(11));
|
||||
assert_eq!(wam.machine_st.heap[11], pstr_offset_as_cell!(7));
|
||||
assert_eq!(wam.machine_st.heap[12], fixnum_as_cell!(Fixnum::build_with(0i64)));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
wam.machine_st.heap.extend(functor!(
|
||||
f_atom,
|
||||
[
|
||||
atom(a_atom),
|
||||
atom(b_atom),
|
||||
atom(a_atom),
|
||||
cell(str_loc_as_cell!(0))
|
||||
]
|
||||
));
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy);
|
||||
}
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 4));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[2], atom_as_cell!(b_atom));
|
||||
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[4], str_loc_as_cell!(0));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[5], str_loc_as_cell!(6));
|
||||
assert_eq!(wam.machine_st.heap[6], atom_as_cell!(f_atom, 4));
|
||||
assert_eq!(wam.machine_st.heap[7], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[8], atom_as_cell!(b_atom));
|
||||
assert_eq!(wam.machine_st.heap[9], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[10], str_loc_as_cell!(6));
|
||||
}
|
||||
}
|
||||
|
||||
1101
src/machine/gc.rs
Normal file
1101
src/machine/gc.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,140 +1,282 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use prolog_parser::ast::Constant;
|
||||
|
||||
use crate::arena::*;
|
||||
use crate::atom_table::*;
|
||||
use crate::forms::*;
|
||||
use crate::machine::machine_indices::*;
|
||||
use crate::machine::partial_string::*;
|
||||
use crate::machine::raw_block::*;
|
||||
use crate::parser::ast::*;
|
||||
use crate::types::*;
|
||||
|
||||
use ordered_float::OrderedFloat;
|
||||
use rug::{Integer, Rational};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::ptr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct StandardHeapTraits {}
|
||||
pub(crate) type Heap = Vec<HeapCellValue>;
|
||||
|
||||
impl RawBlockTraits for StandardHeapTraits {
|
||||
impl From<Literal> for HeapCellValue {
|
||||
#[inline]
|
||||
fn init_size() -> usize {
|
||||
256 * mem::size_of::<HeapCellValue>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn align() -> usize {
|
||||
mem::align_of::<HeapCellValue>()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HeapTemplate<T: RawBlockTraits> {
|
||||
buf: RawBlock<T>,
|
||||
_marker: PhantomData<HeapCellValue>,
|
||||
}
|
||||
|
||||
pub(crate) type Heap = HeapTemplate<StandardHeapTraits>;
|
||||
|
||||
impl<T: RawBlockTraits> Drop for HeapTemplate<T> {
|
||||
fn drop(&mut self) {
|
||||
self.clear();
|
||||
self.buf.deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HeapIntoIter<T: RawBlockTraits> {
|
||||
offset: usize,
|
||||
buf: RawBlock<T>,
|
||||
}
|
||||
|
||||
impl<T: RawBlockTraits> Drop for HeapIntoIter<T> {
|
||||
fn drop(&mut self) {
|
||||
let mut heap = HeapTemplate {
|
||||
buf: self.buf.take(),
|
||||
_marker: PhantomData,
|
||||
};
|
||||
|
||||
heap.truncate(self.offset / mem::size_of::<HeapCellValue>());
|
||||
heap.buf.deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RawBlockTraits> Iterator for HeapIntoIter<T> {
|
||||
type Item = HeapCellValue;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let ptr = self.buf.base as usize + self.offset;
|
||||
self.offset += mem::size_of::<HeapCellValue>();
|
||||
|
||||
if ptr < self.buf.top as usize {
|
||||
unsafe { Some(ptr::read(ptr as *const HeapCellValue)) }
|
||||
} else {
|
||||
None
|
||||
fn from(literal: Literal) -> Self {
|
||||
match literal {
|
||||
Literal::Atom(name) => atom_as_cell!(name),
|
||||
Literal::Char(c) => char_as_cell!(c),
|
||||
Literal::Fixnum(n) => fixnum_as_cell!(n),
|
||||
Literal::Integer(bigint_ptr) => {
|
||||
typed_arena_ptr_as_cell!(bigint_ptr)
|
||||
}
|
||||
Literal::Rational(bigint_ptr) => {
|
||||
typed_arena_ptr_as_cell!(bigint_ptr)
|
||||
}
|
||||
Literal::Float(f) => HeapCellValue::from(f),
|
||||
Literal::String(s) => {
|
||||
if s == atom!("") {
|
||||
empty_list_as_cell!()
|
||||
} else {
|
||||
string_as_cstr_cell!(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HeapIter<'a, T: RawBlockTraits> {
|
||||
offset: usize,
|
||||
buf: &'a RawBlock<T>,
|
||||
}
|
||||
impl TryFrom<HeapCellValue> for Literal {
|
||||
type Error = ();
|
||||
|
||||
impl<'a, T: RawBlockTraits> HeapIter<'a, T> {
|
||||
pub(crate) fn new(buf: &'a RawBlock<T>, offset: usize) -> Self {
|
||||
HeapIter { buf, offset }
|
||||
fn try_from(value: HeapCellValue) -> Result<Literal, ()> {
|
||||
read_heap_cell!(value,
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
if arity == 0 {
|
||||
Ok(Literal::Atom(name))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Char, c) => {
|
||||
Ok(Literal::Char(c))
|
||||
}
|
||||
(HeapCellValueTag::Fixnum, n) => {
|
||||
Ok(Literal::Fixnum(n))
|
||||
}
|
||||
(HeapCellValueTag::F64, f) => {
|
||||
Ok(Literal::Float(f))
|
||||
}
|
||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||
match_untyped_arena_ptr!(cons_ptr,
|
||||
(ArenaHeaderTag::Integer, n) => {
|
||||
Ok(Literal::Integer(n))
|
||||
}
|
||||
(ArenaHeaderTag::Rational, n) => {
|
||||
Ok(Literal::Rational(n))
|
||||
}
|
||||
_ => {
|
||||
Err(())
|
||||
}
|
||||
)
|
||||
}
|
||||
(HeapCellValueTag::CStr, cstr_atom) => {
|
||||
Ok(Literal::String(cstr_atom))
|
||||
}
|
||||
_ => {
|
||||
Err(())
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: RawBlockTraits> Iterator for HeapIter<'a, T> {
|
||||
type Item = &'a HeapCellValue;
|
||||
// sometimes we need to dereference variables that are found only in
|
||||
// the heap without access to the full WAM (e.g., while detecting
|
||||
// cycles in terms), and which therefore may only point other cells in
|
||||
// the heap (thanks to the design of the WAM).
|
||||
pub fn heap_bound_deref(heap: &[HeapCellValue], mut value: HeapCellValue) -> HeapCellValue {
|
||||
loop {
|
||||
let new_value = read_heap_cell!(value,
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
heap[h]
|
||||
}
|
||||
_ => {
|
||||
value
|
||||
}
|
||||
);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let ptr = self.buf.base as usize + self.offset;
|
||||
self.offset += mem::size_of::<HeapCellValue>();
|
||||
|
||||
if ptr < self.buf.top as usize {
|
||||
unsafe { Some(&*(ptr as *const _)) }
|
||||
} else {
|
||||
None
|
||||
if new_value != value && new_value.is_var() {
|
||||
value = new_value;
|
||||
continue;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn heap_bound_store(heap: &[HeapCellValue], value: HeapCellValue) -> HeapCellValue {
|
||||
read_heap_cell!(value,
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
heap[h]
|
||||
}
|
||||
_ => {
|
||||
value
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: usize) {
|
||||
pub fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: usize) {
|
||||
for (index, term) in heap.enumerate() {
|
||||
println!("{} : {}", h + index, term);
|
||||
println!("{} : {:?}", h + index, term);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HeapIterMut<'a, T: RawBlockTraits> {
|
||||
offset: usize,
|
||||
buf: &'a mut RawBlock<T>,
|
||||
}
|
||||
#[inline]
|
||||
pub(crate) fn put_complete_string(
|
||||
heap: &mut Heap,
|
||||
s: &str,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> HeapCellValue {
|
||||
match allocate_pstr(heap, s, atom_tbl) {
|
||||
Some(h) => {
|
||||
heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr.
|
||||
|
||||
impl<'a, T: RawBlockTraits> HeapIterMut<'a, T> {
|
||||
pub(crate) fn new(buf: &'a mut RawBlock<T>, offset: usize) -> Self {
|
||||
HeapIterMut { buf, offset }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: RawBlockTraits> Iterator for HeapIterMut<'a, T> {
|
||||
type Item = &'a mut HeapCellValue;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let ptr = self.buf.base as usize + self.offset;
|
||||
self.offset += mem::size_of::<HeapCellValue>();
|
||||
|
||||
if ptr < self.buf.top as usize {
|
||||
unsafe { Some(&mut *(ptr as *mut _)) }
|
||||
} else {
|
||||
None
|
||||
if heap.len() == h + 1 {
|
||||
let pstr_atom = cell_as_atom!(heap[h]);
|
||||
heap[h] = atom_as_cstr_cell!(pstr_atom);
|
||||
heap_loc_as_cell!(h)
|
||||
} else {
|
||||
heap.push(empty_list_as_cell!());
|
||||
pstr_loc_as_cell!(h)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
empty_list_as_cell!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn put_partial_string(
|
||||
heap: &mut Heap,
|
||||
s: &str,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> HeapCellValue {
|
||||
match allocate_pstr(heap, s, atom_tbl) {
|
||||
Some(h) => {
|
||||
pstr_loc_as_cell!(h)
|
||||
}
|
||||
None => {
|
||||
empty_list_as_cell!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn allocate_pstr(
|
||||
heap: &mut Heap,
|
||||
mut src: &str,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> Option<usize> {
|
||||
let orig_h = heap.len();
|
||||
|
||||
loop {
|
||||
if src == "" {
|
||||
return if orig_h == heap.len() {
|
||||
None
|
||||
} else {
|
||||
let tail_h = heap.len() - 1;
|
||||
heap[tail_h] = heap_loc_as_cell!(tail_h);
|
||||
|
||||
Some(orig_h)
|
||||
};
|
||||
}
|
||||
|
||||
let h = heap.len();
|
||||
|
||||
let (pstr, rest_src) = match PartialString::new(src, atom_tbl) {
|
||||
Some(tuple) => tuple,
|
||||
None => {
|
||||
if src.len() > '\u{0}'.len_utf8() {
|
||||
src = &src['\u{0}'.len_utf8()..];
|
||||
continue;
|
||||
} else if orig_h == h {
|
||||
return None;
|
||||
} else {
|
||||
heap[h - 1] = heap_loc_as_cell!(h - 1);
|
||||
return Some(orig_h);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
heap.push(string_as_pstr_cell!(pstr));
|
||||
|
||||
if rest_src != "" {
|
||||
heap.push(pstr_loc_as_cell!(h + 2));
|
||||
src = rest_src;
|
||||
} else {
|
||||
heap.push(heap_loc_as_cell!(h + 1));
|
||||
return Some(orig_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filtered_iter_to_heap_list<SrcT: Into<HeapCellValue>>(
|
||||
heap: &mut Heap,
|
||||
values: impl Iterator<Item = SrcT>,
|
||||
filter_fn: impl Fn(&Heap, HeapCellValue) -> bool,
|
||||
) -> usize {
|
||||
let head_addr = heap.len();
|
||||
let mut h = head_addr;
|
||||
|
||||
for value in values {
|
||||
let value = value.into();
|
||||
|
||||
if filter_fn(heap, value) {
|
||||
heap.push(list_loc_as_cell!(h + 1));
|
||||
heap.push(value);
|
||||
|
||||
h += 2;
|
||||
}
|
||||
}
|
||||
|
||||
heap.push(empty_list_as_cell!());
|
||||
|
||||
head_addr
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_to_heap_list<Iter, SrcT>(heap: &mut Heap, values: Iter) -> usize
|
||||
where
|
||||
Iter: Iterator<Item = SrcT>,
|
||||
SrcT: Into<HeapCellValue>,
|
||||
{
|
||||
filtered_iter_to_heap_list(heap, values, |_, _| true)
|
||||
}
|
||||
|
||||
pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<LocalCodePtr> {
|
||||
let extract_integer = |s: usize| -> Option<usize> {
|
||||
match Number::try_from(heap[s]) {
|
||||
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
|
||||
Ok(Number::Integer(n)) => n.to_usize(),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
read_heap_cell!(addr,
|
||||
(HeapCellValueTag::Str, s) => {
|
||||
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
|
||||
|
||||
if name == atom!("dir_entry") && arity == 1 {
|
||||
extract_integer(s+1).map(LocalCodePtr::DirEntry)
|
||||
} else {
|
||||
panic!(
|
||||
"to_local_code_ptr crashed with p.i. {}/{}",
|
||||
name.as_str(),
|
||||
arity,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
#[inline]
|
||||
pub(crate) fn new() -> Self {
|
||||
@@ -144,67 +286,40 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn clone(&self, h: usize) -> HeapCellValue {
|
||||
match &self[h] {
|
||||
&HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr),
|
||||
&HeapCellValue::Atom(ref name, ref op) => HeapCellValue::Atom(name.clone(), op.clone()),
|
||||
&HeapCellValue::DBRef(ref db_ref) => HeapCellValue::DBRef(db_ref.clone()),
|
||||
&HeapCellValue::Integer(ref n) => HeapCellValue::Integer(n.clone()),
|
||||
&HeapCellValue::LoadStatePayload(_) => HeapCellValue::Addr(Addr::LoadStatePayload(h)),
|
||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||
}
|
||||
&HeapCellValue::PartialString(..) => HeapCellValue::Addr(Addr::PStrLocation(h, 0)),
|
||||
&HeapCellValue::Rational(ref r) => HeapCellValue::Rational(r.clone()),
|
||||
&HeapCellValue::Stream(_) => HeapCellValue::Addr(Addr::Stream(h)),
|
||||
&HeapCellValue::TcpListener(_) => HeapCellValue::Addr(Addr::TcpListener(h)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn put_complete_string(&mut self, s: &str) -> Addr {
|
||||
if s.is_empty() {
|
||||
return Addr::EmptyList;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn put_constant(&mut self, c: Constant) -> Addr {
|
||||
match c {
|
||||
Constant::Atom(name, op) => Addr::Con(self.push(HeapCellValue::Atom(name, op))),
|
||||
Constant::Char(c) => Addr::Char(c),
|
||||
Constant::EmptyList => Addr::EmptyList,
|
||||
Constant::Fixnum(n) => Addr::Fixnum(n),
|
||||
Constant::Integer(n) => Addr::Con(self.push(HeapCellValue::Integer(n))),
|
||||
Constant::Rational(r) => Addr::Con(self.push(HeapCellValue::Rational(r))),
|
||||
Constant::Float(f) => Addr::Float(f),
|
||||
Constant::String(s) => {
|
||||
if s.is_empty() {
|
||||
Addr::EmptyList
|
||||
} else {
|
||||
self.put_complete_string(&s)
|
||||
/*
|
||||
// TODO: move this to the WAM, then remove the temporary (and by
|
||||
// then, unnecessary and impossible) "arena" argument. OR, remove
|
||||
// this thing totally! if we can. by that I mean, just convert a
|
||||
// little to a HeapCellValue. don't bother writing to the
|
||||
// heap at all. Each of these data is either already inlinable in a
|
||||
// HeapCellValue or a pointer to an GC'ed location in memory.
|
||||
#[inline]
|
||||
pub(crate) fn put_literal(&mut self, literal: Literal) -> HeapCellValue {
|
||||
match literal {
|
||||
Literal::Atom(name) => atom_as_cell!(name),
|
||||
Literal::Char(c) => char_as_cell!(c),
|
||||
Literal::EmptyList => empty_list_as_cell!(),
|
||||
Literal::Fixnum(n) => fixnum_as_cell!(n),
|
||||
Literal::Integer(bigint_ptr) => {
|
||||
let h = self.push(typed_arena_ptr_as_cell!(bigint_ptr));
|
||||
self[h]
|
||||
}
|
||||
Literal::Rational(bigint_ptr) => {
|
||||
let h = self.push(typed_arena_ptr_as_cell!(bigint_ptr));
|
||||
self[h]
|
||||
}
|
||||
Literal::Float(f) => typed_arena_ptr_as_cell!(f),
|
||||
Literal::String(s) => {
|
||||
if s.as_str().is_empty() {
|
||||
empty_list_as_cell!()
|
||||
} else {
|
||||
// TODO: how do we know where the tail is located?? well, there is no tail. separate tag?
|
||||
untyped_arena_ptr_as_cell!(s) // self.put_complete_string(arena, &s)
|
||||
}
|
||||
} // Literal::Usize(n) => Addr::Usize(n),
|
||||
}
|
||||
Constant::Usize(n) => Addr::Usize(n),
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
@@ -225,14 +340,14 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
let h = self.h();
|
||||
|
||||
unsafe {
|
||||
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
||||
ptr::write(self.buf.top as *mut _, val);
|
||||
self.buf.top = new_top;
|
||||
let new_ptr = self.buf.alloc(mem::size_of::<HeapCellValue>());
|
||||
ptr::write(new_ptr as *mut _, val);
|
||||
}
|
||||
|
||||
h
|
||||
}
|
||||
|
||||
/*
|
||||
#[inline]
|
||||
pub(crate) fn atom_at(&self, h: usize) -> bool {
|
||||
if let HeapCellValue::Atom(..) = &self[h] {
|
||||
@@ -265,76 +380,17 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
val @ HeapCellValue::TcpListener(..) => Addr::TcpListener(self.push(val)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn allocate_pstr(&mut self, src: &str) -> Addr {
|
||||
self.write_pstr(src).unwrap_or_else(|| Addr::EmptyList)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
||||
let orig_h = self.h();
|
||||
|
||||
loop {
|
||||
if src == "" {
|
||||
return if orig_h == self.h() {
|
||||
None
|
||||
} else {
|
||||
let tail_h = self.h() - 1;
|
||||
self[tail_h] = HeapCellValue::Addr(Addr::HeapCell(tail_h));
|
||||
|
||||
Some(Addr::PStrLocation(orig_h, 0))
|
||||
};
|
||||
}
|
||||
|
||||
let h = self.h();
|
||||
|
||||
let (pstr, rest_src) = match PartialString::new(src) {
|
||||
Some(tuple) => tuple,
|
||||
None => {
|
||||
if src.len() > '\u{0}'.len_utf8() {
|
||||
src = &src['\u{0}'.len_utf8()..];
|
||||
continue;
|
||||
} else if orig_h == h {
|
||||
return None;
|
||||
} else {
|
||||
self[h - 1] = HeapCellValue::Addr(Addr::HeapCell(h - 1));
|
||||
return Some(Addr::PStrLocation(orig_h, 0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.push(HeapCellValue::PartialString(pstr, true));
|
||||
|
||||
if rest_src != "" {
|
||||
self.push(HeapCellValue::Addr(Addr::PStrLocation(h + 2, 0)));
|
||||
src = rest_src;
|
||||
} else {
|
||||
self.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
|
||||
return Some(Addr::PStrLocation(orig_h, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn truncate(&mut self, h: usize) {
|
||||
let new_top = h * mem::size_of::<HeapCellValue>() + self.buf.base as usize;
|
||||
let mut h = new_top;
|
||||
|
||||
unsafe {
|
||||
while h as *const _ < self.buf.top {
|
||||
let val = h as *mut HeapCellValue;
|
||||
ptr::drop_in_place(val);
|
||||
h += mem::size_of::<HeapCellValue>();
|
||||
}
|
||||
}
|
||||
|
||||
self.buf.top = new_top as *const _;
|
||||
let new_ptr = self.buf.top as usize - h * mem::size_of::<HeapCellValue>();
|
||||
self.buf.ptr = new_ptr as *mut _;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn h(&self) -> usize {
|
||||
(self.buf.top as usize - self.buf.base as usize) / mem::size_of::<HeapCellValue>()
|
||||
(self.buf.top as usize - self.buf.ptr as usize) / mem::size_of::<HeapCellValue>()
|
||||
}
|
||||
|
||||
pub(crate) fn append(&mut self, vals: Vec<HeapCellValue>) {
|
||||
@@ -350,84 +406,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_list<Iter, SrcT>(&mut self, values: Iter) -> usize
|
||||
where
|
||||
Iter: Iterator<Item = SrcT>,
|
||||
SrcT: Into<HeapCellValue>,
|
||||
{
|
||||
let head_addr = self.h();
|
||||
let mut h = head_addr;
|
||||
|
||||
for value in values.map(|v| v.into()) {
|
||||
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||
self.push(value);
|
||||
|
||||
h += 2;
|
||||
}
|
||||
|
||||
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||
|
||||
head_addr
|
||||
}
|
||||
|
||||
/* Create an iterator starting from the passed offset. */
|
||||
pub(crate) fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> {
|
||||
HeapIter::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
|
||||
}
|
||||
|
||||
pub(crate) fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> {
|
||||
HeapIterMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
|
||||
}
|
||||
|
||||
pub(crate) fn into_iter(mut self) -> HeapIntoIter<T> {
|
||||
HeapIntoIter {
|
||||
buf: self.buf.take(),
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn extend<Iter: Iterator<Item = HeapCellValue>>(&mut self, iter: Iter) {
|
||||
for hcv in iter {
|
||||
self.push(hcv);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
||||
let extract_integer = |s: usize| -> Option<usize> {
|
||||
match &self[s] {
|
||||
&HeapCellValue::Addr(Addr::Fixnum(n)) => usize::try_from(n).ok(),
|
||||
&HeapCellValue::Integer(ref n) => n.to_usize(),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
match addr {
|
||||
Addr::Str(s) => {
|
||||
match &self[*s] {
|
||||
HeapCellValue::NamedStr(arity, ref name, _) => {
|
||||
match (name.as_str(), *arity) {
|
||||
("dir_entry", 1) => extract_integer(s + 1).map(LocalCodePtr::DirEntry),
|
||||
/*
|
||||
("top_level", 2) => {
|
||||
if let Some(chunk_num) = extract_integer(s+1) {
|
||||
if let Some(p) = extract_integer(s+2) {
|
||||
return Some(LocalCodePtr::TopLevel(chunk_num, p));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
*/
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: get rid of this!!
|
||||
#[inline]
|
||||
pub(crate) fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
||||
match addr {
|
||||
@@ -437,6 +416,20 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
addr => RefOrOwned::Owned(HeapCellValue::Addr(*addr)),
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
impl<T: RawBlockTraits> Index<u64> for HeapTemplate<T> {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: u64) -> &Self::Output {
|
||||
unsafe {
|
||||
let ptr =
|
||||
self.buf.top as usize - (index as usize + 1) * mem::size_of::<HeapCellValue>();
|
||||
&*(ptr as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
||||
@@ -445,7 +438,7 @@ impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + index * mem::size_of::<HeapCellValue>();
|
||||
let ptr = self.buf.top as usize - (index + 1) * mem::size_of::<HeapCellValue>();
|
||||
&*(ptr as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
@@ -455,8 +448,9 @@ impl<T: RawBlockTraits> IndexMut<usize> for HeapTemplate<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + index * mem::size_of::<HeapCellValue>();
|
||||
let ptr = self.buf.top as usize - (index + 1) * mem::size_of::<HeapCellValue>();
|
||||
&mut *(ptr as *mut HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,53 +1,43 @@
|
||||
use prolog_parser::ast::*;
|
||||
use prolog_parser::clause_name;
|
||||
use crate::parser::ast::*;
|
||||
|
||||
use crate::arena::*;
|
||||
use crate::atom_table::*;
|
||||
use crate::clause_types::*;
|
||||
use crate::fixtures::*;
|
||||
use crate::forms::*;
|
||||
use crate::instructions::*;
|
||||
|
||||
use crate::machine::code_repo::CodeRepo;
|
||||
use crate::machine::heap::*;
|
||||
use crate::machine::loader::*;
|
||||
use crate::machine::machine_errors::MachineStub;
|
||||
use crate::machine::machine_state::*;
|
||||
use crate::machine::partial_string::*;
|
||||
use crate::machine::raw_block::RawBlockTraits;
|
||||
use crate::machine::streams::Stream;
|
||||
use crate::machine::term_stream::LoadStatePayload;
|
||||
use crate::machine::CompilationTarget;
|
||||
use crate::rug::{Integer, Rational};
|
||||
use ordered_float::OrderedFloat;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::convert::TryFrom;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
// use std::mem;
|
||||
use std::net::TcpListener;
|
||||
use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::types::*;
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) struct OrderedOpDirKey(pub(crate) ClauseName, pub(crate) Fixity);
|
||||
pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
|
||||
|
||||
pub(crate) type OssifiedOpDir = BTreeMap<OrderedOpDirKey, (usize, Specifier)>;
|
||||
pub(crate) type OssifiedOpDir = IndexMap<(Atom, Fixity), (usize, Specifier)>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum DBRef {
|
||||
NamedPred(ClauseName, usize, Option<SharedOpDesc>),
|
||||
Op(
|
||||
usize,
|
||||
Specifier,
|
||||
ClauseName,
|
||||
Rc<OssifiedOpDir>,
|
||||
SharedOpDesc,
|
||||
),
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum DBRef {
|
||||
NamedPred(Atom, usize),
|
||||
Op(Atom, Fixity, TypedArenaPtr<OssifiedOpDir>),
|
||||
}
|
||||
|
||||
// 7.2
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub(crate) enum TermOrderCategory {
|
||||
pub enum TermOrderCategory {
|
||||
Variable,
|
||||
FloatingPoint,
|
||||
Integer,
|
||||
@@ -55,43 +45,95 @@ pub(crate) enum TermOrderCategory {
|
||||
Compound,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum Addr {
|
||||
AttrVar(usize),
|
||||
Char(char),
|
||||
Con(usize),
|
||||
CutPoint(usize),
|
||||
EmptyList,
|
||||
Fixnum(isize),
|
||||
Float(OrderedFloat<f64>),
|
||||
Lis(usize),
|
||||
LoadStatePayload(usize),
|
||||
HeapCell(usize),
|
||||
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
||||
StackCell(usize, usize),
|
||||
Str(usize),
|
||||
Stream(usize),
|
||||
TcpListener(usize),
|
||||
Usize(usize),
|
||||
}
|
||||
// the position-dependent heap template:
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd)]
|
||||
pub(crate) enum Ref {
|
||||
AttrVar(usize),
|
||||
HeapCell(usize),
|
||||
StackCell(usize, usize),
|
||||
}
|
||||
/*
|
||||
read_heap_cell!(
|
||||
(HeapCellValueTag::AttrVar, n) => {
|
||||
}
|
||||
(HeapCellValueTag::Lis, n) => {
|
||||
}
|
||||
(HeapCellValueTag::Var, n) => {
|
||||
}
|
||||
(HeapCellValueTag::Str, n) => {
|
||||
}
|
||||
(HeapCellValueTag::PStrOffset, n) => {
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
)
|
||||
*/
|
||||
|
||||
impl Ref {
|
||||
pub(crate) fn as_addr(self) -> Addr {
|
||||
match self {
|
||||
Ref::AttrVar(h) => Addr::AttrVar(h),
|
||||
Ref::HeapCell(h) => Addr::HeapCell(h),
|
||||
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
|
||||
}
|
||||
impl PartialEq<Ref> for HeapCellValue {
|
||||
fn eq(&self, r: &Ref) -> bool {
|
||||
self.as_var() == Some(*r)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<Ref> for HeapCellValue {
|
||||
fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
|
||||
read_heap_cell!(*self,
|
||||
(HeapCellValueTag::StackVar, s1) => {
|
||||
match r.get_tag() {
|
||||
RefTag::StackCell => {
|
||||
let s2 = r.get_value() as usize;
|
||||
s1.partial_cmp(&s2)
|
||||
}
|
||||
_ => Some(Ordering::Greater),
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h1) => {
|
||||
match r.get_tag() {
|
||||
RefTag::StackCell => Some(Ordering::Less),
|
||||
_ => {
|
||||
let h2 = r.get_value() as usize;
|
||||
h1.partial_cmp(&h2)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
/*
|
||||
impl HeapCellValue {
|
||||
#[inline]
|
||||
pub fn as_constant_index(self, machine_st: &MachineState) -> Option<Literal> {
|
||||
read_heap_cell!(self,
|
||||
(HeapCellValueTag::Char, c) => Some(Literal::Char(c)),
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
if arity == 0 {
|
||||
Some(Literal::Atom(name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Fixnum, n) => {
|
||||
Some(Literal::Fixnum(n))
|
||||
}
|
||||
(HeapCellValueTag::F64, f) => {
|
||||
Some(Literal::Float(f))
|
||||
}
|
||||
(HeapCellValueTag::Cons, ptr) => {
|
||||
match_untyped_arena_ptr!(ptr,
|
||||
(ArenaHeaderTag::Integer, n) => {
|
||||
Some(Literal::Integer(n))
|
||||
}
|
||||
(ArenaHeaderTag::Rational, r) => {
|
||||
Some(Literal::Rational(r))
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
impl Ord for Ref {
|
||||
fn cmp(&self, other: &Ref) -> Ordering {
|
||||
match (self, other) {
|
||||
@@ -114,31 +156,6 @@ impl PartialEq<Ref> for Addr {
|
||||
}
|
||||
}
|
||||
|
||||
// for use crate::in MachineState::bind.
|
||||
impl PartialOrd<Ref> for Addr {
|
||||
fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
|
||||
match self {
|
||||
&Addr::StackCell(fr, sc) => match *r {
|
||||
Ref::AttrVar(_) | Ref::HeapCell(_) => Some(Ordering::Greater),
|
||||
Ref::StackCell(fr1, sc1) => {
|
||||
if fr1 < fr || (fr1 == fr && sc1 < sc) {
|
||||
Some(Ordering::Greater)
|
||||
} else if fr1 == fr && sc1 == sc {
|
||||
Some(Ordering::Equal)
|
||||
} else {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
}
|
||||
},
|
||||
&Addr::HeapCell(h) | &Addr::AttrVar(h) => match r {
|
||||
Ref::StackCell(..) => Some(Ordering::Less),
|
||||
Ref::AttrVar(h1) | Ref::HeapCell(h1) => h.partial_cmp(h1),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Addr {
|
||||
#[inline]
|
||||
pub(crate) fn is_heap_bound(&self) -> bool {
|
||||
@@ -171,57 +188,6 @@ impl Addr {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
|
||||
match Number::try_from((*self, heap)) {
|
||||
Ok(Number::Integer(_)) | Ok(Number::Fixnum(_)) | Ok(Number::Rational(_)) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
Ok(Number::Float(_)) => Some(TermOrderCategory::FloatingPoint),
|
||||
_ => match self {
|
||||
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
|
||||
Some(TermOrderCategory::Variable)
|
||||
}
|
||||
Addr::Float(_) => Some(TermOrderCategory::FloatingPoint),
|
||||
&Addr::Con(h) => match &heap[h] {
|
||||
HeapCellValue::Atom(..) => Some(TermOrderCategory::Atom),
|
||||
HeapCellValue::DBRef(_) => None,
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
Addr::Char(_) | Addr::EmptyList => Some(TermOrderCategory::Atom),
|
||||
Addr::Fixnum(_) | Addr::Usize(_) => Some(TermOrderCategory::Integer),
|
||||
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||
Some(TermOrderCategory::Compound)
|
||||
}
|
||||
Addr::CutPoint(_)
|
||||
| Addr::LoadStatePayload(_)
|
||||
| Addr::Stream(_)
|
||||
| Addr::TcpListener(_) => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn as_constant_index(&self, machine_st: &MachineState) -> Option<Constant> {
|
||||
match self {
|
||||
&Addr::Char(c) => Some(Constant::Char(c)),
|
||||
&Addr::Con(h) => match &machine_st.heap[h] {
|
||||
&HeapCellValue::Atom(ref name, _) if name.is_char() => {
|
||||
Some(Constant::Char(name.as_str().chars().next().unwrap()))
|
||||
}
|
||||
&HeapCellValue::Atom(ref name, _) => Some(Constant::Atom(name.clone(), None)),
|
||||
&HeapCellValue::Integer(ref n) => Some(Constant::Integer(n.clone())),
|
||||
&HeapCellValue::Rational(ref n) => Some(Constant::Rational(n.clone())),
|
||||
_ => None,
|
||||
},
|
||||
&Addr::EmptyList => Some(Constant::EmptyList),
|
||||
&Addr::Fixnum(n) => Some(Constant::Fixnum(n)),
|
||||
&Addr::Float(f) => Some(Constant::Float(f)),
|
||||
&Addr::Usize(n) => Some(Constant::Usize(n)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_protected(&self, e: usize) -> bool {
|
||||
match self {
|
||||
&Addr::StackCell(addr, _) if addr >= e => false,
|
||||
@@ -230,61 +196,6 @@ impl Addr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Addr {
|
||||
type Output = Addr;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
match self {
|
||||
Addr::Stream(h) => Addr::Stream(h + rhs),
|
||||
Addr::Con(h) => Addr::Con(h + rhs),
|
||||
Addr::Lis(a) => Addr::Lis(a + rhs),
|
||||
Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
|
||||
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
|
||||
Addr::Str(s) => Addr::Str(s + rhs),
|
||||
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs, n),
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<i64> for Addr {
|
||||
type Output = Addr;
|
||||
|
||||
fn sub(self, rhs: i64) -> Self::Output {
|
||||
if rhs < 0 {
|
||||
match self {
|
||||
Addr::Stream(h) => Addr::Stream(h + rhs.abs() as usize),
|
||||
Addr::Con(h) => Addr::Con(h + rhs.abs() as usize),
|
||||
Addr::Lis(a) => Addr::Lis(a + rhs.abs() as usize),
|
||||
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
|
||||
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
|
||||
Addr::Str(s) => Addr::Str(s + rhs.abs() as usize),
|
||||
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs.abs() as usize, n),
|
||||
_ => self,
|
||||
}
|
||||
} else {
|
||||
self.sub(rhs as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<usize> for Addr {
|
||||
type Output = Addr;
|
||||
|
||||
fn sub(self, rhs: usize) -> Self::Output {
|
||||
match self {
|
||||
Addr::Stream(h) => Addr::Stream(h - rhs),
|
||||
Addr::Con(h) => Addr::Con(h - rhs),
|
||||
Addr::Lis(a) => Addr::Lis(a - rhs),
|
||||
Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
|
||||
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
|
||||
Addr::Str(s) => Addr::Str(s - rhs),
|
||||
Addr::PStrLocation(h, n) => Addr::PStrLocation(h - rhs, n),
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<usize> for Addr {
|
||||
fn sub_assign(&mut self, rhs: usize) {
|
||||
*self = self.clone() - rhs;
|
||||
@@ -305,72 +216,9 @@ impl From<Ref> for TrailRef {
|
||||
TrailRef::Ref(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum HeapCellValue {
|
||||
Addr(Addr),
|
||||
Atom(ClauseName, Option<SharedOpDesc>),
|
||||
DBRef(DBRef),
|
||||
Integer(Rc<Integer>),
|
||||
LoadStatePayload(Box<LoadStatePayload>),
|
||||
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
||||
Rational(Rc<Rational>),
|
||||
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
|
||||
Stream(Stream),
|
||||
TcpListener(TcpListener),
|
||||
}
|
||||
|
||||
impl HeapCellValue {
|
||||
#[inline]
|
||||
pub(crate) fn as_addr(&self, focus: usize) -> Addr {
|
||||
match self {
|
||||
HeapCellValue::Addr(ref a) => *a,
|
||||
HeapCellValue::Atom(..)
|
||||
| HeapCellValue::DBRef(..)
|
||||
| HeapCellValue::Integer(..)
|
||||
| HeapCellValue::Rational(..) => Addr::Con(focus),
|
||||
HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(focus),
|
||||
HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus),
|
||||
HeapCellValue::PartialString(..) => Addr::PStrLocation(focus, 0),
|
||||
HeapCellValue::Stream(_) => Addr::Stream(focus),
|
||||
HeapCellValue::TcpListener(_) => Addr::TcpListener(focus),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn context_free_clone(&self) -> HeapCellValue {
|
||||
match self {
|
||||
&HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr),
|
||||
&HeapCellValue::Atom(ref name, ref op) => HeapCellValue::Atom(name.clone(), op.clone()),
|
||||
&HeapCellValue::DBRef(ref db_ref) => HeapCellValue::DBRef(db_ref.clone()),
|
||||
&HeapCellValue::Integer(ref n) => HeapCellValue::Integer(n.clone()),
|
||||
&HeapCellValue::LoadStatePayload(_) => {
|
||||
HeapCellValue::Atom(clause_name!("$live_term_stream"), None)
|
||||
}
|
||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||
}
|
||||
&HeapCellValue::Rational(ref r) => HeapCellValue::Rational(r.clone()),
|
||||
&HeapCellValue::PartialString(ref pstr, has_tail) => {
|
||||
HeapCellValue::PartialString(pstr.clone(), has_tail)
|
||||
}
|
||||
&HeapCellValue::Stream(ref stream) => HeapCellValue::Stream(stream.clone()),
|
||||
&HeapCellValue::TcpListener(_) => {
|
||||
HeapCellValue::Atom(clause_name!("$tcp_listener"), None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Addr> for HeapCellValue {
|
||||
#[inline]
|
||||
fn from(value: Addr) -> HeapCellValue {
|
||||
HeapCellValue::Addr(value)
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub(crate) enum IndexPtr {
|
||||
pub enum IndexPtr {
|
||||
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||
DynamicIndex(usize),
|
||||
Index(usize),
|
||||
@@ -378,7 +226,7 @@ pub(crate) enum IndexPtr {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub(crate) struct CodeIndex(pub(crate) Rc<Cell<IndexPtr>>);
|
||||
pub struct CodeIndex(pub(crate) Rc<Cell<IndexPtr>>);
|
||||
|
||||
impl Deref for CodeIndex {
|
||||
type Target = Cell<IndexPtr>;
|
||||
@@ -419,7 +267,7 @@ impl Default for CodeIndex {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub(crate) enum REPLCodePtr {
|
||||
pub enum REPLCodePtr {
|
||||
AddDiscontiguousPredicate,
|
||||
AddDynamicPredicate,
|
||||
AddMultifilePredicate,
|
||||
@@ -456,12 +304,11 @@ pub(crate) enum REPLCodePtr {
|
||||
AddNonCountedBacktracking,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(crate) enum CodePtr {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum CodePtr {
|
||||
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
||||
CallN(usize, LocalCodePtr, bool), // arity, local, last call.
|
||||
Local(LocalCodePtr),
|
||||
// DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
|
||||
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
|
||||
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
|
||||
}
|
||||
@@ -488,7 +335,7 @@ impl CodePtr {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub(crate) enum LocalCodePtr {
|
||||
pub enum LocalCodePtr {
|
||||
DirEntry(usize), // offset
|
||||
Halt,
|
||||
IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset
|
||||
@@ -496,7 +343,7 @@ pub(crate) enum LocalCodePtr {
|
||||
}
|
||||
|
||||
impl LocalCodePtr {
|
||||
pub(crate) fn assign_if_local(&mut self, cp: CodePtr) {
|
||||
pub fn assign_if_local(&mut self, cp: CodePtr) {
|
||||
match cp {
|
||||
CodePtr::Local(local) => *self = local,
|
||||
_ => {}
|
||||
@@ -504,7 +351,7 @@ impl LocalCodePtr {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn abs_loc(&self) -> usize {
|
||||
pub fn abs_loc(&self) -> usize {
|
||||
match self {
|
||||
LocalCodePtr::DirEntry(ref p) => *p,
|
||||
LocalCodePtr::IndexingBuf(ref p, ..) => *p,
|
||||
@@ -528,33 +375,21 @@ impl LocalCodePtr {
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn as_functor<T: RawBlockTraits>(&self, heap: &mut HeapTemplate<T>) -> Addr {
|
||||
let addr = Addr::HeapCell(heap.h());
|
||||
|
||||
pub(crate) fn as_functor(&self) -> MachineStub {
|
||||
match self {
|
||||
LocalCodePtr::DirEntry(p) => {
|
||||
heap.append(functor!("dir_entry", [integer(*p)]));
|
||||
functor!(atom!("dir_entry"), [fixnum(*p)])
|
||||
}
|
||||
LocalCodePtr::Halt => {
|
||||
heap.append(functor!("halt"));
|
||||
functor!(atom!("halt"))
|
||||
}
|
||||
/*
|
||||
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
||||
heap.append(functor!(
|
||||
"top_level",
|
||||
[integer(*chunk_num), integer(*offset)]
|
||||
));
|
||||
}
|
||||
*/
|
||||
LocalCodePtr::IndexingBuf(p, o, i) => {
|
||||
heap.append(functor!(
|
||||
"indexed_buf",
|
||||
[integer(*p), integer(*o), integer(*i)]
|
||||
));
|
||||
functor!(
|
||||
atom!("indexed_buf"),
|
||||
[fixnum(*p), fixnum(*o), fixnum(*i)]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,9 +449,8 @@ impl AddAssign<usize> for LocalCodePtr {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
match self {
|
||||
&mut LocalCodePtr::DirEntry(ref mut p) /* |
|
||||
&mut LocalCodePtr::TopLevel(_, ref mut p) */ => *p += rhs,
|
||||
&mut LocalCodePtr::IndexingBuf(_, _, ref mut i) => *i += rhs,
|
||||
&mut LocalCodePtr::DirEntry(ref mut i)
|
||||
| &mut LocalCodePtr::IndexingBuf(_, _, ref mut i) => *i += rhs,
|
||||
&mut LocalCodePtr::Halt => unreachable!(),
|
||||
}
|
||||
}
|
||||
@@ -627,11 +461,7 @@ impl Add<usize> for CodePtr {
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
match self {
|
||||
p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => {
|
||||
// |
|
||||
// p @ CodePtr::DynamicTransaction(..) => {
|
||||
p
|
||||
}
|
||||
p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => p,
|
||||
CodePtr::Local(local) => CodePtr::Local(local + rhs),
|
||||
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
|
||||
CodePtr::Local(local + rhs)
|
||||
@@ -660,12 +490,12 @@ impl SubAssign<usize> for CodePtr {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
||||
pub(crate) type AllocVarDict = IndexMap<Rc<Var>, VarData>;
|
||||
pub(crate) type HeapVarDict = IndexMap<Rc<String>, HeapCellValue>;
|
||||
pub(crate) type AllocVarDict = IndexMap<Rc<String>, VarData>;
|
||||
|
||||
pub(crate) type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<Addr>)>;
|
||||
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>)>;
|
||||
|
||||
pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
|
||||
pub(crate) type StreamAliasDir = IndexMap<Atom, Stream>;
|
||||
pub(crate) type StreamDir = BTreeSet<Stream>;
|
||||
|
||||
pub(crate) type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>>;
|
||||
@@ -676,7 +506,7 @@ pub(crate) type LocalExtensiblePredicates =
|
||||
IndexMap<(CompilationTarget, PredicateKey), LocalPredicateSkeleton>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct IndexStore {
|
||||
pub struct IndexStore {
|
||||
pub(super) code_dir: CodeDir,
|
||||
pub(super) extensible_predicates: ExtensiblePredicates,
|
||||
pub(super) local_extensible_predicates: LocalExtensiblePredicates,
|
||||
@@ -688,31 +518,21 @@ pub(crate) struct IndexStore {
|
||||
pub(super) stream_aliases: StreamAliasDir,
|
||||
}
|
||||
|
||||
impl Default for IndexStore {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexStore {
|
||||
pub(crate) fn get_predicate_skeleton_mut(
|
||||
&mut self,
|
||||
compilation_target: &CompilationTarget,
|
||||
key: &PredicateKey,
|
||||
) -> Option<&mut PredicateSkeleton> {
|
||||
match (key.0.as_str(), key.1) {
|
||||
// ("term_expansion", 2) => self.extensible_predicates.get_mut(key),
|
||||
_ => match compilation_target {
|
||||
CompilationTarget::User => self.extensible_predicates.get_mut(key),
|
||||
CompilationTarget::Module(ref module_name) => {
|
||||
if let Some(module) = self.modules.get_mut(module_name) {
|
||||
module.extensible_predicates.get_mut(key)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
match compilation_target {
|
||||
CompilationTarget::User => self.extensible_predicates.get_mut(key),
|
||||
CompilationTarget::Module(ref module_name) => {
|
||||
if let Some(module) = self.modules.get_mut(module_name) {
|
||||
module.extensible_predicates.get_mut(key)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,7 +557,7 @@ impl IndexStore {
|
||||
&mut self,
|
||||
mut src_compilation_target: CompilationTarget,
|
||||
local_compilation_target: CompilationTarget,
|
||||
listing_src_file_name: Option<ClauseName>,
|
||||
listing_src_file_name: Option<Atom>,
|
||||
key: PredicateKey,
|
||||
) -> Option<&mut LocalPredicateSkeleton> {
|
||||
if let Some(filename) = listing_src_file_name {
|
||||
@@ -748,8 +568,8 @@ impl IndexStore {
|
||||
CompilationTarget::User => self
|
||||
.local_extensible_predicates
|
||||
.get_mut(&(local_compilation_target, key)),
|
||||
CompilationTarget::Module(ref module_name) => {
|
||||
if let Some(module) = self.modules.get_mut(module_name) {
|
||||
CompilationTarget::Module(module_name) => {
|
||||
if let Some(module) = self.modules.get_mut(&module_name) {
|
||||
module
|
||||
.local_extensible_predicates
|
||||
.get_mut(&(local_compilation_target, key))
|
||||
@@ -764,7 +584,7 @@ impl IndexStore {
|
||||
&self,
|
||||
mut src_compilation_target: CompilationTarget,
|
||||
local_compilation_target: CompilationTarget,
|
||||
listing_src_file_name: Option<ClauseName>,
|
||||
listing_src_file_name: Option<Atom>,
|
||||
key: PredicateKey,
|
||||
) -> Option<&LocalPredicateSkeleton> {
|
||||
if let Some(filename) = listing_src_file_name {
|
||||
@@ -775,8 +595,8 @@ impl IndexStore {
|
||||
CompilationTarget::User => self
|
||||
.local_extensible_predicates
|
||||
.get(&(local_compilation_target, key)),
|
||||
CompilationTarget::Module(ref module_name) => {
|
||||
if let Some(module) = self.modules.get(module_name) {
|
||||
CompilationTarget::Module(module_name) => {
|
||||
if let Some(module) = self.modules.get(&module_name) {
|
||||
module
|
||||
.local_extensible_predicates
|
||||
.get(&(local_compilation_target, key))
|
||||
@@ -806,35 +626,30 @@ impl IndexStore {
|
||||
|
||||
pub(crate) fn get_predicate_code_index(
|
||||
&self,
|
||||
name: ClauseName,
|
||||
name: Atom,
|
||||
arity: usize,
|
||||
module: ClauseName,
|
||||
op_spec: Option<SharedOpDesc>,
|
||||
module: Atom,
|
||||
) -> Option<CodeIndex> {
|
||||
if module.as_str() == "user" {
|
||||
match ClauseType::from(name, arity, op_spec) {
|
||||
if module == atom!("user") {
|
||||
match ClauseType::from(name, arity) {
|
||||
ClauseType::Named(name, arity, _) => self.code_dir.get(&(name, arity)).cloned(),
|
||||
ClauseType::Op(name, spec, ..) => self.code_dir.get(&(name, spec.arity())).cloned(),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
self.modules.get(&module).and_then(|module| {
|
||||
match ClauseType::from(name, arity, op_spec) {
|
||||
self.modules
|
||||
.get(&module)
|
||||
.and_then(|module| match ClauseType::from(name, arity) {
|
||||
ClauseType::Named(name, arity, _) => {
|
||||
module.code_dir.get(&(name, arity)).cloned()
|
||||
}
|
||||
ClauseType::Op(name, spec, ..) => {
|
||||
module.code_dir.get(&(name, spec.arity())).cloned()
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_meta_predicate_spec(
|
||||
&self,
|
||||
name: ClauseName,
|
||||
name: Atom,
|
||||
arity: usize,
|
||||
compilation_target: &CompilationTarget,
|
||||
) -> Option<&Vec<MetaSpec>> {
|
||||
@@ -850,9 +665,13 @@ impl IndexStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_dynamic_predicate(&self, module_name: ClauseName, key: PredicateKey) -> bool {
|
||||
match module_name.as_str() {
|
||||
"user" => self
|
||||
pub(crate) fn is_dynamic_predicate(
|
||||
&self,
|
||||
module_name: Atom,
|
||||
key: PredicateKey,
|
||||
) -> bool {
|
||||
match module_name {
|
||||
atom!("user") => self
|
||||
.extensible_predicates
|
||||
.get(&key)
|
||||
.map(|skeleton| skeleton.core.is_dynamic)
|
||||
@@ -870,19 +689,19 @@ impl IndexStore {
|
||||
|
||||
#[inline]
|
||||
pub(super) fn new() -> Self {
|
||||
IndexStore::default()
|
||||
index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
|
||||
}
|
||||
|
||||
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
||||
let iso_ext = clause_name!("iso_ext");
|
||||
let r_w_h = atom!("run_cleaners_with_handling");
|
||||
let r_wo_h = atom!("run_cleaners_without_handling");
|
||||
let iso_ext = atom!("iso_ext");
|
||||
|
||||
let r_w_h = self
|
||||
.get_predicate_code_index(r_w_h, 0, iso_ext.clone(), None)
|
||||
.get_predicate_code_index(r_w_h, 0, iso_ext)
|
||||
.and_then(|item| item.local());
|
||||
let r_wo_h = self
|
||||
.get_predicate_code_index(r_wo_h, 1, iso_ext, None)
|
||||
.get_predicate_code_index(r_wo_h, 1, iso_ext)
|
||||
.and_then(|item| item.local());
|
||||
|
||||
if let Some(r_w_h) = r_w_h {
|
||||
@@ -895,7 +714,7 @@ impl IndexStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type CodeDir = BTreeMap<PredicateKey, CodeIndex>;
|
||||
pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex>;
|
||||
|
||||
pub(crate) enum RefOrOwned<'a, T: 'a> {
|
||||
Borrowed(&'a T),
|
||||
@@ -918,14 +737,4 @@ impl<'a, T> RefOrOwned<'a, T> {
|
||||
&RefOrOwned::Owned(ref r) => r,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_owned(self) -> T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
match self {
|
||||
RefOrOwned::Borrowed(item) => item.clone(),
|
||||
RefOrOwned::Owned(item) => item,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
766
src/machine/mock_wam.rs
Normal file
766
src/machine/mock_wam.rs
Normal file
@@ -0,0 +1,766 @@
|
||||
pub use crate::arena::*;
|
||||
pub use crate::atom_table::*;
|
||||
use crate::heap_print::*;
|
||||
pub use crate::machine::heap::*;
|
||||
pub use crate::machine::Machine;
|
||||
pub use crate::machine::machine_state::*;
|
||||
pub use crate::machine::stack::*;
|
||||
pub use crate::machine::streams::*;
|
||||
pub use crate::macros::*;
|
||||
pub use crate::parser::ast::*;
|
||||
use crate::read::*;
|
||||
pub use crate::types::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::machine::copier::CopierTarget;
|
||||
|
||||
#[cfg(test)]
|
||||
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
||||
|
||||
// a mini-WAM for test purposes.
|
||||
|
||||
pub struct MockWAM {
|
||||
pub machine_st: MachineState,
|
||||
pub op_dir: OpDir,
|
||||
pub flags: MachineFlags,
|
||||
}
|
||||
|
||||
impl MockWAM {
|
||||
pub fn new() -> Self {
|
||||
let op_dir = default_op_dir();
|
||||
|
||||
Self {
|
||||
machine_st: MachineState::new(),
|
||||
op_dir,
|
||||
flags: MachineFlags::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_parsed_term_to_heap(
|
||||
&mut self,
|
||||
input_stream: Stream,
|
||||
) -> Result<TermWriteResult, ParserError> {
|
||||
self.machine_st.read(input_stream, &self.op_dir)
|
||||
}
|
||||
|
||||
pub fn parse_and_write_parsed_term_to_heap(
|
||||
&mut self,
|
||||
term_string: &'static str,
|
||||
) -> Result<TermWriteResult, ParserError> {
|
||||
let stream = Stream::from_static_string(term_string, &mut self.machine_st.arena);
|
||||
self.write_parsed_term_to_heap(stream)
|
||||
}
|
||||
|
||||
pub fn parse_and_print_term(
|
||||
&mut self,
|
||||
term_string: &'static str,
|
||||
) -> Result<String, ParserError> {
|
||||
let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?;
|
||||
|
||||
print_heap_terms(self.machine_st.heap.iter(), term_write_result.heap_loc);
|
||||
|
||||
let mut printer = HCPrinter::new(
|
||||
&mut self.machine_st.heap,
|
||||
&mut self.machine_st.arena,
|
||||
&self.op_dir,
|
||||
PrinterOutputter::new(),
|
||||
heap_loc_as_cell!(term_write_result.heap_loc),
|
||||
);
|
||||
|
||||
printer.var_names = term_write_result
|
||||
.var_dict
|
||||
.into_iter()
|
||||
.map(|(var, cell)| (cell, var))
|
||||
.collect();
|
||||
|
||||
Ok(printer.print().result())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub struct TermCopyingMockWAM<'a> {
|
||||
pub wam: &'a mut MockWAM,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<'a> Index<usize> for TermCopyingMockWAM<'a> {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
fn index(&self, index: usize) -> &HeapCellValue {
|
||||
&self.wam.machine_st.heap[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<'a> IndexMut<usize> for TermCopyingMockWAM<'a> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: usize) -> &mut HeapCellValue {
|
||||
&mut self.wam.machine_st.heap[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<'a> Deref for TermCopyingMockWAM<'a> {
|
||||
type Target = MockWAM;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.wam
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<'a> DerefMut for TermCopyingMockWAM<'a> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.wam
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
|
||||
fn store(&self, val: HeapCellValue) -> HeapCellValue {
|
||||
read_heap_cell!(val,
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
self.wam.machine_st.heap[h]
|
||||
}
|
||||
(HeapCellValueTag::StackVar, s) => {
|
||||
self.wam.machine_st.stack[s]
|
||||
}
|
||||
_ => {
|
||||
val
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn deref(&self, mut val: HeapCellValue) -> HeapCellValue {
|
||||
loop {
|
||||
let value = self.store(val);
|
||||
|
||||
if value.is_var() && value != val {
|
||||
val = value;
|
||||
continue;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&mut self, val: HeapCellValue) {
|
||||
self.wam.machine_st.heap.push(val);
|
||||
}
|
||||
|
||||
fn stack(&mut self) -> &mut Stack {
|
||||
&mut self.wam.machine_st.stack
|
||||
}
|
||||
|
||||
fn threshold(&self) -> usize {
|
||||
self.wam.machine_st.heap.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn all_cells_marked_and_unforwarded(heap: &[HeapCellValue]) {
|
||||
for (idx, cell) in heap.iter().enumerate() {
|
||||
assert_eq!(
|
||||
cell.get_mark_bit(),
|
||||
true,
|
||||
"cell {:?} at index {} is not marked",
|
||||
cell,
|
||||
idx
|
||||
);
|
||||
assert!(
|
||||
cell.get_forwarding_bit() != Some(true),
|
||||
"cell {:?} at index {} is forwarded",
|
||||
cell,
|
||||
idx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn all_cells_unmarked(heap: &Heap) {
|
||||
for (idx, cell) in heap.iter().enumerate() {
|
||||
assert!(
|
||||
!cell.get_mark_bit(),
|
||||
"cell {:?} at index {} is still marked",
|
||||
cell,
|
||||
idx
|
||||
);
|
||||
|
||||
assert!(
|
||||
cell.get_forwarding_bit() != Some(true),
|
||||
"cell {:?} at index {} is still forwarded",
|
||||
cell,
|
||||
idx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn write_parsed_term_to_heap(
|
||||
machine_st: &mut MachineState,
|
||||
input_stream: Stream,
|
||||
op_dir: &OpDir,
|
||||
) -> Result<TermWriteResult, ParserError> {
|
||||
machine_st.read(input_stream, op_dir)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn parse_and_write_parsed_term_to_heap(
|
||||
machine_st: &mut MachineState,
|
||||
term_string: &'static str,
|
||||
op_dir: &OpDir,
|
||||
) -> Result<TermWriteResult, ParserError> {
|
||||
let stream = Stream::from_static_string(term_string, &mut machine_st.arena);
|
||||
write_parsed_term_to_heap(machine_st, stream, op_dir)
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
pub fn test_load_file(&mut self, file: &str) -> Vec<u8> {
|
||||
use std::io::Read;
|
||||
|
||||
let old_output = std::mem::replace(
|
||||
&mut self.user_output,
|
||||
Stream::from_owned_string("".to_owned(), &mut self.machine_st.arena),
|
||||
);
|
||||
|
||||
let stream = Stream::from_owned_string(
|
||||
std::fs::read_to_string(AsRef::<std::path::Path>::as_ref(file)).unwrap(),
|
||||
&mut self.machine_st.arena,
|
||||
);
|
||||
|
||||
self.load_file(file.into(), stream);
|
||||
|
||||
let output = self.user_output.bytes().map(|b| b.unwrap()).collect();
|
||||
self.user_output = old_output;
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn unify_tests() {
|
||||
let mut wam = MachineState::new();
|
||||
let mut op_dir = default_op_dir();
|
||||
|
||||
op_dir.insert(
|
||||
(atom!("+"), Fixity::In),
|
||||
OpDesc::build_with(500, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("-"), Fixity::In),
|
||||
OpDesc::build_with(500, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("*"), Fixity::In),
|
||||
OpDesc::build_with(500, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("/"), Fixity::In),
|
||||
OpDesc::build_with(400, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("="), Fixity::In),
|
||||
OpDesc::build_with(700, XFX as u8),
|
||||
);
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(b,a).", &op_dir).unwrap();
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
str_loc_as_cell!(0),
|
||||
str_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(b,b).", &op_dir).unwrap();
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
str_loc_as_cell!(1),
|
||||
heap_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),Y).", &op_dir).unwrap();
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
heap_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),Y).", &op_dir).unwrap();
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
heap_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),A).", &op_dir).unwrap();
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
heap_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
heap_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.push(pstr_as_cell!(atom!("this is a string")));
|
||||
wam.heap.push(heap_loc_as_cell!(1));
|
||||
|
||||
wam.heap.push(pstr_as_cell!(atom!("this is a string")));
|
||||
wam.heap.push(pstr_loc_as_cell!(4));
|
||||
|
||||
wam.heap.push(pstr_offset_as_cell!(0));
|
||||
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(6)));
|
||||
|
||||
unify!(wam, pstr_loc_as_cell!(0), pstr_loc_as_cell!(2));
|
||||
|
||||
assert!(!wam.fail);
|
||||
|
||||
assert_eq!(wam.heap[1], pstr_loc_as_cell!(4));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.push(list_loc_as_cell!(1));
|
||||
wam.heap.push(atom_as_cell!(atom!("a")));
|
||||
wam.heap.push(list_loc_as_cell!(3));
|
||||
wam.heap.push(atom_as_cell!(atom!("b")));
|
||||
wam.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
wam.heap.push(list_loc_as_cell!(6));
|
||||
wam.heap.push(atom_as_cell!(atom!("a")));
|
||||
wam.heap.push(list_loc_as_cell!(8));
|
||||
wam.heap.push(atom_as_cell!(atom!("b")));
|
||||
wam.heap.push(heap_loc_as_cell!(5));
|
||||
|
||||
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
|
||||
|
||||
assert!(!wam.fail);
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.push(list_loc_as_cell!(1));
|
||||
wam.heap.push(atom_as_cell!(atom!("a")));
|
||||
wam.heap.push(list_loc_as_cell!(3));
|
||||
wam.heap.push(atom_as_cell!(atom!("b")));
|
||||
wam.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
wam.heap.push(list_loc_as_cell!(6));
|
||||
wam.heap.push(atom_as_cell!(atom!("a")));
|
||||
wam.heap.push(list_loc_as_cell!(8));
|
||||
wam.heap.push(atom_as_cell!(atom!("c")));
|
||||
wam.heap.push(heap_loc_as_cell!(5));
|
||||
|
||||
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
|
||||
|
||||
assert!(wam.fail);
|
||||
|
||||
wam.fail = false;
|
||||
all_cells_unmarked(&wam.heap);
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.push(list_loc_as_cell!(1));
|
||||
wam.heap.push(atom_as_cell!(atom!("a")));
|
||||
wam.heap.push(list_loc_as_cell!(3));
|
||||
wam.heap.push(atom_as_cell!(atom!("b")));
|
||||
wam.heap.push(heap_loc_as_cell!(5));
|
||||
|
||||
wam.heap.push(list_loc_as_cell!(6));
|
||||
wam.heap.push(atom_as_cell!(atom!("a")));
|
||||
wam.heap.push(list_loc_as_cell!(8));
|
||||
wam.heap.push(atom_as_cell!(atom!("b")));
|
||||
wam.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
|
||||
|
||||
assert!(!wam.fail);
|
||||
all_cells_unmarked(&wam.heap);
|
||||
wam.heap.clear();
|
||||
|
||||
{
|
||||
let term_write_result_1 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "X = g(X,y).", &op_dir).unwrap();
|
||||
|
||||
print_heap_terms(wam.heap.iter(), term_write_result_1.heap_loc);
|
||||
|
||||
unify!(wam, heap_loc_as_cell!(2), str_loc_as_cell!(4));
|
||||
|
||||
assert_eq!(wam.heap[2], str_loc_as_cell!(4));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unify_with_occurs_check() {
|
||||
let mut wam = MachineState::new();
|
||||
let mut op_dir = default_op_dir();
|
||||
|
||||
op_dir.insert(
|
||||
(atom!("+"), Fixity::In),
|
||||
OpDesc::build_with(500, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("-"), Fixity::In),
|
||||
OpDesc::build_with(500, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("*"), Fixity::In),
|
||||
OpDesc::build_with(400, YFX as u8),
|
||||
);
|
||||
op_dir.insert(
|
||||
(atom!("/"), Fixity::In),
|
||||
OpDesc::build_with(400, YFX as u8),
|
||||
);
|
||||
|
||||
{
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
|
||||
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
unify_with_occurs_check!(
|
||||
wam,
|
||||
str_loc_as_cell!(0),
|
||||
str_loc_as_cell!(term_write_result_2.heap_loc)
|
||||
);
|
||||
|
||||
assert!(wam.fail);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_term_compare() {
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
let mut wam = MachineState::new();
|
||||
|
||||
wam.heap.push(heap_loc_as_cell!(0));
|
||||
wam.heap.push(heap_loc_as_cell!(1));
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(wam, wam.heap[0], wam.heap[1]),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(wam, wam.heap[1], wam.heap[0]),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(wam, wam.heap[0], wam.heap[0]),
|
||||
Some(Ordering::Equal)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(wam, wam.heap[1], wam.heap[1]),
|
||||
Some(Ordering::Equal)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
atom_as_cell!(atom!("atom")),
|
||||
atom_as_cstr_cell!(atom!("string"))
|
||||
),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
atom_as_cell!(atom!("atom")),
|
||||
atom_as_cell!(atom!("atom"))
|
||||
),
|
||||
Some(Ordering::Equal)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
atom_as_cell!(atom!("atom")),
|
||||
atom_as_cell!(atom!("aaa"))
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
fixnum_as_cell!(Fixnum::build_with(6)),
|
||||
heap_loc_as_cell!(1)
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.push(atom_as_cell!(atom!("f"), 1));
|
||||
wam.heap.push(heap_loc_as_cell!(1));
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
heap_loc_as_cell!(0)
|
||||
),
|
||||
Some(Ordering::Equal)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
atom_as_cell!(atom!("a"))
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
// [1,2,3]
|
||||
wam.heap.push(list_loc_as_cell!(1));
|
||||
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(1)));
|
||||
wam.heap.push(list_loc_as_cell!(3));
|
||||
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(2)));
|
||||
wam.heap.push(list_loc_as_cell!(5));
|
||||
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(3)));
|
||||
wam.heap.push(empty_list_as_cell!());
|
||||
|
||||
// [1,2]
|
||||
wam.heap.push(list_loc_as_cell!(8));
|
||||
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(1)));
|
||||
wam.heap.push(list_loc_as_cell!(10));
|
||||
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(2)));
|
||||
wam.heap.push(empty_list_as_cell!());
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
heap_loc_as_cell!(7),
|
||||
heap_loc_as_cell!(7)
|
||||
),
|
||||
Some(Ordering::Equal)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
heap_loc_as_cell!(0),
|
||||
heap_loc_as_cell!(7)
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
empty_list_as_cell!(),
|
||||
heap_loc_as_cell!(7)
|
||||
),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
empty_list_as_cell!(),
|
||||
fixnum_as_cell!(Fixnum::build_with(1))
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
empty_list_as_cell!(),
|
||||
atom_as_cstr_cell!(atom!("string"))
|
||||
),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
empty_list_as_cell!(),
|
||||
atom_as_cell!(atom!("atom"))
|
||||
),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
atom_as_cell!(atom!("atom")),
|
||||
empty_list_as_cell!()
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
|
||||
let one_p_one = typed_arena_ptr_as_cell!(
|
||||
arena_alloc!(OrderedFloat(1.1), &mut wam.arena)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
one_p_one,
|
||||
fixnum_as_cell!(Fixnum::build_with(1))
|
||||
),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
fixnum_as_cell!(Fixnum::build_with(1)),
|
||||
one_p_one
|
||||
),
|
||||
Some(Ordering::Greater)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_cyclic_term_tests() {
|
||||
let mut wam = MachineState::new();
|
||||
|
||||
assert!(!wam.is_cyclic_term(atom_as_cell!(atom!("f"))));
|
||||
assert!(!wam.is_cyclic_term(fixnum_as_cell!(Fixnum::build_with(555))));
|
||||
|
||||
wam.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(0)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))]));
|
||||
|
||||
assert!(!wam.is_cyclic_term(str_loc_as_cell!(0)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(1)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(2)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap[2] = str_loc_as_cell!(0);
|
||||
|
||||
print_heap_terms(wam.heap.iter(), 0);
|
||||
|
||||
assert!(wam.is_cyclic_term(str_loc_as_cell!(0)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap[2] = atom_as_cell!(atom!("b"));
|
||||
wam.heap[1] = str_loc_as_cell!(0);
|
||||
|
||||
assert!(wam.is_cyclic_term(str_loc_as_cell!(0)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
assert!(wam.is_cyclic_term(heap_loc_as_cell!(1)));
|
||||
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
wam.heap.push(pstr_as_cell!(atom!("a string")));
|
||||
wam.heap.push(empty_list_as_cell!());
|
||||
|
||||
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(0)));
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,70 @@
|
||||
use prolog_parser::ast::*;
|
||||
use prolog_parser::tabled_rc::*;
|
||||
use prolog_parser::{clause_name, temp_v};
|
||||
pub mod arithmetic_ops;
|
||||
pub mod attributed_variables;
|
||||
pub mod code_repo;
|
||||
pub mod code_walker;
|
||||
#[macro_use]
|
||||
pub mod loader;
|
||||
pub mod compile;
|
||||
pub mod copier;
|
||||
pub mod gc;
|
||||
pub mod heap;
|
||||
pub mod load_state;
|
||||
pub mod machine_errors;
|
||||
pub mod machine_indices;
|
||||
pub mod machine_state;
|
||||
pub mod machine_state_impl;
|
||||
pub mod mock_wam;
|
||||
pub mod partial_string;
|
||||
pub mod preprocessor;
|
||||
pub mod stack;
|
||||
pub mod streams;
|
||||
pub mod system_calls;
|
||||
pub mod term_stream;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::clause_types::*;
|
||||
use crate::atom_table::*;
|
||||
use crate::forms::*;
|
||||
use crate::instructions::*;
|
||||
use crate::machine::loader::*;
|
||||
use crate::machine::term_stream::{LiveTermStream, LoadStatePayload, TermStream};
|
||||
use crate::read::*;
|
||||
|
||||
mod attributed_variables;
|
||||
pub(super) mod code_repo;
|
||||
pub(crate) mod code_walker;
|
||||
#[macro_use]
|
||||
pub(crate) mod loader;
|
||||
mod compile;
|
||||
mod copier;
|
||||
pub(crate) mod heap;
|
||||
mod load_state;
|
||||
pub(crate) mod machine_errors;
|
||||
pub(crate) mod machine_indices;
|
||||
pub(super) mod machine_state;
|
||||
pub(crate) mod partial_string;
|
||||
mod preprocessor;
|
||||
mod raw_block;
|
||||
mod stack;
|
||||
pub(crate) mod streams;
|
||||
mod term_stream;
|
||||
|
||||
#[macro_use]
|
||||
mod arithmetic_ops;
|
||||
#[macro_use]
|
||||
mod machine_state_impl;
|
||||
mod system_calls;
|
||||
|
||||
use crate::machine::code_repo::*;
|
||||
use crate::machine::compile::*;
|
||||
use crate::machine::heap::*;
|
||||
use crate::machine::loader::*;
|
||||
use crate::machine::machine_errors::*;
|
||||
use crate::machine::machine_indices::*;
|
||||
use crate::machine::machine_state::*;
|
||||
pub use crate::machine::streams::Stream;
|
||||
use crate::machine::streams::*;
|
||||
use crate::types::*;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
//use std::convert::TryFrom;
|
||||
use prolog_parser::ast::ClauseName;
|
||||
use std::fs::File;
|
||||
use std::mem;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Machine {
|
||||
pub(super) machine_st: MachineState,
|
||||
pub(super) inner_heap: Heap,
|
||||
pub(super) policies: MachinePolicies,
|
||||
pub(super) indices: IndexStore,
|
||||
pub(super) code_repo: CodeRepo,
|
||||
pub(super) user_input: Stream,
|
||||
pub(super) user_output: Stream,
|
||||
pub(super) user_error: Stream,
|
||||
pub(super) load_contexts: Vec<LoadContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MachinePolicies {
|
||||
call_policy: Box<dyn CallPolicy>,
|
||||
cut_policy: Box<dyn CutPolicy>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
||||
}
|
||||
|
||||
impl MachinePolicies {
|
||||
#[inline]
|
||||
fn new() -> Self {
|
||||
@@ -80,10 +83,10 @@ impl Default for MachinePolicies {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct LoadContext {
|
||||
pub struct LoadContext {
|
||||
pub(super) path: PathBuf,
|
||||
pub(super) stream: Stream,
|
||||
pub(super) module: ClauseName,
|
||||
pub(super) module: Atom,
|
||||
}
|
||||
|
||||
impl LoadContext {
|
||||
@@ -100,32 +103,49 @@ impl LoadContext {
|
||||
LoadContext {
|
||||
path: path_buf,
|
||||
stream,
|
||||
module: clause_name!("user"),
|
||||
module: atom!("user"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Machine {
|
||||
pub(super) machine_st: MachineState,
|
||||
pub(super) policies: MachinePolicies,
|
||||
pub(super) indices: IndexStore,
|
||||
pub(super) code_repo: CodeRepo,
|
||||
pub(super) user_input: Stream,
|
||||
pub(super) user_output: Stream,
|
||||
pub(super) user_error: Stream,
|
||||
pub(super) load_contexts: Vec<LoadContext>,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_dir() -> PathBuf {
|
||||
std::env::current_dir().unwrap_or(PathBuf::from("./"))
|
||||
env::current_dir().unwrap_or(PathBuf::from("./"))
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/libraries.rs"));
|
||||
|
||||
pub struct MachinePreludeView<'a> {
|
||||
pub indices: &'a mut IndexStore,
|
||||
pub code_repo: &'a mut CodeRepo,
|
||||
pub load_contexts: &'a mut Vec<LoadContext>,
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
fn run_module_predicate(&mut self, module_name: ClauseName, key: PredicateKey) {
|
||||
#[inline]
|
||||
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
|
||||
(
|
||||
MachinePreludeView {
|
||||
indices: &mut self.indices,
|
||||
code_repo: &mut self.code_repo,
|
||||
load_contexts: &mut self.load_contexts,
|
||||
},
|
||||
&mut self.machine_st
|
||||
)
|
||||
}
|
||||
|
||||
pub fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
|
||||
let err = self.machine_st.session_error(err);
|
||||
let stub = functor_stub(key.0, key.1);
|
||||
let err = self.machine_st.error_form(err, stub);
|
||||
|
||||
self.machine_st.throw_exception(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
fn run_module_predicate(&mut self, module_name: Atom, key: PredicateKey) {
|
||||
if let Some(module) = self.indices.modules.get(&module_name) {
|
||||
if let Some(ref code_index) = module.code_dir.get(&key) {
|
||||
let p = code_index.local().unwrap();
|
||||
@@ -140,27 +160,29 @@ impl Machine {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
pub fn load_file(&mut self, path: String, stream: Stream) {
|
||||
self.machine_st[temp_v!(1)] =
|
||||
Addr::Stream(self.machine_st.heap.push(HeapCellValue::Stream(stream)));
|
||||
pub fn load_file(&mut self, path: &str, stream: Stream) {
|
||||
self.machine_st.registers[1] = stream_as_cell!(stream);
|
||||
self.machine_st.registers[2] = atom_as_cell!(
|
||||
self.machine_st.atom_tbl.build_with(path)
|
||||
);
|
||||
|
||||
self.machine_st[temp_v!(2)] = Addr::Con(self.machine_st.heap.push(HeapCellValue::Atom(
|
||||
clause_name!(path, self.machine_st.atom_tbl),
|
||||
None,
|
||||
)));
|
||||
|
||||
self.run_module_predicate(clause_name!("loader"), (clause_name!("file_load"), 2));
|
||||
self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2));
|
||||
}
|
||||
|
||||
fn load_top_level(&mut self) {
|
||||
let mut path_buf = current_dir();
|
||||
path_buf.push("toplevel.pl");
|
||||
|
||||
let path = path_buf.to_str().unwrap().to_string();
|
||||
path_buf.push("src/toplevel.pl");
|
||||
|
||||
self.load_file(path, Stream::from(include_str!("../toplevel.pl")));
|
||||
let path = path_buf.to_str().unwrap();
|
||||
let toplevel_stream = Stream::from_static_string(
|
||||
include_str!("../toplevel.pl"),
|
||||
&mut self.machine_st.arena,
|
||||
);
|
||||
|
||||
if let Some(toplevel) = self.indices.modules.get(&clause_name!("$toplevel")) {
|
||||
self.load_file(path, toplevel_stream);
|
||||
|
||||
if let Some(toplevel) = self.indices.modules.get(&atom!("$toplevel")) {
|
||||
load_module(
|
||||
&mut self.indices.code_dir,
|
||||
&mut self.indices.op_dir,
|
||||
@@ -178,9 +200,15 @@ impl Machine {
|
||||
path_buf.push("machine/attributed_variables.pl");
|
||||
|
||||
bootstrapping_compile(
|
||||
Stream::from(include_str!("attributed_variables.pl")),
|
||||
Stream::from_static_string(
|
||||
include_str!("attributed_variables.pl"),
|
||||
&mut self.machine_st.arena,
|
||||
),
|
||||
self,
|
||||
ListingSource::from_file_and_path(clause_name!("attributed_variables"), path_buf),
|
||||
ListingSource::from_file_and_path(
|
||||
atom!("attributed_variables"),
|
||||
path_buf,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -188,44 +216,49 @@ impl Machine {
|
||||
path_buf.push("machine/project_attributes.pl");
|
||||
|
||||
bootstrapping_compile(
|
||||
Stream::from(include_str!("project_attributes.pl")),
|
||||
Stream::from_static_string(
|
||||
include_str!("project_attributes.pl"),
|
||||
&mut self.machine_st.arena,
|
||||
),
|
||||
self,
|
||||
ListingSource::from_file_and_path(clause_name!("project_attributes"), path_buf),
|
||||
ListingSource::from_file_and_path(atom!("project_attributes"), path_buf),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if let Some(module) = self.indices.modules.get(&clause_name!("$atts")) {
|
||||
if let Some(code_index) = module.code_dir.get(&(clause_name!("driver"), 2)) {
|
||||
if let Some(module) = self.indices.modules.get(&atom!("$atts")) {
|
||||
if let Some(code_index) = module.code_dir.get(&(atom!("driver"), 2)) {
|
||||
self.machine_st.attr_var_init.verify_attrs_loc = code_index.local().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_top_level(&mut self) {
|
||||
use std::env;
|
||||
|
||||
let mut arg_pstrs = vec![];
|
||||
|
||||
for arg in env::args() {
|
||||
arg_pstrs.push(self.machine_st.heap.put_complete_string(&arg));
|
||||
arg_pstrs.push(put_complete_string(
|
||||
&mut self.machine_st.heap,
|
||||
&arg,
|
||||
&mut self.machine_st.atom_tbl,
|
||||
));
|
||||
}
|
||||
|
||||
let list_addr = Addr::HeapCell(self.machine_st.heap.to_list(arg_pstrs.into_iter()));
|
||||
self.machine_st.registers[1] = heap_loc_as_cell!(
|
||||
iter_to_heap_list(&mut self.machine_st.heap, arg_pstrs.into_iter())
|
||||
);
|
||||
|
||||
self.machine_st[temp_v!(1)] = list_addr;
|
||||
|
||||
self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("$repl"), 1));
|
||||
self.run_module_predicate(atom!("$toplevel"), (atom!("$repl"), 1));
|
||||
}
|
||||
|
||||
pub(crate) fn configure_modules(&mut self) {
|
||||
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir) {
|
||||
for arity in 1..66 {
|
||||
let key = (clause_name!("call"), arity);
|
||||
let key = (atom!("call"), arity);
|
||||
|
||||
match loader.code_dir.get(&key) {
|
||||
Some(src_code_index) => {
|
||||
let target_code_index = target_code_dir
|
||||
.entry(key.clone())
|
||||
.entry(key)
|
||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined));
|
||||
|
||||
target_code_index.set(src_code_index.get());
|
||||
@@ -237,15 +270,15 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(loader) = self.indices.modules.swap_remove(&clause_name!("loader")) {
|
||||
if let Some(builtins) = self.indices.modules.get_mut(&clause_name!("builtins")) {
|
||||
if let Some(loader) = self.indices.modules.swap_remove(&atom!("loader")) {
|
||||
if let Some(builtins) = self.indices.modules.get_mut(&atom!("builtins")) {
|
||||
// Import loader's exports into the builtins module so they will be
|
||||
// implicitly included in every further module.
|
||||
load_module(
|
||||
&mut builtins.code_dir,
|
||||
&mut builtins.op_dir,
|
||||
&mut builtins.meta_predicates,
|
||||
&CompilationTarget::Module(clause_name!("builtins")),
|
||||
&CompilationTarget::Module(atom!("builtins")),
|
||||
&loader,
|
||||
);
|
||||
|
||||
@@ -257,7 +290,7 @@ impl Machine {
|
||||
builtins
|
||||
.module_decl
|
||||
.exports
|
||||
.push(ModuleExport::PredicateKey((clause_name!("call"), arity)));
|
||||
.push(ModuleExport::PredicateKey((atom!("call"), arity)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,17 +300,24 @@ impl Machine {
|
||||
|
||||
update_call_n_indices(&loader, &mut self.indices.code_dir);
|
||||
|
||||
self.indices.modules.insert(clause_name!("loader"), loader);
|
||||
self.indices.modules.insert(atom!("loader"), loader);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(user_input: Stream, user_output: Stream, user_error: Stream) -> Self {
|
||||
pub fn new() -> Self {
|
||||
use ref_thread_local::RefThreadLocal;
|
||||
|
||||
let mut machine_st = MachineState::new();
|
||||
|
||||
let user_input = Stream::stdin(&mut machine_st.arena);
|
||||
let user_output = Stream::stdout(&mut machine_st.arena);
|
||||
let user_error = Stream::stderr(&mut machine_st.arena);
|
||||
|
||||
let mut wam = Machine {
|
||||
machine_st: MachineState::new(),
|
||||
machine_st,
|
||||
inner_heap: Heap::new(),
|
||||
policies: MachinePolicies::new(),
|
||||
indices: IndexStore::new(),
|
||||
code_repo: CodeRepo::new(),
|
||||
@@ -293,23 +333,29 @@ impl Machine {
|
||||
lib_path.push("lib");
|
||||
|
||||
bootstrapping_compile(
|
||||
Stream::from(LIBRARIES.borrow()["ops_and_meta_predicates"]),
|
||||
Stream::from_static_string(
|
||||
LIBRARIES.borrow()["ops_and_meta_predicates"],
|
||||
&mut wam.machine_st.arena,
|
||||
),
|
||||
&mut wam,
|
||||
ListingSource::from_file_and_path(
|
||||
clause_name!("ops_and_meta_predicates.pl"),
|
||||
atom!("ops_and_meta_predicates.pl"),
|
||||
lib_path.clone(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
bootstrapping_compile(
|
||||
Stream::from(LIBRARIES.borrow()["builtins"]),
|
||||
Stream::from_static_string(
|
||||
LIBRARIES.borrow()["builtins"],
|
||||
&mut wam.machine_st.arena,
|
||||
),
|
||||
&mut wam,
|
||||
ListingSource::from_file_and_path(clause_name!("builtins.pl"), lib_path.clone()),
|
||||
ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if let Some(builtins) = wam.indices.modules.get(&clause_name!("builtins")) {
|
||||
if let Some(builtins) = wam.indices.modules.get(&atom!("builtins")) {
|
||||
load_module(
|
||||
&mut wam.indices.code_dir,
|
||||
&mut wam.indices.op_dir,
|
||||
@@ -324,15 +370,15 @@ impl Machine {
|
||||
lib_path.pop(); // remove the "lib" at the end
|
||||
|
||||
bootstrapping_compile(
|
||||
Stream::from(include_str!("../loader.pl")),
|
||||
Stream::from_static_string(include_str!("../loader.pl"), &mut wam.machine_st.arena),
|
||||
&mut wam,
|
||||
ListingSource::from_file_and_path(clause_name!("loader.pl"), lib_path.clone()),
|
||||
ListingSource::from_file_and_path(atom!("loader.pl"), lib_path.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
wam.configure_modules();
|
||||
|
||||
if let Some(loader) = wam.indices.modules.get(&clause_name!("loader")) {
|
||||
if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
|
||||
load_module(
|
||||
&mut wam.indices.code_dir,
|
||||
&mut wam.indices.op_dir,
|
||||
@@ -352,38 +398,21 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub(crate) fn configure_streams(&mut self) {
|
||||
self.user_input.options_mut().alias = Some(clause_name!("user_input"));
|
||||
self.user_input.options_mut().set_alias_to_atom_opt(Some(atom!("user_input")));
|
||||
|
||||
self.indices
|
||||
.stream_aliases
|
||||
.insert(clause_name!("user_input"), self.user_input.clone());
|
||||
.insert(atom!("user_input"), self.user_input);
|
||||
|
||||
self.indices.streams.insert(self.user_input.clone());
|
||||
self.indices.streams.insert(self.user_input);
|
||||
|
||||
self.user_output.options_mut().alias = Some(clause_name!("user_output"));
|
||||
self.user_output.options_mut().set_alias_to_atom_opt(Some(atom!("user_output")));
|
||||
|
||||
self.indices
|
||||
.stream_aliases
|
||||
.insert(clause_name!("user_output"), self.user_output.clone());
|
||||
.insert(atom!("user_output"), self.user_output);
|
||||
|
||||
self.user_error.options_mut().alias = Some(clause_name!("user_error"));
|
||||
|
||||
self.indices
|
||||
.stream_aliases
|
||||
.insert(clause_name!("user_error"), self.user_error.clone());
|
||||
|
||||
self.indices.streams.insert(self.user_output.clone());
|
||||
}
|
||||
|
||||
fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
|
||||
let h = self.machine_st.heap.h();
|
||||
|
||||
let err = MachineError::session_error(h, err);
|
||||
let stub = MachineError::functor_stub(key.0, key.1);
|
||||
let err = self.machine_st.error_form(err, stub);
|
||||
|
||||
self.machine_st.throw_exception(err);
|
||||
return;
|
||||
self.indices.streams.insert(self.user_output);
|
||||
}
|
||||
|
||||
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
|
||||
@@ -604,13 +633,14 @@ impl MachineState {
|
||||
self.b0 = self.stack.index_or_frame(b).prelude.b0;
|
||||
self.p = CodePtr::Local(self.stack.index_or_frame(b).prelude.bp);
|
||||
|
||||
self.pdl.clear();
|
||||
self.fail = false;
|
||||
}
|
||||
|
||||
fn check_machine_index(&mut self, code_repo: &CodeRepo) -> bool {
|
||||
match self.p {
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p))
|
||||
| CodePtr::Local(LocalCodePtr::IndexingBuf(p, ..))
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p)) |
|
||||
CodePtr::Local(LocalCodePtr::IndexingBuf(p, ..))
|
||||
if p < code_repo.code.len() => {}
|
||||
CodePtr::Local(LocalCodePtr::Halt) | CodePtr::REPL(..) => {
|
||||
return false;
|
||||
@@ -690,7 +720,9 @@ impl MachineState {
|
||||
self.p = CodePtr::Local(self.attr_var_init.cp);
|
||||
|
||||
let instigating_p = CodePtr::Local(self.attr_var_init.instigating_p);
|
||||
let instigating_instr = code_repo.lookup_instr(false, &instigating_p).unwrap();
|
||||
let instigating_instr = code_repo
|
||||
.lookup_instr(false, &instigating_p)
|
||||
.unwrap();
|
||||
|
||||
if !instigating_instr.as_ref().is_head_instr() {
|
||||
let cp = self.p.local();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,10 @@
|
||||
use prolog_parser::ast::*;
|
||||
use prolog_parser::tabled_rc::*;
|
||||
use prolog_parser::{atom, clause_name, rc_atom};
|
||||
|
||||
use crate::atom_table::*;
|
||||
use crate::clause_types::*;
|
||||
use crate::forms::*;
|
||||
use crate::iterators::*;
|
||||
use crate::machine::load_state::*;
|
||||
use crate::machine::loader::*;
|
||||
use crate::machine::machine_errors::*;
|
||||
use crate::machine::*;
|
||||
use crate::parser::ast::*;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
|
||||
@@ -30,89 +28,81 @@ pub(crate) enum CutContext {
|
||||
HasCutVariable,
|
||||
}
|
||||
|
||||
pub(crate) fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
||||
pub(crate) fn fold_by_str<I>(terms: I, mut term: Term, sym: Atom) -> Term
|
||||
where
|
||||
I: DoubleEndedIterator<Item = Term>,
|
||||
{
|
||||
for prec in terms.rev() {
|
||||
term = Term::Clause(
|
||||
Cell::default(),
|
||||
sym.clone(),
|
||||
vec![Box::new(prec), Box::new(term)],
|
||||
None,
|
||||
);
|
||||
term = Term::Clause(Cell::default(), sym, vec![prec, term]);
|
||||
}
|
||||
|
||||
term
|
||||
}
|
||||
|
||||
pub(crate) fn to_op_decl(
|
||||
prec: usize,
|
||||
spec: &str,
|
||||
name: ClauseName,
|
||||
prec: u16,
|
||||
spec: Atom,
|
||||
name: Atom,
|
||||
) -> Result<OpDecl, CompilationError> {
|
||||
match spec {
|
||||
"xfx" => Ok(OpDecl::new(prec, XFX, name)),
|
||||
"xfy" => Ok(OpDecl::new(prec, XFY, name)),
|
||||
"yfx" => Ok(OpDecl::new(prec, YFX, name)),
|
||||
"fx" => Ok(OpDecl::new(prec, FX, name)),
|
||||
"fy" => Ok(OpDecl::new(prec, FY, name)),
|
||||
"xf" => Ok(OpDecl::new(prec, XF, name)),
|
||||
"yf" => Ok(OpDecl::new(prec, YF, name)),
|
||||
atom!("xfx") => Ok(OpDecl::new(OpDesc::build_with(prec, XFX as u8), name)),
|
||||
atom!("xfy") => Ok(OpDecl::new(OpDesc::build_with(prec, XFY as u8), name)),
|
||||
atom!("yfx") => Ok(OpDecl::new(OpDesc::build_with(prec, YFX as u8), name)),
|
||||
atom!("fx") => Ok(OpDecl::new(OpDesc::build_with(prec, FX as u8), name)),
|
||||
atom!("fy") => Ok(OpDecl::new(OpDesc::build_with(prec, FY as u8), name)),
|
||||
atom!("xf") => Ok(OpDecl::new(OpDesc::build_with(prec, XF as u8), name)),
|
||||
atom!("yf") => Ok(OpDecl::new(OpDesc::build_with(prec, YF as u8), name)),
|
||||
_ => Err(CompilationError::InconsistentEntry),
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_op_decl(
|
||||
mut terms: Vec<Box<Term>>,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
mut terms: Vec<Term>,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> Result<OpDecl, CompilationError> {
|
||||
let name = match *terms.pop().unwrap() {
|
||||
Term::Constant(_, Constant::Atom(name, _)) => name,
|
||||
Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl),
|
||||
let name = match terms.pop().unwrap() {
|
||||
Term::Literal(_, Literal::Atom(name)) => name,
|
||||
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()),
|
||||
_ => return Err(CompilationError::InconsistentEntry),
|
||||
};
|
||||
|
||||
let spec = match *terms.pop().unwrap() {
|
||||
Term::Constant(_, Constant::Atom(name, _)) => name,
|
||||
Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl),
|
||||
let spec = match terms.pop().unwrap() {
|
||||
Term::Literal(_, Literal::Atom(name)) => name,
|
||||
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()),
|
||||
_ => return Err(CompilationError::InconsistentEntry),
|
||||
};
|
||||
|
||||
let prec = match *terms.pop().unwrap() {
|
||||
Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
|
||||
let prec = match terms.pop().unwrap() {
|
||||
Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) {
|
||||
Ok(n) if n <= 1200 => n,
|
||||
_ => return Err(CompilationError::InconsistentEntry),
|
||||
},
|
||||
_ => return Err(CompilationError::InconsistentEntry),
|
||||
};
|
||||
|
||||
to_op_decl(prec, spec.as_str(), name)
|
||||
to_op_decl(prec, spec, name)
|
||||
}
|
||||
|
||||
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> {
|
||||
match term {
|
||||
Term::Clause(_, ref slash, ref mut terms, Some(_))
|
||||
if (slash.as_str() == "/" || slash.as_str() == "//") && terms.len() == 2 =>
|
||||
Term::Clause(_, slash, ref mut terms)
|
||||
if (*slash == atom!("/") || *slash == atom!("//")) && terms.len() == 2 =>
|
||||
{
|
||||
let arity = *terms.pop().unwrap();
|
||||
let name = *terms.pop().unwrap();
|
||||
let arity = terms.pop().unwrap();
|
||||
let name = terms.pop().unwrap();
|
||||
|
||||
let arity = arity
|
||||
.into_constant()
|
||||
.and_then(|c| match c {
|
||||
Constant::Integer(n) => n.to_usize(),
|
||||
Constant::Fixnum(n) => usize::try_from(n).ok(),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or(CompilationError::InvalidModuleExport)?;
|
||||
let arity = match arity {
|
||||
Term::Literal(_, Literal::Integer(n)) => n.to_usize(),
|
||||
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
|
||||
_ => None,
|
||||
}.ok_or(CompilationError::InvalidModuleExport)?;
|
||||
|
||||
let name = name
|
||||
.into_constant()
|
||||
.and_then(|c| c.to_atom())
|
||||
.ok_or(CompilationError::InvalidModuleExport)?;
|
||||
let name = match name {
|
||||
Term::Literal(_, Literal::Atom(name)) => Some(name),
|
||||
_ => None,
|
||||
}.ok_or(CompilationError::InvalidModuleExport)?;
|
||||
|
||||
if slash.as_str() == "/" {
|
||||
if *slash == atom!("/") {
|
||||
Ok((name, arity))
|
||||
} else {
|
||||
Ok((name, arity + 2))
|
||||
@@ -148,13 +138,13 @@ fn setup_scoped_predicate_indicator(term: &mut Term) -> Result<ScopedPredicateKe
|
||||
|
||||
fn setup_module_export(
|
||||
mut term: Term,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> Result<ModuleExport, CompilationError> {
|
||||
setup_predicate_indicator(&mut term)
|
||||
.map(ModuleExport::PredicateKey)
|
||||
.or_else(|_| {
|
||||
if let Term::Clause(_, name, terms, _) = term {
|
||||
if terms.len() == 3 && name.as_str() == "op" {
|
||||
if let Term::Clause(_, name, terms) = term {
|
||||
if terms.len() == 3 && name == atom!("op") {
|
||||
Ok(ModuleExport::OpDecl(setup_op_decl(terms, atom_tbl)?))
|
||||
} else {
|
||||
Err(CompilationError::InvalidModuleDecl)
|
||||
@@ -167,18 +157,18 @@ fn setup_module_export(
|
||||
|
||||
pub(super) fn setup_module_export_list(
|
||||
mut export_list: Term,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> Result<Vec<ModuleExport>, CompilationError> {
|
||||
let mut exports = vec![];
|
||||
|
||||
while let Term::Cons(_, t1, t2) = export_list {
|
||||
let module_export = setup_module_export(*t1, atom_tbl.clone())?;
|
||||
let module_export = setup_module_export(*t1, atom_tbl)?;
|
||||
|
||||
exports.push(module_export);
|
||||
export_list = *t2;
|
||||
}
|
||||
|
||||
if let Term::Constant(_, Constant::EmptyList) = export_list {
|
||||
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
|
||||
Ok(exports)
|
||||
} else {
|
||||
Err(CompilationError::InvalidModuleDecl)
|
||||
@@ -186,35 +176,33 @@ pub(super) fn setup_module_export_list(
|
||||
}
|
||||
|
||||
fn setup_module_decl(
|
||||
mut terms: Vec<Box<Term>>,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
mut terms: Vec<Term>,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> Result<ModuleDecl, CompilationError> {
|
||||
let export_list = *terms.pop().unwrap();
|
||||
let name = terms
|
||||
.pop()
|
||||
.unwrap()
|
||||
.into_constant()
|
||||
.and_then(|c| c.to_atom())
|
||||
.ok_or(CompilationError::InvalidModuleDecl)?;
|
||||
let export_list = terms.pop().unwrap();
|
||||
let name = terms.pop().unwrap();
|
||||
|
||||
let name = match name {
|
||||
Term::Literal(_, Literal::Atom(name)) => Some(name),
|
||||
_ => None,
|
||||
}.ok_or(CompilationError::InvalidModuleDecl)?;
|
||||
|
||||
let exports = setup_module_export_list(export_list, atom_tbl)?;
|
||||
|
||||
Ok(ModuleDecl { name, exports })
|
||||
}
|
||||
|
||||
fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, CompilationError> {
|
||||
match *terms.pop().unwrap() {
|
||||
Term::Clause(_, ref name, ref mut terms, None)
|
||||
if name.as_str() == "library" && terms.len() == 1 =>
|
||||
fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> {
|
||||
match terms.pop().unwrap() {
|
||||
Term::Clause(_, name, mut terms)
|
||||
if name == atom!("library") && terms.len() == 1 =>
|
||||
{
|
||||
terms
|
||||
.pop()
|
||||
.unwrap()
|
||||
.into_constant()
|
||||
.and_then(|c| c.to_atom())
|
||||
.map(|c| ModuleSource::Library(c))
|
||||
.ok_or(CompilationError::InvalidUseModuleDecl)
|
||||
match terms.pop().unwrap() {
|
||||
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
|
||||
_ => Err(CompilationError::InvalidModuleDecl),
|
||||
}
|
||||
}
|
||||
Term::Constant(_, Constant::Atom(ref name, _)) => Ok(ModuleSource::File(name.clone())),
|
||||
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
|
||||
_ => Err(CompilationError::InvalidUseModuleDecl),
|
||||
}
|
||||
}
|
||||
@@ -224,10 +212,10 @@ fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, Compil
|
||||
let dbl_quotes = *terms.pop().unwrap();
|
||||
|
||||
match terms[0].as_ref() {
|
||||
Term::Constant(_, Constant::Atom(ref name, _))
|
||||
Term::Literal(_, Literal::Atom(ref name, _))
|
||||
if name.as_str() == "double_quotes" => {
|
||||
match dbl_quotes {
|
||||
Term::Constant(_, Constant::Atom(name, _)) => {
|
||||
Term::Literal(_, Literal::Atom(name, _)) => {
|
||||
match name.as_str() {
|
||||
"atom" => Ok(DoubleQuotes::Atom),
|
||||
"chars" => Ok(DoubleQuotes::Chars),
|
||||
@@ -250,34 +238,31 @@ fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, Compil
|
||||
type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
|
||||
|
||||
fn setup_qualified_import(
|
||||
mut terms: Vec<Box<Term>>,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
mut terms: Vec<Term>,
|
||||
atom_tbl: &mut AtomTable,
|
||||
) -> Result<UseModuleExport, CompilationError> {
|
||||
let mut export_list = *terms.pop().unwrap();
|
||||
let module_src = match *terms.pop().unwrap() {
|
||||
Term::Clause(_, ref name, ref mut terms, None)
|
||||
if name.as_str() == "library" && terms.len() == 1 =>
|
||||
let mut export_list = terms.pop().unwrap();
|
||||
let module_src = match terms.pop().unwrap() {
|
||||
Term::Clause(_, name, mut terms)
|
||||
if name == atom!("library") && terms.len() == 1 =>
|
||||
{
|
||||
terms
|
||||
.pop()
|
||||
.unwrap()
|
||||
.into_constant()
|
||||
.and_then(|c| c.to_atom())
|
||||
.map(|c| ModuleSource::Library(c))
|
||||
.ok_or(CompilationError::InvalidUseModuleDecl)
|
||||
match terms.pop().unwrap() {
|
||||
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
|
||||
_ => Err(CompilationError::InvalidModuleDecl),
|
||||
}
|
||||
}
|
||||
Term::Constant(_, Constant::Atom(ref name, _)) => Ok(ModuleSource::File(name.clone())),
|
||||
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
|
||||
_ => Err(CompilationError::InvalidUseModuleDecl),
|
||||
}?;
|
||||
|
||||
let mut exports = IndexSet::new();
|
||||
|
||||
while let Term::Cons(_, t1, t2) = export_list {
|
||||
exports.insert(setup_module_export(*t1, atom_tbl.clone())?);
|
||||
exports.insert(setup_module_export(*t1, atom_tbl)?);
|
||||
export_list = *t2;
|
||||
}
|
||||
|
||||
if let Term::Constant(_, Constant::EmptyList) = export_list {
|
||||
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
|
||||
Ok((module_src, exports))
|
||||
} else {
|
||||
Err(CompilationError::InvalidModuleDecl)
|
||||
@@ -322,29 +307,29 @@ fn setup_qualified_import(
|
||||
* -
|
||||
* ?
|
||||
*/
|
||||
fn setup_meta_predicate<'a>(
|
||||
mut terms: Vec<Box<Term>>,
|
||||
load_state: &LoadState<'a>,
|
||||
) -> Result<(ClauseName, ClauseName, Vec<MetaSpec>), CompilationError> {
|
||||
fn setup_meta_predicate<'a, LS: LoadState<'a>>(
|
||||
mut terms: Vec<Term>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
|
||||
fn get_name_and_meta_specs(
|
||||
name: ClauseName,
|
||||
terms: &mut [Box<Term>],
|
||||
) -> Result<(ClauseName, Vec<MetaSpec>), CompilationError> {
|
||||
name: Atom,
|
||||
terms: &mut [Term],
|
||||
) -> Result<(Atom, Vec<MetaSpec>), CompilationError> {
|
||||
let mut meta_specs = vec![];
|
||||
|
||||
for meta_spec in terms.into_iter() {
|
||||
match &**meta_spec {
|
||||
Term::Constant(_, Constant::Atom(meta_spec, _)) => {
|
||||
let meta_spec = match meta_spec.as_str() {
|
||||
"+" => MetaSpec::Plus,
|
||||
"-" => MetaSpec::Minus,
|
||||
"?" => MetaSpec::Either,
|
||||
match meta_spec {
|
||||
Term::Literal(_, Literal::Atom(meta_spec)) => {
|
||||
let meta_spec = match meta_spec {
|
||||
atom!("+") => MetaSpec::Plus,
|
||||
atom!("-") => MetaSpec::Minus,
|
||||
atom!("?") => MetaSpec::Either,
|
||||
_ => return Err(CompilationError::InvalidMetaPredicateDecl),
|
||||
};
|
||||
|
||||
meta_specs.push(meta_spec);
|
||||
}
|
||||
Term::Constant(_, Constant::Fixnum(n)) => match usize::try_from(*n) {
|
||||
Term::Literal(_, Literal::Fixnum(n)) => match usize::try_from(n.get_num()) {
|
||||
Ok(n) if n <= MAX_ARITY => {
|
||||
meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
|
||||
}
|
||||
@@ -361,16 +346,15 @@ fn setup_meta_predicate<'a>(
|
||||
Ok((name, meta_specs))
|
||||
}
|
||||
|
||||
match *terms.pop().unwrap() {
|
||||
Term::Clause(_, name, mut terms, _) if name.as_str() == ":" && terms.len() == 2 => {
|
||||
let spec = *terms.pop().unwrap();
|
||||
let module_name = *terms.pop().unwrap();
|
||||
match terms.pop().unwrap() {
|
||||
Term::Clause(_, name, mut terms) if name == atom!(":") && terms.len() == 2 => {
|
||||
let spec = terms.pop().unwrap();
|
||||
let module_name = terms.pop().unwrap();
|
||||
|
||||
match module_name {
|
||||
Term::Constant(_, Constant::Atom(module_name, _)) => match spec {
|
||||
Term::Clause(_, name, mut terms, _) => {
|
||||
Term::Literal(_, Literal::Atom(module_name)) => match spec {
|
||||
Term::Clause(_, name, mut terms) => {
|
||||
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
|
||||
|
||||
Ok((module_name, name, meta_specs))
|
||||
}
|
||||
_ => Err(CompilationError::InvalidMetaPredicateDecl),
|
||||
@@ -378,10 +362,10 @@ fn setup_meta_predicate<'a>(
|
||||
_ => Err(CompilationError::InvalidMetaPredicateDecl),
|
||||
}
|
||||
}
|
||||
Term::Clause(_, name, mut terms, _) => {
|
||||
Term::Clause(_, name, mut terms) => {
|
||||
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
|
||||
Ok((
|
||||
load_state.compilation_target.module_name(),
|
||||
loader.payload.compilation_target.module_name(),
|
||||
name,
|
||||
meta_specs,
|
||||
))
|
||||
@@ -420,11 +404,11 @@ fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, CompilationEr
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_cut_variables_as(terms: &mut Vec<Term>, name: ClauseName) {
|
||||
fn mark_cut_variables_as(terms: &mut Vec<Term>, name: Atom) {
|
||||
for term in terms.iter_mut() {
|
||||
match term {
|
||||
&mut Term::Constant(_, Constant::Atom(ref mut var, _)) if var.as_str() == "!" => {
|
||||
*var = name.clone()
|
||||
&mut Term::Literal(_, Literal::Atom(ref mut var)) if *var == atom!("!") => {
|
||||
*var = name;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -433,12 +417,12 @@ fn mark_cut_variables_as(terms: &mut Vec<Term>, name: ClauseName) {
|
||||
|
||||
fn mark_cut_variable(term: &mut Term) -> bool {
|
||||
let cut_var_found = match term {
|
||||
&mut Term::Constant(_, Constant::Atom(ref var, _)) if var.as_str() == "!" => true,
|
||||
&mut Term::Literal(_, Literal::Atom(ref var)) if *var == atom!("!") => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if cut_var_found {
|
||||
*term = Term::Var(Cell::default(), rc_atom!("!"));
|
||||
*term = Term::Var(Cell::default(), Rc::new(String::from("!")));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -463,21 +447,21 @@ fn check_for_internal_if_then(terms: &mut Vec<Term>) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(Term::Clause(_, ref name, ref subterms, _)) = terms.last() {
|
||||
if name.as_str() != "->" || subterms.len() != 2 {
|
||||
if let Some(Term::Clause(_, name, ref subterms)) = terms.last() {
|
||||
if *name != atom!("->") || subterms.len() != 2 {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(Term::Clause(_, _, mut subterms, _)) = terms.pop() {
|
||||
let mut conq_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
|
||||
let mut pre_cut_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
|
||||
if let Some(Term::Clause(_, _, mut subterms)) = terms.pop() {
|
||||
let mut conq_terms = VecDeque::from(unfold_by_str(subterms.pop().unwrap(), atom!(",")));
|
||||
let mut pre_cut_terms = VecDeque::from(unfold_by_str(subterms.pop().unwrap(), atom!(",")));
|
||||
|
||||
conq_terms.push_front(Term::Constant(
|
||||
conq_terms.push_front(Term::Literal(
|
||||
Cell::default(),
|
||||
Constant::Atom(clause_name!("blocked_!"), None),
|
||||
Literal::Atom(atom!("blocked_!")),
|
||||
));
|
||||
|
||||
while let Some(term) = pre_cut_terms.pop_back() {
|
||||
@@ -489,37 +473,44 @@ fn check_for_internal_if_then(terms: &mut Vec<Term>) {
|
||||
terms.push(fold_by_str(
|
||||
conq_terms.into_iter(),
|
||||
tail_term,
|
||||
clause_name!(","),
|
||||
atom!(","),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn setup_declaration<'a>(
|
||||
load_state: &LoadState<'a>,
|
||||
mut terms: Vec<Box<Term>>,
|
||||
pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
|
||||
loader: &mut Loader<'a, LS>,
|
||||
mut terms: Vec<Term>,
|
||||
) -> Result<Declaration, CompilationError> {
|
||||
let term = *terms.pop().unwrap();
|
||||
let atom_tbl = load_state.wam.machine_st.atom_tbl.clone();
|
||||
let term = terms.pop().unwrap();
|
||||
|
||||
match term {
|
||||
Term::Clause(_, name, mut terms, _) => match (name.as_str(), terms.len()) {
|
||||
("dynamic", 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||
Term::Clause(_, name, mut terms) => match (name, terms.len()) {
|
||||
(atom!("dynamic"), 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
|
||||
Ok(Declaration::Dynamic(name, arity))
|
||||
}
|
||||
("module", 2) => Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?)),
|
||||
("op", 3) => Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?)),
|
||||
("non_counted_backtracking", 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||
(atom!("module"), 2) => {
|
||||
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
||||
Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?))
|
||||
}
|
||||
(atom!("op"), 3) => {
|
||||
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
||||
Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?))
|
||||
}
|
||||
(atom!("non_counted_backtracking"), 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
|
||||
Ok(Declaration::NonCountedBacktracking(name, arity))
|
||||
}
|
||||
("use_module", 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
|
||||
("use_module", 2) => {
|
||||
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
|
||||
(atom!("use_module"), 2) => {
|
||||
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
||||
let (name, exports) = setup_qualified_import(terms, atom_tbl)?;
|
||||
|
||||
Ok(Declaration::UseQualifiedModule(name, exports))
|
||||
}
|
||||
("meta_predicate", 1) => {
|
||||
let (module_name, name, meta_specs) = setup_meta_predicate(terms, load_state)?;
|
||||
(atom!("meta_predicate"), 1) => {
|
||||
let (module_name, name, meta_specs) = setup_meta_predicate(terms, loader)?;
|
||||
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
|
||||
}
|
||||
_ => Err(CompilationError::InconsistentEntry),
|
||||
@@ -529,43 +520,43 @@ pub(super) fn setup_declaration<'a>(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clause_to_query_term<'a>(
|
||||
load_state: &mut LoadState<'a>,
|
||||
name: ClauseName,
|
||||
terms: Vec<Box<Term>>,
|
||||
fixity: Option<SharedOpDesc>,
|
||||
fn clause_to_query_term<'a, LS: LoadState<'a>>(
|
||||
loader: &mut Loader<'a, LS>,
|
||||
name: Atom,
|
||||
terms: Vec<Term>,
|
||||
) -> QueryTerm {
|
||||
let ct = load_state.get_clause_type(name, terms.len(), fixity);
|
||||
let ct = loader.get_clause_type(name, terms.len());
|
||||
QueryTerm::Clause(Cell::default(), ct, terms, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn qualified_clause_to_query_term<'a>(
|
||||
load_state: &mut LoadState<'a>,
|
||||
module_name: ClauseName,
|
||||
name: ClauseName,
|
||||
terms: Vec<Box<Term>>,
|
||||
fixity: Option<SharedOpDesc>,
|
||||
fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
|
||||
loader: &mut Loader<'a, LS>,
|
||||
module_name: Atom,
|
||||
name: Atom,
|
||||
terms: Vec<Term>,
|
||||
) -> QueryTerm {
|
||||
let ct = load_state.get_qualified_clause_type(module_name, name, terms.len(), fixity);
|
||||
let ct = loader.get_qualified_clause_type(module_name, name, terms.len());
|
||||
QueryTerm::Clause(Cell::default(), ct, terms, false)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Preprocessor {
|
||||
flags: MachineFlags,
|
||||
queue: VecDeque<VecDeque<Term>>,
|
||||
}
|
||||
|
||||
impl Preprocessor {
|
||||
pub(super) fn new() -> Self {
|
||||
pub(super) fn new(flags: MachineFlags) -> Self {
|
||||
Preprocessor {
|
||||
flags,
|
||||
queue: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_fact(&mut self, term: Term) -> Result<Term, CompilationError> {
|
||||
match term {
|
||||
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => Ok(term),
|
||||
Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => Ok(term),
|
||||
_ => Err(CompilationError::InadmissibleFact),
|
||||
}
|
||||
}
|
||||
@@ -579,20 +570,17 @@ impl Preprocessor {
|
||||
}
|
||||
}
|
||||
|
||||
vars.insert(rc_atom!("!"));
|
||||
vars.insert(Rc::new(String::from("!")));
|
||||
vars.into_iter()
|
||||
.map(|v| Term::Var(Cell::default(), v))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn fabricate_rule_body(&self, vars: &Vec<Term>, body_term: Term) -> Term {
|
||||
let vars_of_head = vars.iter().cloned().map(Box::new).collect();
|
||||
let head_term = Term::Clause(Cell::default(), clause_name!(""), vars_of_head, None);
|
||||
let head_term = Term::Clause(Cell::default(), atom!(""), vars.clone());
|
||||
let rule = vec![head_term, body_term];
|
||||
|
||||
let rule = vec![Box::new(head_term), Box::new(body_term)];
|
||||
let turnstile = clause_name!(":-");
|
||||
|
||||
Term::Clause(Cell::default(), turnstile, rule, None)
|
||||
Term::Clause(Cell::default(), atom!(":-"), rule)
|
||||
}
|
||||
|
||||
// the terms form the body of the rule. We create a head, by
|
||||
@@ -609,16 +597,16 @@ impl Preprocessor {
|
||||
|
||||
fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
|
||||
let vars = self.compute_head(&body_term);
|
||||
let results = unfold_by_str(body_term, ";")
|
||||
let results = unfold_by_str(body_term, atom!(";"))
|
||||
.into_iter()
|
||||
.map(|term| {
|
||||
let mut subterms = unfold_by_str(term, ",");
|
||||
let mut subterms = unfold_by_str(term, atom!(","));
|
||||
mark_cut_variables(&mut subterms);
|
||||
|
||||
check_for_internal_if_then(&mut subterms);
|
||||
|
||||
let term = subterms.pop().unwrap();
|
||||
let clause = fold_by_str(subterms.into_iter(), term, clause_name!(","));
|
||||
let clause = fold_by_str(subterms.into_iter(), term, atom!(","));
|
||||
|
||||
self.fabricate_rule_body(&vars, clause)
|
||||
})
|
||||
@@ -628,80 +616,78 @@ impl Preprocessor {
|
||||
}
|
||||
|
||||
fn fabricate_if_then(&self, prec: Term, conq: Term) -> (JumpStub, VecDeque<Term>) {
|
||||
let mut prec_seq = unfold_by_str(prec, ",");
|
||||
let comma_sym = clause_name!(",");
|
||||
let cut_sym = atom!("!");
|
||||
let mut prec_seq = unfold_by_str(prec, atom!(","));
|
||||
let comma_sym = atom!(",");
|
||||
let cut_sym = Literal::Atom(atom!("!"));
|
||||
|
||||
prec_seq.push(Term::Constant(Cell::default(), cut_sym));
|
||||
prec_seq.push(Term::Literal(Cell::default(), cut_sym));
|
||||
|
||||
mark_cut_variables_as(&mut prec_seq, clause_name!("blocked_!"));
|
||||
mark_cut_variables_as(&mut prec_seq, atom!("blocked_!"));
|
||||
|
||||
let mut conq_seq = unfold_by_str(conq, ",");
|
||||
let mut conq_seq = unfold_by_str(conq, atom!(","));
|
||||
|
||||
mark_cut_variables(&mut conq_seq);
|
||||
prec_seq.extend(conq_seq.into_iter());
|
||||
|
||||
let back_term = Box::new(prec_seq.pop().unwrap());
|
||||
let front_term = Box::new(prec_seq.pop().unwrap());
|
||||
let back_term = prec_seq.pop().unwrap();
|
||||
let front_term = prec_seq.pop().unwrap();
|
||||
|
||||
let body_term = Term::Clause(
|
||||
Cell::default(),
|
||||
comma_sym.clone(),
|
||||
comma_sym,
|
||||
vec![front_term, back_term],
|
||||
None,
|
||||
);
|
||||
|
||||
self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
|
||||
}
|
||||
|
||||
fn to_query_term<'a>(
|
||||
fn to_query_term<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
term: Term,
|
||||
) -> Result<QueryTerm, CompilationError> {
|
||||
match term {
|
||||
Term::Constant(_, Constant::Atom(name, fixity)) => {
|
||||
if name.as_str() == "!" || name.as_str() == "blocked_!" {
|
||||
Term::Literal(_, Literal::Atom(name)) => {
|
||||
if name == atom!("!") || name == atom!("blocked_!") {
|
||||
Ok(QueryTerm::BlockedCut)
|
||||
} else {
|
||||
Ok(clause_to_query_term(load_state, name, vec![], fixity))
|
||||
Ok(clause_to_query_term(loader, name, vec![]))
|
||||
}
|
||||
}
|
||||
Term::Constant(_, Constant::Char('!')) => Ok(QueryTerm::BlockedCut),
|
||||
Term::Literal(_, Literal::Char('!')) => Ok(QueryTerm::BlockedCut),
|
||||
Term::Var(_, ref v) if v.as_str() == "!" => {
|
||||
Ok(QueryTerm::UnblockedCut(Cell::default()))
|
||||
}
|
||||
Term::Clause(r, name, mut terms, fixity) => match (name.as_str(), terms.len()) {
|
||||
(";", 2) => {
|
||||
let term = Term::Clause(r, name.clone(), terms, fixity);
|
||||
Term::Clause(r, name, mut terms) => match (name, terms.len()) {
|
||||
(atom!(";"), 2) => {
|
||||
let term = Term::Clause(r, name, terms);
|
||||
|
||||
let (stub, clauses) = self.fabricate_disjunct(term);
|
||||
self.queue.push_back(clauses);
|
||||
|
||||
Ok(QueryTerm::Jump(stub))
|
||||
}
|
||||
("->", 2) => {
|
||||
let conq = *terms.pop().unwrap();
|
||||
let prec = *terms.pop().unwrap();
|
||||
(atom!("->"), 2) => {
|
||||
let conq = terms.pop().unwrap();
|
||||
let prec = terms.pop().unwrap();
|
||||
|
||||
let (stub, clauses) = self.fabricate_if_then(prec, conq);
|
||||
self.queue.push_back(clauses);
|
||||
|
||||
Ok(QueryTerm::Jump(stub))
|
||||
}
|
||||
("\\+", 1) => {
|
||||
terms.push(Box::new(Term::Constant(
|
||||
(atom!("\\+"), 1) => {
|
||||
terms.push(Term::Literal(
|
||||
Cell::default(),
|
||||
Constant::Atom(clause_name!("$fail"), None),
|
||||
)));
|
||||
Literal::Atom(atom!("$fail")),
|
||||
));
|
||||
|
||||
let conq =
|
||||
Term::Constant(Cell::default(), Constant::Atom(clause_name!("true"), None));
|
||||
let conq = Term::Literal(Cell::default(), Literal::Atom(atom!("true")));
|
||||
|
||||
let prec = Term::Clause(Cell::default(), clause_name!("->"), terms, None);
|
||||
let terms = vec![Box::new(prec), Box::new(conq)];
|
||||
let prec = Term::Clause(Cell::default(), atom!("->"), terms);
|
||||
let terms = vec![prec, conq];
|
||||
|
||||
let term = Term::Clause(Cell::default(), clause_name!(";"), terms, None);
|
||||
let term = Term::Clause(Cell::default(), atom!(";"), terms);
|
||||
let (stub, clauses) = self.fabricate_disjunct(term);
|
||||
|
||||
debug_assert!(clauses.len() > 0);
|
||||
@@ -709,104 +695,102 @@ impl Preprocessor {
|
||||
|
||||
Ok(QueryTerm::Jump(stub))
|
||||
}
|
||||
("$get_level", 1) => {
|
||||
if let Term::Var(_, ref var) = *terms[0] {
|
||||
(atom!("$get_level"), 1) => {
|
||||
if let Term::Var(_, ref var) = &terms[0] {
|
||||
Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone()))
|
||||
} else {
|
||||
Err(CompilationError::InadmissibleQueryTerm)
|
||||
}
|
||||
}
|
||||
(":", 2) => {
|
||||
let predicate_name = *terms.pop().unwrap();
|
||||
let module_name = *terms.pop().unwrap();
|
||||
(atom!(":"), 2) => {
|
||||
let predicate_name = terms.pop().unwrap();
|
||||
let module_name = terms.pop().unwrap();
|
||||
|
||||
match (module_name, predicate_name) {
|
||||
(
|
||||
Term::Constant(_, Constant::Atom(module_name, _)),
|
||||
Term::Constant(_, Constant::Atom(predicate_name, fixity)),
|
||||
Term::Literal(_, Literal::Atom(module_name)),
|
||||
Term::Literal(_, Literal::Atom(predicate_name)),
|
||||
) => Ok(qualified_clause_to_query_term(
|
||||
load_state,
|
||||
loader,
|
||||
module_name,
|
||||
predicate_name,
|
||||
vec![],
|
||||
fixity,
|
||||
)),
|
||||
(
|
||||
Term::Constant(_, Constant::Atom(module_name, _)),
|
||||
Term::Clause(_, name, terms, fixity),
|
||||
Term::Literal(_, Literal::Atom(module_name)),
|
||||
Term::Clause(_, name, terms),
|
||||
) => Ok(qualified_clause_to_query_term(
|
||||
load_state,
|
||||
loader,
|
||||
module_name,
|
||||
name,
|
||||
terms,
|
||||
fixity,
|
||||
)),
|
||||
(module_name, predicate_name) => {
|
||||
terms.push(Box::new(module_name));
|
||||
terms.push(Box::new(predicate_name));
|
||||
terms.push(module_name);
|
||||
terms.push(predicate_name);
|
||||
|
||||
Ok(clause_to_query_term(load_state, name, terms, fixity))
|
||||
Ok(clause_to_query_term(loader, name, terms))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => Ok(clause_to_query_term(load_state, name, terms, fixity)),
|
||||
_ => Ok(clause_to_query_term(loader, name, terms)),
|
||||
},
|
||||
Term::Var(..) => Ok(QueryTerm::Clause(
|
||||
Cell::default(),
|
||||
ClauseType::CallN,
|
||||
vec![Box::new(term)],
|
||||
vec![term],
|
||||
false,
|
||||
)),
|
||||
_ => Err(CompilationError::InadmissibleQueryTerm),
|
||||
}
|
||||
}
|
||||
|
||||
fn pre_query_term<'a>(
|
||||
fn pre_query_term<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
term: Term,
|
||||
) -> Result<QueryTerm, CompilationError> {
|
||||
match term {
|
||||
Term::Clause(r, name, mut subterms, fixity) => {
|
||||
if subterms.len() == 1 && name.as_str() == "$call_with_default_policy" {
|
||||
self.to_query_term(load_state, *subterms.pop().unwrap())
|
||||
Term::Clause(r, name, mut subterms) => {
|
||||
if subterms.len() == 1 && name == atom!("$call_with_default_policy") {
|
||||
self.to_query_term(loader, subterms.pop().unwrap())
|
||||
.map(|mut query_term| {
|
||||
query_term.set_default_caller();
|
||||
query_term
|
||||
})
|
||||
} else {
|
||||
let clause = Term::Clause(r, name, subterms, fixity);
|
||||
self.to_query_term(load_state, clause)
|
||||
let clause = Term::Clause(r, name, subterms);
|
||||
self.to_query_term(loader, clause)
|
||||
}
|
||||
}
|
||||
_ => self.to_query_term(load_state, term),
|
||||
_ => self.to_query_term(loader, term),
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_query<'a>(
|
||||
fn setup_query<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
terms: Vec<Box<Term>>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
terms: Vec<Term>,
|
||||
cut_context: CutContext,
|
||||
) -> Result<Vec<QueryTerm>, CompilationError> {
|
||||
let mut query_terms = vec![];
|
||||
let mut work_queue = VecDeque::from(terms);
|
||||
|
||||
while let Some(term) = work_queue.pop_front() {
|
||||
let mut term = *term;
|
||||
let mut term = term;
|
||||
|
||||
if let Term::Clause(cell, name, terms, op_spec) = term {
|
||||
if name.as_str() == "," && terms.len() == 2 {
|
||||
let term = Term::Clause(cell, name, terms, op_spec);
|
||||
let mut subterms = unfold_by_str(term, ",");
|
||||
if let Term::Clause(cell, name, terms) = term {
|
||||
if name == atom!(",") && terms.len() == 2 {
|
||||
let term = Term::Clause(cell, name, terms);
|
||||
let mut subterms = unfold_by_str(term, atom!(","));
|
||||
|
||||
while let Some(subterm) = subterms.pop() {
|
||||
work_queue.push_front(Box::new(subterm));
|
||||
work_queue.push_front(subterm);
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
term = Term::Clause(cell, name, terms, op_spec);
|
||||
term = Term::Clause(cell, name, terms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,30 +798,30 @@ impl Preprocessor {
|
||||
mark_cut_variable(&mut term);
|
||||
}
|
||||
|
||||
query_terms.push(self.pre_query_term(load_state, term)?);
|
||||
query_terms.push(self.pre_query_term(loader, term)?);
|
||||
}
|
||||
|
||||
Ok(query_terms)
|
||||
}
|
||||
|
||||
fn setup_rule<'a>(
|
||||
fn setup_rule<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
mut terms: Vec<Box<Term>>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
mut terms: Vec<Term>,
|
||||
cut_context: CutContext,
|
||||
) -> Result<Rule, CompilationError> {
|
||||
let post_head_terms: Vec<_> = terms.drain(1..).collect();
|
||||
let mut query_terms = self.setup_query(load_state, post_head_terms, cut_context)?;
|
||||
let mut query_terms = self.setup_query(loader, post_head_terms, cut_context)?;
|
||||
|
||||
let clauses = query_terms.drain(1..).collect();
|
||||
let qt = query_terms.pop().unwrap();
|
||||
|
||||
match *terms.pop().unwrap() {
|
||||
Term::Clause(_, name, terms, _) => Ok(Rule {
|
||||
match terms.pop().unwrap() {
|
||||
Term::Clause(_, name, terms) => Ok(Rule {
|
||||
head: (name, terms, qt),
|
||||
clauses,
|
||||
}),
|
||||
Term::Constant(_, Constant::Atom(name, _)) => Ok(Rule {
|
||||
Term::Literal(_, Literal::Atom(name)) => Ok(Rule {
|
||||
head: (name, vec![], qt),
|
||||
clauses,
|
||||
}),
|
||||
@@ -845,37 +829,37 @@ impl Preprocessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_term_to_query<'a>(
|
||||
fn try_term_to_query<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
terms: Vec<Box<Term>>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
terms: Vec<Term>,
|
||||
cut_context: CutContext,
|
||||
) -> Result<TopLevel, CompilationError> {
|
||||
Ok(TopLevel::Query(self.setup_query(
|
||||
load_state,
|
||||
loader,
|
||||
terms,
|
||||
cut_context,
|
||||
)?))
|
||||
}
|
||||
|
||||
pub(super) fn try_term_to_tl<'a>(
|
||||
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
term: Term,
|
||||
cut_context: CutContext,
|
||||
) -> Result<TopLevel, CompilationError> {
|
||||
match term {
|
||||
Term::Clause(r, name, terms, fixity) => {
|
||||
if name.as_str() == "?-" {
|
||||
self.try_term_to_query(load_state, terms, cut_context)
|
||||
} else if name.as_str() == ":-" && terms.len() == 2 {
|
||||
Term::Clause(r, name, terms) => {
|
||||
if name == atom!("?-") {
|
||||
self.try_term_to_query(loader, terms, cut_context)
|
||||
} else if name == atom!(":-") && terms.len() == 2 {
|
||||
Ok(TopLevel::Rule(self.setup_rule(
|
||||
load_state,
|
||||
loader,
|
||||
terms,
|
||||
cut_context,
|
||||
)?))
|
||||
} else {
|
||||
let term = Term::Clause(r, name, terms, fixity);
|
||||
let term = Term::Clause(r, name, terms);
|
||||
Ok(TopLevel::Fact(self.setup_fact(term)?))
|
||||
}
|
||||
}
|
||||
@@ -883,30 +867,30 @@ impl Preprocessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>>(
|
||||
fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
terms: I,
|
||||
cut_context: CutContext,
|
||||
) -> Result<VecDeque<TopLevel>, CompilationError> {
|
||||
let mut results = VecDeque::new();
|
||||
|
||||
for term in terms.into_iter() {
|
||||
results.push_back(self.try_term_to_tl(load_state, term, cut_context)?);
|
||||
results.push_back(self.try_term_to_tl(loader, term, cut_context)?);
|
||||
}
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub(super) fn parse_queue<'a>(
|
||||
pub(super) fn parse_queue<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
load_state: &mut LoadState<'a>,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
) -> Result<VecDeque<TopLevel>, CompilationError> {
|
||||
let mut queue = VecDeque::new();
|
||||
|
||||
while let Some(terms) = self.queue.pop_front() {
|
||||
let clauses = merge_clauses(&mut self.try_terms_to_tls(
|
||||
load_state,
|
||||
loader,
|
||||
terms,
|
||||
CutContext::HasCutVariable,
|
||||
)?)?;
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::types::*;
|
||||
|
||||
use crate::machine::machine_indices::*;
|
||||
use crate::machine::raw_block::*;
|
||||
use crate::raw_block::*;
|
||||
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::ptr;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StackTraits {}
|
||||
|
||||
impl RawBlockTraits for StackTraits {
|
||||
impl RawBlockTraits for Stack {
|
||||
#[inline]
|
||||
fn init_size() -> usize {
|
||||
10 * 1024 * 1024
|
||||
@@ -18,31 +17,23 @@ impl RawBlockTraits for StackTraits {
|
||||
|
||||
#[inline]
|
||||
fn align() -> usize {
|
||||
mem::align_of::<Addr>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn base_offset(base: *const u8) -> *const u8 {
|
||||
unsafe { base.offset(Self::align() as isize) }
|
||||
mem::align_of::<HeapCellValue>()
|
||||
}
|
||||
}
|
||||
|
||||
const fn prelude_size<Prelude>() -> usize {
|
||||
let size = mem::size_of::<Prelude>();
|
||||
let align = mem::align_of::<Addr>();
|
||||
|
||||
(size & !(align - 1)) + align
|
||||
#[inline(always)]
|
||||
pub const fn prelude_size<Prelude>() -> usize {
|
||||
mem::size_of::<Prelude>()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Stack {
|
||||
buf: RawBlock<StackTraits>,
|
||||
_marker: PhantomData<Addr>,
|
||||
pub struct Stack {
|
||||
buf: RawBlock<Stack>,
|
||||
_marker: PhantomData<HeapCellValue>,
|
||||
}
|
||||
|
||||
impl Drop for Stack {
|
||||
fn drop(&mut self) {
|
||||
self.drop_in_place();
|
||||
self.buf.deallocate();
|
||||
}
|
||||
}
|
||||
@@ -57,7 +48,7 @@ pub(crate) struct AndFramePrelude {
|
||||
pub(crate) univ_prelude: FramePrelude,
|
||||
pub(crate) e: usize,
|
||||
pub(crate) cp: LocalCodePtr,
|
||||
pub(crate) interrupt_cp: LocalCodePtr,
|
||||
pub(crate) interrupt_cp: LocalCodePtr, // TODO: get rid of it!
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -67,22 +58,22 @@ pub(crate) struct AndFrame {
|
||||
|
||||
impl AndFrame {
|
||||
pub(crate) fn size_of(num_cells: usize) -> usize {
|
||||
prelude_size::<AndFramePrelude>() + num_cells * mem::size_of::<Addr>()
|
||||
prelude_size::<AndFramePrelude>() + num_cells * mem::size_of::<HeapCellValue>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for AndFrame {
|
||||
type Output = Addr;
|
||||
type Output = HeapCellValue;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
let prelude_offset = prelude_size::<AndFramePrelude>();
|
||||
let index_offset = (index - 1) * mem::size_of::<Addr>();
|
||||
let index_offset = (index - 1) * mem::size_of::<HeapCellValue>();
|
||||
|
||||
unsafe {
|
||||
let ptr = mem::transmute::<&AndFrame, *const u8>(self);
|
||||
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||
|
||||
&*(ptr as *const Addr)
|
||||
&*(ptr as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,13 +81,35 @@ impl Index<usize> for AndFrame {
|
||||
impl IndexMut<usize> for AndFrame {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
let prelude_offset = prelude_size::<AndFramePrelude>();
|
||||
let index_offset = (index - 1) * mem::size_of::<Addr>();
|
||||
let index_offset = (index - 1) * mem::size_of::<HeapCellValue>();
|
||||
|
||||
unsafe {
|
||||
let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
|
||||
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||
|
||||
&mut *(ptr as *mut Addr)
|
||||
&mut *(ptr as *mut HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Stack {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + index;
|
||||
&*(ptr as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Stack {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + index;
|
||||
&mut *(ptr as *mut HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,18 +132,18 @@ pub(crate) struct OrFrame {
|
||||
}
|
||||
|
||||
impl Index<usize> for OrFrame {
|
||||
type Output = Addr;
|
||||
type Output = HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
let prelude_offset = prelude_size::<OrFramePrelude>();
|
||||
let index_offset = index * mem::size_of::<Addr>();
|
||||
let index_offset = index * mem::size_of::<HeapCellValue>();
|
||||
|
||||
unsafe {
|
||||
let ptr = mem::transmute::<&OrFrame, *const u8>(self);
|
||||
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||
|
||||
&*(ptr as *const Addr)
|
||||
&*(ptr as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,20 +152,20 @@ impl IndexMut<usize> for OrFrame {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
let prelude_offset = prelude_size::<OrFramePrelude>();
|
||||
let index_offset = index * mem::size_of::<Addr>();
|
||||
let index_offset = index * mem::size_of::<HeapCellValue>();
|
||||
|
||||
unsafe {
|
||||
let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
|
||||
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||
|
||||
&mut *(ptr as *mut Addr)
|
||||
&mut *(ptr as *mut HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OrFrame {
|
||||
pub(crate) fn size_of(num_cells: usize) -> usize {
|
||||
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
|
||||
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<HeapCellValue>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,26 +177,39 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn alloc(&mut self, frame_size: usize) -> *mut u8 {
|
||||
loop {
|
||||
let ptr = self.buf.alloc(frame_size);
|
||||
|
||||
if ptr.is_null() {
|
||||
self.buf.grow();
|
||||
} else {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn allocate_and_frame(&mut self, num_cells: usize) -> usize {
|
||||
let frame_size = AndFrame::size_of(num_cells);
|
||||
|
||||
unsafe {
|
||||
let new_top = self.buf.new_block(frame_size);
|
||||
let e = self.buf.top as usize - self.buf.base as usize;
|
||||
let e = self.buf.ptr as usize - self.buf.base as usize;
|
||||
let new_ptr = self.alloc(frame_size);
|
||||
let mut offset = prelude_size::<AndFramePrelude>();
|
||||
|
||||
for idx in 0..num_cells {
|
||||
let offset = prelude_size::<AndFramePrelude>() + idx * mem::size_of::<Addr>();
|
||||
ptr::write(
|
||||
(self.buf.top as usize + offset) as *mut Addr,
|
||||
Addr::StackCell(e, idx + 1),
|
||||
(new_ptr as usize + offset) as *mut HeapCellValue,
|
||||
stack_loc_as_cell!(AndFrame, e, idx + 1),
|
||||
);
|
||||
|
||||
offset += mem::size_of::<HeapCellValue>();
|
||||
}
|
||||
|
||||
let and_frame = &mut *(self.buf.top as *mut AndFrame);
|
||||
let and_frame = &mut *(new_ptr as *mut AndFrame);
|
||||
and_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||
|
||||
self.buf.top = new_top;
|
||||
|
||||
e
|
||||
}
|
||||
}
|
||||
@@ -192,27 +218,27 @@ impl Stack {
|
||||
let frame_size = OrFrame::size_of(num_cells);
|
||||
|
||||
unsafe {
|
||||
let new_top = self.buf.new_block(frame_size);
|
||||
let b = self.buf.top as usize - self.buf.base as usize;
|
||||
let b = self.buf.ptr as usize - self.buf.base as usize;
|
||||
let new_ptr = self.alloc(frame_size);
|
||||
let mut offset = prelude_size::<OrFramePrelude>();
|
||||
|
||||
for idx in 0..num_cells {
|
||||
let offset = prelude_size::<OrFramePrelude>() + idx * mem::size_of::<Addr>();
|
||||
ptr::write(
|
||||
(self.buf.top as usize + offset) as *mut Addr,
|
||||
Addr::StackCell(b, idx),
|
||||
(new_ptr as usize + offset) as *mut HeapCellValue,
|
||||
stack_loc_as_cell!(OrFrame, b, idx),
|
||||
);
|
||||
|
||||
offset += mem::size_of::<HeapCellValue>();
|
||||
}
|
||||
|
||||
let or_frame = &mut *(self.buf.top as *mut OrFrame);
|
||||
let or_frame = &mut *(new_ptr as *mut OrFrame);
|
||||
or_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||
|
||||
self.buf.top = new_top;
|
||||
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub(crate) fn index_and_frame(&self, e: usize) -> &AndFrame {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + e;
|
||||
@@ -220,7 +246,7 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub(crate) fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + e;
|
||||
@@ -228,7 +254,7 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub(crate) fn index_or_frame(&self, b: usize) -> &OrFrame {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + b;
|
||||
@@ -236,7 +262,7 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub(crate) fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + b;
|
||||
@@ -244,31 +270,65 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub(crate) fn truncate(&mut self, b: usize) {
|
||||
if b == 0 {
|
||||
self.inner_truncate(mem::align_of::<Addr>());
|
||||
} else {
|
||||
self.inner_truncate(b);
|
||||
let base = self.buf.base as usize + b;
|
||||
|
||||
if base < self.buf.ptr as usize {
|
||||
self.buf.ptr = base as *mut _;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner_truncate(&mut self, b: usize) {
|
||||
let base = b + self.buf.base as usize;
|
||||
|
||||
if base < self.buf.top as usize {
|
||||
self.buf.top = base as *const _;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn drop_in_place(&mut self) {
|
||||
self.truncate(mem::align_of::<Addr>());
|
||||
|
||||
debug_assert!(if self.buf.top.is_null() {
|
||||
self.buf.top == self.buf.base
|
||||
} else {
|
||||
self.buf.top as usize == self.buf.base as usize + mem::align_of::<Addr>()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
fn stack_tests() {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
let e = wam.machine_st.stack.allocate_and_frame(10); // create an AND frame!
|
||||
let and_frame = wam.machine_st.stack.index_and_frame_mut(e);
|
||||
|
||||
assert_eq!(
|
||||
e,
|
||||
0// 10 * mem::size_of::<HeapCellValue>() + prelude_size::<AndFrame>()
|
||||
);
|
||||
|
||||
assert_eq!(and_frame.prelude.univ_prelude.num_cells, 10);
|
||||
|
||||
for idx in 0..10 {
|
||||
assert_eq!(and_frame[idx + 1], stack_loc_as_cell!(AndFrame, e, idx + 1));
|
||||
}
|
||||
|
||||
and_frame[5] = empty_list_as_cell!();
|
||||
|
||||
assert_eq!(and_frame[5], empty_list_as_cell!());
|
||||
|
||||
let b = wam.machine_st.stack.allocate_or_frame(5);
|
||||
|
||||
let or_frame = wam.machine_st.stack.index_or_frame_mut(b);
|
||||
|
||||
for idx in 0..5 {
|
||||
assert_eq!(or_frame[idx], stack_loc_as_cell!(OrFrame, b, idx));
|
||||
}
|
||||
|
||||
let next_e = wam.machine_st.stack.allocate_and_frame(9); // create an AND frame!
|
||||
let and_frame = wam.machine_st.stack.index_and_frame_mut(next_e);
|
||||
|
||||
for idx in 0..9 {
|
||||
assert_eq!(and_frame[idx + 1], stack_loc_as_cell!(AndFrame, next_e, idx + 1));
|
||||
}
|
||||
|
||||
let and_frame = wam.machine_st.stack.index_and_frame(e);
|
||||
assert_eq!(and_frame[5], empty_list_as_cell!());
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.stack[stack_loc!(AndFrame, e, 5)],
|
||||
empty_list_as_cell!()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,48 +1,53 @@
|
||||
use prolog_parser::ast::*;
|
||||
use prolog_parser::parser::*;
|
||||
|
||||
use crate::machine::machine_errors::CompilationError;
|
||||
use crate::forms::*;
|
||||
use crate::machine::*;
|
||||
use crate::machine::load_state::*;
|
||||
use crate::machine::loader::*;
|
||||
use crate::machine::machine_errors::*;
|
||||
use crate::parser::ast::*;
|
||||
use crate::parser::parser::*;
|
||||
|
||||
use crate::predicate_queue;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
|
||||
pub(crate) trait TermStream: Sized {
|
||||
type Evacuable;
|
||||
pub struct LoadStatePayload<TS> {
|
||||
pub term_stream: TS,
|
||||
pub(super) compilation_target: CompilationTarget,
|
||||
pub(super) retraction_info: RetractionInfo,
|
||||
pub(super) module_op_exports: ModuleOpExports,
|
||||
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
|
||||
pub(super) predicates: PredicateQueue,
|
||||
pub(super) clause_clauses: Vec<(Term, Term)>,
|
||||
}
|
||||
|
||||
pub trait TermStream: Sized {
|
||||
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError>;
|
||||
fn eof(&mut self) -> Result<bool, CompilationError>;
|
||||
fn listing_src(&self) -> &ListingSource;
|
||||
fn evacuate<'a>(loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct BootstrappingTermStream<'a> {
|
||||
pub struct BootstrappingTermStream<'a> {
|
||||
listing_src: ListingSource,
|
||||
parser: Parser<'a, Stream>,
|
||||
pub(super) parser: Parser<'a, Stream>,
|
||||
}
|
||||
|
||||
impl<'a> BootstrappingTermStream<'a> {
|
||||
#[inline]
|
||||
pub(super) fn from_prolog_stream(
|
||||
stream: &'a mut PrologStream,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
flags: MachineFlags,
|
||||
pub(super) fn from_char_reader(
|
||||
stream: Stream,
|
||||
machine_st: &'a mut MachineState,
|
||||
listing_src: ListingSource,
|
||||
) -> Self {
|
||||
let parser = Parser::new(stream, atom_tbl, flags);
|
||||
Self {
|
||||
parser,
|
||||
listing_src,
|
||||
}
|
||||
let parser = Parser::new(stream, machine_st);
|
||||
Self { parser, listing_src }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TermStream for BootstrappingTermStream<'a> {
|
||||
type Evacuable = CompilationTarget;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError> {
|
||||
self.parser.reset();
|
||||
@@ -61,24 +66,9 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
|
||||
fn listing_src(&self) -> &ListingSource {
|
||||
&self.listing_src
|
||||
}
|
||||
|
||||
fn evacuate(mut loader: Loader<Self>) -> Result<Self::Evacuable, SessionError> {
|
||||
if !loader.predicates.is_empty() {
|
||||
loader.compile_and_submit()?;
|
||||
}
|
||||
|
||||
loader
|
||||
.load_state
|
||||
.retraction_info
|
||||
.reset(loader.load_state.wam.code_repo.code.len());
|
||||
|
||||
loader.load_state.remove_module_op_exports();
|
||||
|
||||
Ok(loader.load_state.compilation_target.take())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LiveTermStream {
|
||||
pub struct LiveTermStream {
|
||||
pub(super) term_queue: VecDeque<Term>,
|
||||
pub(super) listing_src: ListingSource,
|
||||
}
|
||||
@@ -93,28 +83,18 @@ impl LiveTermStream {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LoadStatePayload {
|
||||
pub(super) term_stream: LiveTermStream,
|
||||
pub(super) compilation_target: CompilationTarget,
|
||||
pub(super) retraction_info: RetractionInfo,
|
||||
pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>,
|
||||
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
|
||||
pub(super) predicates: PredicateQueue,
|
||||
pub(super) clause_clauses: Vec<(Term, Term)>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for LoadStatePayload {
|
||||
impl<TS> fmt::Debug for LoadStatePayload<TS> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "LoadStatePayload")
|
||||
}
|
||||
}
|
||||
|
||||
impl LoadStatePayload {
|
||||
pub(super) fn new(wam: &Machine) -> Self {
|
||||
impl<TS> LoadStatePayload<TS> {
|
||||
pub(super) fn new(code_repo_len: usize, term_stream: TS) -> Self {
|
||||
Self {
|
||||
term_stream: LiveTermStream::new(ListingSource::User),
|
||||
term_stream,
|
||||
compilation_target: CompilationTarget::default(),
|
||||
retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
|
||||
retraction_info: RetractionInfo::new(code_repo_len),
|
||||
module_op_exports: vec![],
|
||||
non_counted_bt_preds: IndexSet::new(),
|
||||
predicates: predicate_queue![],
|
||||
@@ -124,8 +104,6 @@ impl LoadStatePayload {
|
||||
}
|
||||
|
||||
impl TermStream for LiveTermStream {
|
||||
type Evacuable = LoadStatePayload;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
|
||||
Ok(self.term_queue.pop_front().unwrap())
|
||||
@@ -140,9 +118,4 @@ impl TermStream for LiveTermStream {
|
||||
fn listing_src(&self) -> &ListingSource {
|
||||
&self.listing_src
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn evacuate(loader: Loader<Self>) -> Result<LoadStatePayload, SessionError> {
|
||||
Ok(loader.to_load_state_payload())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user