introduce bespoke Heap type for in-heap partial strings

This commit is contained in:
Mark Thom
2024-05-13 18:00:56 -06:00
committed by Mark Thom
parent f7bbdfe73a
commit c0f72704ec
54 changed files with 7836 additions and 7167 deletions

View File

@@ -48,7 +48,7 @@ macro_rules! drop_iter_on_err {
};
}
fn zero_divisor_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen {
fn zero_divisor_eval_error(stub_gen: impl Fn() -> MachineStub + 'static) -> MachineStubGen {
Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor);
let stub = stub_gen();
@@ -57,7 +57,7 @@ fn zero_divisor_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> Mach
})
}
fn undefined_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen {
fn undefined_eval_error(stub_gen: impl Fn() -> MachineStub + 'static) -> MachineStubGen {
Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::Undefined);
let stub = stub_gen();
@@ -69,7 +69,7 @@ fn undefined_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> Machine
fn numerical_type_error(
valid_type: ValidType,
n: Number,
stub_gen: impl Fn() -> FunctorStub + 'static,
stub_gen: impl Fn() -> MachineStub + 'static,
) -> MachineStubGen {
Box::new(move |machine_st| {
let type_error = machine_st.type_error(valid_type, n);
@@ -528,7 +528,7 @@ pub(crate) fn min(n1: Number, n2: Number) -> Result<Number, MachineStubGen> {
pub fn rational_from_number(
n: Number,
stub_gen: impl Fn() -> FunctorStub + 'static,
stub_gen: impl Fn() -> MachineStub + 'static,
arena: &mut Arena,
) -> Result<TypedArenaPtr<Rational>, MachineStubGen> {
match n {
@@ -1140,7 +1140,7 @@ impl MachineState {
pub fn get_rational(
&mut self,
at: &ArithmeticTerm,
caller: impl Fn() -> FunctorStub + 'static,
caller: impl Fn() -> MachineStub + 'static,
) -> Result<TypedArenaPtr<Rational>, MachineStub> {
let n = self.get_number(at)?;
@@ -1154,6 +1154,8 @@ impl MachineState {
&mut self,
value: HeapCellValue,
) -> Result<Number, MachineStub> {
debug_assert!(value.is_ref());
let stub_gen = || functor_stub(atom!("is"), 2);
let root_loc = if value.is_ref() && !value.is_stack_var() {
@@ -1178,7 +1180,7 @@ impl MachineState {
(HeapCellValueTag::Str, s) => {
cell_as_atom_cell!(self.heap[s]).get_name_and_arity()
}
(HeapCellValueTag::Lis | HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset |
(HeapCellValueTag::Lis | // HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset |
HeapCellValueTag::PStrLoc) => {
(atom!("."), 2)
}
@@ -1458,7 +1460,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();
assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.heap_loc)),
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
Ok(Number::Fixnum(Fixnum::build_with(8))),
);
@@ -1468,7 +1470,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "5 * 4 - 1.", &op_dir).unwrap();
assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.heap_loc)),
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
Ok(Number::Fixnum(Fixnum::build_with(19))),
);
@@ -1478,7 +1480,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "sign(-1).", &op_dir).unwrap();
assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.heap_loc)),
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
Ok(Number::Fixnum(Fixnum::build_with(-1)))
);
}

View File

@@ -38,6 +38,7 @@ verify_attrs([], _, _, []).
call_goals([ListOfGoalLists | ListsCubed]) :-
'$debug_hook',
call_goals_0(ListOfGoalLists),
call_goals(ListsCubed).
call_goals([]).

View File

@@ -6,7 +6,6 @@ use crate::types::*;
use indexmap::IndexSet;
use std::cmp::Ordering;
use std::vec::IntoIter;
pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
@@ -55,32 +54,36 @@ impl MachineState {
self.attr_var_init.bindings.push((h, addr));
}
fn populate_var_and_value_lists(&mut self) -> (HeapCellValue, HeapCellValue) {
fn populate_var_and_value_lists(&mut self) -> Result<(HeapCellValue, HeapCellValue), usize> {
let size = self.attr_var_init.bindings.len();
let iter = self
.attr_var_init
.bindings
.iter()
.map(|(ref h, _)| attr_var_as_cell!(*h));
let var_list_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, iter));
let var_list_addr = sized_iter_to_heap_list(&mut self.heap, size, iter)?;
let iter = self.attr_var_init.bindings.drain(0..).map(|(_, ref v)| *v);
let value_list_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, iter));
let value_list_addr = sized_iter_to_heap_list(&mut self.heap, size, iter)?;
(var_list_addr, value_list_addr)
Ok((var_list_addr, value_list_addr))
}
fn verify_attributes(&mut self) {
fn verify_attributes(&mut self) -> Result<(), usize> {
for (h, _) in &self.attr_var_init.bindings {
self.heap[*h] = attr_var_as_cell!(*h);
}
let (var_list_addr, value_list_addr) = self.populate_var_and_value_lists();
let (var_list_addr, value_list_addr) = self.populate_var_and_value_lists()?;
self[temp_v!(1)] = var_list_addr;
self[temp_v!(2)] = value_list_addr;
Ok(())
}
pub(super) fn gather_attr_vars_created_since(&mut self, b: usize) -> IntoIter<HeapCellValue> {
pub(super) fn gather_attr_vars_created_since(&mut self, b: usize) -> Vec<HeapCellValue> {
let mut attr_vars: Vec<_> = if b >= self.attr_var_init.attr_var_queue.len() {
vec![]
} else {
@@ -104,10 +107,10 @@ impl MachineState {
});
attr_vars.dedup();
attr_vars.into_iter()
attr_vars
}
pub(super) fn verify_attr_interrupt(&mut self, p: usize, arity: usize) {
pub(super) fn verify_attr_interrupt(&mut self, p: usize, arity: usize) -> Result<(), usize> {
self.allocate(arity + 3);
let e = self.e;
@@ -121,14 +124,18 @@ impl MachineState {
and_frame[arity + 2] = fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[arity + 3] = fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
self.verify_attributes();
self.verify_attributes()?;
self.num_of_args = 3;
self.b0 = self.b;
self.p = p;
Ok(())
}
pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> {
debug_assert!(cell.is_ref());
let mut seen_set = IndexSet::new();
let mut seen_vars = vec![];
let root_loc = if cell.is_ref() {

View File

@@ -1232,15 +1232,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
fn compile_standalone_clause(
&mut self,
term: FocusedHeap,
term: TermWriteResult,
settings: CodeGenSettings,
) -> Result<StandaloneCompileResult, SessionError> {
let mut preprocessor = Preprocessor::new(settings);
let clause = self.try_term_to_tl(term, &mut preprocessor)?;
let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
let clause = preprocessor.try_term_to_tl(self, term)?;
let machine_st = LS::machine_st(&mut self.payload);
let mut cg = CodeGenerator::new(settings);
let clause_code = cg.compile_predicate(vec![clause])?;
let clause_code = cg.compile_predicate(&mut machine_st.heap, vec![clause])?;
Ok(StandaloneCompileResult {
clause_code,
@@ -1265,11 +1266,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut preprocessor = Preprocessor::new(settings);
for term in predicates.predicates.drain(0..) {
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
clauses.push(preprocessor.try_term_to_tl(self, term)?);
}
let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
let mut code = cg.compile_predicate(clauses)?;
let machine_st = LS::machine_st(&mut self.payload);
let mut cg = CodeGenerator::new(settings);
let mut code = cg.compile_predicate(&mut machine_st.heap, clauses)?;
if settings.is_extensible {
let mut clause_clause_locs = VecDeque::new();
@@ -1466,7 +1469,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
pub(super) fn incremental_compile_clause(
&mut self,
key: PredicateKey,
clause: FocusedHeap,
clause: TermWriteResult,
compilation_target: CompilationTarget,
non_counted_bt: bool,
append_or_prepend: AppendOrPrepend,
@@ -2005,7 +2008,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
&mut self,
key: PredicateKey,
compilation_target: CompilationTarget,
clause_clauses: Vec<FocusedHeap>,
clause_clauses: Vec<TermWriteResult>,
append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> {
let clause_clause_compilation_target = match compilation_target {
@@ -2099,15 +2102,19 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
let key = self
let key = match self
.payload
.predicates
.first()
.and_then(|cl| {
let arity = ClauseInfo::arity(cl);
ClauseInfo::name(cl).map(|name| (name, arity))
})
.ok_or(SessionError::NamelessEntry)?;
.map(|term| term.focus) {
Some(focus) => {
clause_predicate_key(self.machine_heap(), focus)
.ok_or(SessionError::NamelessEntry)?
}
None => {
return Err(SessionError::NamelessEntry);
}
};
let listing_src_file_name = self.listing_src_file_name();
@@ -2285,34 +2292,40 @@ impl Machine {
) -> Result<(), SessionError> {
let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
let new_header_loc = self.machine_st.heap.len();
let new_header_loc = self.machine_st.heap.cell_len();
let arity = vars.len();
let term_loc = self.machine_st.heap.cell_len() + 1 + arity;
self.machine_st.heap.push(atom_as_cell!(atom!(""), arity));
let mut writer = self.machine_st.heap.reserve(4 + arity)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
for var in vars {
self.machine_st.heap.push(var);
}
writer.write_with(move |section| {
section.push_cell(atom_as_cell!(atom!(""), arity));
let head_loc = if arity > 0 {
str_loc_as_cell!(new_header_loc)
} else {
heap_loc_as_cell!(new_header_loc)
};
for var in vars {
section.push_cell(var);
}
let term_loc = self.machine_st.heap.len();
let head_loc = if arity > 0 {
str_loc_as_cell!(new_header_loc)
} else {
heap_loc_as_cell!(new_header_loc)
};
self.machine_st.heap.push(atom_as_cell!(atom!(":-"), 2));
self.machine_st.heap.push(head_loc);
self.machine_st.heap.push(body_cell);
section.push_cell(atom_as_cell!(atom!(":-"), 2));
section.push_cell(head_loc);
section.push_cell(body_cell);
});
let mut compile = || {
use crate::heap_iter::eager_stackful_preorder_iter;
let mut loader: Loader<'_, InlineLoadState<'_>> =
Loader::new(self, InlineTermStream {});
let mut term = loader.copy_term_from_heap(str_loc_as_cell!(term_loc));
let machine_st = InlineLoadState::machine_st(&mut loader.payload);
let term_loc = str_loc_as_cell!(term_loc);
let term = TermWriteResult::from(&mut machine_st.heap, term_loc)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
let settings = CodeGenSettings {
global_clock_tick: None,
@@ -2320,12 +2333,6 @@ impl Machine {
non_counted_bt: true,
};
let value = term.heap[term.focus];
term.inverse_var_locs = inverse_var_locs_from_iter(
eager_stackful_preorder_iter(&mut term.heap, value),
);
loader.compile_standalone_clause(term, settings)
};

View File

@@ -1,10 +1,11 @@
use crate::atom_table::*;
use crate::machine::get_structure_index;
use crate::machine::heap::*;
use crate::machine::stack::*;
use crate::types::*;
use std::mem;
use std::ops::IndexMut;
use std::ops::{IndexMut, Range};
type Trail = Vec<(Ref, HeapCellValue)>;
@@ -17,22 +18,31 @@ pub enum AttrVarPolicy {
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 push_cell(&mut self, value: HeapCellValue) -> Result<(), usize>;
fn push_attr_var_queue(&mut self, attr_var_loc: usize);
fn stack(&mut self) -> &mut Stack;
fn threshold(&self) -> usize;
// returns the tail location of the pstr on success
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize>;
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize;
fn pstr_at(&self, loc: usize) -> bool;
fn next_non_pstr_cell_index(&self, loc: usize) -> usize;
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize>;
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize>;
}
pub(crate) fn copy_term<T: CopierTarget>(
target: T,
addr: HeapCellValue,
attr_var_policy: AttrVarPolicy,
) {
) -> Result<(), usize> {
let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
copy_term_state.copy_term_impl(addr);
copy_term_state.copy_attr_var_lists();
copy_term_state.copy_term_impl(addr)?;
copy_term_state.copy_attr_var_lists()?;
copy_term_state.unwind_trail();
Ok(())
}
#[derive(Debug)]
@@ -67,14 +77,14 @@ impl<T: CopierTarget> CopyTermState<T> {
self.trail.push((Ref::heap_cell(addr), trail_item));
}
fn copy_list(&mut self, addr: usize) {
fn copy_list(&mut self, addr: usize) -> Result<(), usize> {
for offset in 0..2 {
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 Ok(());
}
}
_ => {
@@ -83,14 +93,10 @@ impl<T: CopierTarget> CopyTermState<T> {
}
let threshold = self.target.threshold();
self.target.copy_slice_to_end(addr .. addr + 2)?;
*self.value_at_scan() = list_loc_as_cell!(threshold);
for i in 0..2 {
let hcv = self.target[addr + i];
self.target.push(hcv);
}
let cdr = self
.target
.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
@@ -113,80 +119,72 @@ impl<T: CopierTarget> CopyTermState<T> {
}
self.scan += 1;
Ok(())
}
fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) {
read_heap_cell!(self.target[pstr_loc],
(HeapCellValueTag::PStrLoc, h) => {
debug_assert!(h >= self.old_h);
/*
* write a null byte to the first word of a partial string to
* flag that it has been copied followed by the copied
* string's index in the next 7 bytes. write the bytes in big
* endian order so that the null byte is at index 0.
*/
fn write_pstr_index(&mut self, head_cell_idx: usize, threshold: usize) {
let bytes = u64::to_be_bytes(threshold as u64);
debug_assert_eq!(bytes[0], 0);
self.target[head_cell_idx] = HeapCellValue::from_bytes(bytes);
}
*self.value_at_scan() = match scan_tag {
HeapCellValueTag::PStrLoc => {
pstr_loc_as_cell!(h)
}
tag => {
debug_assert_eq!(tag, HeapCellValueTag::PStrOffset);
pstr_offset_as_cell!(h)
}
};
fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> {
let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc);
let head_byte_idx = heap_index!(head_cell_idx);
let pstr_offset = pstr_loc - head_byte_idx;
self.scan += 1;
return;
}
(HeapCellValueTag::Var, h) => {
debug_assert!(h >= self.old_h);
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
// if a partial string has been copied previously, we
// track it by writing a null byte to its first word, which is trailed,
// and then the new pstr_loc in the word's remaining 7 bytes. see write_pstr_index
// comment.
*self.value_at_scan() = pstr_offset_as_cell!(h);
self.scan += 1;
if self.target[head_cell_idx].into_bytes()[0] == 0u8 {
let head_bytes = self.target[head_cell_idx].into_bytes();
let new_pstr_loc = u64::from_be_bytes(head_bytes) as usize;
return;
}
_ => {}
);
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(new_pstr_loc) + pstr_offset);
self.scan += 1;
return Ok(());
}
let threshold = self.target.threshold();
let tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?;
let replacement = read_heap_cell!(self.target[pstr_loc],
(HeapCellValueTag::CStr) => {
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(threshold) + pstr_offset);
*self.value_at_scan() = pstr_offset_as_cell!(threshold);
self.target.push(self.target[pstr_loc]);
self.trail.push((Ref::heap_cell(head_cell_idx), self.target[head_cell_idx]));
self.write_pstr_index(head_cell_idx, threshold);
heap_loc_as_cell!(threshold)
}
_ => {
*self.value_at_scan() = if scan_tag == HeapCellValueTag::PStrLoc {
pstr_loc_as_cell!(threshold)
} else {
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
pstr_offset_as_cell!(threshold)
};
let tail_cell = self.target[tail_loc];
let mut writer = self.target.reserve(1)?;
self.target.push(self.target[pstr_loc]);
self.target.push(self.target[pstr_loc + 1]);
pstr_loc_as_cell!(threshold)
}
);
writer.write_with(|section| {
section.push_cell(tail_cell);
});
self.scan += 1;
let trail_item = mem::replace(&mut self.target[pstr_loc], replacement);
self.trail.push((Ref::heap_cell(pstr_loc), trail_item));
Ok(())
}
fn copy_attr_var_lists(&mut self) {
fn copy_attr_var_lists(&mut self) -> Result<(), usize> {
while !self.attr_var_list_locs.is_empty() {
let iter = std::mem::take(&mut self.attr_var_list_locs);
let mut list_loc_vec = std::mem::take(&mut self.attr_var_list_locs);
for (threshold, list_loc) in iter {
while let Some((threshold, list_loc)) = list_loc_vec.pop() {
self.target[threshold] = list_loc_as_cell!(self.target.threshold());
self.target.push_attr_var_queue(threshold - 1);
self.copy_attr_var_list(list_loc);
self.copy_attr_var_list(list_loc)?;
}
}
Ok(())
}
/*
@@ -194,36 +192,36 @@ impl<T: CopierTarget> CopyTermState<T> {
* structure which is ensured by this function and not at all by
* the vanilla copier.
*/
fn copy_attr_var_list(&mut self, mut list_addr: HeapCellValue) {
fn copy_attr_var_list(&mut self, mut list_addr: HeapCellValue) -> Result<(), usize> {
while let HeapCellValueTag::Lis = list_addr.get_tag() {
let threshold = self.target.threshold();
let heap_loc = list_addr.get_value() as usize;
let str_loc = self.target[heap_loc].get_value() as usize;
let str_cell = self.target[str_loc];
let mut writer = self.target.reserve(3).unwrap();
self.target.push(heap_loc_as_cell!(threshold + 2));
self.target.push(heap_loc_as_cell!(threshold + 1));
writer.write_with(|section| {
section.push_cell(heap_loc_as_cell!(threshold + 2));
section.push_cell(heap_loc_as_cell!(threshold + 1));
read_heap_cell!(self.target[str_loc],
(HeapCellValueTag::Atom) => {
self.target.push(self.target[str_loc]);
if str_cell.to_atom().is_some() {
section.push_cell(str_cell);
}
(HeapCellValueTag::Str) => {
self.copy_term_impl(self.target[str_loc]);
}
_ => {
unreachable!();
}
);
});
debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
self.copy_term_impl(str_cell)?;
list_addr = self.target[heap_loc + 1];
if HeapCellValueTag::Lis == list_addr.get_tag() {
self.target[threshold + 1] = list_loc_as_cell!(self.target.threshold());
}
}
Ok(())
}
fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) {
fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) -> Result<(), usize> {
read_heap_cell!(addr,
(HeapCellValueTag::Var, h) => {
self.target[frontier] = heap_loc_as_cell!(frontier);
@@ -250,8 +248,12 @@ impl<T: CopierTarget> CopyTermState<T> {
self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
self.target.push(attr_var_as_cell!(threshold));
self.target.push(heap_loc_as_cell!(threshold + 1));
let mut writer = self.target.reserve(2).unwrap();
writer.write_with(|section| {
section.push_cell(attr_var_as_cell!(threshold));
section.push_cell(heap_loc_as_cell!(threshold + 1));
});
let old_list_link = self.target[h + 1];
self.trail.push((Ref::heap_cell(h + 1), old_list_link));
@@ -266,9 +268,11 @@ impl<T: CopierTarget> CopyTermState<T> {
unreachable!()
}
);
Ok(())
}
fn copy_var(&mut self, addr: HeapCellValue) {
fn copy_var(&mut self, addr: HeapCellValue) -> Result<(), usize> {
let index = addr.get_value() as usize;
let rd = self.target.deref(addr);
let ra = self.target.store(rd);
@@ -278,7 +282,7 @@ impl<T: CopierTarget> CopyTermState<T> {
if h >= self.old_h {
*self.value_at_scan() = ra;
self.scan += 1;
return;
return Ok(());
}
}
(HeapCellValueTag::Lis, h) => {
@@ -292,46 +296,57 @@ impl<T: CopierTarget> CopyTermState<T> {
);
self.scan += 1;
return;
return Ok(());
}
}
_ => {}
);
if rd == ra {
self.reinstantiate_var(ra, self.scan);
self.reinstantiate_var(ra, self.scan)?;
self.scan += 1;
} else {
*self.value_at_scan() = ra;
}
Ok(())
}
fn copy_structure(&mut self, addr: usize) {
fn copy_structure(&mut self, addr: usize) -> Result<(), usize> {
read_heap_cell!(self.target[addr],
(HeapCellValueTag::Atom, (name, arity)) => {
(HeapCellValueTag::Atom, (_name, arity)) => {
let threshold = self.target.threshold();
*self.value_at_scan() = str_loc_as_cell!(threshold);
self.target.copy_slice_to_end(addr .. addr + 1 + arity)?;
let trail_item = mem::replace(
&mut self.target[addr],
str_loc_as_cell!(threshold),
);
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];
self.target.push(hcv);
}
*/
if !self.target.pstr_at(addr + 1 + arity) {
let index_cell = self.target[addr + 1 + arity];
let index_cell = self.target[addr + 1 + arity];
if get_structure_index(index_cell).is_some() {
// copy the index pointer trailing this
// inlined or expanded goal.
let mut writer = self.target.reserve(1).unwrap();
if get_structure_index(index_cell).is_some() {
// copy the index pointer trailing this
// inlined or expanded goal.
self.target.push(index_cell);
writer.write_with(|section| {
section.push_cell(index_cell);
});
}
}
}
(HeapCellValueTag::Str, h) => {
@@ -343,37 +358,51 @@ impl<T: CopierTarget> CopyTermState<T> {
);
self.scan += 1;
Ok(())
}
fn copy_term_impl(&mut self, addr: HeapCellValue) {
fn copy_term_impl(&mut self, addr: HeapCellValue) -> Result<(), usize> {
self.scan = self.target.threshold();
self.target.push(addr);
let mut writer = self.target.reserve(1)?;
writer.write_with(|section| {
section.push_cell(addr);
});
while self.scan < self.target.threshold() {
if self.target.pstr_at(self.scan) {
self.scan = self.target.next_non_pstr_cell_index(self.scan);
continue;
}
let addr = *self.value_at_scan();
read_heap_cell!(addr,
(HeapCellValueTag::Lis, h) => {
if h >= self.old_h {
self.scan += 1;
continue;
} else {
self.copy_list(h);
self.copy_list(h)
}
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var) => {
self.copy_var(addr);
self.copy_var(addr)
}
(HeapCellValueTag::Str, h) => {
self.copy_structure(h);
self.copy_structure(h)
}
(HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrOffset, pstr_loc) => {
self.copy_partial_string(addr.get_tag(), pstr_loc);
(HeapCellValueTag::PStrLoc, pstr_loc) => {
self.copy_partial_string(pstr_loc)
}
_ => {
self.scan += 1;
continue;
}
);
)?;
}
Ok(())
}
fn unwind_trail(mut self) {
@@ -395,19 +424,25 @@ impl<T: CopierTarget> CopyTermState<T> {
#[cfg(test)]
mod tests {
use super::*;
use crate::functor_macro::*;
use crate::machine::mock_wam::*;
#[test]
fn copier_tests() {
let mut wam = MockWAM::new();
// clear the heap of resource error data etc
wam.machine_st.heap.clear();
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)]));
let mut functor_writer = Heap::functor_writer(
functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]),
);
functor_writer(&mut wam.machine_st.heap).unwrap();
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));
@@ -415,7 +450,7 @@ mod tests {
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy);
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
// check that the original heap state is still intact.
@@ -430,69 +465,62 @@ mod tests {
wam.machine_st.heap.clear();
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
writer.write_with(|section| {
section.push_pstr("abc ");
section.push_cell(pstr_loc_as_cell!(heap_index!(2)));
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &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)));
section.push_pstr("def");
section.push_cell(pstr_loc_as_cell!(0));
});
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy);
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
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))
wam.machine_st.heap.slice_to_str(0, "abc ".len()),
"abc "
);
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[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(
wam.machine_st.heap[12],
fixnum_as_cell!(Fixnum::build_with(0i64))
wam.machine_st.heap.slice_to_str(heap_index!(2), "def".len()),
"def"
);
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(0));
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(5)));
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(5), "abc ".len()),
"abc "
);
assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7)));
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(7), "def".len()),
"def"
);
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(heap_index!(5)));
wam.machine_st.heap.clear();
wam.machine_st.heap.extend(functor!(
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
atom(a_atom),
atom(b_atom),
atom(a_atom),
cell(str_loc_as_cell!(0))
atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(a_atom),
str_loc_as_cell(0)
]
));
functor_writer(&mut wam.machine_st.heap).unwrap();
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy);
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 4));

