introduce bespoke Heap type for in-heap partial strings
This commit is contained in:
@@ -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)))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ verify_attrs([], _, _, []).
|
||||
|
||||
|
||||
call_goals([ListOfGoalLists | ListsCubed]) :-
|
||||
'$debug_hook',
|
||||
call_goals_0(ListOfGoalLists),
|
||||
call_goals(ListsCubed).
|
||||
call_goals([]).
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
1268
src/machine/gc.rs
1268
src/machine/gc.rs
File diff suppressed because it is too large
Load Diff
1444
src/machine/heap.rs
1444
src/machine/heap.rs
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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..) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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())))
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user