View File

@@ -1,4 +1,5 @@
use crate::atom_table::*;
use crate::machine::heap::*;
use crate::types::*;
/* Use the pointer reversal technique of the Deutsch-Schorr-Waite
@@ -11,7 +12,7 @@ use crate::types::*;
* - Cells are only marked during the backward phase
* - Visiting subterms of a visited compound does not immediately shift to the backward phase
* - The heads of LIS structures are both marked and forwarded rather
* than just forwarded to distinguish them from tails;
* than just forwarded to distinguish them from tails
* continue_forwarding() checks for this before entering the forward
* phase
*
@@ -22,7 +23,7 @@ use crate::types::*;
#[derive(Debug)]
pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> {
pub(crate) heap: &'a mut [HeapCellValue],
pub(crate) heap: &'a mut Heap,
start: usize,
current: usize,
next: u64,
@@ -31,7 +32,7 @@ pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> {
}
impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
pub(crate) fn new(heap: &'a mut Heap, start: usize) -> Self {
heap[start].set_forwarding_bit(true);
let next = heap[start].get_value();
@@ -127,7 +128,7 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
self.current = next;
self.next = temp;
if self.next < self.heap.len() as u64 {
if self.next < self.heap.cell_len() as u64 {
return Some(HeapCellValue::build_with(tag, next as u64));
}
}
@@ -205,8 +206,7 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
}
HeapCellValueTag::PStrLoc => {
let h = self.next as usize;
let cell = self.heap[h];
let last_cell_loc = h + 1;
let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
if self.heap[last_cell_loc].get_forwarding_bit() {
if self.cycle_detection_active() {
@@ -225,39 +225,7 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
self.heap[last_cell_loc].set_value(self.current as u64);
self.current = last_cell_loc;
return Some(cell);
}
HeapCellValueTag::PStrOffset => {
let h = self.next as usize;
let cell = self.heap[h];
let last_cell_loc = h + 1;
if self.heap[h].get_tag() == HeapCellValueTag::PStr {
if self.heap[last_cell_loc].get_forwarding_bit() {
if self.cycle_detection_active() {
self.cycle_found = true;
return None;
} else if self.backward() {
return None;
}
continue;
}
self.heap[last_cell_loc].set_forwarding_bit(true);
self.next = self.heap[last_cell_loc].get_value();
self.heap[last_cell_loc].set_value(self.current as u64);
self.current = last_cell_loc;
} else {
debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::CStr);
self.next = self.heap[h].get_value();
self.heap[h].set_value(self.current as u64);
self.current = h;
}
return Some(cell);
return Some(pstr_loc_as_cell!(h));
}
tag @ HeapCellValueTag::Atom => {
let cell = HeapCellValue::build_with(tag, self.next);
@@ -269,11 +237,6 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
return None;
}
}
HeapCellValueTag::PStr => {
if self.backward() {
return None;
}
}
_ => {
return Some(self.backward_and_return());
}

View File

@@ -3,6 +3,7 @@ use crate::forms::*;
use crate::instructions::*;
use crate::iterators::fact_iterator;
use crate::machine::Stack;
use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::CompilationError;
use crate::machine::preprocessor::*;
@@ -320,13 +321,12 @@ impl VariableClassifier {
}
}
pub fn classify_fact(
pub fn classify_fact<'a, LS: LoadState<'a>>(
mut self,
term: &mut FocusedHeap,
loader: &mut Loader<'a, LS>,
term: &TermWriteResult,
) -> Result<ClassifyFactResult, CompilationError> {
let focus = term.focus;
self.classify_head_variables(term, focus)?;
self.classify_head_variables(loader, &term, term.focus)?;
Ok(self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
@@ -337,12 +337,14 @@ impl VariableClassifier {
pub fn classify_rule<'a, LS: LoadState<'a>>(
mut self,
loader: &mut Loader<'a, LS>,
term: &mut FocusedHeap,
term: &TermWriteResult,
) -> Result<ClassifyRuleResult, CompilationError> {
let head_loc = term.nth_arg(term.focus, 1).unwrap();
let body_loc = term.nth_arg(term.focus, 2).unwrap();
let heap = &mut LS::machine_st(&mut loader.payload).heap;
self.classify_head_variables(term, head_loc)?;
let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
let body_loc = term_nth_arg(heap, term.focus, 2).unwrap();
self.classify_head_variables(loader, &term, head_loc)?;
self.root_set.insert(self.current_branch_num.clone());
let mut query_terms = self.classify_body_variables(loader, term, body_loc)?;
@@ -385,8 +387,8 @@ impl VariableClassifier {
&mut self,
arg_c: usize,
arity: usize,
term: &mut FocusedHeap,
term_loc: usize,
term: &mut FocusedHeapRefMut,
inverse_var_locs: &InverseVarLocs,
context: GenContext,
) {
let classify_info = ClassifyInfo { arg_c, arity };
@@ -394,9 +396,9 @@ impl VariableClassifier {
let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>(
&mut term.heap,
term.heap,
&mut stack,
term_loc,
term.focus,
);
// second arg is true to iterate the root, which may be a variable
@@ -407,7 +409,7 @@ impl VariableClassifier {
}
let var_loc = subterm.get_value() as usize;
let var = to_classified_var(&term.inverse_var_locs, var_loc);
let var = to_classified_var(inverse_var_locs, var_loc);
self.probe_body_var(
context,
@@ -468,27 +470,21 @@ impl VariableClassifier {
self.probe_body_var(context, var_info);
}
fn classify_head_variables(
fn classify_head_variables<'a, LS: LoadState<'a>>(
&mut self,
term: &mut FocusedHeap,
loader: &mut Loader<'a, LS>,
term: &TermWriteResult,
head_loc: usize,
) -> Result<(), CompilationError> {
let arity = read_heap_cell!(term.deref_loc(head_loc),
(HeapCellValueTag::Str, s) => {
cell_as_atom_cell!(term.heap[s]).get_arity()
}
(HeapCellValueTag::Atom) => {
return Ok(());
}
_ => {
return Err(CompilationError::InvalidRuleHead);
}
);
let heap = &mut LS::machine_st(&mut loader.payload).heap;
let arity = term_predicate_key(heap, head_loc)
.and_then(|(_, arity)| Some(arity))
.ok_or(CompilationError::InvalidRuleHead)?;
let mut classify_info = ClassifyInfo { arg_c: 1, arity };
if arity > 0 {
let (_term_loc, value) = subterm_index(&term.heap, head_loc);
let (_term_loc, value) = subterm_index(heap, head_loc);
let str_offset = value.get_value() as usize;
debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
@@ -497,7 +493,7 @@ impl VariableClassifier {
let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>(
&mut term.heap,
heap,
&mut stack,
idx,
);
@@ -571,11 +567,11 @@ impl VariableClassifier {
fn classify_body_variables<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
terms: &mut FocusedHeap,
terms: &TermWriteResult,
term_loc: usize,
) -> Result<ChunkedTermVec, CompilationError> {
let mut state_stack = vec![TraversalState::Term {
subterm: terms.heap[term_loc],
subterm: loader.machine_heap()[term_loc],
term_loc,
}];
let mut build_stack = ChunkedTermVec::new();
@@ -684,13 +680,21 @@ impl VariableClassifier {
for (arg_c, term_loc) in
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
{
self.probe_body_term(arg_c + 1, $key.1, terms, term_loc, context);
let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
self.probe_body_term(
arg_c + 1,
$key.1,
&mut term,
&terms.inverse_var_locs,
context,
);
}
build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
loader,
$key,
terms.as_ref_mut($term_loc),
&terms,
HeapCellValue::build_with($tag, $term_loc as u64),
self.call_policy,
)));
@@ -706,9 +710,17 @@ impl VariableClassifier {
let context = build_stack.current_gen_context();
for (arg_c, term_loc) in
($term_loc + 1..$term_loc + $key.1 + 1).enumerate()
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
{
self.probe_body_term(arg_c + 1, $key.1, terms, term_loc, context);
let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
self.probe_body_term(
arg_c + 1,
$key.1,
&mut term,
&terms.inverse_var_locs,
context,
);
}
build_stack.push_chunk_term(QueryTerm::Clause(
@@ -716,7 +728,7 @@ impl VariableClassifier {
loader,
$key,
$module_name,
terms.as_ref_mut($term_loc),
&terms,
HeapCellValue::build_with($tag, $term_loc as u64),
self.call_policy,
),
@@ -725,26 +737,28 @@ impl VariableClassifier {
}
loop {
let heap = loader.machine_heap();
read_heap_cell!(subterm,
(HeapCellValueTag::Str, subterm_loc) => {
let (name, arity) = cell_as_atom_cell!(terms.heap[subterm_loc])
let (name, arity) = cell_as_atom_cell!(heap[subterm_loc])
.get_name_and_arity();
match (name, arity) {
(atom!("->") | atom!(";") | atom!(","), 3) => {
if blunt_index_ptr(&mut terms.heap, (name, 2), subterm_loc) {
subterm = terms.heap[subterm_loc];
if blunt_index_ptr(heap, (name, 2), subterm_loc) {
subterm = heap[subterm_loc];
continue;
}
add_chunk!((name, 2), HeapCellValueTag::Str, subterm_loc);
}
(atom!(","), 2) => {
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap();
let head = terms.heap[head_loc];
let head_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let tail_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let head = heap[head_loc];
let iter = unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(","))
let iter = unfold_by_str_locs(heap, tail_loc, atom!(","))
.into_iter()
.rev()
.chain(std::iter::once((head, head_loc)))
@@ -754,15 +768,15 @@ impl VariableClassifier {
state_stack.extend(iter);
}
(atom!(";"), 2) => {
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap();
let head_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let tail_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let head = terms.heap[head_loc];
let head = heap[head_loc];
let first_branch_num = self.current_branch_num.split();
let branches: Vec<_> = std::iter::once((head, head_loc))
.chain(
unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(";"))
unfold_by_str_locs(heap, tail_loc, atom!(";"))
.into_iter(),
)
.collect();
@@ -807,11 +821,11 @@ impl VariableClassifier {
build_stack.current_chunk_num += 1;
}
(atom!("->"), 2) => {
let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
let then_term_loc = terms.nth_arg(subterm_loc, 2).unwrap();
let if_term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let then_term_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let if_term = terms.heap[if_term_loc];
let then_term = terms.heap[then_term_loc];
let if_term = heap[if_term_loc];
let then_term = heap[then_term_loc];
let prev_b = if matches!(
state_stack.last(),
@@ -851,8 +865,8 @@ impl VariableClassifier {
self.var_num += 1;
}
(atom!("\\+"), 1) => {
let not_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
let not_term = terms.heap[not_term_loc];
let not_term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let not_term = heap[not_term_loc];
let build_stack_len = build_stack.len();
build_stack.reserve_branch(2);
@@ -886,18 +900,19 @@ impl VariableClassifier {
self.var_num += 1;
}
(atom!(":"), 2) => {
let module_name_loc = terms.nth_arg(subterm_loc, 1).unwrap();
let predicate_term_loc = terms.nth_arg(subterm_loc, 2).unwrap();
let module_name_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let predicate_term_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let mut focused = FocusedHeapRefMut::from(heap, module_name_loc);
let module_name = terms.deref_loc(module_name_loc);
let predicate_term = terms.deref_loc(predicate_term_loc);
let module_name = focused.deref_loc(module_name_loc);
let predicate_term = focused.deref_loc(predicate_term_loc);
read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
read_heap_cell!(predicate_term,
(HeapCellValueTag::Str, s) => {
let key = cell_as_atom_cell!(terms.heap[s])
let key = cell_as_atom_cell!(heap[s])
.get_name_and_arity();
add_qualified_chunk!(
@@ -933,25 +948,40 @@ impl VariableClassifier {
let context = build_stack.current_gen_context();
self.probe_body_term(1, 0, terms, module_name_loc, context);
self.probe_body_term(2, 0, terms, predicate_term_loc, context);
focused.focus = module_name_loc;
let h = terms.heap.len();
self.probe_body_term(
1, 0, &mut focused, &terms.inverse_var_locs, context,
);
terms.heap.push(atom_as_cell!(atom!("call"), 1));
terms.heap.push(str_loc_as_cell!(subterm_loc));
focused.focus = predicate_term_loc;
self.probe_body_term(
2, 0, &mut focused, &terms.inverse_var_locs, context,
);
let h = heap.cell_len();
heap.push_cell(atom_as_cell!(atom!("call"), 1))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
heap.push_cell(str_loc_as_cell!(subterm_loc))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
loader,
(atom!("call"), 1),
terms.as_ref_mut(h),
terms,
str_loc_as_cell!(h),
self.call_policy,
)));
}
(atom!("$call_with_inference_counting"), 1) => {
let term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
let subterm = terms.deref_loc(term_loc);
let term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let heap = loader.machine_heap();
let subterm = heap_bound_store(
heap,
heap_bound_deref(heap, heap[term_loc]),
);
state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
state_stack.push(TraversalState::Term { subterm, term_loc });
@@ -973,17 +1003,9 @@ impl VariableClassifier {
add_chunk!((name, 0), HeapCellValueTag::Var, term_loc);
}
}
(HeapCellValueTag::Char, c) => {
if c == '!' {
let context = build_stack.current_gen_context();
state_stack.push(self.new_cut_state(context));
} else {
return Err(CompilationError::InadmissibleQueryTerm);
}
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h != term_loc {
subterm = terms.heap[h];
subterm = heap[h];
term_loc = h;
continue;
}

View File

@@ -1,5 +1,6 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::functor_macro::*;
use crate::instructions::*;
use crate::machine::arithmetic_ops::*;
use crate::machine::machine_errors::*;
@@ -24,7 +25,10 @@ macro_rules! try_or_throw {
match $e {
Ok(val) => val,
Err(msg) => {
$s.throw_exception(msg);
if !msg.is_empty() {
$s.throw_exception(msg);
}
$s.backtrack();
continue;
}
@@ -32,6 +36,15 @@ macro_rules! try_or_throw {
}};
}
macro_rules! backtrack_on_resource_error {
($machine_st:expr, $val:expr) => {
step_or_resource_error!($machine_st, $val, {
$machine_st.backtrack();
continue;
})
};
}
macro_rules! increment_call_count {
($s:expr) => {{
if !$s.increment_call_count() {
@@ -55,6 +68,15 @@ macro_rules! try_or_throw_gen {
}};
}
macro_rules! push_cell {
($machine_st:expr, $cell:expr) => {{
step_or_resource_error!($machine_st, $machine_st.heap.push_cell($cell), {
$machine_st.backtrack();
continue;
})
}};
}
static INSTRUCTIONS_PER_INTERRUPT_POLL: usize = 256;
impl MachineState {
@@ -113,12 +135,15 @@ impl MachineState {
}
pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
let old_h = self.heap.len();
let old_h = self.heap.cell_len();
let a1 = self.registers[1];
let a2 = self.registers[2];
copy_term(CopyTerm::new(self), a1, attr_var_policy);
step_or_resource_error!(
self,
copy_term(CopyTerm::new(self), a1, attr_var_policy)
);
unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
}
@@ -135,10 +160,16 @@ impl MachineState {
list.dedup_by(|v1, v2| compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal));
let heap_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, list.into_iter()));
let heap_addr = resource_error_call_result!(
self,
sized_iter_to_heap_list(
&mut self.heap,
list.len(),
list.into_iter(),
)
);
let target_addr = self.registers[2];
unify_fn!(*self, target_addr, heap_addr);
Ok(())
}
@@ -160,8 +191,14 @@ impl MachineState {
compare_term_test!(self, a1.0, a2.0, var_comparison).unwrap_or(Ordering::Less)
});
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
let heap_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, key_pairs));
let heap_addr = resource_error_call_result!(
self,
sized_iter_to_heap_list(
&mut self.heap,
key_pairs.len(),
key_pairs.into_iter().map(|kp| kp.1),
)
);
let target_addr = self.registers[2];
@@ -201,13 +238,13 @@ impl MachineState {
v
}
(HeapCellValueTag::PStrLoc |
HeapCellValueTag::Lis |
HeapCellValueTag::CStr) => {
HeapCellValueTag::Lis) => {
// HeapCellValueTag::CStr) => {
l
}
(HeapCellValueTag::Fixnum |
HeapCellValueTag::CutPoint |
HeapCellValueTag::Char |
// HeapCellValueTag::Char |
HeapCellValueTag::F64) => {
c
}
@@ -242,6 +279,7 @@ impl MachineState {
)
}
/*
#[inline(always)]
pub(crate) fn constant_to_literal(&self, addr: HeapCellValue) -> Literal {
read_heap_cell!(addr,
@@ -288,6 +326,7 @@ impl MachineState {
}
)
}
*/
#[inline(always)]
pub(crate) fn select_switch_on_structure_index(
@@ -464,9 +503,9 @@ impl Machine {
}
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
let lit = self.machine_st.constant_to_literal(addr);
// let lit = self.machine_st.constant_to_literal(addr);
let offset = match hm.get(&lit) {
let offset = match hm.get(&addr) {
Some(offset) => *offset,
_ => IndexingCodePtr::Fail,
};
@@ -1245,22 +1284,32 @@ impl Machine {
self.machine_st.allocate(num_cells);
}
&Instruction::DefaultCallAcyclicTerm => {
let addr = self.machine_st.registers[1];
let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) {
self.machine_st.backtrack();
} else {
self.machine_st.p += 1;
if addr.is_ref() {
self.machine_st.heap[0] = addr;
if self.machine_st.is_cyclic_term(0) {
self.machine_st.backtrack();
continue;
}
}
self.machine_st.p += 1;
}
&Instruction::DefaultExecuteAcyclicTerm => {
let addr = self.machine_st.registers[1];
let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) {
self.machine_st.backtrack();
} else {
self.machine_st.p = self.machine_st.cp;
if addr.is_ref() {
self.machine_st.heap[0] = addr;
if self.machine_st.is_cyclic_term(0) {
self.machine_st.backtrack();
continue;
}
}
self.machine_st.p = self.machine_st.cp;
}
&Instruction::DefaultCallArg => {
try_or_throw!(self.machine_st, self.machine_st.try_arg());
@@ -1497,24 +1546,34 @@ impl Machine {
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallAcyclicTerm => {
let addr = self.machine_st.registers[1];
let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) {
self.machine_st.backtrack();
} else {
increment_call_count!(self.machine_st);
self.machine_st.p += 1;
if addr.is_ref() {
self.machine_st.heap[0] = addr;
if self.machine_st.is_cyclic_term(0) {
self.machine_st.backtrack();
continue;
}
}
increment_call_count!(self.machine_st);
self.machine_st.p += 1;
}
&Instruction::ExecuteAcyclicTerm => {
let addr = self.machine_st.registers[1];
let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) {
self.machine_st.backtrack();
} else {
increment_call_count!(self.machine_st);
self.machine_st.p = self.machine_st.cp;
if addr.is_ref() {
self.machine_st.heap[0] = addr;
if self.machine_st.is_cyclic_term(0) {
self.machine_st.backtrack();
continue;
}
}
increment_call_count!(self.machine_st);
self.machine_st.p = self.machine_st.cp;
}
&Instruction::CallArg => {
try_or_throw!(self.machine_st, self.machine_st.try_arg());
@@ -2282,9 +2341,6 @@ impl Machine {
self.machine_st.backtrack();
}
}
(HeapCellValueTag::Char) => {
self.machine_st.p += 1;
}
_ => {
self.machine_st.backtrack();
}
@@ -2313,9 +2369,6 @@ impl Machine {
self.machine_st.backtrack();
}
}
(HeapCellValueTag::Char) => {
self.machine_st.p = self.machine_st.cp;
}
_ => {
self.machine_st.backtrack();
}
@@ -2327,7 +2380,7 @@ impl Machine {
.store(self.machine_st.deref(self.machine_st[r]));
read_heap_cell!(d,
(HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
(HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
HeapCellValueTag::Cons) => {
self.machine_st.p += 1;
}
@@ -2359,7 +2412,7 @@ impl Machine {
.store(self.machine_st.deref(self.machine_st[r]));
read_heap_cell!(d,
(HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
(HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
HeapCellValueTag::Cons) => {
self.machine_st.p = self.machine_st.cp;
}
@@ -2392,8 +2445,8 @@ impl Machine {
read_heap_cell!(d,
(HeapCellValueTag::Lis |
HeapCellValueTag::PStrLoc |
HeapCellValueTag::CStr) => {
HeapCellValueTag::PStrLoc) => {
// HeapCellValueTag::CStr) => {
self.machine_st.p += 1;
}
(HeapCellValueTag::Str, s) => {
@@ -2425,8 +2478,8 @@ impl Machine {
read_heap_cell!(d,
(HeapCellValueTag::Lis |
HeapCellValueTag::PStrLoc |
HeapCellValueTag::CStr) => {
HeapCellValueTag::PStrLoc) => {
// HeapCellValueTag::CStr) => {
self.machine_st.p = self.machine_st.cp;
}
(HeapCellValueTag::Str, s) => {
@@ -2664,8 +2717,6 @@ impl Machine {
&Instruction::CallNamed(arity, name, ref idx) => {
let idx = idx.get();
// println!("calling {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
if self.machine_st.fail {
@@ -2677,8 +2728,6 @@ impl Machine {
&Instruction::ExecuteNamed(arity, name, ref idx) => {
let idx = idx.get();
// println!("executing {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
if self.machine_st.fail {
@@ -2690,8 +2739,6 @@ impl Machine {
&Instruction::DefaultCallNamed(arity, name, ref idx) => {
let idx = idx.get();
// println!("calling {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
if self.machine_st.fail {
@@ -2701,8 +2748,6 @@ impl Machine {
&Instruction::DefaultExecuteNamed(arity, name, ref idx) => {
let idx = idx.get();
// println!("executing {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
if self.machine_st.fail {
@@ -2720,8 +2765,7 @@ impl Machine {
self.machine_st.p = self.machine_st.cp;
}
&Instruction::GetConstant(_, c, reg) => {
let value = self.machine_st.deref(self.machine_st[reg]);
self.machine_st.write_literal_to_var(value, c);
unify!(self.machine_st, self.machine_st[reg], c);
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::GetList(_, reg) => {
@@ -2730,17 +2774,7 @@ impl Machine {
read_heap_cell!(store_v,
(HeapCellValueTag::PStrLoc, h) => {
let (h, n) = pstr_loc_and_offset(&self.machine_st.heap, h);
self.machine_st.s = HeapPtr::PStrChar(h, n.get_num() as usize);
self.machine_st.s_offset = 0;
self.machine_st.mode = MachineMode::Read;
}
(HeapCellValueTag::CStr) => {
let h = self.machine_st.heap.len();
self.machine_st.heap.push(store_v);
self.machine_st.s = HeapPtr::PStrChar(h, 0);
self.machine_st.s = HeapPtr::PStr(h);
self.machine_st.s_offset = 0;
self.machine_st.mode = MachineMode::Read;
}
@@ -2763,9 +2797,9 @@ impl Machine {
self.machine_st.mode = MachineMode::Read;
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(list_loc_as_cell!(h+1));
push_cell!(self.machine_st, list_loc_as_cell!(h+1));
self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
self.machine_st.mode = MachineMode::Write;
@@ -2778,29 +2812,61 @@ impl Machine {
self.machine_st.p += 1;
}
&Instruction::GetPartialString(_, string, reg, has_tail) => {
&Instruction::GetPartialString(_, ref string, reg) => {
use crate::machine::partial_string::{HeapPStrIter, PStrCmpResult};
let deref_v = self.machine_st.deref(self.machine_st[reg]);
let store_v = self.machine_st.store(deref_v);
read_heap_cell!(store_v,
(HeapCellValueTag::Str |
HeapCellValueTag::Lis |
HeapCellValueTag::PStrLoc |
HeapCellValueTag::CStr) => {
self.machine_st.match_partial_string(store_v, string, has_tail);
HeapCellValueTag::PStrLoc) => {
debug_assert!(store_v.is_ref());
self.machine_st.heap[0] = store_v;
let heap_pstr_iter = HeapPStrIter::new(&self.machine_st.heap, 0);
match heap_pstr_iter.compare_pstr_to_string(string) {
Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc }) => {
self.machine_st.s_offset = chars_matched;
self.machine_st.s = HeapPtr::PStr(pstr_loc);
self.machine_st.mode = MachineMode::Read;
}
Some(PStrCmpResult::PartialPStrMatch { string, var_loc }) => {
let cell = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(string)
);
self.machine_st.mode = MachineMode::Write;
unify!(self.machine_st, cell, heap_loc_as_cell!(var_loc));
}
Some(PStrCmpResult::ListMatch { list_loc }) => {
self.machine_st.s_offset = 0;
self.machine_st.s = HeapPtr::HeapCell(list_loc);
self.machine_st.mode = MachineMode::Read;
}
None => {
self.machine_st.backtrack();
continue;
}
}
}
(HeapCellValueTag::AttrVar |
HeapCellValueTag::StackVar |
HeapCellValueTag::Var) => {
let target_cell = self.machine_st.push_str_to_heap(
&string.as_str(),
has_tail,
let target_cell = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(string)
);
self.machine_st.bind(
store_v.as_var().unwrap(),
target_cell,
);
self.machine_st.mode = MachineMode::Write;
}
_ => {
self.machine_st.backtrack();
@@ -2833,10 +2899,10 @@ impl Machine {
);
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(str_loc_as_cell!(h+1));
self.machine_st.heap.push(atom_as_cell!(name, arity));
push_cell!(self.machine_st, str_loc_as_cell!(h+1));
push_cell!(self.machine_st, atom_as_cell!(name, arity));
self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
self.machine_st.mode = MachineMode::Write;
@@ -2870,8 +2936,7 @@ impl Machine {
match self.machine_st.mode {
MachineMode::Read => {
let addr = self.machine_st.read_s();
self.machine_st.write_literal_to_var(addr, v);
unify!(&mut self.machine_st, addr, v);
if self.machine_st.fail {
self.machine_st.backtrack();
@@ -2881,7 +2946,7 @@ impl Machine {
}
}
MachineMode::Write => {
self.machine_st.heap.push(v);
push_cell!(self.machine_st, v);
}
}
@@ -2906,17 +2971,17 @@ impl Machine {
let value = self
.machine_st
.store(self.machine_st.deref(self.machine_st[reg]));
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
read_heap_cell!(value,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, hc) => {
let value = self.machine_st.heap[hc];
self.machine_st.heap.push(value);
push_cell!(self.machine_st, value);
self.machine_st.s_offset += 1;
}
_ => {
self.machine_st.heap.push(heap_loc_as_cell!(h));
push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)(
&mut self.machine_st,
Ref::heap_cell(h),
@@ -2932,13 +2997,14 @@ impl Machine {
&Instruction::UnifyVariable(reg) => {
match self.machine_st.mode {
MachineMode::Read => {
self.machine_st[reg] = self.machine_st.read_s();
let value = self.machine_st.read_s();
self.machine_st[reg] = value;
self.machine_st.s_offset += 1;
}
MachineMode::Write => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h));
push_cell!(self.machine_st, heap_loc_as_cell!(h));
self.machine_st[reg] = heap_loc_as_cell!(h);
}
}
@@ -2961,8 +3027,8 @@ impl Machine {
}
}
MachineMode::Write => {
let h = self.machine_st.heap.len();
self.machine_st.heap.push(heap_loc_as_cell!(h));
let h = self.machine_st.heap.cell_len();
push_cell!(self.machine_st, heap_loc_as_cell!(h));
let addr = self.machine_st.store(self.machine_st[reg]);
(self.machine_st.bind_fn)(
@@ -2974,7 +3040,7 @@ impl Machine {
// the former code of this match arm was:
// let addr = self.machine_st.store(self.machine_st[reg]);
// self.machine_st.heap.push(HeapCellValue::Addr(addr));
// push_cell!(self.machine_st, HeapCellValue::Addr(addr));
// the old code didn't perform the occurs
// check when enabled and so it was changed to
@@ -2991,10 +3057,10 @@ impl Machine {
self.machine_st.s_offset += n;
}
MachineMode::Write => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
for i in h..h + n {
self.machine_st.heap.push(heap_loc_as_cell!(i));
push_cell!(self.machine_st, heap_loc_as_cell!(i));
}
}
}
@@ -3126,38 +3192,26 @@ impl Machine {
}
}
}
&Instruction::PutConstant(_, c, reg) => {
self.machine_st[reg] = c;
&Instruction::PutConstant(_, cell, reg) => {
self.machine_st[reg] = cell;
self.machine_st.p += 1;
}
&Instruction::PutList(_, reg) => {
self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.len());
self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.cell_len());
self.machine_st.p += 1;
}
&Instruction::PutPartialString(_, string, reg, has_tail) => {
let pstr_addr = if has_tail {
if string != atom!("") {
let h = self.machine_st.heap.len();
self.machine_st.heap.push(string_as_pstr_cell!(string));
&Instruction::PutPartialString(_, ref string, reg) => {
self.machine_st[reg] = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(&string)
);
// the tail will be pushed by the next
// instruction, so don't push one here.
pstr_loc_as_cell!(h)
} else {
empty_list_as_cell!()
}
} else {
string_as_cstr_cell!(string)
};
self.machine_st[reg] = pstr_addr;
self.machine_st.p += 1;
}
&Instruction::PutStructure(name, arity, reg) => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(atom_as_cell!(name, arity));
push_cell!(self.machine_st, atom_as_cell!(name, arity));
self.machine_st[reg] = str_loc_as_cell!(h);
self.machine_st.p += 1;
@@ -3171,9 +3225,9 @@ impl Machine {
if addr.is_protected(self.machine_st.e) {
self.machine_st.registers[arg] = addr;
} else {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h));
push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)(
&mut self.machine_st,
Ref::heap_cell(h),
@@ -3197,8 +3251,8 @@ impl Machine {
self.machine_st.registers[arg] = self.machine_st[norm];
}
RegType::Temp(_) => {
let h = self.machine_st.heap.len();
self.machine_st.heap.push(heap_loc_as_cell!(h));
let h = self.machine_st.heap.cell_len();
push_cell!(self.machine_st, heap_loc_as_cell!(h));
self.machine_st[norm] = heap_loc_as_cell!(h);
self.machine_st.registers[arg] = heap_loc_as_cell!(h);
@@ -3208,7 +3262,7 @@ impl Machine {
self.machine_st.p += 1;
}
&Instruction::SetConstant(c) => {
self.machine_st.heap.push(c);
push_cell!(self.machine_st, c);
self.machine_st.p += 1;
}
&Instruction::SetLocalValue(reg) => {
@@ -3216,37 +3270,37 @@ impl Machine {
let stored_v = self.machine_st.store(addr);
if stored_v.is_stack_var() {
let h = self.machine_st.heap.len();
self.machine_st.heap.push(heap_loc_as_cell!(h));
let h = self.machine_st.heap.cell_len();
push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)(
&mut self.machine_st,
Ref::heap_cell(h),
stored_v,
);
} else {
self.machine_st.heap.push(stored_v);
push_cell!(self.machine_st, stored_v);
}
self.machine_st.p += 1;
}
&Instruction::SetVariable(reg) => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h));
push_cell!(self.machine_st, heap_loc_as_cell!(h));
self.machine_st[reg] = heap_loc_as_cell!(h);
self.machine_st.p += 1;
}
&Instruction::SetValue(reg) => {
let heap_val = self.machine_st.store(self.machine_st[reg]);
self.machine_st.heap.push(heap_val);
push_cell!(self.machine_st, heap_val);
self.machine_st.p += 1;
}
&Instruction::SetVoid(n) => {
let h = self.machine_st.heap.len();
let h = self.machine_st.heap.cell_len();
for i in h..h + n {
self.machine_st.heap.push(heap_loc_as_cell!(i));
push_cell!(self.machine_st, heap_loc_as_cell!(i));
}
self.machine_st.p += 1;
@@ -3363,11 +3417,11 @@ impl Machine {
}
&Instruction::CallCopyToLiftedHeap => {
self.copy_to_lifted_heap();
self.machine_st.p += 1;
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteCopyToLiftedHeap => {
self.copy_to_lifted_heap();
self.machine_st.p = self.machine_st.cp;
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallCreatePartialString => {
self.create_partial_string();
@@ -3519,15 +3573,6 @@ impl Machine {
self.dynamic_module_resolution(arity - 2)
);
/*
println!(
"(slow) calling {}:{}/{}",
module_name.as_str(),
key.0.as_str(),
key.1,
);
*/
try_or_throw!(self.machine_st, self.call_clause(module_name, key));
if self.machine_st.fail {
@@ -3540,15 +3585,6 @@ impl Machine {
self.dynamic_module_resolution(arity - 2)
);
/*
println!(
"(slow) executing {}:{}/{}",
module_name.as_str(),
key.0.as_str(),
key.1,
);
*/
try_or_throw!(self.machine_st, self.execute_clause(module_name, key));
if self.machine_st.fail {
@@ -4291,11 +4327,11 @@ impl Machine {
}
&Instruction::CallSetBall => {
self.set_ball();
self.machine_st.p += 1;
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteSetBall => {
self.set_ball();
self.machine_st.p = self.machine_st.cp;
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallPushBallStack => {
self.push_ball_stack();
@@ -4630,19 +4666,19 @@ impl Machine {
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallLoadHTML => {
self.load_html();
backtrack_on_resource_error!(self.machine_st, self.load_html());
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteLoadHTML => {
self.load_html();
backtrack_on_resource_error!(self.machine_st, self.load_html());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallLoadXML => {
self.load_xml();
backtrack_on_resource_error!(self.machine_st, self.load_xml());
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteLoadXML => {
self.load_xml();
backtrack_on_resource_error!(self.machine_st, self.load_xml());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallGetEnv => {
@@ -5119,13 +5155,18 @@ impl Machine {
let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r));
let h = self.machine_st.heap.len();
self.machine_st
.heap
.extend(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
let mut writer = Heap::functor_writer(
functor!(atom!("-"), [fixnum(n), fixnum(p)]),
);
let str_cell = backtrack_on_resource_error!(
&mut self.machine_st,
writer(&mut self.machine_st.heap)
);
let r = r.as_var().unwrap();
self.machine_st.bind(r, str_loc_as_cell!(h));
self.machine_st.bind(r, str_cell);
step_or_fail!(self, self.machine_st.p += 1);
}
@@ -5137,13 +5178,18 @@ impl Machine {
let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r));
let h = self.machine_st.heap.len();
self.machine_st
.heap
.extend(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
let mut writer = Heap::functor_writer(
functor!(atom!("-"), [fixnum(n), fixnum(p)]),
);
let str_cell = backtrack_on_resource_error!(
&mut self.machine_st,
writer(&mut self.machine_st.heap)
);
let r = r.as_var().unwrap();
self.machine_st.bind(r, str_loc_as_cell!(h));
self.machine_st.bind(r, str_cell);
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,15 +3,14 @@ use std::collections::BTreeMap;
use crate::atom_table;
use crate::heap_iter::{stackful_post_order_iter, NonListElider};
use crate::machine::machine_indices::VarKey;
use crate::machine::mock_wam::CompositeOpDir;
use crate::machine::{
ArenaHeaderTag, F64Offset, F64Ptr, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC,
LIB_QUERY_SUCCESS,
};
use crate::parser::ast::{Var, VarPtr};
use crate::parser::parser::{Parser, Tokens};
use crate::read::{write_term_to_heap, TermWriteResult};
use crate::parser::ast::{TermWriteResult, Var};
use crate::parser::lexer::LexerParser;
use crate::parser::parser::Tokens;
use crate::types::UntypedArenaPtr;
use dashu::{Integer, Rational};
@@ -171,29 +170,22 @@ impl Term {
pub(crate) fn from_heapcell(
machine: &mut Machine,
heap_cell: HeapCellValue,
var_names: &mut IndexMap<HeapCellValue, VarPtr>,
var_names: &mut IndexMap<HeapCellValue, Var>,
) -> Self {
// Adapted from MachineState::read_term_from_heap
let mut term_stack = vec![];
let iter = stackful_post_order_iter::<NonListElider>(
machine.machine_st.heap[0] = heap_cell;
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut machine.machine_st.heap,
&mut machine.machine_st.stack,
heap_cell,
0,
);
let mut anon_count: usize = 0;
let var_ptr_cmp = |a, b| match a {
Var::Named(name_a) => match b {
Var::Named(name_b) => name_a.cmp(&name_b),
_ => Ordering::Less,
},
_ => match b {
Var::Named(_) => Ordering::Greater,
_ => Ordering::Equal,
},
};
for addr in iter {
while let Some(addr) = iter.next() {
let addr = unmark_cell_bits!(addr);
read_heap_cell!(addr,
@@ -242,29 +234,28 @@ impl Term {
term_stack.push(list);
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let var = var_names.get(&addr).map(|x| x.borrow().clone());
let var = var_names.get(&addr).cloned();
match var {
Some(Var::Named(name)) => term_stack.push(Term::Var(name)),
Some(name) => term_stack.push(Term::Var(name.to_string())),
_ => {
let anon_name = loop {
// Generate a name for the anonymous variable
let anon_name = count_to_letter_code(anon_count);
// Find if this name is already being used
var_names.sort_by(|_, a, _, b| {
var_ptr_cmp(a.borrow().clone(), b.borrow().clone())
});
var_names.sort_by(|_, a, _, b| a.cmp(b));
let binary_result = var_names.binary_search_by(|_,a| {
let var_ptr = Var::Named(anon_name.clone());
var_ptr_cmp(a.borrow().clone(), var_ptr.clone())
let a: &String = a.as_ref();
a.cmp(&anon_name)
});
match binary_result {
Ok(_) => anon_count += 1, // Name already used
Err(_) => {
// Name not used, assign it to this variable
let var_ptr = VarPtr::from(Var::Named(anon_name.clone()));
var_names.insert(addr, var_ptr);
let var = anon_name.clone();
var_names.insert(addr, Var::from(var));
break anon_name;
},
}
@@ -276,9 +267,6 @@ impl Term {
(HeapCellValueTag::F64, f) => {
term_stack.push(Term::Float((*f).into()));
}
(HeapCellValueTag::Char, c) => {
term_stack.push(Term::Atom(c.into()));
}
(HeapCellValueTag::Fixnum, n) => {
term_stack.push(Term::Integer(n.into()));
}
@@ -310,9 +298,6 @@ impl Term {
);
}
}
(HeapCellValueTag::CStr, s) => {
term_stack.push(Term::String(s.as_str().to_string()));
}
(HeapCellValueTag::Atom, (name, arity)) => {
//let h = iter.focus().value() as usize;
//let mut arity = arity;
@@ -354,8 +339,9 @@ impl Term {
term_stack.push(Term::Compound(name.as_str().to_string(), subterms));
}
}
(HeapCellValueTag::PStr, atom) => {
(HeapCellValueTag::PStrLoc, pstr_loc) => {
let tail = term_stack.pop().unwrap();
let char_iter = iter.base_iter.heap.char_iter(pstr_loc);
match tail {
Term::Atom(atom) => {
@@ -363,21 +349,18 @@ impl Term {
term_stack.push(Term::String(atom.as_str().to_string()));
}
},
Term::List(l) if l.is_empty() => {
term_stack.push(Term::String(char_iter.collect()));
}
Term::List(l) => {
let mut list: Vec<Term> = atom
.as_str()
.to_string()
.chars()
let mut list: Vec<Term> = char_iter
.map(|x| Term::Atom(x.to_string()))
.collect();
list.extend(l.into_iter());
term_stack.push(Term::List(list));
},
_ => {
let mut list: Vec<Term> = atom
.as_str()
.to_string()
.chars()
let mut list: Vec<Term> = char_iter
.map(|x| Term::Atom(x.to_string()))
.collect();
@@ -403,19 +386,6 @@ impl Term {
}
}
}
// I dont know if this is needed here.
/*
(HeapCellValueTag::PStrLoc, h) => {
let atom = cell_as_atom_cell!(iter.heap[h]).get_name();
let tail = term_stack.pop().unwrap();
term_stack.push(Term::PartialString(
Cell::default(),
atom.as_str().to_owned(),
Box::new(tail),
));
}
*/
_ => {
unreachable!();
}
@@ -432,7 +402,7 @@ pub struct QueryState<'a> {
machine: &'a mut Machine,
term: TermWriteResult,
stub_b: usize,
var_names: IndexMap<HeapCellValue, VarPtr>,
var_names: IndexMap<HeapCellValue, Var>,
called: bool,
}
@@ -472,7 +442,7 @@ impl Iterator for QueryState<'_> {
if let Err(resource_err_loc) = machine
.machine_st
.heap
.append(&machine.machine_st.ball.stub)
.append(machine.machine_st.ball.stub.splice(..))
{
return Some(Err(Term::from_heapcell(
machine,
@@ -589,13 +559,13 @@ impl Machine {
or_frame.prelude.attr_var_queue_len = 0;
self.machine_st.b = stub_b;
self.machine_st.hb = self.machine_st.heap.len();
self.machine_st.hb = self.machine_st.heap.cell_len();
self.machine_st.block = stub_b;
}
/// Runs a query.
pub fn run_query(&mut self, query: impl Into<String>) -> QueryState {
let mut parser = Parser::new(
let mut parser = LexerParser::new(
Stream::from_owned_string(query.into(), &mut self.machine_st.arena),
&mut self.machine_st,
);

View File

@@ -2,7 +2,6 @@ use crate::forms::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::preprocessor::*;
use crate::machine::term_stream::*;
use crate::machine::*;
use crate::parser::ast::*;
@@ -434,19 +433,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.retract_local_clauses_impl(clause_clause_compilation_target, key, clause_locs);
}
pub(super) fn try_term_to_tl(
&mut self,
term: FocusedHeap,
preprocessor: &mut Preprocessor,
) -> Result<PredicateClause, SessionError> {
let tl = preprocessor.try_term_to_tl(self, term)?;
Ok(match tl {
TopLevel::Fact(fact, var_data) => PredicateClause::Fact(fact, var_data),
TopLevel::Rule(rule, var_data) => PredicateClause::Rule(rule, var_data),
})
}
#[inline]
pub(super) fn remove_module_op_exports(&mut self) {
for (mut op_decl, record) in self.payload.module_op_exports.drain(0..) {

View File

@@ -20,6 +20,25 @@ use std::convert::TryFrom;
use std::fmt;
use std::ops::{Deref, DerefMut};
impl TermWriteResult {
pub(super) fn from(heap: &mut Heap, value: HeapCellValue) -> Result<Self, usize> {
let focus = heap.index_of(value)?;
let mut stack = Stack::uninitialized();
heap[0] = value;
let inverse_var_locs = inverse_var_locs_from_iter(
stackful_preorder_iter::<NonListElider>(
heap,
&mut stack,
0,
),
);
Ok(Self { focus, inverse_var_locs })
}
}
/*
* The loader compiles Prolog terms read from a TermStream instance,
* which may be incremental or monolithic. The monolithic term stream
@@ -176,18 +195,18 @@ impl CompilationTarget {
}
pub struct PredicateQueue {
pub(super) predicates: Vec<FocusedHeap>,
pub(super) compilation_target: CompilationTarget,
pub predicates: Vec<TermWriteResult>,
pub compilation_target: CompilationTarget,
}
impl PredicateQueue {
#[inline]
pub(super) fn push(&mut self, clause: FocusedHeap) {
self.predicates.push(clause);
pub(super) fn push(&mut self, term_write_result: TermWriteResult) {
self.predicates.push(term_write_result);
}
#[inline]
pub(crate) fn first(&self) -> Option<&FocusedHeap> {
pub(crate) fn first(&self) -> Option<&TermWriteResult> {
self.predicates.first()
}
@@ -381,7 +400,6 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
let repo_len = loader.wam_prelude.code.len();
loader.payload.retraction_info.reset(repo_len);
loader.remove_module_op_exports();
Ok(loader.payload.compilation_target)
@@ -399,7 +417,7 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
#[inline(always)]
fn machine_st(loader: &mut Self::LoaderFieldType) -> &mut MachineState {
loader.term_stream.parser.lexer.machine_st
loader.term_stream.lexer_parser.machine_st
}
#[inline(always)]
@@ -491,23 +509,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
pub(crate) fn copy_term_from_heap(&mut self, cell: HeapCellValue) -> FocusedHeap {
use crate::iterators::fact_iterator;
let mut term = FocusedHeap::empty();
let mut stack = Stack::uninitialized();
let machine_st = LS::machine_st(&mut self.payload);
term.copy_term_from_machine_heap(machine_st, cell);
term.inverse_var_locs = inverse_var_locs_from_iter(
fact_iterator::<false>(
&mut term.heap,
&mut stack,
0,
),
);
term
#[inline]
pub(super) fn machine_heap(&mut self) -> &mut Heap {
&mut LS::machine_st(&mut self.payload).heap
}
pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
@@ -525,14 +529,26 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
let mut term = load_state.term_stream.next(&composite_op_dir)?;
let predicate_focus_opt = load_state.predicates.first().map(|term_write_result| {
term_write_result.focus
});
if !term.is_consistent(&load_state.predicates) {
self.compile_and_submit()?;
let machine_st = LS::machine_st(&mut self.payload);
let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus);
if let Some(predicate_focus) = predicate_focus_opt {
let predicate_key_opt = clause_predicate_key(&machine_st.heap, predicate_focus);
debug_assert!(predicate_key_opt.is_some());
if term_key_opt != predicate_key_opt {
self.compile_and_submit()?;
}
}
if Some(atom!(":-")) == term.name(term.focus) && term.arity(term.focus) == 1 {
let new_focus = term.nth_arg(term.focus, 1).unwrap();
let term = term.as_ref_mut(new_focus);
if Some((atom!(":-"), 1)) == term_key_opt {
let machine_st = LS::machine_st(&mut self.payload);
term.focus = term_nth_arg(&machine_st.heap, term.focus, 1).unwrap();
return Ok(Some(setup_declaration(self, term)?));
}
@@ -1055,48 +1071,55 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let machine_st = LS::machine_st(&mut self.payload);
let cell = machine_st[r];
let export_list = FocusedHeapRefMut::from_cell(&mut machine_st.heap, cell);
let focus = machine_st.heap.cell_len();
machine_st.heap.push_cell(cell)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
let export_list = FocusedHeapRefMut { heap: &mut machine_st.heap, focus };
let export_list = setup_module_export_list(export_list)?;
Ok(export_list.into_iter().collect())
}
fn clause_clause(&mut self, cell: HeapCellValue) -> Result<FocusedHeap, CompilationError> {
fn clause_clause(&mut self, cell: HeapCellValue) -> Result<TermWriteResult, CompilationError> {
let machine_st = LS::machine_st(&mut self.payload);
let mut term = FocusedHeap::empty();
let focus = machine_st.heap.cell_len();
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity();
term.copy_term_from_machine_heap(machine_st, cell);
let focus = term.heap.len();
let mut writer = machine_st.heap.reserve(4)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
term.heap.push(str_loc_as_cell!(focus+1));
term.heap.push(atom_as_cell!(atom!("clause"), 2));
writer.write_with(|section| {
section.push_cell(str_loc_as_cell!(focus+1));
section.push_cell(atom_as_cell!(atom!("clause"), 2));
match (name, arity) {
(atom!(":-"), 2) => {
term.heap.push(heap_loc_as_cell!(2));
term.heap.push(heap_loc_as_cell!(3));
match (name, arity) {
(atom!(":-"), 2) => {
section.push_cell(heap_loc_as_cell!(s+1));
section.push_cell(heap_loc_as_cell!(s+2));
}
_ => {
section.push_cell(str_loc_as_cell!(s));
section.push_cell(atom_as_cell!(atom!("true")));
}
}
_ => {
term.heap.push(heap_loc_as_cell!(0));
term.heap.push(atom_as_cell!(atom!("true")));
}
}
term.focus = focus;
});
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
term.heap.push(str_loc_as_cell!(1));
term.heap.push(atom_as_cell!(atom!("clause"), 2));
term.heap.push(atom_as_cell!(name));
term.heap.push(atom_as_cell!(atom!("true")));
let mut writer = machine_st.heap.reserve(4)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
term.focus = 0;
writer.write_with(|section| {
section.push_cell(str_loc_as_cell!(focus+1));
section.push_cell(atom_as_cell!(atom!("clause"), 2));
section.push_cell(atom_as_cell!(name));
section.push_cell(atom_as_cell!(atom!("true")));
});
} else {
return Err(CompilationError::InadmissibleFact);
}
@@ -1106,11 +1129,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
);
let value = term.heap[term.focus];
term.inverse_var_locs = inverse_var_locs_from_iter(
eager_stackful_preorder_iter(&mut term.heap, value),
);
Ok(term)
Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?)
}
fn add_extensible_predicate_declaration(
@@ -1330,18 +1350,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
fn add_clause_clause_if_dynamic(&mut self, value: HeapCellValue) -> Result<(), SessionError> {
let machine_st = LS::machine_st(&mut self.payload);
let term = FocusedHeapRefMut::from_cell(&mut machine_st.heap, value);
let key_opt = clause_predicate_key_from_heap(&machine_st.heap, value);
let name_opt = ClauseInfo::name(&term);
if let Some(predicate_name) = name_opt {
let arity = ClauseInfo::arity(&term);
if let Some((predicate_name, predicate_arity)) = key_opt {
let predicates_compilation_target = self.payload.predicates.compilation_target;
let is_dynamic = self
.wam_prelude
.indices
.get_predicate_skeleton(&predicates_compilation_target, &(predicate_name, arity))
.get_predicate_skeleton(
&predicates_compilation_target,
&(predicate_name, predicate_arity),
)
.map(|skeleton| skeleton.core.is_dynamic)
.unwrap_or(false);
@@ -1574,11 +1594,14 @@ impl Machine {
pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
let value = self.machine_st.registers[1];
let term = resource_error_call_result!(
self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value)
);
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
let add_clause = || {
let term = loader.copy_term_from_heap(value);
loader.incremental_compile_clause(
(atom!("term_expansion"), 2),
term,
@@ -1599,31 +1622,40 @@ impl Machine {
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let value = self.machine_st.registers[2];
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
let compilation_target = match target_module_name {
atom!("user") => CompilationTarget::User,
_ => CompilationTarget::Module(target_module_name),
};
let add_clause = || {
let term = loader.copy_term_from_heap(value);
let value = self.machine_st.registers[2];
let term = resource_error_call_result!(
self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value)
);
let indexing_arg = match term.name(term.focus) {
Some(atom!(":-")) => term.nth_arg(term.focus, 1).and_then(|h| term.nth_arg(h, 1)),
Some(_) => term.nth_arg(term.focus, 1),
let add_clause = || {
let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) {
Some((atom!(":-"), _)) => {
term_nth_arg(&self.machine_st.heap, term.focus, 1).and_then(|h| {
term_nth_arg(&self.machine_st.heap, h, 1)
})
}
Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1),
None => None,
};
if let Some(indexing_term_loc) = indexing_arg {
if let Some(indexing_name) = term.name(indexing_term_loc) {
loader
.wam_prelude
.indices
.goal_expansion_indices
.insert((indexing_name, term.arity(indexing_term_loc)));
}
let key_opt = indexing_arg_opt.and_then(|indexing_term_loc| {
term_predicate_key(&self.machine_st.heap, indexing_term_loc)
});
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
if let Some((name, arity)) = key_opt {
loader
.wam_prelude
.indices
.goal_expansion_indices
.insert((name, arity));
}
loader.incremental_compile_clause(
@@ -1929,19 +1961,16 @@ impl Machine {
let stub_gen = || functor_stub(key.0, key.1);
let assert_clause = self.machine_st.registers[2];
let (name, arity) = {
let term = FocusedHeapRefMut::from_cell(&mut self.machine_st.heap, assert_clause);
(ClauseInfo::name(&term), ClauseInfo::arity(&term))
};
let key_opt = clause_predicate_key_from_heap(&self.machine_st.heap, assert_clause);
let mut compile_assert = |assert_clause, name, arity| {
let mut compile_assert = |assert_clause, key_opt| {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target;
let name = if let Some(name) = name {
name
let (name, arity) = if let Some(key) = key_opt {
key
} else {
return Err(SessionError::from(CompilationError::InvalidRuleHead));
};
@@ -1979,11 +2008,16 @@ impl Machine {
// if a new predicate was just created, make it dynamic.
loader.add_dynamic_predicate(compilation_target, name, arity)?;
let asserted_clause = loader.copy_term_from_heap(assert_clause);
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
// let asserted_clause = loader.copy_term_from_heap(assert_clause);
let term = TermWriteResult::from(&mut machine_st.heap, assert_clause)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
loader.incremental_compile_clause(
(name, arity),
asserted_clause,
term,
compilation_target,
false,
append_or_prepend,
@@ -2004,7 +2038,7 @@ impl Machine {
LiveLoadAndMachineState::evacuate(loader)
};
match compile_assert(assert_clause, name, arity) {
match compile_assert(assert_clause, key_opt) {
Ok(_) => Ok(()),
Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
@@ -2206,11 +2240,21 @@ impl Machine {
};
let mut loader = self.loader_from_heap_evacuable(temp_v!(4));
let predicate_focus_opt = loader.payload.predicates.first().map(|term_write_result| {
term_write_result.focus
});
let is_consistent = if let Some(predicate_focus) = predicate_focus_opt {
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
clause_predicate_key(&machine_st.heap, predicate_focus) == Some(key)
} else {
true
};
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
(!loader.payload.predicates.is_empty()
&& loader.payload.predicates.compilation_target != compilation_target)
|| !key.is_consistent(&loader.payload.predicates);
&& loader.payload.predicates.compilation_target != compilation_target)
|| !is_consistent;
let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result)
@@ -2278,29 +2322,36 @@ impl Machine {
.get_meta_predicate_spec(predicate_name, arity, &compilation_target)
{
Some(meta_specs) => {
let term_loc = self.machine_st.heap.len();
let term_loc = self.machine_st.heap.cell_len();
self.machine_st
.heap
.push(atom_as_cell!(predicate_name, arity));
self.machine_st
.heap
.extend(meta_specs.iter().map(|meta_spec| match meta_spec {
MetaSpec::Minus => atom_as_cell!(atom!("+")),
MetaSpec::Plus => atom_as_cell!(atom!("-")),
MetaSpec::Either => atom_as_cell!(atom!("?")),
MetaSpec::Colon => atom_as_cell!(atom!(":")),
MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
fixnum_as_cell!(Fixnum::build_with(*arg_num as i64))
}
}));
let mut writer = match self.machine_st.heap.reserve(3 + meta_specs.len()) {
Ok(writer) => writer,
Err(err_loc) => {
self.machine_st.throw_resource_error(err_loc);
return;
}
};
let heap_loc = self.machine_st.heap.len();
writer.write_with(|section| {
section.push_cell(atom_as_cell!(predicate_name, arity));
self.machine_st
.heap
.push(atom_as_cell!(atom!("meta_predicate"), 1));
self.machine_st.heap.push(str_loc_as_cell!(term_loc));
for meta_spec in meta_specs.iter() {
section.push_cell(match meta_spec {
MetaSpec::Minus => atom_as_cell!(atom!("+")),
MetaSpec::Plus => atom_as_cell!(atom!("-")),
MetaSpec::Either => atom_as_cell!(atom!("?")),
MetaSpec::Colon => atom_as_cell!(atom!(":")),
MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
fixnum_as_cell!(Fixnum::build_with(*arg_num as i64))
}
});
}
section.push_cell(atom_as_cell!(atom!("meta_predicate"), 1));
section.push_cell(str_loc_as_cell!(term_loc));
});
let heap_loc = self.machine_st.heap.cell_len() - 2;
unify!(
self.machine_st,
@@ -2411,13 +2462,16 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
}
let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
let value = machine_st[term_reg];
let value = machine_st.store(MachineState::deref(&machine_st, machine_st[term_reg]));
self.add_clause_clause_if_dynamic(value)?;
let term = self.copy_term_from_heap(value);
self.payload.term_stream.term_queue.push_back(term);
let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
let term = TermWriteResult::from(&mut machine_st.heap, value)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
self.payload.term_stream.term_queue.push_back(term);
self.load()
}
}

View File

@@ -5,6 +5,7 @@ use crate::parser::ast::*;
#[cfg(feature = "ffi")]
use crate::ffi::FFIError;
use crate::forms::*;
use crate::functor_macro::*;
use crate::machine::heap::*;
use crate::machine::loader::CompilationTarget;
use crate::machine::machine_state::*;
@@ -12,20 +13,13 @@ use crate::machine::streams::*;
use crate::machine::system_calls::BrentAlgState;
use crate::types::*;
pub type MachineStub = Vec<HeapCellValue>;
pub type MachineStub = Vec<FunctorElement>;
pub type MachineStubGen = Box<dyn Fn(&mut MachineState) -> MachineStub>;
#[derive(Debug, Clone, Copy)]
enum ErrorProvenance {
Constructed, // if constructed, offset the addresses.
Received, // otherwise, preserve the addresses.
}
#[derive(Debug)]
pub(crate) struct MachineError {
stub: MachineStub,
location: Option<ParserErrorSrc>,
from: ErrorProvenance,
}
// from 7.12.2 b) of 13211-1:1995
@@ -91,45 +85,26 @@ impl TypeError for HeapCellValue {
fn type_error(self, _machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!(
atom!("type_error"),
[atom(valid_type.as_atom()), cell(self)]
[atom_as_cell((valid_type.as_atom())), cell(self)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
impl TypeError for MachineStub {
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
fn type_error(self, _machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!(
atom!("type_error"),
[atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
[self]
[atom_as_cell((valid_type.as_atom())), functor(self)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
}
impl TypeError for FunctorStub {
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!(
atom!("type_error"),
[atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
[self]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
}
@@ -139,15 +114,14 @@ impl TypeError for Number {
let stub = functor!(
atom!("type_error"),
[
atom(valid_type.as_atom()),
number(&mut machine_st.arena, self)
atom_as_cell((valid_type.as_atom())),
number(self, (&mut machine_st.arena))
]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
@@ -171,16 +145,15 @@ impl PermissionError for Atom {
let stub = functor!(
atom!("permission_error"),
[
atom(perm.as_atom()),
atom(index_atom),
cell(atom_as_cell!(self))
atom_as_cell((perm.as_atom())),
atom_as_cell(index_atom),
atom_as_cell(self)
]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
@@ -214,13 +187,12 @@ impl PermissionError for HeapCellValue {
let stub = functor!(
atom!("permission_error"),
[atom(perm.as_atom()), atom(index_atom), cell(cell)]
[atom_as_cell((perm.as_atom())), atom_as_cell(index_atom), cell(cell)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
@@ -228,24 +200,22 @@ impl PermissionError for HeapCellValue {
impl PermissionError for MachineStub {
fn permission_error(
self,
machine_st: &mut MachineState,
_machine_st: &mut MachineState,
index_atom: Atom,
perm: Permission,
) -> MachineError {
let stub = functor!(
atom!("permission_error"),
[
atom(perm.as_atom()),
atom(index_atom),
str(machine_st.heap.len(), 0)
],
[self]
atom_as_cell((perm.as_atom())),
atom_as_cell(index_atom),
functor(self)
]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
}
@@ -256,32 +226,11 @@ pub(super) trait DomainError {
impl DomainError for HeapCellValue {
fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(atom!("domain_error"), [atom(error.as_atom()), cell(self)]);
let stub = functor!(atom!("domain_error"), [atom_as_cell((error.as_atom())), cell(self)]);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
impl DomainError for FunctorStub {
fn domain_error(
self,
machine_st: &mut MachineState,
valid_type: DomainErrorType,
) -> MachineError {
let stub = functor!(
atom!("domain_error"),
[atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
[self]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
}
@@ -290,26 +239,33 @@ impl DomainError for Number {
fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(
atom!("domain_error"),
[atom(error.as_atom()), number(&mut machine_st.arena, self)]
[atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
pub(super) type FunctorStub = [HeapCellValue; 3];
impl DomainError for MachineStub {
fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(
atom!("domain_error"),
[atom_as_cell((error.as_atom())), functor(self)]
);
MachineError {
stub,
location: None,
}
}
}
#[inline(always)]
pub(super) fn functor_stub(name: Atom, arity: usize) -> FunctorStub {
[
atom_as_cell!(atom!("/"), 2),
atom_as_cell!(name),
fixnum_as_cell!(Fixnum::build_with(arity as i64)),
]
pub(super) fn functor_stub(name: Atom, arity: usize) -> MachineStub {
functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)])
}
impl MachineState {
@@ -320,17 +276,15 @@ impl MachineState {
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError {
let stub = functor!(atom!("evaluation_error"), [atom(eval_error.as_atom())]);
let stub = functor!(atom!("evaluation_error"), [atom_as_cell((eval_error.as_atom()))]);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
@@ -339,18 +293,17 @@ impl MachineState {
ResourceError::FiniteMemory(size_requested) => {
functor!(
atom!("resource_error"),
[atom(atom!("finite_memory")), cell(size_requested)]
[atom_as_cell((atom!("finite_memory"))), cell(size_requested)]
)
}
ResourceError::OutOfFiles => {
functor!(atom!("resource_error"), [atom(atom!("file_descriptors"))])
functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))])
}
};
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
@@ -367,13 +320,12 @@ impl MachineState {
ExistenceError::Module(name) => {
let stub = functor!(
atom!("existence_error"),
[atom(atom!("source_sink")), atom(name)]
[atom_as_cell((atom!("source_sink"))), atom_as_cell(name)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
ExistenceError::QualifiedProcedure {
@@ -381,36 +333,30 @@ impl MachineState {
name,
arity,
} => {
let h = self.heap.len();
let ind_stub = functor!(atom!("/"), [atom(name), fixnum(arity)]);
let res_stub = functor!(atom!(":"), [atom(module_name), str(h + 3, 0)], [ind_stub]);
let ind_stub = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]);
let res_stub = functor!(atom!(":"), [atom_as_cell(module_name), functor(ind_stub)]);
let stub = functor!(
atom!("existence_error"),
[atom(atom!("procedure")), str(h, 0)],
[res_stub]
[atom_as_cell((atom!("procedure"))), functor(res_stub)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
ExistenceError::Procedure(name, arity) => {
let culprit = functor!(atom!("/"), [atom(name), fixnum(arity)]);
let culprit = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]);
let stub = functor!(
atom!("existence_error"),
[atom(atom!("procedure")), str(self.heap.len(), 0)],
[culprit]
[atom_as_cell((atom!("procedure"))), functor(culprit)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
ExistenceError::ModuleSource(source) => {
@@ -418,43 +364,75 @@ impl MachineState {
let stub = functor!(
atom!("existence_error"),
[atom(atom!("source_sink")), str(self.heap.len(), 0)],
[source_stub]
[atom_as_cell((atom!("source_sink"))), functor(source_stub)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
ExistenceError::SourceSink(culprit) => {
let stub = functor!(
atom!("existence_error"),
[atom(atom!("source_sink")), cell(culprit)]
[atom_as_cell((atom!("source_sink"))), cell(culprit)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
ExistenceError::Stream(culprit) => {
let stub = functor!(
atom!("existence_error"),
[atom(atom!("stream")), cell(culprit)]
[atom_as_cell((atom!("stream"))), cell(culprit)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
}
pub(crate) fn directive_error(&mut self, err: DirectiveError) -> MachineError {
match err {
DirectiveError::ExpectedDirective(_term) => self.domain_error(
DomainErrorType::Directive,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidDirective(name, arity) => {
self.domain_error(DomainErrorType::Directive, functor_stub(name, arity))
}
DirectiveError::InvalidOpDeclNameType(_term) => self.type_error(
ValidType::List,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecDomain(_term) => self.domain_error(
DomainErrorType::OperatorSpecifier,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecValue(atom) => {
self.domain_error(DomainErrorType::OperatorSpecifier, atom_as_cell!(atom))
}
DirectiveError::InvalidOpDeclPrecType(_term) => self.type_error(
ValidType::Integer,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclPrecDomain(num) => {
self.domain_error(DomainErrorType::OperatorPriority, fixnum_as_cell!(num))
}
DirectiveError::ShallNotCreate(atom) => {
self.permission_error(Permission::Create, atom!("operator"), atom)
}
DirectiveError::ShallNotModify(atom) => {
self.permission_error(Permission::Modify, atom!("operator"), atom)
}
}
}
pub(super) fn permission_error<T: PermissionError>(
&mut self,
err: Permission,
@@ -471,7 +449,6 @@ impl MachineState {
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
match err {
ArithmeticError::UninstantiatedVar => self.instantiation_error(),
ArithmeticError::NonEvaluableFunctor(cell, arity) => {
let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]);
@@ -495,7 +472,6 @@ impl MachineState {
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
@@ -505,15 +481,11 @@ impl MachineState {
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1)
.into_iter()
.collect::<MachineStub>(),
),
SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1)
.into_iter()
.collect::<MachineStub>(),
),
SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(Permission::Modify, atom!("static_module"), module)
@@ -524,8 +496,7 @@ impl MachineState {
let stub = functor!(
atom!("module_does_not_contain_claimed_export"),
[atom(module_name), str(self.heap.len() + 4, 0)],
[functor_stub]
[atom_as_cell(module_name), functor(functor_stub)]
);
self.permission_error(Permission::Access, atom!("private_procedure"), stub)
@@ -536,7 +507,7 @@ impl MachineState {
self.permission_error(
Permission::Modify,
atom!("module"),
functor!(error_atom, [atom(module_name)]),
functor!(error_atom, [atom_as_cell(module_name)]),
)
}
SessionError::NamelessEntry => {
@@ -555,15 +526,12 @@ impl MachineState {
}
SessionError::CompilationError(err) => self.syntax_error(err),
SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key) => {
let functor_stub = functor_stub(key.0, key.1);
let stub = functor!(
atom!(":"),
[
atom(compilation_target.module_name()),
str(self.heap.len() + 4, 0)
],
[functor_stub]
atom_as_cell((compilation_target.module_name())),
functor((key.0), [fixnum((key.1))])
]
);
self.permission_error(
@@ -587,30 +555,27 @@ impl MachineState {
}
let location = err.line_and_col_num();
let len = self.heap.len();
let stub = err.as_functor();
let stub = functor!(atom!("syntax_error"), [str(len, 0)], [stub]);
let stub = functor!(atom!("syntax_error"), [functor(stub)]);
MachineError {
stub,
location,
from: ErrorProvenance::Constructed,
}
}
pub(super) fn representation_error(&mut self, flag: RepFlag) -> MachineError {
let stub = functor!(atom!("representation_error"), [atom(flag.as_atom())]);
pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
#[cfg(feature = "ffi")]
pub(super) fn ffi_error(&mut self, err: FFIError) -> MachineError {
pub(super) fn ffi_error(&self, err: FFIError) -> MachineError {
let error_atom = match err {
FFIError::ValueCast => atom!("value_cast"),
FFIError::ValueDontFit => atom!("value_dont_fit"),
@@ -619,62 +584,44 @@ impl MachineState {
FFIError::FunctionNotFound => atom!("function_not_found"),
FFIError::StructNotFound => atom!("struct_not_found"),
};
let stub = functor!(atom!("ffi_error"), [atom(error_atom)]);
let stub = functor!(atom!("ffi_error"), [atom_as_cell(error_atom)]);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
pub(super) fn error_form(&mut self, err: MachineError, src: FunctorStub) -> MachineStub {
let h = self.heap.len();
let location = err.location;
let stub_addition_len = if err.len() == 1 {
0 // if err contains 1 cell, it can be inlined at stub[1].
pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
if let Some(ParserErrorSrc { line_num, .. }) = err.location {
functor!(atom!("error"), [functor((err.stub)),
functor((atom!(":")), [functor(src),
number(line_num, (&mut self.arena))])])
} else {
err.len()
};
let mut stub = vec![
atom_as_cell!(atom!("error"), 2),
str_loc_as_cell!(h + 3),
str_loc_as_cell!(h + 3 + stub_addition_len),
];
if stub_addition_len > 0 {
stub.extend(err.into_iter(3));
} else {
stub[1] = err.stub[0];
functor!(atom!("error"), [functor((err.stub)),
functor(src)])
}
}
if let Some(ParserErrorSrc { line_num, .. }) = location {
stub.push(atom_as_cell!(atom!(":"), 2));
stub.push(str_loc_as_cell!(h + 6 + stub_addition_len));
stub.push(integer_as_cell!(Number::arena_from(
line_num,
&mut self.arena
)));
}
stub.extend(src.iter());
stub
// throw an error pre-allocated in the heap
pub(super) fn throw_resource_error(&mut self, err_loc: usize) {
self.registers[1] = str_loc_as_cell!(err_loc);
self.set_ball();
self.unwind_stack();
}
pub(super) fn throw_exception(&mut self, err: MachineStub) {
let h = self.heap.len();
let err_len = err.len();
self.ball.boundary = 0;
self.ball.stub.truncate(0);
self.heap.extend(err);
let mut writer = Heap::functor_writer(err);
self.registers[1] = if err_len == 1 {
heap_loc_as_cell!(h)
} else {
str_loc_as_cell!(h)
self.registers[1] = match writer(&mut self.heap) {
Ok(loc) => loc,
Err(resource_err_loc) => {
self.throw_resource_error(resource_err_loc);
return;
}
};
self.set_ball();
@@ -682,21 +629,6 @@ impl MachineState {
}
}
impl MachineError {
fn into_iter(self, offset: usize) -> Box<dyn Iterator<Item = HeapCellValue>> {
match self.from {
ErrorProvenance::Constructed => {
Box::new(self.stub.into_iter().map(move |hcv| hcv + offset))
}
ErrorProvenance::Received => Box::new(self.stub.into_iter()),
}
}
fn len(&self) -> usize {
self.stub.len()
}
}
#[derive(Debug)]
pub enum CompilationError {
Arithmetic(ArithmeticError),
@@ -715,12 +647,12 @@ pub enum CompilationError {
#[derive(Debug)]
pub enum DirectiveError {
ExpectedDirective(Term),
ExpectedDirective(HeapCellValue),
InvalidDirective(Atom, usize /* arity */),
InvalidOpDeclNameType(Term),
InvalidOpDeclSpecDomain(Term),
InvalidOpDeclNameType(HeapCellValue),
InvalidOpDeclSpecDomain(HeapCellValue),
InvalidOpDeclSpecValue(Atom),
InvalidOpDeclPrecType(Term),
InvalidOpDeclPrecType(HeapCellValue),
InvalidOpDeclPrecDomain(Fixnum),
ShallNotCreate(Atom),
ShallNotModify(Atom),
@@ -757,11 +689,9 @@ impl CompilationError {
functor!(atom!("exceeded_max_arity"))
}
CompilationError::InadmissibleFact => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_fact"))
}
CompilationError::InadmissibleQueryTerm => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_query_term"))
}
CompilationError::InvalidDirective(_) => {
@@ -776,8 +706,8 @@ impl CompilationError {
CompilationError::InvalidModuleExport => {
functor!(atom!("invalid_module_export"))
}
CompilationError::InvalidModuleResolution(ref module_name) => {
functor!(atom!("no_such_module"), [atom(module_name)])
&CompilationError::InvalidModuleResolution(module_name) => {
functor!(atom!("no_such_module"), [atom_as_cell(module_name)])
}
CompilationError::InvalidRuleHead => {
functor!(atom!("invalid_head_of_rule")) // TODO: type_error(callable, _).
@@ -896,14 +826,13 @@ impl EvalError {
// used by '$skip_max_list'.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CycleSearchResult {
Cyclic(usize),
Cyclic { lambda: usize }, // number of steps
EmptyList,
NotList(usize, HeapCellValue), // the list length until the second argument in the heap
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
ProperList(usize), // the list length.
PStrLocation(usize, usize, usize), // list length (up to max), the heap address of the PStr, the offset
UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address).
UntouchedCStr(Atom, usize),
NotList { num_steps: usize, heap_loc: HeapCellValue },
PartialList { num_steps: usize, heap_loc: HeapCellValue },
ProperList { num_steps: usize },
PStrLocation { num_steps: usize, pstr_loc: HeapCellValue },
UntouchedList { num_steps: usize, list_loc: usize },
}
impl MachineState {
@@ -915,11 +844,11 @@ impl MachineState {
let sorted = self.store(self.deref(self.registers[2]));
match BrentAlgState::detect_cycles(&self.heap, list) {
CycleSearchResult::PartialList(..) => {
CycleSearchResult::PartialList { .. } => {
let err = self.instantiation_error();
return Err(self.error_form(err, stub_gen()));
}
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => {
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } => {
let err = self.type_error(ValidType::List, list);
return Err(self.error_form(err, stub_gen()));
}
@@ -927,7 +856,7 @@ impl MachineState {
};
match BrentAlgState::detect_cycles(&self.heap, sorted) {
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) if !sorted.is_var() => {
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !sorted.is_var() => {
let err = self.type_error(ValidType::List, sorted);
Err(self.error_form(err, stub_gen()))
}
@@ -939,7 +868,7 @@ impl MachineState {
let stub_gen = || functor_stub(atom!("keysort"), 2);
match BrentAlgState::detect_cycles(&self.heap, list) {
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) if !list.is_var() => {
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !list.is_var() => {
let err = self.type_error(ValidType::List, list);
Err(self.error_form(err, stub_gen()))
}
@@ -1001,11 +930,11 @@ impl MachineState {
let sorted = self.store(self.deref(self[temp_v!(2)]));
match BrentAlgState::detect_cycles(&self.heap, pairs) {
CycleSearchResult::PartialList(..) => {
CycleSearchResult::PartialList { .. } => {
let err = self.instantiation_error();
Err(self.error_form(err, stub_gen()))
}
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => {
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } => {
let err = self.type_error(ValidType::List, pairs);
Err(self.error_form(err, stub_gen()))
}

View File

@@ -169,6 +169,13 @@ impl From<TypedArenaPtr<IndexPtr>> for CodeIndex {
}
}
impl From<CodeIndex> for HeapCellValue {
#[inline(always)]
fn from(idx: CodeIndex) -> HeapCellValue {
untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx))
}
}
impl CodeIndex {
#[inline]
pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self {
@@ -208,10 +215,12 @@ impl CodeIndex {
std::mem::replace(self.0.deref_mut(), value)
}
/*
#[inline(always)]
pub(crate) fn as_ptr(&self) -> *const IndexPtr {
self.0.as_ptr()
}
*/
}
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;

View File

@@ -1,6 +1,7 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
use crate::functor_macro::*;
use crate::heap_iter::*;
use crate::heap_print::*;
use crate::machine::attributed_variables::*;
@@ -12,7 +13,6 @@ use crate::machine::stack::*;
use crate::machine::streams::*;
use crate::machine::Machine;
use crate::parser::ast::*;
use crate::read::TermWriteResult;
use crate::types::*;
use crate::parser::dashu::Integer;
@@ -21,7 +21,7 @@ use indexmap::IndexMap;
use std::convert::TryFrom;
use std::fmt;
use std::ops::{Index, IndexMut};
use std::ops::{Index, IndexMut, Range};
use std::rc::Rc;
use std::sync::Arc;
@@ -36,8 +36,8 @@ pub(super) enum MachineMode {
#[derive(Debug, Clone)]
pub(super) enum HeapPtr {
HeapCell(usize),
PStrChar(usize, usize),
PStrLocation(usize, usize),
PStr(usize), // Char(usize),
// PStrLocation(usize),
}
impl Default for HeapPtr {
@@ -184,8 +184,9 @@ impl IndexMut<RegType> for MachineState {
}
}
pub type CallResult = Result<(), Vec<HeapCellValue>>;
pub type CallResult = Result<(), Vec<FunctorElement>>;
/*
#[inline(always)]
pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixnum) {
read_heap_cell!(heap[index],
@@ -200,30 +201,44 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
}
)
}
*/
fn push_var_eq_functors(
heap: &mut Heap,
size: usize,
iter: impl Iterator<Item = (usize, Var)>,
atom_tbl: &AtomTable,
) -> Vec<HeapCellValue> {
let mut list_of_var_eqs = vec![];
) -> Result<HeapCellValue, usize> {
let src_h = heap.cell_len();
for (var_loc, var) in iter { // (var, binding) in iter {
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let h = heap.len();
let binding = heap[var_loc];
if size > 0 {
let mut writer = heap.reserve(1 + 5 * size)?;
heap.push(atom_as_cell!(atom!("="), 2));
heap.push(atom_as_cell!(var_atom));
heap.push(binding);
writer.write_with(|section| {
for (var_loc, var) in iter { // (var, binding) in iter {
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let binding = heap_loc_as_cell!(var_loc);
list_of_var_eqs.push(str_loc_as_cell!(h));
section.push_cell(atom_as_cell!(atom!("="), 2));
section.push_cell(atom_as_cell!(var_atom));
section.push_cell(binding);
}
for idx in 0 .. size {
section.push_cell(list_loc_as_cell!(section.cell_len() + 1));
section.push_cell(str_loc_as_cell!(src_h + 3 * idx));
}
section.push_cell(empty_list_as_cell!());
});
Ok(heap_loc_as_cell!(src_h + 3 * size))
} else {
Ok(empty_list_as_cell!())
}
list_of_var_eqs
}
/*
pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
iter: Iter,
boundary: i64,
@@ -232,6 +247,7 @@ pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
let diff = boundary - h;
iter.map(move |heap_value| heap_value - diff)
}
*/
#[derive(Debug)]
pub struct Ball {
@@ -252,8 +268,17 @@ impl Ball {
self.stub.clear();
}
pub(super) fn copy_and_align(&self, h: usize) -> Heap {
copy_and_align_iter(self.stub.iter().cloned(), self.boundary as i64, h as i64).collect()
pub(super) fn copy_and_align_to(&self, dest: &mut Heap) -> Result<usize, usize> {
let h = dest.cell_len();
let diff = self.boundary as i64 - h as i64;
dest.append(self.stub.splice(..))?;
for cell in &mut dest.splice_mut(h ..) {
*cell = *cell - diff;
}
Ok(h)
}
}
@@ -285,21 +310,6 @@ impl<'a> IndexMut<usize> for CopyTerm<'a> {
}
impl<'a> CopierTarget for CopyTerm<'a> {
#[inline(always)]
fn threshold(&self) -> usize {
self.state.heap.len()
}
#[inline(always)]
fn push(&mut self, hcv: HeapCellValue) {
self.state.heap.push(hcv);
}
#[inline(always)]
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.state.attr_var_init.attr_var_queue.push(attr_var_loc);
}
#[inline(always)]
fn store(&self, value: HeapCellValue) -> HeapCellValue {
self.state.store(value)
@@ -310,10 +320,56 @@ impl<'a> CopierTarget for CopyTerm<'a> {
self.state.deref(value)
}
#[inline(always)]
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.state.attr_var_init.attr_var_queue.push(attr_var_loc);
}
#[inline(always)]
fn stack(&mut self) -> &mut Stack {
&mut self.state.stack
}
#[inline(always)]
fn threshold(&self) -> usize {
self.state.heap.cell_len()
}
#[inline(always)]
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
self.state.heap.copy_pstr_within(pstr_loc)
}
#[inline(always)]
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
self.state.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
}
#[inline(always)]
fn pstr_at(&self, loc: usize) -> bool {
self.state.heap.pstr_vec()[loc]
}
#[inline(always)]
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
// unwrap is safe here because a partial string is always
// followed by a tail cell, i.e. a non-pstr cell, supposing
// self.state.heap[loc] is a pstr cell
self.state.heap.pstr_vec()[loc ..].first_zero().unwrap()
}
#[inline(always)]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.state.heap.reserve(num_cells)
}
#[inline(always)]
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
self.state.heap.copy_slice_to_end(bounds)
}
}
#[derive(Debug)]
@@ -321,7 +377,6 @@ pub(crate) struct CopyBallTerm<'a> {
attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack,
heap: &'a mut Heap,
heap_boundary: usize,
stub: &'a mut Heap,
}
@@ -332,13 +387,10 @@ impl<'a> CopyBallTerm<'a> {
heap: &'a mut Heap,
stub: &'a mut Heap,
) -> Self {
let hb = heap.len();
CopyBallTerm {
attr_var_queue,
stack,
heap,
heap_boundary: hb,
stub,
}
}
@@ -348,10 +400,10 @@ impl<'a> Index<usize> for CopyBallTerm<'a> {
type Output = HeapCellValue;
fn index(&self, index: usize) -> &Self::Output {
if index < self.heap_boundary {
if index < self.heap.cell_len() {
&self.heap[index]
} else {
let index = index - self.heap_boundary;
let index = index - self.heap.cell_len();
&self.stub[index]
}
}
@@ -359,10 +411,10 @@ impl<'a> Index<usize> for CopyBallTerm<'a> {
impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index < self.heap_boundary {
if index < self.heap.cell_len() {
&mut self.heap[index]
} else {
let index = index - self.heap_boundary;
let index = index - self.heap.cell_len();
&mut self.stub[index]
}
}
@@ -370,11 +422,7 @@ impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
impl<'a> CopierTarget for CopyBallTerm<'a> {
fn threshold(&self) -> usize {
self.heap_boundary + self.stub.len()
}
fn push(&mut self, value: HeapCellValue) {
self.stub.push(value);
self.heap.cell_len() + self.stub.cell_len()
}
#[inline(always)]
@@ -385,10 +433,10 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
fn store(&self, value: HeapCellValue) -> HeapCellValue {
read_heap_cell!(value,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
if h < self.heap_boundary {
if h < self.heap.cell_len() {
self.heap[h]
} else {
let index = h - self.heap_boundary;
let index = h - self.heap.cell_len();
self.stub[index]
}
}
@@ -417,6 +465,67 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
fn stack(&mut self) -> &mut Stack {
self.stack
}
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
debug_assert!(pstr_loc < self.heap.byte_len());
let (string, tail_loc) = self.heap.scan_slice_to_str(pstr_loc);
self.stub.allocate_pstr(string)?;
Ok(tail_loc)
}
#[inline]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.stub.reserve(num_cells)
}
#[inline]
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
if pstr_loc >= self.heap.byte_len() {
self.stub.pstr_vec()[0 .. cell_index!(pstr_loc - self.heap.byte_len())]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
} else {
self.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
}
}
#[inline]
fn pstr_at(&self, loc: usize) -> bool {
if loc >= self.heap.cell_len() {
self.stub.pstr_vec()[loc - self.heap.cell_len()]
} else {
self.heap.pstr_vec()[loc]
}
}
#[inline]
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
let zero_from_loc = if loc >= self.heap.cell_len() {
self.stub.pstr_vec()[loc - self.heap.cell_len() ..].first_zero().unwrap()
} else {
self.heap.pstr_vec()[loc ..].first_zero().unwrap()
};
zero_from_loc + loc
}
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
let len = bounds.end - bounds.start;
let mut stub_writer = self.stub.reserve(len)?;
stub_writer.write_with(|section| {
for idx in bounds {
section.push_cell(self.heap[idx]);
}
});
Ok(())
}
}
impl MachineState {
@@ -467,10 +576,6 @@ impl MachineState {
let addr = self.store(self.deref(addr));
read_heap_cell!(addr,
(HeapCellValueTag::Char, c) => {
chars.push(c);
continue;
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
if let Some(c) = name.as_char() {
@@ -543,35 +648,37 @@ impl MachineState {
pub fn write_read_term_options(
&mut self,
mut var_list: Vec<(Var, HeapCellValue, usize)>,
singleton_var_list: Vec<HeapCellValue>,
singletons_heap_list: HeapCellValue,
) -> CallResult {
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
/*
let list_of_var_eqs = push_var_eq_functors(
&mut self.heap,
var_list.iter().map(|(var_name, var, _)| {
(var.get_value() as usize, var_name.clone())
}),
num_vars,
&self.atom_tbl,
);
*/
let singleton_addr = self.registers[3];
let singletons_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
singleton_var_list.into_iter()
));
unify_fn!(*self, singletons_offset, singleton_addr);
unify_fn!(*self, singletons_heap_list, singleton_addr);
if self.fail {
return Ok(());
}
let vars_addr = self.registers[4];
let vars_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
var_list.into_iter().map(|(_, cell, _)| cell)
));
let vars_offset = resource_error_call_result!(
self,
sized_iter_to_heap_list(
&mut self.heap,
var_list.len(),
var_list.iter().map(|(_, cell, _)| *cell),
)
);
unify_fn!(*self, vars_offset, vars_addr);
@@ -580,23 +687,41 @@ impl MachineState {
}
let var_names_addr = self.registers[5];
/*
let var_names_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
list_of_var_eqs.into_iter()
));
*/
let var_names_offset = resource_error_call_result!(
self,
push_var_eq_functors(
&mut self.heap,
var_list.len(),
var_list.iter().map(|(var_name, var, _)| {
(var.get_value() as usize, var_name.clone())
}),
&self.atom_tbl,
)
);
Ok(unify_fn!(*self, var_names_offset, var_names_addr))
}
pub fn read_term_body(&mut self, term: TermWriteResult) -> CallResult {
let heap_loc = read_heap_cell!(self.heap[term.heap_loc],
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
let heap_loc = self.heap[term.focus];
/*
read_heap_cell!(self.heap[term.heap_loc],
(HeapCellValueTag::PStr) => { // | HeapCellValueTag::PStrOffset) => {
pstr_loc_as_cell!(term.heap_loc)
}
_ => {
heap_loc_as_cell!(term.heap_loc)
}
);
*/
unify_fn!(*self, heap_loc, self.registers[2]);
@@ -612,7 +737,7 @@ impl MachineState {
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
for cell in eager_stackful_preorder_iter(&mut self.heap, heap_loc) {
for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus) {
let cell = unmark_cell_bits!(cell);
if let Some(var) = cell.as_var() {
@@ -624,29 +749,33 @@ impl MachineState {
}
}
let singleton_var_list = push_var_eq_functors(
&mut self.heap,
term.inverse_var_locs
.iter()
.filter_map(|(var_loc, var_name)| {
// add h to offset the term variable into its heap location.
let r = Ref::heap_cell(*var_loc);
let singleton_var_list = resource_error_call_result!(
self,
push_var_eq_functors(
&mut self.heap,
singleton_var_set
.iter()
.filter(|(var, is_singleton)| {
**is_singleton && term.inverse_var_locs.contains_key(
&(var.get_value() as usize)
)
})
.count(),
term.inverse_var_locs
.iter()
.filter_map(|(var_loc, var_name)| {
let r = Ref::heap_cell(*var_loc);
if singleton_var_set.get(&r).cloned().unwrap_or(false) {
Some((*var_loc, var_name.clone()))
} else {
None
}
}),
&self.atom_tbl,
if singleton_var_set.get(&r).cloned().unwrap_or(false) {
Some((*var_loc, var_name.clone()))
} else {
None
}
}),
&self.atom_tbl,
)
);
/*
for var in term_write_result.var_dict.values_mut() {
*var = heap_bound_deref(&self.heap, *var);
}
*/
let mut var_list = Vec::with_capacity(singleton_var_set.len());
for (var_loc, var_name) in term.inverse_var_locs {
@@ -744,7 +873,7 @@ impl MachineState {
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? {
OnEOF::Return => {
return self.write_read_term_options(vec![], vec![])
return self.write_read_term_options(vec![], empty_list_as_cell!());
}
OnEOF::Continue => continue,
}
@@ -793,9 +922,6 @@ impl MachineState {
}
read_heap_cell!(atom,
(HeapCellValueTag::Char, c) => {
var_names.insert(var, Rc::new(c.to_string()));
}
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
var_names.insert(var, Rc::new(name.as_str().to_owned()));
@@ -884,16 +1010,20 @@ impl MachineState {
}
);
let h = self.heap.len();
self.heap.push(term_to_be_printed);
let term_loc = self.heap.cell_len();
step_or_resource_error!(
self,
self.heap.push_cell(term_to_be_printed),
{ return Ok(None); }
);
let mut printer = HCPrinter::new(
&mut self.heap,
Arc::clone(&self.atom_tbl),
&mut self.stack,
op_dir,
PrinterOutputter::new(),
h,
term_loc,
);
printer.ignore_ops = ignore_ops;
@@ -984,42 +1114,6 @@ impl MachineState {
}
);
}
pub(crate) fn directive_error(&mut self, err: DirectiveError) -> MachineError {
match err {
DirectiveError::ExpectedDirective(_term) => self.domain_error(
DomainErrorType::Directive,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidDirective(name, arity) => {
self.domain_error(DomainErrorType::Directive, functor_stub(name, arity))
}
DirectiveError::InvalidOpDeclNameType(_term) => self.type_error(
ValidType::List,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecDomain(_term) => self.domain_error(
DomainErrorType::OperatorSpecifier,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecValue(atom) => {
self.domain_error(DomainErrorType::OperatorSpecifier, atom_as_cell!(atom))
}
DirectiveError::InvalidOpDeclPrecType(_term) => self.type_error(
ValidType::Integer,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclPrecDomain(num) => {
self.domain_error(DomainErrorType::OperatorPriority, fixnum_as_cell!(num))
}
DirectiveError::ShallNotCreate(atom) => {
self.permission_error(Permission::Create, atom!("operator"), atom)
}
DirectiveError::ShallNotModify(atom) => {
self.permission_error(Permission::Modify, atom!("operator"), atom)
}
}
}
}
#[allow(clippy::upper_case_acronyms)]

File diff suppressed because it is too large Load Diff

View File

@@ -4,16 +4,12 @@ pub use crate::machine::machine_state::*;
pub use crate::machine::streams::*;
pub use crate::machine::*;
pub use crate::parser::ast::*;
use crate::read::*;
pub use crate::types::*;
use std::sync::Arc;
#[cfg(test)]
use crate::machine::copier::CopierTarget;
#[cfg(test)]
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
// a mini-WAM for test purposes.
@@ -31,7 +27,6 @@ impl MockWAM {
Self {
machine_st: MachineState::new(),
op_dir,
//flags: MachineFlags::default(),
}
}
@@ -56,7 +51,7 @@ impl MockWAM {
) -> Result<String, CompilationError> {
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);
print_heap_terms(self.machine_st.heap.splice(..), term_write_result.focus);
let var_names = term_write_result
.inverse_var_locs
@@ -68,11 +63,10 @@ impl MockWAM {
let mut printer = HCPrinter::new(
&mut self.machine_st.heap,
Arc::clone(&self.machine_st.atom_tbl),
&mut self.machine_st.stack,
&self.op_dir,
PrinterOutputter::new(),
term_write_result.heap_loc,
term_write_result.focus,
);
printer.var_names = var_names;
@@ -154,10 +148,6 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
}
}
fn push(&mut self, val: HeapCellValue) {
self.wam.machine_st.heap.push(val);
}
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.wam
.machine_st
@@ -171,43 +161,123 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
}
fn threshold(&self) -> usize {
self.wam.machine_st.heap.len()
self.wam.machine_st.heap.cell_len()
}
#[inline(always)]
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
self.wam.machine_st.heap.copy_pstr_within(pstr_loc)
}
#[inline(always)]
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
self.wam.machine_st.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
}
#[inline(always)]
fn pstr_at(&self, loc: usize) -> bool {
self.wam.machine_st.heap.pstr_vec()[loc]
}
#[inline(always)]
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
// unwrap is safe here because a partial string is always
// followed by a tail cell, i.e. a non-pstr cell, supposing
// self.machine_st.heap[loc] is a pstr cell
self.wam.machine_st.heap.pstr_vec()[loc ..].first_zero()
.map(|idx| idx + loc)
.unwrap()
}
#[inline(always)]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.wam.machine_st.heap.reserve(num_cells)
}
#[inline(always)]
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
self.wam.machine_st.heap.copy_slice_to_end(bounds)
}
}
#[cfg(test)]
pub fn all_cells_marked_and_unforwarded(heap: &[HeapCellValue]) {
for (idx, cell) in heap.iter().enumerate() {
pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
let mut idx = 0;
let cell_len = iter.cell_len();
while idx < cell_len {
let curr_idx = idx;
let cell = if iter.pstr_at(idx) {
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
idx = last_cell_loc;
iter[last_cell_loc - 1]
} else {
idx += 1;
iter[curr_idx]
};
assert!(
cell.get_mark_bit(),
"cell {:?} at index {} is not marked",
cell,
idx
curr_idx
);
assert!(
!cell.get_forwarding_bit(),
"cell {:?} at index {} is forwarded",
cell,
idx
curr_idx
);
}
}
#[cfg(test)]
pub fn all_cells_unmarked(heap: &Heap) {
for (idx, cell) in heap.iter().enumerate() {
pub fn unmark_all_cells(mut iter: impl SizedHeapMut) {
let mut idx = 0;
let cell_len = iter.cell_len();
while idx < cell_len {
if iter.pstr_at(idx) {
iter[idx].set_mark_bit(false);
let last_cell_loc = {
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
last_cell_loc
};
iter[last_cell_loc].set_mark_bit(false);
idx = last_cell_loc;
} else {
iter[idx].set_mark_bit(false);
idx += 1;
}
}
}
#[cfg(test)]
pub fn all_cells_unmarked(iter: impl SizedHeap) {
let mut idx = 0;
let cell_len = iter.cell_len();
while idx < cell_len {
let curr_idx = idx;
let cell = if iter.pstr_at(idx) {
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
idx = last_cell_loc;
iter[last_cell_loc - 1]
} else {
idx += 1;
iter[curr_idx]
};
assert!(
!cell.get_mark_bit(),
"cell {:?} at index {} is still marked",
cell,
idx
);
assert!(
!cell.get_forwarding_bit(),
"cell {:?} at index {} is still forwarded",
cell,
idx
curr_idx
);
}
}
@@ -256,6 +326,8 @@ impl Machine {
mod tests {
use super::*;
use crate::functor_macro::FunctorElement;
#[test]
fn unify_tests() {
let mut wam = MachineState::new();
@@ -276,13 +348,13 @@ mod tests {
unify!(
wam,
str_loc_as_cell!(0),
str_loc_as_cell!(term_write_result_2.heap_loc)
str_loc_as_cell!(term_write_result_2.focus)
);
assert!(wam.fail);
}
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
@@ -296,14 +368,14 @@ mod tests {
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.heap_loc),
heap_loc_as_cell!(term_write_result_2.heap_loc)
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
@@ -317,14 +389,14 @@ mod tests {
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.heap_loc),
heap_loc_as_cell!(term_write_result_2.heap_loc)
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
@@ -338,14 +410,14 @@ mod tests {
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.heap_loc),
heap_loc_as_cell!(term_write_result_2.heap_loc)
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
@@ -359,14 +431,14 @@ mod tests {
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.heap_loc),
heap_loc_as_cell!(term_write_result_2.heap_loc)
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
@@ -378,95 +450,119 @@ mod tests {
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);
all_cells_unmarked(wam.heap.splice(..));
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.heap_loc),
heap_loc_as_cell!(term_write_result_2.heap_loc)
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear();
wam.heap.push(pstr_as_cell!(atom!("this is a string")));
wam.heap.push(heap_loc_as_cell!(1));
let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(pstr_as_cell!(atom!("this is a string")));
wam.heap.push(pstr_loc_as_cell!(4));
writer.write_with(|section| {
section.push_pstr("this is a string"); // 0
wam.heap.push(pstr_offset_as_cell!(0));
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(6)));
let h = section.cell_len();
assert_eq!(h, 3);
unify!(wam, pstr_loc_as_cell!(0), pstr_loc_as_cell!(2));
section.push_cell(heap_loc_as_cell!(h)); // 3
section.push_pstr("this is a string"); // 4
let h = section.cell_len();
assert_eq!(h + 1, 8);
section.push_cell(pstr_loc_as_cell!(heap_index!(h + 1))); // 7
section.push_pstr("this is a string"); // 8
section.push_cell(pstr_loc_as_cell!(heap_index!(h + 1)));
});
unify!(wam, pstr_loc_as_cell!(0), pstr_loc_as_cell!(heap_index!(4)));
assert!(!wam.fail);
assert_eq!(wam.heap[1], pstr_loc_as_cell!(4));
assert_eq!(wam.heap[3], pstr_loc_as_cell!(heap_index!(8)));
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
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));
let mut writer = wam.heap.reserve(96).unwrap();
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));
writer.write_with(|section| {
section.push_cell(list_loc_as_cell!(1));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(3));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(0));
section.push_cell(list_loc_as_cell!(6));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(8));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(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);
all_cells_unmarked(wam.heap.splice(..));
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));
let mut writer = wam.heap.reserve(96).unwrap();
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));
writer.write_with(|section| {
section.push_cell(list_loc_as_cell!(1));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(3));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(0));
section.push_cell(list_loc_as_cell!(6));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(8));
section.push_cell(atom_as_cell!(atom!("c")));
section.push_cell(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);
all_cells_unmarked(wam.heap.splice(..));
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));
let mut writer = wam.heap.reserve(96).unwrap();
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));
writer.write_with(|section| {
section.push_cell(list_loc_as_cell!(1));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(3));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(5));
section.push_cell(list_loc_as_cell!(6));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(8));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(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);
all_cells_unmarked(wam.heap.splice(..));
}
#[test]
@@ -485,12 +581,12 @@ mod tests {
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);
all_cells_unmarked(wam.heap.splice(..));
unify_with_occurs_check!(
wam,
heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.heap_loc)
heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(wam.fail);
@@ -503,8 +599,15 @@ mod tests {
let mut wam = MachineState::new();
wam.heap.push(heap_loc_as_cell!(0));
wam.heap.push(heap_loc_as_cell!(1));
// clear the heap of resource error data etc
wam.heap.clear();
let mut writer = wam.heap.reserve(96).unwrap();
writer.write_with(|section| {
section.push_cell(heap_loc_as_cell!(0));
section.push_cell(heap_loc_as_cell!(1));
});
assert_eq!(
compare_term_test!(wam, wam.heap[0], wam.heap[1]),
@@ -526,11 +629,13 @@ mod tests {
Some(Ordering::Equal)
);
let cstr_cell = wam.allocate_cstr("string").unwrap();
assert_eq!(
compare_term_test!(
wam,
atom_as_cell!(atom!("atom")),
atom_as_cstr_cell!(atom!("string"))
cstr_cell
),
Some(Ordering::Less)
);
@@ -564,8 +669,12 @@ mod tests {
wam.heap.clear();
wam.heap.push(atom_as_cell!(atom!("f"), 1));
wam.heap.push(heap_loc_as_cell!(1));
let mut writer = wam.heap.reserve(96).unwrap();
writer.write_with(|section| {
section.push_cell(atom_as_cell!(atom!("f"), 1));
section.push_cell(heap_loc_as_cell!(1));
});
assert_eq!(
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
@@ -579,21 +688,25 @@ mod tests {
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!());
let mut writer = wam.heap.reserve(96).unwrap();
// [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!());
writer.write_with(|section| {
// [1,2,3]
section.push_cell(list_loc_as_cell!(1));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(1)));
section.push_cell(list_loc_as_cell!(3));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(2)));
section.push_cell(list_loc_as_cell!(5));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(3)));
section.push_cell(empty_list_as_cell!());
// [1,2]
section.push_cell(list_loc_as_cell!(8));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(1)));
section.push_cell(list_loc_as_cell!(10));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(2)));
section.push_cell(empty_list_as_cell!());
});
assert_eq!(
compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
@@ -619,11 +732,13 @@ mod tests {
Some(Ordering::Greater)
);
let cstr_cell = wam.allocate_cstr("string").unwrap();
assert_eq!(
compare_term_test!(
wam,
empty_list_as_cell!(),
atom_as_cstr_cell!(atom!("string"))
cstr_cell
),
Some(Ordering::Less)
);
@@ -655,55 +770,66 @@ mod tests {
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))));
let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(heap_loc_as_cell!(0));
writer.write_with(|section| {
section.push_cell(atom_as_cell!(atom!("f")));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(555)));
section.push_cell(heap_loc_as_cell!(0));
});
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(0)));
assert!(!wam.is_cyclic_term(0));
assert!(!wam.is_cyclic_term(1));
assert!(!wam.is_cyclic_term(2));
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear();
wam.heap
.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))]));
let mut functor_writer = Heap::functor_writer(
functor!(
atom!("f"),
[atom_as_cell((atom!("a"))),
atom_as_cell((atom!("b")))]
),
);
assert!(!wam.is_cyclic_term(str_loc_as_cell!(0)));
functor_writer(&mut wam.heap).unwrap();
all_cells_unmarked(&wam.heap);
let h = wam.heap.cell_len();
wam.heap.push_cell(str_loc_as_cell!(0)).unwrap();
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(1)));
assert!(!wam.is_cyclic_term(h));
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(2)));
assert!(!wam.is_cyclic_term(1));
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
assert!(!wam.is_cyclic_term(2));
all_cells_unmarked(wam.heap.splice(..));
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)));
assert!(wam.is_cyclic_term(2));
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
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)));
assert!(wam.is_cyclic_term(1));
all_cells_unmarked(&wam.heap);
assert!(wam.is_cyclic_term(heap_loc_as_cell!(1)));
all_cells_unmarked(&wam.heap);
all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear();
wam.heap.push(pstr_as_cell!(atom!("a string")));
wam.heap.push(empty_list_as_cell!());
let h = wam.heap.cell_len();
wam.allocate_cstr("a string").unwrap();
assert!(!wam.is_cyclic_term(pstr_loc_as_cell!(0)));
assert!(!wam.is_cyclic_term(h));
}
}

View File

@@ -485,7 +485,10 @@ impl Machine {
#[inline(always)]
pub(crate) fn run_verify_attr_interrupt(&mut self, arity: usize) {
let p = self.machine_st.attr_var_init.verify_attrs_loc;
self.machine_st.verify_attr_interrupt(p, arity);
step_or_resource_error!(
self.machine_st,
self.machine_st.verify_attr_interrupt(p, arity)
);
}
fn next_clause_applicable(&mut self, mut offset: usize) -> bool {
@@ -505,12 +508,11 @@ impl Machine {
s,
)) => {
cell = self.deref_register(arg);
self.machine_st
.select_switch_on_term_index(cell, v, c, l, s)
self.machine_st.select_switch_on_term_index(cell, v, c, l, s)
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
let lit = self.machine_st.constant_to_literal(cell);
hm.get(&lit).cloned().unwrap_or(IndexingCodePtr::Fail)
// let lit = self.machine_st.constant_to_literal(cell);
hm.get(&cell).cloned().unwrap_or(IndexingCodePtr::Fail)
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(hm)) => {
self.machine_st.select_switch_on_structure_index(cell, hm)
@@ -536,6 +538,7 @@ impl Machine {
if cell.is_var() {
offset += 1;
/*
} else if lit.get_tag() == HeapCellValueTag::CStr {
read_heap_cell!(cell,
(HeapCellValueTag::CStr) => {
@@ -562,8 +565,10 @@ impl Machine {
return false;
}
);
*/
} else {
self.machine_st.write_literal_to_var(cell, lit);
unify!(self.machine_st, cell, lit);
// self.machine_st.write_literal_to_var(cell, lit);
if self.machine_st.fail {
self.machine_st.fail = false;
@@ -577,7 +582,7 @@ impl Machine {
let cell = self.deref_register(t);
read_heap_cell!(cell,
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {// | HeapCellValueTag::CStr) => {
offset += 1;
}
(HeapCellValueTag::Str, s) => {
@@ -618,25 +623,32 @@ impl Machine {
}
&Instruction::GetPartialString(
Level::Shallow,
string,
ref string,
RegType::Temp(t),
has_tail,
// has_tail,
) => {
use crate::machine::partial_string::HeapPStrIter;
let cell = self.deref_register(t);
read_heap_cell!(cell,
(HeapCellValueTag::CStr, cstr) => {
if !has_tail && string != cstr {
(HeapCellValueTag::PStrLoc) => {
self.machine_st.heap[0] = cell;
let iter = HeapPStrIter::new(&self.machine_st.heap, 0);
if iter.compare_pstr_to_string(&string).is_none() {
return false;
}
offset += 1;
}
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
(HeapCellValueTag::Lis) => {
offset += 1;
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity();
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity();
if name == atom!(".") && arity == 2 {
offset += 1;
@@ -759,7 +771,7 @@ impl Machine {
or_frame.prelude.boip = 0;
or_frame.prelude.biip = 0;
or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len();
or_frame.prelude.h = self.machine_st.heap.cell_len();
or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
@@ -770,7 +782,7 @@ impl Machine {
or_frame[i] = self.machine_st.registers[i + 1];
}
self.machine_st.hb = self.machine_st.heap.len();
self.machine_st.hb = self.machine_st.heap.cell_len();
}
self.machine_st.p += 1;
@@ -791,7 +803,7 @@ impl Machine {
or_frame.prelude.boip = self.machine_st.oip;
or_frame.prelude.biip = self.machine_st.iip + iip_offset; // 1
or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len();
or_frame.prelude.h = self.machine_st.heap.cell_len();
or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
@@ -802,7 +814,7 @@ impl Machine {
or_frame[i] = self.machine_st.registers[i + 1];
}
self.machine_st.hb = self.machine_st.heap.len();
self.machine_st.hb = self.machine_st.heap.cell_len();
// self.machine_st.oip = 0;
// self.machine_st.iip = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ use crate::codegen::CodeGenSettings;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::disjuncts::*;
use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::CodeIndex;
@@ -27,25 +28,42 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError
fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
let (focus, _cell) = subterm_index(term.heap, term.focus);
let name = match term.name(focus+3) {
Some(name) => name,
None => return Err(CompilationError::InconsistentEntry),
let name = match term_predicate_key(term.heap, focus+3) {
Some((name, 0)) => name,
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]),
));
}
};
let spec = match term.name(focus+2) {
Some(name) => name,
None => return Err(CompilationError::InconsistentEntry),
let spec = match term_predicate_key(term.heap, focus+2) {
Some((name, _)) => name,
None => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]),
));
}
};
let prec = read_heap_cell!(term.deref_loc(focus+1),
let spec = to_op_decl_spec(spec)?;
let prec = term.deref_loc(focus+1);
let prec = read_heap_cell!(prec,
(HeapCellValueTag::Fixnum, n) => {
match u16::try_from(n.get_num()) {
Ok(n) if n <= 1200 => n,
_ => return Err(CompilationError::InconsistentEntry),
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecDomain(n),
));
}
}
}
_ => {
return Err(CompilationError::InconsistentEntry);
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecType(prec),
));
}
);
@@ -71,10 +89,9 @@ fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
}
fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> {
let name_opt = term.name(term.focus);
let arity = term.arity(term.focus);
let key_opt = term_predicate_key(term.heap, term.focus);
if let (Some(atom!("/") | atom!("//")), 2) = (name_opt, arity) {
if let Some((atom!("/") | atom!("//"), 2)) = key_opt {
let arity_loc = term.nth_arg(term.focus, 2).unwrap();
let arity = match Number::try_from(term.deref_loc(arity_loc)) {
@@ -85,11 +102,11 @@ fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, C
.ok_or(CompilationError::InvalidModuleExport)?;
let name_loc = term.nth_arg(term.focus, 1).unwrap();
let name = term
.name(name_loc)
let name = term_predicate_key(term.heap, name_loc)
.map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleExport)?;
if name_opt == Some(atom!("/")) {
if matches!(key_opt, Some((atom!("/"), _))) {
Ok((name, arity))
} else {
Ok((name, arity + 2))
@@ -103,10 +120,9 @@ fn setup_module_export(term: &FocusedHeapRefMut) -> Result<ModuleExport, Compila
setup_predicate_indicator(term)
.map(ModuleExport::PredicateKey)
.or_else(|_| {
let name_opt = term.name(term.focus);
let arity = term.arity(term.focus);
let key_opt = term_predicate_key(term.heap, term.focus);
if let (Some(atom!("op")), 3) = (name_opt, arity) {
if let Some((atom!("op"), 3)) = key_opt {
Ok(ModuleExport::OpDecl(setup_op_decl(term)?))
} else {
Err(CompilationError::InvalidModuleDecl)
@@ -131,48 +147,46 @@ pub(super) fn setup_module_export_list(
let mut focus = term.focus;
loop {
read_heap_cell!(term.heap[focus],
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == focus {
break;
} else {
focus = h;
}
}
(HeapCellValueTag::Lis, l) => {
let term = FocusedHeapRefMut {
heap: term.heap,
focus: l,
};
exports.push(setup_module_export(&term)?);
read_heap_cell!(term.heap[focus],
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == focus {
break;
} else {
focus = h;
}
}
(HeapCellValueTag::Lis, l) => {
let term = FocusedHeapRefMut {
heap: term.heap,
focus: l,
};
focus = l + 1;
}
(HeapCellValueTag::Atom, (name, _arity)) => {
if name == atom!("[]") {
return Ok(exports);
} else {
break;
}
}
_ => {
break;
}
);
exports.push(setup_module_export(&term)?);
focus = l + 1;
}
(HeapCellValueTag::Atom, (name, _arity)) => {
if name == atom!("[]") {
return Ok(exports);
} else {
break;
}
}
_ => {
break;
}
);
}
Err(CompilationError::InvalidModuleDecl)
}
fn setup_module_decl(term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
let name = term
.name(term.focus + 1)
fn setup_module_decl(mut term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
let name = term_predicate_key(term.heap, term.focus + 1)
.map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleDecl)?;
let export_list = FocusedHeapRefMut {
heap: term.heap,
focus: term.focus + 2,
};
let exports = setup_module_export_list(export_list)?;
term.focus = term.focus + 2;
let exports = setup_module_export_list(term)?;
Ok(ModuleDecl { name, exports })
}
@@ -224,8 +238,8 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
heap: term.heap,
focus,
};
exports.insert(setup_module_export(&term)?);
exports.insert(setup_module_export(&term)?);
focus = focus + 1;
}
@@ -276,7 +290,7 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
*/
fn setup_meta_predicate<'a, LS: LoadState<'a>>(
term: FocusedHeapRefMut,
term: TermWriteResult,
loader: &mut Loader<'a, LS>,
) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
fn get_meta_specs(
@@ -319,24 +333,27 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
Ok(meta_specs)
}
read_heap_cell!(term.deref_loc(term.focus+1),
let heap = loader.machine_heap();
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus+1]));
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(term.heap[s]).get_name_and_arity();
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
match (name, arity) {
(atom!(":"), 2) => {
let module_name = term.heap[s+1];
let spec = term.heap[s+2];
let module_name = heap[s+1];
let spec = heap[s+2];
read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
read_heap_cell!(spec,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(term.heap[s])
let (name, arity) = cell_as_atom_cell!(heap[s])
.get_name_and_arity();
let term = FocusedHeapRefMut { heap: term.heap, focus: s };
let term = FocusedHeapRefMut { heap, focus: s };
return Ok((module_name, name, get_meta_specs(term, arity)?));
}
_ => {
@@ -351,9 +368,11 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
);
}
_ => {
let term = FocusedHeapRefMut { heap: term.heap, focus: s };
let term = FocusedHeapRefMut { heap, focus: s };
let specs = get_meta_specs(term, arity)?;
let module_name = loader.payload.compilation_target.module_name();
return Ok((module_name, name, get_meta_specs(term, arity)?));
return Ok((module_name, name, specs));
}
}
@@ -367,38 +386,41 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
term: FocusedHeapRefMut,
mut term: TermWriteResult,
) -> Result<Declaration, CompilationError> {
let mut focus = term.focus;
let machine_st = LS::machine_st(&mut loader.payload);
loop {
read_heap_cell!(term.heap[focus],
let decl = machine_st.heap[focus];
read_heap_cell!(decl,
(HeapCellValueTag::Atom, (name, arity)) => {
let term = FocusedHeapRefMut { heap: term.heap, focus };
let mut focused = FocusedHeapRefMut::from(&mut machine_st.heap, focus);
return match (name, arity) {
(atom!("dynamic"), 1) => {
let (name, arity) = setup_predicate_indicator(&term)?;
let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::Dynamic(name, arity))
}
(atom!("module"), 2) => {
Ok(Declaration::Module(setup_module_decl(term)?))
Ok(Declaration::Module(setup_module_decl(focused)?))
}
(atom!("op"), 3) => {
Ok(Declaration::Op(setup_op_decl(&term)?))
Ok(Declaration::Op(setup_op_decl(&focused)?))
}
(atom!("non_counted_backtracking"), 1) => {
let focus = term.nth_arg(term.focus, 1).unwrap();
let (name, arity) = setup_predicate_indicator(&FocusedHeapRefMut { heap: term.heap, focus })?;
focused.focus = focused.nth_arg(focused.focus, 1).unwrap();
let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::NonCountedBacktracking(name, arity))
}
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&term)?)),
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&focused)?)),
(atom!("use_module"), 2) => {
let (name, exports) = setup_qualified_import(term)?;
let (name, exports) = setup_qualified_import(focused)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
(atom!("meta_predicate"), 1) => {
term.focus = focus;
let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
}
@@ -415,13 +437,13 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
focus = h;
} else {
return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(heap_loc_as_cell!(h)),
DirectiveError::ExpectedDirective(decl),
));
}
}
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(term.heap[focus])
DirectiveError::ExpectedDirective(decl),
));
}
);
@@ -432,41 +454,44 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
module_name: Atom,
arity: usize,
term: &FocusedHeapRefMut,
term: &TermWriteResult,
meta_specs: Vec<MetaSpec>,
) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
use crate::machine::heap::Heap;
let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default());
for (subterm_loc, meta_spec) in (term.focus + 1..term.focus + arity + 1).zip(meta_specs) {
if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
if let Some(name) = term.name(subterm_loc) {
let predicate_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
if let Some((name, arity)) = predicate_key_opt {
if name == atom!("$call") {
continue;
}
let arity = term.arity(subterm_loc);
struct QualifiedNameInfo {
module_name: Atom,
name: Atom,
arity: usize,
qualified_term_loc: usize,
}
fn get_qualified_name(
term: &FocusedHeapRefMut,
heap: &Heap,
module_term_loc: usize,
qualified_term_loc: usize,
) -> Option<QualifiedNameInfo> {
let (module_term_loc, _) = subterm_index(term.heap, module_term_loc);
let (qualified_term_loc, _) = subterm_index(term.heap, qualified_term_loc);
let (module_term_loc, _) = subterm_index(heap, module_term_loc);
let (qualified_term_loc, _) = subterm_index(heap, qualified_term_loc);
read_heap_cell!(term.heap[module_term_loc],
read_heap_cell!(heap[module_term_loc],
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
if let Some(name) = term.name(qualified_term_loc) {
if let Some((name, arity)) = term_predicate_key(heap, qualified_term_loc) {
return Some(QualifiedNameInfo {
module_name,
name,
arity,
qualified_term_loc,
});
}
@@ -478,23 +503,20 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
None
}
let (subterm_loc, _) = subterm_index(term.heap, subterm_loc);
let subterm_arity = term.arity(subterm_loc);
let subterm_name_opt = term.name(subterm_loc);
let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
let (module_name, key, term_loc) =
if subterm_name_opt == Some(atom!(":")) && subterm_arity == 2 {
debug_assert_eq!(term.heap[subterm_loc].get_tag(), HeapCellValueTag::Atom);
match get_qualified_name(term, subterm_loc + 1, subterm_loc + 2) {
if subterm_key_opt == Some((atom!(":"), 2)) {
match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) {
Some(QualifiedNameInfo {
module_name,
name,
arity,
qualified_term_loc,
}) => (
module_name,
(name, term.arity(qualified_term_loc) + supp_args),
(name, arity + supp_args),
qualified_term_loc,
),
None => {
@@ -505,7 +527,7 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
(module_name, (name, arity + supp_args), subterm_loc)
};
if let Some(index_ptr) = fetch_index_ptr(term.heap, key.1, term_loc) {
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), key.1, term_loc) {
index_ptrs.insert(term_loc, index_ptr);
continue;
}
@@ -525,13 +547,13 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
terms: FocusedHeapRefMut,
terms: &TermWriteResult,
term: HeapCellValue,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// root-level clauses.
blunt_index_ptr(terms.heap, key, terms.focus);
blunt_index_ptr(loader.machine_heap(), key, terms.focus);
let mut ct = loader.get_clause_type(key.0, key.1);
@@ -539,11 +561,10 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name();
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs);
build_meta_predicate_clause(loader, module_name, arity, terms, meta_specs);
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
arity,
term,
code_indices,
call_policy,
@@ -555,7 +576,6 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
QueryClause {
ct,
arity: key.1,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
@@ -567,13 +587,13 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
module_name: Atom,
terms: FocusedHeapRefMut,
terms: &TermWriteResult,
term: HeapCellValue,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// root-level clauses.
blunt_index_ptr(terms.heap, key, terms.focus);
blunt_index_ptr(loader.machine_heap(), key, terms.focus);
let mut ct = loader.get_qualified_clause_type(module_name, key.0, key.1);
@@ -584,7 +604,6 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
arity,
term,
code_indices,
call_policy,
@@ -596,7 +615,6 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
QueryClause {
ct,
arity: key.1,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
@@ -613,15 +631,18 @@ impl Preprocessor {
Preprocessor { settings }
}
pub fn setup_fact(
pub fn setup_fact<'a, LS: LoadState<'a>>(
&mut self,
mut term: FocusedHeap,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
) -> Result<(Fact, VarData), CompilationError> {
if term.name(term.focus).is_some() {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let var_data = classifier.classify_fact(&mut term)?;
let heap = loader.machine_heap();
Ok((Fact { term }, var_data))
if term_predicate_key(heap, term.focus).is_some() {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let var_data = classifier.classify_fact(loader, &term)?;
Ok((Fact { term_loc: term.focus }, var_data))
} else {
Err(CompilationError::InadmissibleFact)
}
@@ -630,14 +651,16 @@ impl Preprocessor {
fn setup_rule<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
mut term: FocusedHeap,
term: TermWriteResult,
) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let (clauses, var_data) = classifier.classify_rule(loader, &mut term)?;
let head_loc = term.nth_arg(term.focus, 1).unwrap();
let (clauses, var_data) = classifier.classify_rule(loader, &term)?;
if term.name(head_loc).is_some() {
Ok((Rule { term, clauses }, var_data))
let heap = loader.machine_heap();
let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
if term_predicate_key(heap, head_loc).is_some() {
Ok((Rule { term_loc: term.focus, clauses }, var_data))
} else {
Err(CompilationError::InvalidRuleHead)
}
@@ -646,19 +669,18 @@ impl Preprocessor {
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: FocusedHeap,
) -> Result<TopLevel, CompilationError> {
let name = term.name(term.focus);
let arity = term.arity(term.focus);
term: TermWriteResult,
) -> Result<PredicateClause, CompilationError> {
let heap = &LS::machine_st(&mut loader.payload).heap;
match (name, arity) {
(Some(atom!(":-")), 2) => {
match term_predicate_key(heap, term.focus) {
Some((atom!(":-"), 2)) => {
let (rule, var_data) = self.setup_rule(loader, term)?;
Ok(TopLevel::Rule(rule, var_data))
Ok(PredicateClause::Rule(rule, var_data))
}
_ => {
let (fact, var_data) = self.setup_fact(term)?;
Ok(TopLevel::Fact(fact, var_data))
let (fact, var_data) = self.setup_fact(loader, term)?;
Ok(PredicateClause::Fact(fact, var_data))
}
}
}

View File

@@ -1,12 +1,12 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::functor_macro::*;
use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::read::*;
#[cfg(feature = "http")]
use crate::http::HttpResponse;
use crate::machine::heap::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
@@ -476,7 +476,7 @@ impl StreamOptions {
#[inline]
pub fn get_alias(self) -> Option<Atom> {
if self.has_alias() {
Some(Atom::from(self.alias() << 3))
Some(Atom::from(self.alias()))
} else {
None
}
@@ -487,7 +487,7 @@ impl StreamOptions {
self.set_has_alias(alias.is_some());
if let Some(alias) = alias {
self.set_alias(alias.flat_index());
self.set_alias(alias.index);
}
}
}
@@ -1953,7 +1953,7 @@ impl MachineState {
let err = self.permission_error(
Permission::Open,
atom!("source_sink"),
functor!(atom!("alias"), [atom(alias)]),
functor!(atom!("alias"), [atom_as_cell(alias)]),
);
self.error_form(err, stub)
@@ -1961,7 +1961,7 @@ impl MachineState {
pub(crate) fn reposition_error(&mut self, stub_name: Atom, stub_arity: usize) -> MachineStub {
let stub = functor_stub(stub_name, stub_arity);
let rep_stub = functor!(atom!("reposition"), [atom(atom!("true"))]);
let rep_stub = functor!(atom!("reposition"), [atom_as_cell((atom!("true")))]);
let err = self.permission_error(Permission::Open, atom!("source_sink"), rep_stub);
self.error_form(err, stub)

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@ use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::*;
use crate::parser::ast::*;
use crate::parser::lexer::*;
use crate::parser::parser::*;
use crate::read::devour_whitespace;
@@ -20,11 +21,11 @@ pub struct LoadStatePayload<TS> {
pub(super) module_op_exports: ModuleOpExports,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>,
pub(super) predicates: PredicateQueue,
pub(super) clause_clauses: Vec<FocusedHeap>,
pub(super) clause_clauses: Vec<TermWriteResult>,
}
pub trait TermStream: Sized {
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError>;
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError>;
fn eof(&mut self) -> Result<bool, CompilationError>;
fn listing_src(&self) -> &ListingSource;
}
@@ -32,7 +33,7 @@ pub trait TermStream: Sized {
#[derive(Debug)]
pub struct BootstrappingTermStream<'a> {
listing_src: ListingSource,
pub(super) parser: Parser<'a, Stream>,
pub(super) lexer_parser: LexerParser<'a, Stream>,
}
impl<'a> BootstrappingTermStream<'a> {
@@ -42,26 +43,23 @@ impl<'a> BootstrappingTermStream<'a> {
machine_st: &'a mut MachineState,
listing_src: ListingSource,
) -> Self {
let parser = Parser::new(stream, machine_st);
Self {
parser,
listing_src,
}
let lexer_parser = LexerParser::new(stream, machine_st);
Self { lexer_parser, listing_src }
}
}
impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline]
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
self.parser.reset();
self.parser
.read_term(op_dir, Tokens::Default)
.map_err(CompilationError::from)
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
let result = self.lexer_parser.read_term(op_dir, Tokens::Default)
.map_err(CompilationError::from);
result
}
#[inline]
fn eof(&mut self) -> Result<bool, CompilationError> {
devour_whitespace(&mut self.parser) // eliminate dangling comments before checking for EOF.
devour_whitespace(&mut self.lexer_parser) // eliminate dangling comments before checking for EOF.
.map_err(CompilationError::from)
}
@@ -72,7 +70,7 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
}
pub struct LiveTermStream {
pub(super) term_queue: VecDeque<FocusedHeap>,
pub(super) term_queue: VecDeque<TermWriteResult>,
pub(super) listing_src: ListingSource,
}
@@ -108,7 +106,7 @@ impl<TS> LoadStatePayload<TS> {
impl TermStream for LiveTermStream {
#[inline]
fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Ok(self.term_queue.pop_front().unwrap())
}
@@ -126,7 +124,7 @@ impl TermStream for LiveTermStream {
pub struct InlineTermStream {}
impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default())))
}

View File

@@ -2,11 +2,9 @@ use crate::arena::*;
use crate::forms::*;
use crate::heap_iter::{stackful_preorder_iter, NonListElider};
use crate::machine::machine_state::*;
use crate::machine::partial_string::*;
use crate::machine::*;
use crate::types::*;
use std::cmp::Ordering;
use std::ops::{Deref, DerefMut};
use derive_more::*;
@@ -14,6 +12,18 @@ use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use num_order::NumOrd;
impl MachineState {
pub(crate) fn partial_string_to_pdl(&mut self, pstr_loc: usize, l: usize) {
let (c, succ_cell) = self.heap.last_str_char_and_tail(pstr_loc);
self.pdl.push(heap_loc_as_cell!(l + 1));
self.pdl.push(succ_cell);
self.pdl.push(heap_loc_as_cell!(l));
self.pdl.push(char_as_cell!(c));
}
}
pub(crate) trait Unifier: DerefMut<Target = MachineState> {
fn unify_structure(&mut self, s1: usize, value: HeapCellValue) {
// s1 is the value of a STR cell.
@@ -82,8 +92,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = true;
}
}
(HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr | HeapCellValueTag::PStr) => {
Self::unify_partial_string(self, list_loc_as_cell!(l1), value)
(HeapCellValueTag::PStrLoc, l) => {
Self::unify_partial_string(self, l, list_loc_as_cell!(l1))
}
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), list_loc_as_cell!(l1));
@@ -100,261 +110,40 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
);
}
fn unify_complete_string(&mut self, atom: Atom, value: HeapCellValue) {
fn unify_partial_string(&mut self, pstr_loc: usize, value: HeapCellValue) {
if let Some(r) = value.as_var() {
if atom == atom!("") {
Self::bind(self, r, atom_as_cell!(atom!("[]")));
} else {
Self::bind(self, r, atom_as_cstr_cell!(atom));
}
return;
}
read_heap_cell!(value,
(HeapCellValueTag::Atom, (cstr_atom, arity)) if atom == atom!("") => {
debug_assert_eq!(arity, 0);
self.fail = cstr_atom != atom!("[]");
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
if arity == 0 {
self.fail = atom == atom!("") && name != atom!("[]");
} else {
// this is intentionally the same policy for
// value.tag() == Lis and PStrLoc. they're not
// grouped together to allow for arity == 0.
Self::unify_partial_string(self, atom_as_cstr_cell!(atom), value);
if !self.pdl.is_empty() {
Self::unify_internal(self);
}
}
}
(HeapCellValueTag::CStr, cstr_atom) => {
self.fail = atom != cstr_atom;
}
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
Self::unify_partial_string(self, atom_as_cstr_cell!(atom), value);
if !self.pdl.is_empty() {
Self::unify_internal(self);
}
}
_ => {
self.fail = true;
}
);
}
// the return value of unify_partial_string is interpreted as
// follows:
//
// Some(None) -- the strings are equal, nothing to unify
// Some(Some(f2,f1)) -- prefixes equal, try to unify focus values f2, f1
// None -- prefixes not equal, unification fails
//
// d1's tag is assumed to be one of LIS, STR or PSTRLOC.
fn unify_partial_string(&mut self, value_1: HeapCellValue, value_2: HeapCellValue) {
if let Some(r) = value_2.as_var() {
Self::bind(self, r, value_1);
Self::bind(self, r, pstr_loc_as_cell!(pstr_loc));
return;
}
let machine_st = self.deref_mut();
let s1 = machine_st.heap.len();
read_heap_cell!(value,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity();
machine_st.heap.push(value_1);
machine_st.heap.push(value_2);
let mut pstr_iter1 = HeapPStrIter::new(&machine_st.heap, s1);
let mut pstr_iter2 = HeapPStrIter::new(&machine_st.heap, s1 + 1);
fn unify_sequence(
machine_st: &mut MachineState,
iter: PStrIteratee,
source_cell: HeapCellValue,
) -> bool {
match iter {
PStrIteratee::Char(focus, _) => {
machine_st.pdl.push(machine_st.heap[focus]);
machine_st.pdl.push(source_cell);
}
PStrIteratee::PStrSegment(focus, _, n) => {
read_heap_cell!(machine_st.heap[focus],
(HeapCellValueTag::CStr | HeapCellValueTag::PStr, pstr_atom) => {
if focus < machine_st.heap.len() - 2 {
machine_st.heap.pop();
machine_st.heap.pop();
}
if n == 0 {
let target_cell = match machine_st.heap[focus].get_tag() {
HeapCellValueTag::CStr => {
atom_as_cstr_cell!(pstr_atom)
}
HeapCellValueTag::PStr => {
pstr_loc_as_cell!(focus)
}
_ => {
unreachable!()
}
};
machine_st.pdl.push(target_cell);
machine_st.pdl.push(source_cell);
} else {
let h_len = machine_st.heap.len();
machine_st.heap.push(pstr_offset_as_cell!(focus));
machine_st.heap.push(fixnum_as_cell!(
Fixnum::build_with(n as i64)
));
machine_st.pdl.push(pstr_loc_as_cell!(h_len));
machine_st.pdl.push(source_cell);
}
return true;
}
(HeapCellValueTag::PStrOffset, pstr_loc) => {
let n0 = cell_as_fixnum!(machine_st.heap[focus+1])
.get_num() as usize;
if pstr_loc < machine_st.heap.len() - 2 {
machine_st.heap.pop();
machine_st.heap.pop();
}
if n == n0 {
machine_st.pdl.push(pstr_loc_as_cell!(focus));
machine_st.pdl.push(source_cell);
} else {
let h_len = machine_st.heap.len();
machine_st.heap.push(pstr_offset_as_cell!(pstr_loc));
machine_st.heap.push(fixnum_as_cell!(
Fixnum::build_with(n as i64)
));
machine_st.pdl.push(pstr_loc_as_cell!(h_len));
machine_st.pdl.push(source_cell);
}
return true;
}
_ => {
}
);
if focus < machine_st.heap.len() - 2 {
machine_st.heap.pop();
machine_st.heap.pop();
}
machine_st.pdl.push(machine_st.heap[focus]);
machine_st.pdl.push(source_cell);
return true;
}
}
false
}
match compare_pstr_prefixes(&mut pstr_iter1, &mut pstr_iter2) {
PStrCmpResult::Ordered(Ordering::Equal) => {}
PStrCmpResult::Ordered(Ordering::Less) => {
if pstr_iter2.focus.as_var().is_none() {
machine_st.fail = true;
if name == atom!(".") && arity == 2 {
machine_st.partial_string_to_pdl(pstr_loc, s+1);
} else {
machine_st.pdl.push(empty_list_as_cell!());
machine_st.pdl.push(pstr_iter2.focus);
}
}
PStrCmpResult::Ordered(Ordering::Greater) => {
if pstr_iter1.focus.as_var().is_none() {
machine_st.fail = true;
} else {
machine_st.pdl.push(empty_list_as_cell!());
machine_st.pdl.push(pstr_iter1.focus);
}
}
continuable @ PStrCmpResult::FirstIterContinuable(iteratee)
| continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
if continuable.is_second_iter() {
std::mem::swap(&mut pstr_iter1, &mut pstr_iter2);
}
(HeapCellValueTag::Lis, l) => {
machine_st.partial_string_to_pdl(pstr_loc, l);
}
(HeapCellValueTag::PStrLoc, other_pstr_loc) => {
let cmp_result = machine_st.heap.compare_pstr_segments(pstr_loc, other_pstr_loc);
let mut chars_iter = PStrCharsIter {
iter: pstr_iter1,
item: Some(iteratee),
};
let mut focus = pstr_iter2.focus;
'outer: {
while let Some(c) = chars_iter.peek() {
read_heap_cell!(focus,
(HeapCellValueTag::Lis, l) => {
let val = pstr_iter2.heap[l];
machine_st.pdl.push(val);
machine_st.pdl.push(char_as_cell!(c));
focus = pstr_iter2.heap[l+1];
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(pstr_iter2.heap[s])
.get_name_and_arity();
if name == atom!(".") && arity == 2 {
machine_st.pdl.push(pstr_iter2.heap[s+1]);
machine_st.pdl.push(char_as_cell!(c));
focus = pstr_iter2.heap[s+2];
} else {
machine_st.fail = true;
break 'outer;
}
}
(HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
unify_sequence(machine_st, chars_iter.item.unwrap(), focus);
return;
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if unify_sequence(machine_st, chars_iter.item.unwrap(), heap_loc_as_cell!(h)) {
return;
}
break 'outer;
}
_ => {
machine_st.fail = true;
break 'outer;
}
);
chars_iter.next();
}
chars_iter.iter.next();
machine_st.pdl.push(focus);
machine_st.pdl.push(chars_iter.iter.focus);
if cmp_result.continue_pstr_compare(&mut machine_st.pdl).is_some() {
debug_assert!(matches!(cmp_result, PStrSegmentCmpResult::Mismatch { .. }));
machine_st.fail = true;
}
}
PStrCmpResult::Unordered => {
machine_st.pdl.push(pstr_iter1.focus);
machine_st.pdl.push(pstr_iter2.focus);
_ => {
machine_st.fail = true;
}
}
machine_st.heap.pop();
machine_st.heap.pop();
);
}
fn unify_atom(&mut self, atom: Atom, value: HeapCellValue) {
@@ -368,6 +157,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = !(arity == 0 && name == atom);
}
/*
(HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => {
self.fail = cstr_atom != atom!("");
}
@@ -378,6 +168,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = true;
}
}
*/
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), atom_as_cell!(atom));
}
@@ -412,11 +203,13 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = true;
}
}
/*
(HeapCellValueTag::Char, c2) => {
if c != c2 {
self.fail = true;
}
}
*/
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), char_as_cell!(c));
}
@@ -610,7 +403,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
tabu_list.insert((d1, d2));
}
}
(HeapCellValueTag::PStrLoc) => {
(HeapCellValueTag::PStrLoc, l) => {
read_heap_cell!(d2,
(HeapCellValueTag::PStrLoc |
HeapCellValueTag::Lis |
@@ -619,8 +412,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
continue;
}
}
(HeapCellValueTag::CStr |
HeapCellValueTag::AttrVar |
(HeapCellValueTag::AttrVar |
HeapCellValueTag::Var |
HeapCellValueTag::StackVar) => {
}
@@ -630,13 +422,14 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
}
);
Self::unify_partial_string(self, d1, d2);
Self::unify_partial_string(self, l, d2);
if !self.fail && !d2.is_constant() {
let d2 = self.store(d2);
tabu_list.insert((d1, d2));
}
}
/*
(HeapCellValueTag::CStr) => {
read_heap_cell!(d2,
(HeapCellValueTag::AttrVar, h) => {
@@ -667,15 +460,18 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
Self::unify_partial_string(self, d2, d1);
}
*/
(HeapCellValueTag::F64, f1) => {
Self::unify_f64(self, f1, d2);
}
(HeapCellValueTag::Fixnum, n1) => {
Self::unify_fixnum(self, n1, d2);
}
/*
(HeapCellValueTag::Char, c1) => {
Self::unify_char(self, c1, d2);
}
*/
(HeapCellValueTag::Cons, ptr_1) => {
Self::unify_constant(self, ptr_1, d2);
}
@@ -709,12 +505,12 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
let value = machine_st.store(MachineState::deref(machine_st, value));
if value.is_ref() && !value.is_stack_var() {
let root_loc = value.get_value() as usize;
machine_st.heap[0] = value;
for cell in stackful_preorder_iter::<NonListElider>(
&mut machine_st.heap,
&mut machine_st.stack,
root_loc, // value,
0,
) {
let cell = unmark_cell_bits!(cell);