remove pstr_vec

This commit is contained in:
Mark Thom
2024-12-06 21:47:36 -08:00
committed by Mark Thom
parent 3c85ef2724
commit ae4d12a123
40 changed files with 2262 additions and 1891 deletions

View File

@@ -479,7 +479,6 @@ impl Div<Number> for Number {
}
}
impl PartialEq for Number {
fn eq(&self, rhs: &Self) -> bool {
match (self, rhs) {
@@ -563,7 +562,6 @@ impl PartialOrd for Number {
}
}
impl Ord for Number {
fn cmp(&self, rhs: &Number) -> Ordering {
match (self, rhs) {

View File

@@ -66,7 +66,7 @@ impl AtomCell {
debug_assert!(string.len() <= INLINED_ATOM_MAX_LEN);
let mut string_buf: [u8; 8] = [0u8; 8];
string_buf[.. string.len()].copy_from_slice(string.as_bytes());
string_buf[..string.len()].copy_from_slice(string.as_bytes());
let encoding = u64::from_le_bytes(string_buf);
AtomCell::new()
@@ -80,7 +80,7 @@ impl AtomCell {
#[inline]
pub fn new_char_inlined(c: char) -> Self {
let mut char_buf = [0u8;8];
let mut char_buf = [0u8; 8];
c.encode_utf8(&mut char_buf);
let encoding = u64::from_le_bytes(char_buf);
@@ -109,7 +109,9 @@ impl AtomCell {
#[inline]
pub fn get_name(self) -> Atom {
Atom { index: (self.name() << 1) | self.is_inlined() as u64 }
Atom {
index: (self.name() << 1) | self.is_inlined() as u64,
}
}
#[inline]
@@ -216,21 +218,22 @@ impl Hash for Atom {
pub enum AtomString<'a> {
Static(&'a str),
Inlined([u8;8]),
Inlined([u8; 8]),
Dynamic(AtomTableRef<str>),
}
fn inlined_to_str<'a>(bytes: &'a [u8;8]) -> &'a str {
fn inlined_to_str<'a>(bytes: &'a [u8; 8]) -> &'a str {
// allow the '\0\' atom to be represented as the 0-valued inlined atom
let slice_len = if bytes[0] == 0 {
1
} else {
bytes.iter().position(|&b| b == 0u8).unwrap_or(INLINED_ATOM_MAX_LEN)
bytes
.iter()
.position(|&b| b == 0u8)
.unwrap_or(INLINED_ATOM_MAX_LEN)
};
unsafe {
str::from_utf8_unchecked(&bytes[..slice_len])
}
unsafe { str::from_utf8_unchecked(&bytes[..slice_len]) }
}
impl std::fmt::Debug for AtomString<'_> {

View File

@@ -295,8 +295,10 @@ impl DebrayAllocator {
self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
temp_v!(arg)
} else {
if let VarAlloc::Perm { allocation: PermVarAllocation::Pending, .. } =
&self.var_data.records[var_num].allocation
if let VarAlloc::Perm {
allocation: PermVarAllocation::Pending,
..
} = &self.var_data.records[var_num].allocation
{
self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
} else {
@@ -337,22 +339,16 @@ impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator {
fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
heap: &Heap,
arity: usize,
heap_loc: usize,
) -> Option<Instruction> {
match fetch_index_ptr(heap, arity, heap_loc) {
Some(index_ptr) => {
if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
let subterm = HeapCellValue::from(*index_ptr);
return Some(Target::constant_subterm(subterm));
} else if !heap[heap_loc.saturating_sub(1)].get_mark_bit() {
if let Some(index_ptr) = fetch_index_ptr(heap, heap_loc) {
let subterm = HeapCellValue::from(index_ptr);
return Some(Target::constant_subterm(subterm));
}
None => {
// if Level::Shallow == lvl {
if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
let subterm = HeapCellValue::from(*index_ptr);
return Some(Target::constant_subterm(subterm));
}
// }
}
}
None
@@ -495,23 +491,28 @@ impl CodeGenerator {
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
if arity == 0 {
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, arity, heap_loc) {
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, heap_loc) {
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_structure(lvl, name, 0, r));
target.push_back(instr);
target.push_back(Target::to_structure(lvl, name, 0, r));
} else if lvl == Level::Shallow {
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_constant(lvl, atom_as_cell!(name), r));
}
} else {
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_structure(lvl, name, arity, r));
<CodeGenerator as AddToFreeList<'a, Target>>::add_term_to_free_list(
self,
r,
);
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, heap_loc) {
target.push_back(instr);
}
target.push_back(Target::to_structure(lvl, name, arity, r));
let free_list_regs: Vec<_> = (heap_loc + 1 ..= heap_loc + arity)
.map(|subterm_loc| {
let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc);
@@ -522,10 +523,6 @@ impl CodeGenerator {
})
.collect();
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, arity, heap_loc) {
target.push_back(instr);
}
for r_opt in free_list_regs {
if let Some(r) = r_opt {
<CodeGenerator as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
@@ -583,11 +580,11 @@ impl CodeGenerator {
let heap_loc = iter.focus().value() as usize;
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
let (pstr_str, tail_loc) = iter.scan_slice_to_str(pstr_loc);
let HeapStringScan { string, tail_idx } = iter.scan_slice_to_str(pstr_loc);
target.push_back(Target::to_pstr(lvl, Rc::new(pstr_str.to_owned()), r));
target.push_back(Target::to_pstr(lvl, Rc::new(string.to_owned()), r));
let (tail_loc, tail) = subterm_index(iter.deref(), tail_loc);
let (tail_loc, tail) = subterm_index(iter.deref(), tail_idx);
self.subterm_to_instr::<Target>(
tail, tail_loc, context, index_ptrs, &mut target,
);
@@ -676,12 +673,11 @@ impl CodeGenerator {
&InlinedClauseType::CompareNumber(mut cmp) => {
self.marker.reset_arg(2);
let (mut lcode, at_1) =
if let Some(r) = variable_marker(&mut self.marker) {
(CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
} else {
self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
};
let (mut lcode, at_1) = if let Some(r) = variable_marker(&mut self.marker) {
(CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
} else {
self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
};
let (mut rcode, at_2) =
self.compile_arith_expr(terms, first_arg_loc + 1, 2, context, 2)?;
@@ -720,41 +716,41 @@ impl CodeGenerator {
if let Some(r) = variable_marker(&mut self.marker) {
instr!("atomic", r)
} else {
read_heap_cell!(first_arg,
(HeapCellValueTag::Fixnum |
HeapCellValueTag::F64) => {
instr!("$succeed")
}
(HeapCellValueTag::Cons, cons_ptr) => {
match cons_ptr.get_tag() {
ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
instr!("$succeed")
}
_ => {
instr!("$fail")
}
}
}
(HeapCellValueTag::Atom, (_name, arity)) => {
if arity == 0 {
instr!("$succeed")
} else {
instr!("$fail")
}
}
(HeapCellValueTag::Lis
| HeapCellValueTag::Str
| HeapCellValueTag::PStrLoc) => {
instr!("$fail")
}
_ => {
if first_arg.is_constant() {
instr!("$succeed")
} else {
instr!("$fail")
}
}
)
read_heap_cell!(first_arg,
(HeapCellValueTag::Fixnum |
HeapCellValueTag::F64) => {
instr!("$succeed")
}
(HeapCellValueTag::Cons, cons_ptr) => {
match cons_ptr.get_tag() {
ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
instr!("$succeed")
}
_ => {
instr!("$fail")
}
}
}
(HeapCellValueTag::Atom, (_name, arity)) => {
if arity == 0 {
instr!("$succeed")
} else {
instr!("$fail")
}
}
(HeapCellValueTag::Lis
| HeapCellValueTag::Str
| HeapCellValueTag::PStrLoc) => {
instr!("$fail")
}
_ => {
if first_arg.is_constant() {
instr!("$succeed")
} else {
instr!("$fail")
}
}
)
}
}
InlinedClauseType::IsCompound(..) => {
@@ -860,7 +856,7 @@ impl CodeGenerator {
}
}
}
},
}
InlinedClauseType::IsVar(..) => {
self.marker.reset_arg(1);
@@ -871,7 +867,7 @@ impl CodeGenerator {
} else {
instr!("$fail")
}
},
}
};
// inlined predicates are never counted, so this overrides nothing.
@@ -901,8 +897,7 @@ impl CodeGenerator {
) -> Result<(), CompilationError> {
macro_rules! compile_expr {
($self:expr, $terms:expr, $context:expr, $code:expr) => {{
let (acode, at) =
$self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
let (acode, at) = $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
$code.extend(acode.into_iter());
at
}};
@@ -1067,13 +1062,11 @@ impl CodeGenerator {
code.push_back(instr!("deallocate"));
}
code.push_back(
if self.marker.in_tail_position {
instr!("$succeed").into_execute()
} else {
instr!("$succeed")
},
);
code.push_back(if self.marker.in_tail_position {
instr!("$succeed").into_execute()
} else {
instr!("$succeed")
});
}
QueryTerm::Clause(clause) => {
self.compile_query_line(
@@ -1145,7 +1138,10 @@ impl CodeGenerator {
self.marker.var_data = var_data;
let term = FocusedHeapRefMut { heap, focus: *term_loc };
let term = FocusedHeapRefMut {
heap,
focus: *term_loc,
};
let mut code = VecDeque::new();
let head_loc = term.nth_arg(term.focus, 1).unwrap();
@@ -1216,11 +1212,7 @@ impl CodeGenerator {
let mut stack = Stack::uninitialized();
let iter = query_iterator::<true>(&mut term.heap, &mut stack, clause.term_loc());
let query = self.compile_target::<QueryInstruction, _>(
iter,
&clause.code_indices,
context,
);
let query = self.compile_target::<QueryInstruction, _>(iter, &clause.code_indices, context);
code.extend(query);
self.add_call(code, clause.ct.to_instr(), clause.call_policy);
@@ -1342,20 +1334,14 @@ impl CodeGenerator {
skip_stub_try_me_else = !self.settings.is_dynamic();
}
let arg = clause.args(heap)
.map(|r| heap[r.start() + optimal_index]);
let arg = clause.args(heap).map(|r| heap[r.start() + optimal_index]);
if let Some(arg) = arg {
let index = code.len();
if clauses_len > 1 || self.settings.is_extensible {
let arg = heap_bound_store(heap, heap_bound_deref(heap, arg));
code_offsets.index_term(
heap,
arg,
index,
&mut clause_index_info,
);
code_offsets.index_term(heap, arg, index, &mut clause_index_info);
}
}

View File

@@ -172,7 +172,9 @@ impl DebrayAllocator {
for var_num in subsumed_hits {
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm { ref mut allocation, .. } => {
VarAlloc::Perm {
ref mut allocation, ..
} => {
if let PermVarAllocation::Done {
shallow_safety,
deep_safety,
@@ -233,7 +235,7 @@ impl DebrayAllocator {
let num_occurrences = self.var_data.records[var_num].num_occurrences;
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm { allocation, ..} => {
VarAlloc::Perm { allocation, .. } => {
let shallow_safety = VarSafetyStatus::needed_if(
shallow_safety.contains(var_num),
branch_designator,
@@ -514,10 +516,12 @@ impl DebrayAllocator {
self.perm_free_list.pop_front();
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm { reg: p, allocation: PermVarAllocation::Pending }
if *p > 0 => {
return Some(std::mem::replace(p, 0));
}
VarAlloc::Perm {
reg: p,
allocation: PermVarAllocation::Pending,
} if *p > 0 => {
return Some(std::mem::replace(p, 0));
}
_ => {}
}
} else {
@@ -543,11 +547,12 @@ impl DebrayAllocator {
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm {
allocation: PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
allocation:
PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
..
} => {
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -568,11 +573,12 @@ impl DebrayAllocator {
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm {
allocation: PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
allocation:
PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
..
} => {
// GetVariable in head chunk is considered safe.
@@ -612,10 +618,11 @@ impl DebrayAllocator {
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm {
allocation: PermVarAllocation::Done {
ref mut shallow_safety,
..
},
allocation:
PermVarAllocation::Done {
ref mut shallow_safety,
..
},
..
} => {
if !self.in_tail_position
@@ -648,10 +655,11 @@ impl DebrayAllocator {
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm {
allocation: PermVarAllocation::Done {
ref mut deep_safety,
..
},
allocation:
PermVarAllocation::Done {
ref mut deep_safety,
..
},
..
} => {
if self
@@ -921,10 +929,7 @@ impl Allocator for DebrayAllocator {
}
fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) {
let head_cell = heap_bound_store(
heap,
heap_bound_deref(heap, heap_loc_as_cell!(head_loc)),
);
let head_cell = heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(head_loc)));
read_heap_cell!(head_cell,
(HeapCellValueTag::Str, s) => {
@@ -933,7 +938,9 @@ impl Allocator for DebrayAllocator {
self.reset_arg(arity);
self.arity = arity;
for (idx, arg) in heap.splice(s+1 ..= s+arity).enumerate() {
for (c_idx, heap_idx) in (s+1 ..= s+arity).enumerate() {
let arg = heap[heap_idx];
if arg.is_var() {
let var = heap_bound_store(
heap,
@@ -953,11 +960,11 @@ impl Allocator for DebrayAllocator {
let r = self.get_var_binding(var_num);
if !r.is_perm() && r.reg_num() == 0 {
self.in_use.insert(idx + 1);
self.shallow_temp_mappings.insert(idx + 1, var_num);
self.in_use.insert(c_idx + 1);
self.shallow_temp_mappings.insert(c_idx + 1, var_num);
self.var_data.records[var_num]
.allocation
.set_register(idx + 1);
.set_register(c_idx + 1);
}
}
VarPtr::Anon => {}

View File

@@ -1,7 +1,7 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::instructions::*;
use crate::functor_macro::*;
use crate::instructions::*;
use crate::machine::disjuncts::VarData;
use crate::machine::heap::*;
// use crate::machine::loader::PredicateQueue;
@@ -80,8 +80,8 @@ impl GenContext {
#[inline]
pub fn chunk_type(&self) -> ChunkType {
match self {
GenContext::Head => ChunkType::Head,
GenContext::Mid(_) => ChunkType::Mid,
GenContext::Head => ChunkType::Head,
GenContext::Mid(_) => ChunkType::Mid,
GenContext::Last(_) => ChunkType::Last,
}
}
@@ -118,7 +118,10 @@ impl ChunkType {
#[derive(Debug)]
pub enum ChunkedTerms {
Branch(Vec<VecDeque<ChunkedTerms>>),
Chunk { chunk_num: usize, terms: VecDeque<QueryTerm> },
Chunk {
chunk_num: usize,
terms: VecDeque<QueryTerm>,
},
}
#[derive(Debug)]
@@ -190,7 +193,8 @@ impl ChunkedTermVec {
}
pub fn current_gen_context(&self) -> GenContext {
self.current_chunk_type.to_gen_context(self.current_chunk_num)
self.current_chunk_type
.to_gen_context(self.current_chunk_num)
}
pub fn push_chunk_term(&mut self, term: QueryTerm) {
@@ -290,9 +294,7 @@ pub fn clause_predicate_key(heap: &impl SizedHeap, term_loc: usize) -> Option<Pr
let key_opt = term_predicate_key(heap, term_loc);
if Some((atom!(":-"), 2)) == key_opt {
term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| {
term_predicate_key(heap, arg_loc)
})
term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| term_predicate_key(heap, arg_loc))
} else {
key_opt
}

View File

@@ -1,3 +1,6 @@
//! A macro to construct functor terms ready to be written to the WAM
//! heap.
use crate::atom_table::*;
use crate::instructions::IndexingCodePtr;
use crate::machine::heap::Heap;
@@ -5,7 +8,7 @@ use crate::parser::ast::Fixnum;
use crate::types::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FunctorElement {
pub(crate) enum FunctorElement {
AbsoluteCell(HeapCellValue),
Cell(HeapCellValue),
InnerFunctor(u64, Vec<FunctorElement>),
@@ -190,19 +193,19 @@ pub(crate) fn variadic_functor(
let num_items = key_value_pairs.len();
for (idx, _) in key_value_pairs.iter().enumerate() {
arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(2 + num_items * 2 + idx)));
arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(
2 + num_items * 2 + idx
)));
arg_vec.push(FunctorElement::Cell(list_loc_as_cell!(5 + idx)));
}
arg_vec.pop();
arg_vec.push(FunctorElement::Cell(empty_list_as_cell!()));
arg_vec.extend(key_value_pairs
.into_iter()
.map(|kv_func| {
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
}));
arg_vec.extend(key_value_pairs.into_iter().map(|kv_func| {
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
}));
arg_vec
}
@@ -211,13 +214,15 @@ pub(crate) fn variadic_functor(
#[allow(unused_parens)]
mod tests {
use super::*;
use FunctorElement::*;
use std::string::String;
use FunctorElement::*;
#[test]
fn basic_terms() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
char_as_cell('c')]);
let functor = functor!(
atom!("first"),
[atom_as_cell((atom!("a"))), char_as_cell('c')]
);
assert_eq!(functor.len(), 3);
@@ -225,10 +230,14 @@ mod tests {
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(char_as_cell!('c')));
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1),
fixnum(2)]),
char_as_cell('c')]);
let functor = functor!(
atom!("second"),
[
atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
char_as_cell('c')
]
);
assert_eq!(functor.len(), 5);
@@ -236,13 +245,20 @@ mod tests {
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(str_loc_as_cell!(4)));
assert_eq!(functor[3], Cell(char_as_cell!('c')));
assert_eq!(functor[4], InnerFunctor(3, functor!(atom!("b"), [fixnum(1),
fixnum(2)])));
assert_eq!(
functor[4],
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
);
let functor = functor!(atom!("third"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1), fixnum(2)]),
char_as_cell('c')]);
let functor = functor!(
atom!("third"),
[
atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1), fixnum(2)]),
char_as_cell('c')
]
);
assert_eq!(functor.len(), 7);
@@ -251,14 +267,25 @@ mod tests {
assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(8)));
assert_eq!(functor[4], Cell(char_as_cell!('c')));
assert_eq!(functor[5], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)])));
assert_eq!(
functor[5],
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
);
assert_eq!(
functor[6],
InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)]))
);
let functor = functor!(atom!("fourth"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1)]),
functor((atom!("d")), [fixnum(453), fixnum(2)]),
char_as_cell('c')]);
let functor = functor!(
atom!("fourth"),
[
atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1)]),
functor((atom!("d")), [fixnum(453), fixnum(2)]),
char_as_cell('c')
]
);
assert_eq!(functor.len(), 9);
@@ -268,14 +295,26 @@ mod tests {
assert_eq!(functor[3], Cell(str_loc_as_cell!(9)));
assert_eq!(functor[4], Cell(str_loc_as_cell!(11)));
assert_eq!(functor[5], Cell(char_as_cell!('c')));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
assert_eq!(functor[7], InnerFunctor(2, functor!(atom!("c"), [fixnum(1)])));
assert_eq!(functor[8], InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)])));
assert_eq!(
functor[6],
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
);
assert_eq!(
functor[7],
InnerFunctor(2, functor!(atom!("c"), [fixnum(1)]))
);
assert_eq!(
functor[8],
InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)]))
);
}
#[test]
fn basic_terms_in_heap() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), char_as_cell('b')]);
let functor = functor!(
atom!("first"),
[atom_as_cell((atom!("a"))), char_as_cell('b')]
);
assert_eq!(functor.len(), 3);
@@ -291,10 +330,15 @@ mod tests {
heap.truncate(2);
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1), fixnum(2)]),
char_as_cell('b')]);
let functor = functor!(
atom!("second"),
[
atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1), fixnum(2)]),
char_as_cell('b')
]
);
assert_eq!(functor.len(), 7);
@@ -318,14 +362,24 @@ mod tests {
#[test]
fn nested_functors() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
functor((atom!("d")), [fixnum(1),
functor((atom!("b")),
[atom_as_cell((atom!("c"))),
char_as_cell('c')])]),
functor((atom!("e")), [fixnum(453),
fixnum(2)]),
char_as_cell('b')]);
let functor = functor!(
atom!("first"),
[
atom_as_cell((atom!("a"))),
functor(
(atom!("d")),
[
fixnum(1),
functor(
(atom!("b")),
[atom_as_cell((atom!("c"))), char_as_cell('c')]
)
]
),
functor((atom!("e")), [fixnum(453), fixnum(2)]),
char_as_cell('b')
]
);
assert_eq!(functor.len(), 7);
@@ -334,24 +388,47 @@ mod tests {
assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(11)));
assert_eq!(functor[4], Cell(char_as_cell!('b')));
assert_eq!(functor[5], InnerFunctor(6, vec![Cell(atom_as_cell!(atom!("d"), 2)),
Cell(fixnum_as_cell!(Fixnum::build_with(1))),
Cell(str_loc_as_cell!(3)),
InnerFunctor(3, functor!(atom!("b"), [atom_as_cell((atom!("c"))),
char_as_cell('c')]))]));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("e"), [fixnum(453),
fixnum(2)])));
assert_eq!(
functor[5],
InnerFunctor(
6,
vec![
Cell(atom_as_cell!(atom!("d"), 2)),
Cell(fixnum_as_cell!(Fixnum::build_with(1))),
Cell(str_loc_as_cell!(3)),
InnerFunctor(
3,
functor!(atom!("b"), [atom_as_cell((atom!("c"))), char_as_cell('c')])
)
]
)
);
assert_eq!(
functor[6],
InnerFunctor(3, functor!(atom!("e"), [fixnum(453), fixnum(2)]))
);
}
#[test]
fn nested_functors_in_heap() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
functor((atom!("second")), [fixnum(1),
functor((atom!("third")), [atom_as_cell((atom!("b"))),
char_as_cell('c')])]),
functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
char_as_cell('b')]);
let functor = functor!(
atom!("first"),
[
atom_as_cell((atom!("a"))),
functor(
(atom!("second")),
[
fixnum(1),
functor(
(atom!("third")),
[atom_as_cell((atom!("b"))), char_as_cell('c')]
)
]
),
functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
char_as_cell('b')
]
);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor);
@@ -392,33 +469,43 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(heap.slice_to_str(heap_index!(2), "a string".len()), "a string");
assert_eq!(
heap.slice_to_str(heap_index!(2), "a string".len()),
"a string"
);
assert_eq!(heap[4], empty_list_as_cell!());
heap.truncate(0);
let functor = functor!(atom!("second"), [string((String::from("a stuttered\0 string")))]);
let functor = functor!(
atom!("second"),
[string((String::from("a stuttered\0 string")))]
);
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 7);
assert_eq!(heap.cell_len(), 8);
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(heap.slice_to_str(heap_index!(2), "a stuttered".len()), "a stuttered");
assert_eq!(
heap.slice_to_str(heap_index!(2), "a stuttered".len()),
"a stuttered"
);
assert_eq!(heap[4], pstr_loc_as_cell!(heap_index!(5)));
assert_eq!(heap.slice_to_str(heap_index!(5), " string".len()), " string");
assert_eq!(heap[6], empty_list_as_cell!());
assert_eq!(
heap.slice_to_str(heap_index!(5), " string".len()),
" string"
);
assert_eq!(heap[7], empty_list_as_cell!());
}
#[test]
fn functors_with_lists_in_heap() {
let functor = functor!(
atom!("first"),
[list([fixnum(1),
atom_as_cell((atom!("a"))),
fixnum(2)])]
[list([fixnum(1), atom_as_cell((atom!("a"))), fixnum(2)])]
);
assert_eq!(functor.len(), 3);
@@ -462,8 +549,10 @@ mod tests {
let code_ptr = IndexingCodePtr::Internal(0);
let functor = functor!(
atom!("first"),
[string((String::from("a string"))),
indexing_code_ptr(code_ptr)]
[
string((String::from("a string"))),
indexing_code_ptr(code_ptr)
]
);
let mut heap = Heap::new();
@@ -476,18 +565,30 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6));
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
assert_eq!(
heap.slice_to_str(heap_index!(3), "a string".len()),
"a string"
);
assert_eq!(heap[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0)));
heap.truncate(0);
let functor = functor!(atom!("second"),
[string((String::from("a string"))),
functor((atom!("third")), [atom_as_cell((atom!("a"))),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)])]);
let functor = functor!(
atom!("second"),
[
string((String::from("a string"))),
functor(
(atom!("third")),
[
atom_as_cell((atom!("a"))),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)
]
)
]
);
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
@@ -497,24 +598,43 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6));
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
assert_eq!(
heap.slice_to_str(heap_index!(3), "a string".len()),
"a string"
);
assert_eq!(heap[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3));
assert_eq!(heap[7], atom_as_cell!(atom!("a")));
assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10)));
assert_eq!(heap[9], str_loc_as_cell!(13));
assert_eq!(heap.slice_to_str(heap_index!(10), "another string".len()), "another string");
assert_eq!(
heap.slice_to_str(heap_index!(10), "another string".len()),
"another string"
);
assert_eq!(heap[12], empty_list_as_cell!());
assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0)));
let functor = functor!(atom!("fourth"),
[string((String::from("a string"))),
functor((atom!("a")),
[functor((atom!("fifth")), [fixnum(5),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)]),
string((String::from("and another")))])]);
let functor = functor!(
atom!("fourth"),
[
string((String::from("a string"))),
functor(
(atom!("a")),
[
functor(
(atom!("fifth")),
[
fixnum(5),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)
]
),
string((String::from("and another")))
]
)
]
);
heap.truncate(0);
@@ -526,7 +646,10 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6));
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
assert_eq!(
heap.slice_to_str(heap_index!(3), "a string".len()),
"a string"
);
assert_eq!(heap[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2));
assert_eq!(heap[7], str_loc_as_cell!(9));
@@ -535,11 +658,17 @@ mod tests {
assert_eq!(heap[10], fixnum_as_cell!(Fixnum::build_with(5)));
assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13)));
assert_eq!(heap[12], str_loc_as_cell!(16));
assert_eq!(heap.slice_to_str(heap_index!(13), "another string".len()), "another string");
assert_eq!(
heap.slice_to_str(heap_index!(13), "another string".len()),
"another string"
);
assert_eq!(heap[15], empty_list_as_cell!());
assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[17], fixnum_as_cell!(Fixnum::build_with(0)));
assert_eq!(heap.slice_to_str(heap_index!(18), "and another".len()), "and another");
assert_eq!(
heap.slice_to_str(heap_index!(18), "and another".len()),
"and another"
);
assert_eq!(heap[20], empty_list_as_cell!());
}
@@ -550,17 +679,16 @@ mod tests {
let stub = functor!(
atom!("existence_error"),
[atom_as_cell((atom!("procedure"))), functor((culprit.clone()))]
[
atom_as_cell((atom!("procedure"))),
functor((culprit.clone()))
]
);
println!("{:?}", stub);
// now the error form
let lineless_error_form = functor!(
atom!("error"),
[functor(stub),
functor(culprit)]
);
let lineless_error_form = functor!(atom!("error"), [functor(stub), functor(culprit)]);
println!("{:?}", lineless_error_form);

View File

@@ -116,10 +116,10 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> {
}
}
(HeapCellValueTag::PStrLoc, h) => {
let (_, tail_loc) = self.heap.scan_slice_to_str(h);
let tail_idx = self.heap.scan_slice_to_str(h).tail_idx;
self.heap[tail_loc].set_mark_bit(self.mark_phase);
self.iter_stack.push(self.heap[tail_loc]);
self.heap[tail_idx].set_mark_bit(self.mark_phase);
self.iter_stack.push(self.heap[tail_idx]);
}
_ => {
}
@@ -452,12 +452,12 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
}
(HeapCellValueTag::PStrLoc, vh) => {
let cell = *cell;
let (_, tail_loc) = self.heap.scan_slice_to_str(vh);
let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx;
// forward the current PStrLoc cell if the zero
// byte at the end of the string buffer
// is marked
let buf_bytes = self.heap[tail_loc - 1].into_bytes();
let buf_bytes = self.heap[tail_idx - 1].into_bytes();
if buf_bytes[7] != 0u8 {
let cell = self.read_cell_mut(h);
@@ -469,9 +469,9 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
// is never inspected, which it isn't.
self.push_if_unmarked(
IterStackLoc::iterable_loc(tail_loc - 1, HeapOrStackTag::Heap),
IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap),
);
self.stack.push(IterStackLoc::mark_loc(tail_loc, HeapOrStackTag::Heap));
self.stack.push(IterStackLoc::mark_loc(tail_idx, HeapOrStackTag::Heap));
return Some(cell);
}
@@ -502,7 +502,6 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
}
}
impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
type Item = HeapCellValue;
@@ -707,9 +706,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom)]),
);
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
));
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).unwrap();
@@ -733,7 +731,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -758,10 +756,7 @@ mod tests {
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(f_atom, 4)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(a_atom)
@@ -778,7 +773,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -794,7 +789,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -837,7 +832,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
// now make the list cyclic.
wam.machine_st.heap[4] = heap_loc_as_cell!(0);
@@ -939,8 +934,6 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -955,9 +948,11 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)]
[
atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
));
functor_writer(&mut wam.machine_st.heap).unwrap();
@@ -1003,7 +998,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
@@ -1044,7 +1039,7 @@ mod tests {
// instance.
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
@@ -1074,7 +1069,7 @@ mod tests {
// instance.
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
@@ -1126,7 +1121,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1147,7 +1142,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
@@ -1193,7 +1188,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
@@ -1427,7 +1422,10 @@ mod tests {
wam.machine_st.heap.clear();
{
wam.machine_st.heap.push_cell(fixnum_as_cell!(Fixnum::build_with(0))).unwrap();
wam.machine_st
.heap
.push_cell(fixnum_as_cell!(Fixnum::build_with(0)))
.unwrap();
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
@@ -1439,7 +1437,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1473,7 +1471,7 @@ mod tests {
assert!(iter.next().is_none());
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1504,7 +1502,7 @@ mod tests {
assert!(iter.next().is_none());
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1564,7 +1562,7 @@ mod tests {
assert!(iter.next().is_none());
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(wam.machine_st.heap[0], str_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2));
@@ -1634,13 +1632,6 @@ mod tests {
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 9);
/*
while let Some(_) = iter.next() {
print_heap_terms(iter.heap.iter(), 0);
println!("");
}
*/
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
list_loc_as_cell!(7)
@@ -1693,9 +1684,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom)]),
);
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
));
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
let h = wam.machine_st.heap.cell_len();
@@ -1924,7 +1914,7 @@ mod tests {
);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -2021,7 +2011,11 @@ mod tests {
let functor = functor!(
f_atom,
[atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
[
atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
);
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2098,7 +2092,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -2163,7 +2157,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -2202,7 +2196,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -2221,18 +2215,18 @@ mod tests {
2,
);
assert_eq!(
iter.heap.slice_to_str(0, "a string".len()),
"a string"
);
assert_eq!(
iter.next().unwrap(),
empty_list_as_cell!()
);
assert_eq!(iter.heap.slice_to_str(0, "a string".len()), "a string");
assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap.slice_to_str(0, "a string".len()), "a string");
assert_eq!(wam.machine_st.heap[1], HeapCellValue::build_with(HeapCellValueTag::Cons, 0));
for idx in 2 ..= 3 {
assert!(!wam.machine_st.heap[idx].get_mark_bit());
assert!(!wam.machine_st.heap[idx].get_forwarding_bit());
}
wam.machine_st.heap.clear();
@@ -2291,9 +2285,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom)]),
);
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
));
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
let h = wam.machine_st.heap.cell_len();
@@ -2325,7 +2318,6 @@ mod tests {
wam.machine_st.heap.clear();
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
@@ -2361,10 +2353,7 @@ mod tests {
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(a_atom)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(f_atom, 4)
@@ -2519,7 +2508,7 @@ mod tests {
);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -2616,7 +2605,11 @@ mod tests {
let functor = functor!(
f_atom,
[atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
[
atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
);
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2694,7 +2687,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -2761,7 +2754,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
}
@@ -2778,9 +2771,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom)]),
);
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
));
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).unwrap();
@@ -2969,7 +2961,7 @@ mod tests {
);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -3039,7 +3031,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
@@ -3053,11 +3045,18 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
let functor = functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]);
let functor = functor!(
f_atom,
[
atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
);
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -3116,7 +3115,7 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -3164,6 +3163,6 @@ mod tests {
assert_eq!(iter.next(), None);
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
}
}

View File

@@ -486,7 +486,12 @@ pub struct HCPrinter<'a, Outputter> {
pub double_quotes: bool,
}
fn ambiguity_check(outputter: &impl HCValueOutputter, quoted: bool, last_item_idx: usize, atom: &str) -> bool {
fn ambiguity_check(
outputter: &impl HCValueOutputter,
quoted: bool,
last_item_idx: usize,
atom: &str,
) -> bool {
let tail = &outputter.as_str()[last_item_idx..];
if atom == "," || !quoted || non_quoted_token(atom.chars()) {
@@ -1132,7 +1137,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
}
macro_rules! emit_char {
($c:expr) => ({
($c:expr) => {{
append_str!(self, "'.'");
push_char!(self, '(');
@@ -1141,14 +1146,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Close);
char_count += 1;
});
}};
}
match iteratee {
PStrIteratee::Char { value, .. } => {
emit_char!(value);
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
PStrIteratee::PStrSlice {
slice_loc,
slice_len,
} => {
let s = iter.heap.slice_to_str(slice_loc, slice_len);
for c in s.chars() {
@@ -1181,10 +1189,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if max_depth == 0 {
while let Some(iteratee) = iter.next() {
let iter: Box<dyn Iterator<Item = char>> = match iteratee {
PStrIteratee::Char { value: c, .. } => {
Box::new(std::iter::once(c))
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
PStrIteratee::PStrSlice {
slice_loc,
slice_len,
} => {
let s = iter.heap.slice_to_str(slice_loc, slice_len);
Box::new(s.chars())
}
@@ -1201,10 +1210,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
while let Some(iteratee) = iter.next() {
let iter: Box<dyn Iterator<Item = char>> = match iteratee {
PStrIteratee::Char { value: c, .. } => {
Box::new(std::iter::once(c))
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
PStrIteratee::PStrSlice {
slice_loc,
slice_len,
} => {
let s = iter.heap.slice_to_str(slice_loc, slice_len);
Box::new(s.chars())
}
@@ -1583,22 +1593,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
} else {
/*
let end_cell_h = Heap::neighboring_cell_offset(pstr_loc);
let end_cell = self.iter.heap[end_cell_h];
let end_cell = heap_bound_store(
self.iter.heap,
heap_bound_deref(self.iter.heap, end_cell),
);
if end_cell != empty_list_as_cell!() {
self.iter.push_stack(
IterStackLoc::iterable_loc(end_cell_h, HeapOrStackTag::Heap),
);
}
*/
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
}
}
@@ -1872,9 +1868,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom)]),
);
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
));
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).unwrap();
@@ -1893,7 +1888,7 @@ mod tests {
assert_eq!(output.result(), "f(a,b)");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1925,7 +1920,7 @@ mod tests {
assert_eq!(output.result(), "f(a,b,a,...)");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1968,7 +1963,7 @@ mod tests {
assert_eq!(output.result(), "[L|L]");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -1984,9 +1979,11 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)]
[
atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
));
functor_writer(&mut wam.machine_st.heap).unwrap();
@@ -2005,7 +2002,7 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)]");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -2023,7 +2020,7 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|...]");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
{
let mut printer = HCPrinter::new(
@@ -2043,7 +2040,7 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
// issue #382
wam.machine_st.heap.clear();
@@ -2077,7 +2074,7 @@ mod tests {
assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -2100,7 +2097,7 @@ mod tests {
assert_eq!(output.result(), "[a,b,c|_1]");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2131,7 +2128,7 @@ mod tests {
assert_eq!(output.result(), "\"abcabc\"");
}
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.clear();
@@ -2140,14 +2137,14 @@ mod tests {
"=(X,[a,b,c|X])"
);
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(
&wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(),
"[a,b,[a],[a,b,c]]"
);
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(
&wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].")
@@ -2155,11 +2152,11 @@ mod tests {
"[[a,b,c],e,f,[g,e,h,Y,v,X,Y]]"
);
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(&wam.parse_and_print_term("f((a,b)).").unwrap(), "f((a,b))");
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
@@ -2171,14 +2168,14 @@ mod tests {
"[a|[]+b]"
);
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
"[a|[b|c]*d]"
);
all_cells_unmarked(wam.machine_st.heap.splice(..));
all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));

View File

@@ -1110,12 +1110,11 @@ pub(crate) fn constant_key_alternatives(
constants.push(
Fixnum::build_with_checked(value)
.map(|n| fixnum_as_cell!(n))
.unwrap()
.unwrap(),
);
}
}
_ => {
}
_ => {}
}
/*
@@ -1465,11 +1464,7 @@ impl<I: Indexer> CodeOffsets<I> {
self.indices.lists().push_back(index);
}
fn index_constant(
&mut self,
constant: HeapCellValue,
index: usize,
) -> Vec<HeapCellValue> {
fn index_constant(&mut self, constant: HeapCellValue, index: usize) -> Vec<HeapCellValue> {
let overlapping_constants = constant_key_alternatives(constant);
let code = self.indices.constants().entry(constant).or_default();

View File

@@ -14,7 +14,9 @@ use std::iter::*;
use std::ops::Deref;
use std::vec::Vec;
pub(crate) trait TermIterator: Deref<Target = Heap> + Iterator<Item = HeapCellValue> {
pub(crate) trait TermIterator:
Deref<Target = Heap> + Iterator<Item = HeapCellValue>
{
fn focus(&self) -> IterStackLoc;
fn level(&mut self) -> Level;
}
@@ -45,9 +47,9 @@ fn record_path(
}
}
(HeapCellValueTag::Lis) => {
root_terms.insert(root_loc);
break;
}
root_terms.insert(root_loc);
break;
}
_ => {
if cell.is_ref() {
root_terms.insert(cell.get_value() as usize);
@@ -228,7 +230,10 @@ pub(crate) enum ClauseItem<'a> {
FirstBranch(usize),
NextBranch,
BranchEnd(usize),
Chunk { chunk_num: usize, terms: &'a VecDeque<QueryTerm> },
Chunk {
chunk_num: usize,
terms: &'a VecDeque<QueryTerm>,
},
}
#[derive(Debug)]
@@ -271,10 +276,9 @@ impl<'a> ClauseIterator<'a> {
while let Some(state) = self.state_stack.pop() {
match state {
ClauseIteratorState::RemainingBranches(terms, focus)
if terms.len() == focus => {
depth += 1;
}
ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => {
depth += 1;
}
_ => {
self.state_stack.push(state);
break;
@@ -292,25 +296,27 @@ impl<'a> Iterator for ClauseIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
while let Some(state) = self.state_stack.pop() {
match state {
ClauseIteratorState::RemainingChunks(chunks, focus)
if focus < chunks.len() => {
if focus + 1 < chunks.len() {
self.state_stack
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
} else {
self.remaining_chunks_on_stack -= 1;
}
ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
if focus + 1 < chunks.len() {
self.state_stack
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
} else {
self.remaining_chunks_on_stack -= 1;
}
match &chunks[focus] {
ChunkedTerms::Branch(branches) => {
self.state_stack
.push(ClauseIteratorState::RemainingBranches(branches, 0));
}
&ChunkedTerms::Chunk { chunk_num, ref terms } => {
return Some(ClauseItem::Chunk { chunk_num, terms });
}
match &chunks[focus] {
ChunkedTerms::Branch(branches) => {
self.state_stack
.push(ClauseIteratorState::RemainingBranches(branches, 0));
}
&ChunkedTerms::Chunk {
chunk_num,
ref terms,
} => {
return Some(ClauseItem::Chunk { chunk_num, terms });
}
}
}
ClauseIteratorState::RemainingChunks(chunks, focus) => {
debug_assert_eq!(chunks.len(), focus);
}

View File

@@ -568,6 +568,7 @@ parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
% maplist isn't
% declared as a
% meta-predicate yet
'$debug_hook',
catch(lists:maplist(Selector, Options, OptionPairs0),
error(E, _),
builtins:throw(error(E, Stub))) ->

View File

@@ -1165,9 +1165,8 @@ impl MachineState {
return Err(self.error_form(type_error, stub_gen()));
};
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut self.heap, &mut self.stack, root_loc,
);
let mut iter =
stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, root_loc);
while let Some(value) = iter.next() {
if value.get_forwarding_bit() {

View File

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

View File

@@ -145,7 +145,9 @@ impl MachineState {
};
let mut iter = stackful_preorder_iter::<NonListElider>(
&mut self.heap, &mut self.stack, root_loc, // cell,
&mut self.heap,
&mut self.stack,
root_loc, // cell,
);
while let Some(value) = iter.next() {

View File

@@ -2102,19 +2102,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
let key = match self
.payload
.predicates
.first()
.map(|term| term.focus) {
Some(focus) => {
clause_predicate_key(self.machine_heap(), focus)
.ok_or(SessionError::NamelessEntry)?
}
None => {
return Err(SessionError::NamelessEntry);
}
};
let key = match self.payload.predicates.first().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();
@@ -2290,13 +2284,18 @@ impl Machine {
term_reg: RegType,
vars: Vec<HeapCellValue>,
) -> Result<(), SessionError> {
let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
let body_cell = self
.machine_st
.store(self.machine_st.deref(self.machine_st[term_reg]));
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;
let mut writer = self.machine_st.heap.reserve(4 + arity)
let mut writer = self
.machine_st
.heap
.reserve(4 + arity)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
writer.write_with(move |section| {

View File

@@ -1,13 +1,71 @@
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use crate::atom_table::*;
use crate::machine::get_structure_index;
use crate::machine::heap::*;
use crate::machine::stack::*;
use crate::types::*;
use scryer_modular_bitfield::specifiers::*;
use scryer_modular_bitfield::*;
use std::collections::BTreeMap;
use std::mem;
use std::ops::{IndexMut, Range};
type Trail = Vec<(Ref, HeapCellValue)>;
#[derive(BitfieldSpecifier, Copy, Clone, Debug)]
#[bits = 6]
enum TrailRefTag {
HeapCell = 0b001011,
StackCell = 0b001101,
AttrVar = 0b010001,
PStrLoc = 0b001111,
}
#[bitfield]
#[repr(u64)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct TrailRef {
val: B56,
#[allow(unused)]
m: bool,
#[allow(unused)]
f: bool,
tag: TrailRefTag,
}
impl TrailRef {
#[inline(always)]
fn heap_cell(h: usize) -> Self {
TrailRef::new()
.with_tag(TrailRefTag::HeapCell)
.with_val(h as u64)
}
#[inline(always)]
fn stack_cell(h: usize) -> Self {
TrailRef::new()
.with_tag(TrailRefTag::StackCell)
.with_val(h as u64)
}
#[inline(always)]
fn attr_var(h: usize) -> Self {
TrailRef::new()
.with_tag(TrailRefTag::AttrVar)
.with_val(h as u64)
}
#[inline(always)]
fn pstr_loc(h: usize) -> Self {
TrailRef::new()
.with_tag(TrailRefTag::PStrLoc)
.with_val(h as u64)
}
}
type Trail = Vec<(TrailRef, HeapCellValue)>;
#[derive(Debug, Clone, Copy)]
pub enum AttrVarPolicy {
@@ -18,15 +76,12 @@ pub enum AttrVarPolicy {
pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
fn store(&self, value: HeapCellValue) -> HeapCellValue;
fn deref(&self, value: HeapCellValue) -> 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 as_slice_from<'a>(&'a self, from: usize) -> Box<dyn Iterator<Item = u8> + 'a>;
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>;
}
@@ -35,14 +90,25 @@ pub(crate) fn copy_term<T: CopierTarget>(
target: T,
addr: HeapCellValue,
attr_var_policy: AttrVarPolicy,
) -> Result<(), usize> {
) -> Result<usize, usize> {
let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
let old_threshold = copy_term_state.target.threshold();
copy_term_state.copy_term_impl(addr)?;
copy_term_state.copy_attr_var_lists()?;
copy_term_state.unwind_trail();
Ok(())
let new_threshold = copy_term_state.target.threshold();
copy_term_state.copy_pstrs()?;
Ok(new_threshold - old_threshold)
}
#[derive(Debug)]
pub struct PStrData {
pre_old_h_tail_loc: usize,
post_old_h_tail_loc: usize,
post_old_h_pstr_loc_locs: IndexSet<usize, FxBuildHasher>,
}
#[derive(Debug)]
@@ -53,6 +119,9 @@ struct CopyTermState<T: CopierTarget> {
target: T,
attr_var_policy: AttrVarPolicy,
attr_var_list_locs: Vec<(usize, HeapCellValue)>,
// keys of pstr_loc_locs are byte indices rounded down to the
// nearest cell boundary
pstr_loc_locs: BTreeMap<usize, PStrData>,
}
impl<T: CopierTarget> CopyTermState<T> {
@@ -64,6 +133,7 @@ impl<T: CopierTarget> CopyTermState<T> {
target,
attr_var_policy,
attr_var_list_locs: vec![],
pstr_loc_locs: BTreeMap::new(),
}
}
@@ -74,7 +144,7 @@ impl<T: CopierTarget> CopyTermState<T> {
fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
let trail_item = mem::replace(&mut self.target[addr], list_loc_as_cell!(threshold));
self.trail.push((Ref::heap_cell(addr), trail_item));
self.trail.push((TrailRef::heap_cell(addr), trail_item));
}
fn copy_list(&mut self, addr: usize) -> Result<(), usize> {
@@ -93,7 +163,7 @@ impl<T: CopierTarget> CopyTermState<T> {
}
let threshold = self.target.threshold();
self.target.copy_slice_to_end(addr .. addr + 2)?;
self.target.copy_slice_to_end(addr..addr + 2)?;
*self.value_at_scan() = list_loc_as_cell!(threshold);
@@ -122,54 +192,90 @@ impl<T: CopierTarget> CopyTermState<T> {
Ok(())
}
/*
* 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);
}
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;
// 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.
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;
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(new_pstr_loc) + pstr_offset);
self.scan += 1;
return Ok(());
match self.pstr_loc_locs.range_mut(..=pstr_loc).next_back() {
Some((
_prev_pstr_loc,
&mut PStrData {
pre_old_h_tail_loc,
ref mut post_old_h_pstr_loc_locs,
..
},
)) if pre_old_h_tail_loc >= cell_index!(pstr_loc) => {
post_old_h_pstr_loc_locs.insert(self.scan);
self.scan += 1;
return Ok(());
}
_ => {}
}
let threshold = self.target.threshold();
let tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?;
let offset = self
.target
.as_slice_from(pstr_loc)
.take_while(|b| *b != 0u8)
.count();
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(threshold) + pstr_offset);
let left_pstr_boundary = cell_index!(pstr_loc + offset);
let flag = u64::from_be_bytes(self.target[left_pstr_boundary].into_bytes());
let pstr_loc_idx = cell_index!(pstr_loc);
self.trail.push((Ref::heap_cell(head_cell_idx), self.target[head_cell_idx]));
self.write_pstr_index(head_cell_idx, threshold);
if flag == 1 {
if left_pstr_boundary != pstr_loc_idx {
let mut pstr_data = self
.pstr_loc_locs
.remove(&heap_index!(left_pstr_boundary))
.unwrap();
let tail_cell = self.target[tail_loc];
let mut writer = self.target.reserve(1)?;
pstr_data.post_old_h_pstr_loc_locs.insert(self.scan);
self.pstr_loc_locs
.insert(heap_index!(cell_index!(pstr_loc)), pstr_data);
writer.write_with(|section| {
section.push_cell(tail_cell);
});
let old_cell = self.target[pstr_loc_idx];
self.target[pstr_loc_idx] = HeapCellValue::from_bytes(u64::to_be_bytes(1));
self.trail
.push((TrailRef::pstr_loc(pstr_loc_idx), old_cell));
} else {
let pstr_data = self
.pstr_loc_locs
.get_mut(&heap_index!(left_pstr_boundary))
.unwrap();
pstr_data.post_old_h_pstr_loc_locs.insert(self.scan);
}
} else {
let old_cell = self.target[pstr_loc_idx];
self.target[pstr_loc_idx] = HeapCellValue::from_bytes(u64::to_be_bytes(1));
self.trail
.push((TrailRef::pstr_loc(pstr_loc_idx), old_cell));
let old_tail_idx = if (pstr_loc + offset + 1) % Heap::heap_cell_alignment() == 0 {
cell_index!(pstr_loc + offset) + 2
} else {
cell_index!(pstr_loc + offset) + 1
};
let tail_cell = self.target[old_tail_idx];
let new_tail_idx = self.target.threshold();
let mut writer = self.target.reserve(1)?;
writer.write_with(|section| {
section.push_cell(tail_cell);
});
let mut post_old_h_pstr_loc_locs = IndexSet::with_hasher(FxBuildHasher::default());
post_old_h_pstr_loc_locs.insert(self.scan);
let pstr_data = PStrData {
pre_old_h_tail_loc: old_tail_idx,
post_old_h_tail_loc: new_tail_idx,
post_old_h_pstr_loc_locs,
};
self.pstr_loc_locs
.insert(heap_index!(pstr_loc_idx), pstr_data);
}
self.scan += 1;
Ok(())
}
@@ -210,6 +316,7 @@ impl<T: CopierTarget> CopyTermState<T> {
});
debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
self.copy_term_impl(str_cell)?;
list_addr = self.target[heap_loc + 1];
@@ -227,13 +334,13 @@ impl<T: CopierTarget> CopyTermState<T> {
self.target[frontier] = heap_loc_as_cell!(frontier);
self.target[h] = heap_loc_as_cell!(frontier);
self.trail.push((Ref::heap_cell(h), heap_loc_as_cell!(h)));
self.trail.push((TrailRef::heap_cell(h), heap_loc_as_cell!(h)));
}
(HeapCellValueTag::StackVar, s) => {
self.target[frontier] = heap_loc_as_cell!(frontier);
self.target.stack()[s] = heap_loc_as_cell!(frontier);
self.trail.push((Ref::stack_cell(s), stack_loc_as_cell!(s)));
self.trail.push((TrailRef::stack_cell(s), stack_loc_as_cell!(s)));
}
(HeapCellValueTag::AttrVar, h) => {
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
@@ -245,10 +352,10 @@ impl<T: CopierTarget> CopyTermState<T> {
self.target[frontier] = heap_loc_as_cell!(threshold);
self.target[h] = heap_loc_as_cell!(threshold);
self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
self.trail.push((TrailRef::attr_var(h), attr_var_as_cell!(h)));
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
let mut writer = self.target.reserve(2).unwrap();
let mut writer = self.target.reserve(2)?;
writer.write_with(|section| {
section.push_cell(attr_var_as_cell!(threshold));
@@ -256,7 +363,7 @@ impl<T: CopierTarget> CopyTermState<T> {
});
let old_list_link = self.target[h + 1];
self.trail.push((Ref::heap_cell(h + 1), old_list_link));
self.trail.push((TrailRef::heap_cell(h + 1), old_list_link));
self.target[h + 1] = heap_loc_as_cell!(threshold + 1);
if old_list_link.get_tag() == HeapCellValueTag::Lis {
@@ -317,7 +424,21 @@ impl<T: CopierTarget> CopyTermState<T> {
(HeapCellValueTag::Atom, (_name, arity)) => {
let threshold = self.target.threshold();
*self.value_at_scan() = str_loc_as_cell!(threshold);
let index_cell = self.target[addr.saturating_sub(1)];
*self.value_at_scan() = 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();
writer.write_with(|section| {
section.push_cell(index_cell);
});
str_loc_as_cell!(threshold + 1)
} else {
str_loc_as_cell!(threshold)
};
self.target.copy_slice_to_end(addr .. addr + 1 + arity)?;
@@ -326,28 +447,7 @@ impl<T: CopierTarget> CopyTermState<T> {
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];
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();
writer.write_with(|section| {
section.push_cell(index_cell);
});
}
}
self.trail.push((TrailRef::heap_cell(addr), trail_item));
}
(HeapCellValueTag::Str, h) => {
*self.value_at_scan() = str_loc_as_cell!(h);
@@ -370,11 +470,6 @@ impl<T: CopierTarget> CopyTermState<T> {
});
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,
@@ -405,17 +500,40 @@ impl<T: CopierTarget> CopyTermState<T> {
Ok(())
}
fn unwind_trail(mut self) {
for (r, value) in self.trail {
let index = r.get_value() as usize;
fn copy_pstrs(&mut self) -> Result<(), usize> {
while let Some((least_pstr_loc, pstr_data)) = self.pstr_loc_locs.pop_first() {
let threshold = heap_index!(self.target.threshold());
match r.get_tag() {
RefTag::AttrVar | RefTag::HeapCell => {
for pstr_loc_loc in pstr_data.post_old_h_pstr_loc_locs {
let pstr_loc = self.target[pstr_loc_loc].get_value() as usize;
self.target[pstr_loc_loc] =
pstr_loc_as_cell!(threshold + pstr_loc - least_pstr_loc);
}
self.target.copy_pstr_to_threshold(least_pstr_loc)?;
let mut writer = self.target.reserve(1)?;
writer.write_with(|section| {
section.push_cell(heap_loc_as_cell!(pstr_data.post_old_h_tail_loc));
});
}
Ok(())
}
fn unwind_trail(&mut self) {
for (r, value) in self.trail.drain(..) {
let index = r.val() as usize;
match r.tag() {
TrailRefTag::AttrVar | TrailRefTag::HeapCell => {
self.target[index] = value;
self.target[index].set_mark_bit(false);
self.target[index].set_forwarding_bit(false);
}
RefTag::StackCell => self.target.stack()[index] = value,
TrailRefTag::StackCell => self.target.stack()[index] = value,
TrailRefTag::PStrLoc => self.target[index] = value,
}
}
}
@@ -438,9 +556,10 @@ mod tests {
let a_atom = atom!("a");
let b_atom = atom!("b");
let mut functor_writer = Heap::functor_writer(
functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(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();
@@ -480,29 +599,233 @@ mod tests {
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(
wam.machine_st.heap.slice_to_str(0, "abc ".len()),
"abc "
);
assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc ");
assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(2), "def".len()),
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[4], pstr_loc_as_cell!(heap_index!(7)));
assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(9)));
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!(5), "abc ".len()),
wam.machine_st
.heap
.slice_to_str(heap_index!(7), "abc ".len()),
"abc "
);
assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7)));
assert_eq!(wam.machine_st.heap[8], heap_loc_as_cell!(5));
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(7), "def".len()),
wam.machine_st
.heap
.slice_to_str(heap_index!(9), "def".len()),
"def"
);
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(heap_index!(5)));
assert_eq!(wam.machine_st.heap[10], heap_loc_as_cell!(6));
wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
writer.write_with(|section| {
section.push_pstr("abc ");
section.push_cell(pstr_loc_as_cell!(heap_index!(2) + 9));
section.push_pstr("defdefdefdef");
section.push_cell(pstr_loc_as_cell!(0));
});
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc ");
assert_eq!(
wam.machine_st.heap[1],
pstr_loc_as_cell!(heap_index!(2) + 9)
);
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(2), "defdefdefdef".len()),
"defdefdefdef"
);
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(0));
assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(8)));
assert_eq!(
wam.machine_st.heap[6],
pstr_loc_as_cell!(heap_index!(10) + 1)
);
assert_eq!(wam.machine_st.heap[7], pstr_loc_as_cell!(heap_index!(8)));
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(8), "abc ".len()),
"abc "
);
assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(6));
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(10), "fdef".len()),
"fdef"
);
assert_eq!(wam.machine_st.heap[11], heap_loc_as_cell!(7));
wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
writer.write_with(|section| {
section.push_pstr("012345678912345");
section.push_cell(pstr_loc_as_cell!(heap_index!(0)));
});
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
"012345678912345"
);
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(heap_index!(0)));
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(6)));
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(6), "012345678912345".len()),
"012345678912345"
);
assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(6)));
wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
writer.write_with(|section| {
section.push_pstr("012345678912345");
section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 9));
});
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
"012345678912345"
);
assert_eq!(
wam.machine_st.heap[3],
pstr_loc_as_cell!(heap_index!(0) + 9)
);
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(6)));
assert_eq!(
wam.machine_st.heap[5],
pstr_loc_as_cell!(heap_index!(6) + 9)
);
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(6), "012345678912345".len()),
"012345678912345"
);
assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(5));
wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
writer.write_with(|section| {
section.push_pstr("012345678912345");
section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 7));
});
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(11), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
"012345678912345"
);
assert_eq!(
wam.machine_st.heap[3],
pstr_loc_as_cell!(heap_index!(0) + 7)
);
assert_eq!(
wam.machine_st.heap[4],
pstr_loc_as_cell!(heap_index!(6) + 11)
);
assert_eq!(
wam.machine_st.heap[5],
pstr_loc_as_cell!(heap_index!(6) + 7)
);
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(6), "012345678912345".len()),
"012345678912345"
);
assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(5));
wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
writer.write_with(|section| {
section.push_pstr("012345678912345");
section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 12));
});
{
let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(11), AttrVarPolicy::DeepCopy).unwrap();
}
assert_eq!(
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
"012345678912345"
);
assert_eq!(
wam.machine_st.heap[3],
pstr_loc_as_cell!(heap_index!(0) + 12)
);
assert_eq!(
wam.machine_st.heap[4],
pstr_loc_as_cell!(heap_index!(6) + 3)
);
assert_eq!(
wam.machine_st.heap[5],
pstr_loc_as_cell!(heap_index!(6) + 4)
);
assert_eq!(
wam.machine_st
.heap
.slice_to_str(heap_index!(6), "8912345".len()),
"8912345"
);
assert_eq!(wam.machine_st.heap[8], heap_loc_as_cell!(5));
wam.machine_st.heap.clear();
@@ -528,7 +851,6 @@ mod tests {
assert_eq!(wam.machine_st.heap[2], atom_as_cell!(b_atom));
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(a_atom));
assert_eq!(wam.machine_st.heap[4], str_loc_as_cell!(0));
assert_eq!(wam.machine_st.heap[5], str_loc_as_cell!(6));
assert_eq!(wam.machine_st.heap[6], atom_as_cell!(f_atom, 4));
assert_eq!(wam.machine_st.heap[7], atom_as_cell!(a_atom));

View File

@@ -206,9 +206,9 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
}
HeapCellValueTag::PStrLoc => {
let h = self.next as usize;
let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
let tail_idx = self.heap.scan_slice_to_str(h).tail_idx;
if self.heap[last_cell_loc].get_forwarding_bit() {
if self.heap[tail_idx].get_forwarding_bit() {
if self.cycle_detection_active() {
self.cycle_found = true;
return None;
@@ -219,11 +219,11 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
continue;
}
self.heap[last_cell_loc].set_forwarding_bit(true);
self.heap[tail_idx].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;
self.next = self.heap[tail_idx].get_value();
self.heap[tail_idx].set_value(self.current as u64);
self.current = tail_idx;
return Some(pstr_loc_as_cell!(h));
}

View File

@@ -2,11 +2,11 @@ use crate::atom_table::*;
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::*;
use crate::machine::Stack;
use crate::parser::ast::*;
use crate::parser::dashu::Rational;
use crate::types::*;
@@ -229,7 +229,8 @@ impl VarLocsToNums {
}
pub fn get(&self, idx: VarPtrIndex) -> VarPtr {
self.map.get(&idx)
self.map
.get(&idx)
.cloned()
.map(VarPtr::Numbered)
.unwrap_or_else(|| VarPtr::Anon)
@@ -260,8 +261,10 @@ impl VarData {
if let Some(global_cut_var_num) = global_cut_var_num {
let term = QueryTerm::GetLevel(global_cut_var_num);
self.records[global_cut_var_num].allocation =
VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending };
self.records[global_cut_var_num].allocation = VarAlloc::Perm {
reg: 0,
allocation: PermVarAllocation::Pending,
};
match build_stack.front_mut() {
Some(ChunkedTerms::Branch(_)) => {
@@ -395,11 +398,7 @@ impl VariableClassifier {
let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>(
term.heap,
&mut stack,
term.focus,
);
let mut iter = fact_iterator::<false>(term.heap, &mut stack, term.focus);
// second arg is true to iterate the root, which may be a variable
while let Some(subterm) = iter.next() {
@@ -425,8 +424,7 @@ impl VariableClassifier {
fn probe_body_var(&mut self, context: GenContext, var_info: VarInfo) {
let chunk_num = context.chunk_num();
let branch_info_v = self.branch_map.entry(var_info.var)
.or_default();
let branch_info_v = self.branch_map.entry(var_info.var).or_default();
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
!self.root_set.contains(&last_bi.branch_num)
@@ -489,14 +487,10 @@ impl VariableClassifier {
debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
for idx in str_offset + 1 ..= str_offset + arity {
for idx in str_offset + 1..=str_offset + arity {
let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>(
heap,
&mut stack,
idx,
);
let mut iter = fact_iterator::<false>(heap, &mut stack, idx);
while let Some(subterm) = iter.next() {
if !subterm.is_var() {
@@ -661,13 +655,14 @@ impl VariableClassifier {
mut term_loc,
} => {
// return true iff new chunk should be added.
let update_chunk_data = |build_stack: &mut ChunkedTermVec, key: PredicateKey| {
if ClauseType::is_inlined(key.0, key.1) {
build_stack.try_set_chunk_at_inlined_boundary()
} else {
build_stack.try_set_chunk_at_call_boundary()
}
};
let update_chunk_data =
|build_stack: &mut ChunkedTermVec, key: PredicateKey| {
if ClauseType::is_inlined(key.0, key.1) {
build_stack.try_set_chunk_at_inlined_boundary()
} else {
build_stack.try_set_chunk_at_call_boundary()
}
};
macro_rules! add_chunk {
($key:expr, $tag:expr, $term_loc:expr) => {{
@@ -678,9 +673,10 @@ impl VariableClassifier {
let context = build_stack.current_gen_context();
for (arg_c, term_loc) in
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
($term_loc + 1..=$term_loc + $key.1).enumerate()
{
let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
let mut term =
FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
self.probe_body_term(
arg_c + 1,
@@ -710,9 +706,10 @@ impl VariableClassifier {
let context = build_stack.current_gen_context();
for (arg_c, term_loc) in
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
($term_loc + 1..=$term_loc + $key.1).enumerate()
{
let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
let mut term =
FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
self.probe_body_term(
arg_c + 1,
@@ -1043,8 +1040,8 @@ impl BranchMap {
for (var, branches) in self.iter_mut() {
let (mut var_num, var_num_incr) = match var {
&ClassifiedVar::InSitu { var_num} => (var_num, false),
_ => (var_data.records.len(), true)
&ClassifiedVar::InSitu { var_num } => (var_num, false),
_ => (var_data.records.len(), true),
};
for branch in branches.iter_mut() {
@@ -1088,7 +1085,10 @@ impl BranchMap {
let chunk_num = chunk.term_loc.chunk_num();
var_data.var_locs_to_nums.insert(
VarPtrIndex { chunk_num, term_loc },
VarPtrIndex {
chunk_num,
term_loc,
},
var_num,
);
}

View File

@@ -140,10 +140,7 @@ impl MachineState {
let a1 = self.registers[1];
let a2 = self.registers[2];
step_or_resource_error!(
self,
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);
}
@@ -162,11 +159,7 @@ impl MachineState {
let heap_addr = resource_error_call_result!(
self,
sized_iter_to_heap_list(
&mut self.heap,
list.len(),
list.into_iter(),
)
sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter(),)
);
let target_addr = self.registers[2];
@@ -5155,9 +5148,8 @@ impl Machine {
let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r));
let mut writer = Heap::functor_writer(
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,
@@ -5178,9 +5170,8 @@ impl Machine {
let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r));
let mut writer = Heap::functor_writer(
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,

File diff suppressed because it is too large Load Diff

View File

@@ -5,22 +5,17 @@ use crate::types::*;
use std::alloc;
use std::convert::TryFrom;
use std::mem;
use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
use std::ptr;
use std::sync::Once;
use super::MachineState;
use bitvec::prelude::*;
use bitvec::slice::BitSlice;
const ALIGN: usize = Heap::heap_cell_alignment();
#[derive(Debug)]
pub struct Heap {
inner: InnerHeap,
pstr_vec: BitVec,
resource_err_loc: usize,
}
@@ -90,40 +85,51 @@ unsafe impl Sync for Heap {}
static RESOURCE_ERROR_OFFSET_INIT: Once = Once::new();
#[derive(Debug)]
pub struct HeapStringScan<'a> {
pub string: &'a str,
pub tail_idx: usize,
}
// return the string at ptr and the tail location relative to ptr.
// pstr_vec records the location of each string cell starting at index
// 0.
fn scan_slice_to_str(orig_ptr: *const u8, pstr_vec: &BitSlice) -> (&str, usize) {
unsafe {
debug_assert_eq!(pstr_vec[0], true);
unsafe fn scan_slice_to_str<'a>(heap_slice: &'a [u8]) -> HeapStringScan<'a> {
let string_len = heap_slice.iter().position(|b| *b == 0u8).unwrap();
let zero_byte_addr = heap_slice.as_ptr().add(string_len);
let sentinel_len = pstr_sentinel_length(zero_byte_addr as usize);
let tail_idx = cell_index!(
(string_len + sentinel_len).next_multiple_of(ALIGN)
+ if sentinel_len <= 1 { heap_index!(1) } else { 0 }
);
let tail_cell_offset = pstr_vec[0..].first_zero().unwrap();
let offset = (ALIGN - orig_ptr.align_offset(ALIGN)) % 8;
let buf_len = heap_index!(tail_cell_offset) - offset;
let slice = std::slice::from_raw_parts(orig_ptr, buf_len);
let str_slice = &heap_slice[..string_len];
// skip the final buffer byte which may not be 0 depending on
// the context, i.e. marking by an iterator. it is counted by
// the initial 1 as part of the padding but for this reason
// mustn't be allowed to stop the count.
let padding_len = 1 + slice.iter()
.rev()
.skip(1)
.position(|b| *b != 0u8)
.unwrap();
let s_len = slice.len() - padding_len;
(std::str::from_utf8_unchecked(&slice[0 .. s_len]), tail_cell_offset)
HeapStringScan {
string: std::str::from_utf8_unchecked(str_slice),
tail_idx,
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum PStrSegmentCmpResult {
Mismatch { c1: char, c2: char },
FirstMatch { pstr_loc1: usize, pstr_loc2: usize, l1_offset: usize },
SecondMatch { pstr_loc1: usize, pstr_loc2: usize, l2_offset: usize },
BothMatch { pstr_loc1: usize, pstr_loc2: usize, null_offset: usize },
Mismatch {
c1: char,
c2: char,
},
FirstMatch {
pstr_loc1: usize,
pstr_loc2: usize,
l1_offset: usize,
},
SecondMatch {
pstr_loc1: usize,
pstr_loc2: usize,
l2_offset: usize,
},
BothMatch {
pstr_loc1: usize,
pstr_loc2: usize,
null_offset: usize,
},
}
impl PStrSegmentCmpResult {
@@ -132,24 +138,36 @@ impl PStrSegmentCmpResult {
pdl: &mut Vec<HeapCellValue>,
) -> Option<std::cmp::Ordering> {
match self {
PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset } => {
let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + l1_offset);
PStrSegmentCmpResult::FirstMatch {
pstr_loc1,
pstr_loc2,
l1_offset,
} => {
let tail1 = Heap::pstr_tail_idx(pstr_loc1 + l1_offset);
let rest_of_l2 = pstr_loc_as_cell!(pstr_loc2 + l1_offset);
pdl.push(heap_loc_as_cell!(tail1));
pdl.push(rest_of_l2);
}
PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset } => {
let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + l2_offset);
PStrSegmentCmpResult::SecondMatch {
pstr_loc1,
pstr_loc2,
l2_offset,
} => {
let tail2 = Heap::pstr_tail_idx(pstr_loc2 + l2_offset);
let rest_of_l1 = pstr_loc_as_cell!(pstr_loc1 + l2_offset);
pdl.push(rest_of_l1);
pdl.push(heap_loc_as_cell!(tail2));
}
PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset } => {
PStrSegmentCmpResult::BothMatch {
pstr_loc1,
pstr_loc2,
null_offset,
} => {
// exhaustive match
let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + null_offset);
let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + null_offset);
let tail1 = Heap::pstr_tail_idx(pstr_loc1 + null_offset);
let tail2 = Heap::pstr_tail_idx(pstr_loc2 + null_offset);
pdl.push(heap_loc_as_cell!(tail1));
pdl.push(heap_loc_as_cell!(tail2));
@@ -163,162 +181,18 @@ impl PStrSegmentCmpResult {
}
}
#[derive(Debug)]
pub(crate) struct HeapView<'a> {
slice: *const u8,
cell_offset: usize,
slice_cell_len: usize,
pstr_slice: &'a BitSlice,
}
impl<'a> HeapView<'a> {
/*
pub fn get(&self, idx: usize) -> Option<HeapCellValue> {
if idx < self.slice_cell_len {
Some(*self.index(idx))
} else {
None
}
}
*/
fn iter_follow(&mut self) -> Option<HeapCellValue> {
if self.slice_cell_len == 0 {
None
} else {
let cell;
if self.pstr_slice[0] {
cell = pstr_loc_as_cell!(heap_index!(self.cell_offset));
let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
self.slice_cell_len -= next_cell_idx;
self.cell_offset += next_cell_idx;
self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
} else {
unsafe {
cell = ptr::read(self.slice as *mut HeapCellValue);
self.slice = self.slice.add(heap_index!(1));
}
self.cell_offset += 1;
self.slice_cell_len -= 1;
self.pstr_slice = &self.pstr_slice[1 ..];
}
Some(cell)
}
}
}
impl<'a> Iterator for HeapView<'a> {
type Item = HeapCellValue;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter_follow()
}
}
impl<'a> Index<usize> for HeapView<'a> {
type Output = HeapCellValue;
fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(idx < self.slice_cell_len);
unsafe {
&*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
}
}
}
#[derive(Debug)]
pub(crate) struct HeapViewMut<'a> {
slice: *mut u8,
cell_offset: usize,
slice_cell_len: usize,
pstr_slice: &'a BitSlice,
}
impl<'a> HeapViewMut<'a> {
fn iter_follow(&mut self) -> Option<&'a mut HeapCellValue> {
if self.slice_cell_len == 0 {
None
} else {
let cell;
loop {
if self.pstr_slice[0] {
let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
self.slice_cell_len -= next_cell_idx;
self.cell_offset += next_cell_idx;
self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
} else {
unsafe {
cell = &mut *(self.slice as *mut HeapCellValue);
self.slice = self.slice.add(heap_index!(1));
}
self.cell_offset += 1;
self.slice_cell_len -= 1;
self.pstr_slice = &self.pstr_slice[1 ..];
break;
}
}
Some(cell)
}
}
}
impl<'a> Index<usize> for HeapViewMut<'a> {
type Output = HeapCellValue;
fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(idx < self.slice_cell_len);
unsafe {
&*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
}
}
}
impl<'a> IndexMut<usize> for HeapViewMut<'a> {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
debug_assert!(idx < self.slice_cell_len);
unsafe {
&mut *(self.slice.add(heap_index!(idx)) as *mut HeapCellValue)
}
}
}
impl<'a> Iterator for &'a mut HeapViewMut<'a> {
type Item = &'a mut HeapCellValue;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter_follow()
}
}
#[derive(Debug)]
pub struct PStrWriteInfo {
pstr_loc: usize,
}
#[derive(Debug)]
pub(crate) struct ReservedHeapSection<'a> {
pub(crate) struct ReservedHeapSection {
heap_ptr: *mut u8,
heap_cell_len: usize,
pstr_vec: &'a mut BitVec,
}
impl<'a> ReservedHeapSection<'a> {
impl ReservedHeapSection {
#[inline]
pub(crate) fn cell_len(&self) -> usize {
self.heap_cell_len
@@ -326,16 +200,16 @@ impl<'a> ReservedHeapSection<'a> {
pub(crate) fn push_cell(&mut self, cell: HeapCellValue) {
unsafe {
ptr::write(self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _, cell);
ptr::write(
self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _,
cell,
);
}
self.pstr_vec.push(false);
// self.pstr_vec.push(false);
self.heap_cell_len += 1;
}
fn push_pstr_segment(
&mut self,
src: &str,
) -> usize {
fn push_pstr_segment(&mut self, src: &str) -> usize {
if src.is_empty() {
return 0;
}
@@ -354,23 +228,30 @@ impl<'a> ReservedHeapSection<'a> {
let align_offset = pstr_sentinel_length(zero_region_idx);
ptr::write_bytes(
self.heap_ptr.add(zero_region_idx),
0u8,
align_offset,
);
ptr::write_bytes(self.heap_ptr.add(zero_region_idx), 0u8, align_offset);
cells_written = if align_offset == 1 {
ptr::write_bytes(
self.heap_ptr.add(zero_region_idx + 1),
0u8,
size_of::<HeapCellValue>(),
);
// ensure there are at least two bytes in the boundary
// buffer separating the string data from the tail
// cell
cell_index!(src.len() + align_offset + size_of::<HeapCellValue>())
} else {
cell_index!(src.len() + align_offset)
};
cells_written = cell_index!(src.len() + align_offset);
self.heap_cell_len += cells_written;
}
cells_written
}
pub(crate) fn push_pstr(
&mut self,
mut src: &str,
) -> Option<HeapCellValue> {
pub(crate) fn push_pstr(&mut self, mut src: &str) -> Option<HeapCellValue> {
let orig_h = self.cell_len();
if src.is_empty() {
@@ -386,18 +267,14 @@ impl<'a> ReservedHeapSection<'a> {
loop {
let null_char_idx = src.find('\u{0}').unwrap_or_else(|| src.len());
let cell_len = self.cell_len();
let cells_written = self.push_pstr_segment(&src[0..null_char_idx]);
let tail_idx = self.cell_len();
self.pstr_vec.resize(cell_len + cells_written, true);
if cells_written == 0 {
return None;
} else if null_char_idx + 1 < src.len() {
self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1)));
src = &src[null_char_idx + 1 ..];
src = &src[null_char_idx + 1..];
} else {
return Some(pstr_loc_as_cell!(heap_index!(orig_h)));
}
@@ -420,7 +297,12 @@ impl<'a> ReservedHeapSection<'a> {
cursor: 0,
}];
while let Some(FunctorData { functor, cell_offset, mut cursor }) = functor_stack.pop() {
while let Some(FunctorData {
functor,
cell_offset,
mut cursor,
}) = functor_stack.pop()
{
while cursor < functor.len() {
match &functor[cursor] {
&FunctorElement::AbsoluteCell(cell) => {
@@ -460,15 +342,13 @@ impl<'a> ReservedHeapSection<'a> {
}
}
impl<'a> Index<usize> for ReservedHeapSection<'a> {
impl Index<usize> for ReservedHeapSection {
type Output = HeapCellValue;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(idx < self.heap_cell_len);
unsafe {
&*(self.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
}
unsafe { &*(self.heap_ptr as *const HeapCellValue).add(idx) }
}
}
@@ -489,7 +369,7 @@ fn pstr_sentinel_length(chunk_len: usize) -> usize {
#[must_use]
#[derive(Debug)]
pub struct HeapWriter<'a> {
section: ReservedHeapSection<'a>,
section: ReservedHeapSection,
heap_byte_len: &'a mut usize,
}
@@ -504,13 +384,12 @@ impl<'a> HeapWriter<'a> {
*self.heap_byte_len = heap_index!(self.section.heap_cell_len);
// return the number of bytes written
Ok(heap_index!(self.section.heap_cell_len - old_section_cell_len))
Ok(heap_index!(
self.section.heap_cell_len - old_section_cell_len
))
}
pub(crate) fn write_with(
&mut self,
writer: impl FnOnce(&mut ReservedHeapSection),
) -> usize {
pub(crate) fn write_with(&mut self, writer: impl FnOnce(&mut ReservedHeapSection)) -> usize {
let old_section_cell_len = self.section.heap_cell_len;
writer(&mut self.section);
*self.heap_byte_len = heap_index!(self.section.heap_cell_len);
@@ -522,7 +401,7 @@ impl<'a> HeapWriter<'a> {
#[inline]
pub(crate) fn truncate(&mut self, cell_offset: usize) {
self.section.heap_cell_len = cell_offset;
self.section.pstr_vec.truncate(cell_offset);
// self.section.pstr_vec.truncate(cell_offset);
*self.heap_byte_len = heap_index!(cell_offset);
}
@@ -543,9 +422,7 @@ impl<'a> Index<usize> for HeapWriter<'a> {
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(heap_index!(idx) < *self.heap_byte_len);
unsafe {
&*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
}
unsafe { &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) }
}
}
@@ -553,9 +430,7 @@ impl<'a> IndexMut<usize> for HeapWriter<'a> {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
debug_assert!(heap_index!(idx) < *self.heap_byte_len);
unsafe {
&mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue)
}
unsafe { &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue) }
}
}
@@ -564,17 +439,29 @@ impl<'a> SizedHeap for HeapWriter<'a> {
self.section.cell_len()
}
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
let (s, tail_cell_offset) = scan_slice_to_str(
unsafe { self.section.heap_ptr.add(slice_loc) },
&self.section.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
);
fn scan_slice_to_str(&self, slice_loc: usize) -> HeapStringScan {
let HeapStringScan { string, tail_idx } = unsafe {
let slice = std::slice::from_raw_parts(
self.section.heap_ptr.byte_add(slice_loc),
heap_index!(self.section.heap_cell_len) - slice_loc,
);
(s, cell_index!(slice_loc) + tail_cell_offset)
scan_slice_to_str(slice)
};
HeapStringScan {
string,
tail_idx: cell_index!(slice_loc) + tail_idx,
}
}
fn pstr_at(&self, cell_offset: usize) -> bool {
self.section.pstr_vec[cell_offset]
fn as_slice(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts(
self.section.heap_ptr,
heap_index!(self.section.heap_cell_len),
)
}
}
}
@@ -588,20 +475,23 @@ impl Heap {
byte_len: 0,
byte_cap: 0,
},
pstr_vec: bitvec![],
resource_err_loc: 0,
}
}
// takes a heap index, returns a cell index
#[inline]
pub const fn pstr_tail_idx(pstr_zero_byte_loc: usize) -> usize {
if (pstr_zero_byte_loc + 1) % Heap::heap_cell_alignment() == 0 {
cell_index!(pstr_zero_byte_loc) + 2
} else {
cell_index!(pstr_zero_byte_loc) + 1
}
}
#[inline(always)]
unsafe fn grow(&mut self) -> bool {
let result = self.inner.grow();
if result {
self.pstr_vec.reserve(cell_index!(self.inner.byte_cap));
}
result
self.inner.grow()
}
#[inline]
@@ -624,7 +514,7 @@ impl Heap {
byte_len: 0,
byte_cap: heap_index!(cap),
},
pstr_vec: bitvec![],
// pstr_vec: bitvec![],
resource_err_loc: 0,
})
}
@@ -641,7 +531,6 @@ impl Heap {
section = ReservedHeapSection {
heap_ptr: self.inner.ptr,
heap_cell_len: self.cell_len(),
pstr_vec: &mut self.pstr_vec,
};
break;
} else if !self.grow() {
@@ -656,28 +545,42 @@ impl Heap {
})
}
pub(crate) fn last_cell_mut(&mut self) -> Option<&mut HeapCellValue> {
if self.inner.byte_len == 0 {
None
} else {
unsafe {
Some(&mut *(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
as *mut HeapCellValue))
}
}
}
pub(crate) fn last_cell(&mut self) -> Option<HeapCellValue> {
if self.inner.byte_len == 0 {
None
} else {
unsafe {
Some(ptr::read(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
as *const HeapCellValue))
Some(ptr::read(
self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
as *const HeapCellValue,
))
}
}
}
pub(crate) fn append(&mut self, other_heap: &impl SizedHeap) -> Result<(), usize> {
let other_len = heap_index!(other_heap.cell_len());
loop {
if self.free_space() >= other_len {
let heap_slice = unsafe {
std::slice::from_raw_parts_mut(
self.inner.ptr.add(self.inner.byte_len),
other_len,
)
};
heap_slice.copy_from_slice(other_heap.as_slice());
self.inner.byte_len += heap_index!(other_heap.cell_len());
break;
} else if unsafe { !self.grow() } {
return Err(self.resource_error_offset());
}
}
Ok(())
}
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.inner.byte_len == 0
@@ -703,31 +606,31 @@ impl Heap {
self.inner.byte_len = 0;
self.inner.byte_cap = 0;
self.pstr_vec.clear();
// self.pstr_vec.clear();
}
pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> {
unsafe {
loop {
if self.free_space() >= heap_index!(heap_slice.slice_cell_len) {
ptr::copy_nonoverlapping(
heap_slice.slice,
self.inner.ptr.add(self.inner.byte_len),
heap_index!(heap_slice.slice_cell_len),
);
// pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> {
// unsafe {
// loop {
// if self.free_space() >= heap_index!(heap_slice.slice_cell_len) {
// ptr::copy_nonoverlapping(
// heap_slice.slice,
// self.inner.ptr.add(self.inner.byte_len),
// heap_index!(heap_slice.slice_cell_len),
// );
self.inner.byte_len += heap_index!(heap_slice.slice_cell_len);
self.pstr_vec.extend(heap_slice.pstr_slice.iter());
// self.inner.byte_len += heap_index!(heap_slice.slice_cell_len);
// // self.pstr_vec.extend(heap_slice.pstr_slice.iter());
break;
} else if !self.grow() {
return Err(self.resource_error_offset());
}
}
}
// break;
// } else if !self.grow() {
// return Err(self.resource_error_offset());
// }
// }
// }
Ok(())
}
// Ok(())
// }
pub(crate) fn store_resource_error(&mut self) {
RESOURCE_ERROR_OFFSET_INIT.call_once(move || {
@@ -763,11 +666,23 @@ impl Heap {
for ((idx, c1), c2) in str1.char_indices().zip(str2.chars()) {
if c1 == '\u{0}' && c2 == '\u{0}' {
return PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset: idx };
return PStrSegmentCmpResult::BothMatch {
pstr_loc1,
pstr_loc2,
null_offset: idx,
};
} else if c1 == '\u{0}' {
return PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset: idx };
return PStrSegmentCmpResult::FirstMatch {
pstr_loc1,
pstr_loc2,
l1_offset: idx,
};
} else if c2 == '\u{0}' {
return PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset: idx };
return PStrSegmentCmpResult::SecondMatch {
pstr_loc1,
pstr_loc2,
l2_offset: idx,
};
} else if c1 != c2 {
return PStrSegmentCmpResult::Mismatch { c1, c2 };
}
@@ -822,7 +737,7 @@ impl Heap {
// - Invariant: from `InnerHeap`, `self.inner.byte_cap < isize::MAX`.
let cell_ptr = (self.inner.ptr as *mut HeapCellValue).add(self.cell_len());
cell_ptr.write(cell);
self.pstr_vec.push(false);
// self.pstr_vec.push(false);
self.inner.byte_len += heap_index!(1);
}
@@ -866,6 +781,7 @@ impl Heap {
Range { start, end }
}
/*
pub(crate) fn splice<R: RangeBounds<usize>>(
&self,
range: R,
@@ -876,7 +792,7 @@ impl Heap {
slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
cell_offset: range.start,
slice_cell_len: range.end - range.start,
pstr_slice: &self.pstr_vec.as_bitslice()[range],
// pstr_slice: &self.pstr_vec.as_bitslice()[range],
}
}
@@ -890,9 +806,10 @@ impl Heap {
slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
cell_offset: range.start,
slice_cell_len: range.end - range.start,
pstr_slice: &self.pstr_vec.as_bitslice()[range],
// pstr_slice: &self.pstr_vec.as_bitslice()[range],
}
}
*/
pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
let size_in_heap = Self::compute_pstr_size(src);
@@ -911,39 +828,18 @@ impl Heap {
})
}
const fn heap_cell_alignment() -> usize {
pub const fn heap_cell_alignment() -> usize {
// yes, size_of, not align_of. the alignment of HeapCellValue
// is 1 byte. In the heap, though, its alignment must be its
// size.
mem::size_of::<HeapCellValue>()
}
// takes a byte offset into the Heap ptr.
#[inline(always)]
pub(crate) const fn neighboring_cell_offset(offset: usize) -> usize {
cell_index!((offset & !(ALIGN - 1)) + ALIGN)
}
#[inline]
pub(crate) fn iter(&self) -> HeapView {
HeapView {
slice: self.inner.ptr,
cell_offset: 0,
slice_cell_len: cell_index!(self.inner.byte_len),
pstr_slice: &self.pstr_vec.as_bitslice(),
}
}
#[inline]
pub(crate) fn pstr_vec(&self) -> &BitSlice<usize> {
self.pstr_vec.as_bitslice()
size_of::<HeapCellValue>()
}
#[inline]
pub(crate) fn char_at(&self, byte_idx: usize) -> char {
let s = unsafe {
let char_ptr = self.inner.ptr.add(byte_idx);
let slice = std::slice::from_raw_parts(char_ptr, mem::size_of::<char>());
let slice = std::slice::from_raw_parts(char_ptr, size_of::<char>());
std::str::from_utf8_unchecked(&slice)
};
@@ -961,7 +857,7 @@ impl Heap {
let succ_len = loc + c.len_utf8();
if chars_iter.next() == Some('\u{0}') {
(c, heap_loc_as_cell!(Self::neighboring_cell_offset(succ_len)))
(c, heap_loc_as_cell!(Self::pstr_tail_idx(succ_len)))
} else {
(c, pstr_loc_as_cell!(succ_len))
}
@@ -971,8 +867,8 @@ impl Heap {
// copies only the string, not its tail. returns the cell index of
// the tail location
pub(crate) fn copy_pstr_within(&mut self, pstr_loc: usize) -> Result<usize, usize> {
let (s, tail_loc) = self.scan_slice_to_str(pstr_loc);
let s_len = s.len();
let HeapStringScan { string, tail_idx } = self.scan_slice_to_str(pstr_loc);
let s_len = string.len();
let align_offset = pstr_sentinel_length(s_len);
let copy_size = s_len + align_offset;
@@ -980,15 +876,10 @@ impl Heap {
unsafe {
loop {
if self.free_space() >= copy_size {
let slice = std::slice::from_raw_parts_mut(
self.inner.ptr,
self.inner.byte_len + s_len,
);
let slice =
std::slice::from_raw_parts_mut(self.inner.ptr, self.inner.byte_len + s_len);
slice.copy_within(
pstr_loc .. pstr_loc + s_len,
self.inner.byte_len,
);
slice.copy_within(pstr_loc..pstr_loc + s_len, self.inner.byte_len);
ptr::write_bytes(
self.inner.ptr.add(self.inner.byte_len + s_len),
@@ -996,8 +887,17 @@ impl Heap {
align_offset,
);
self.inner.byte_len += copy_size;
self.pstr_vec.resize(self.cell_len(), true);
if align_offset == 1 {
ptr::write_bytes(
self.inner.ptr.add(self.inner.byte_len + copy_size),
0u8,
size_of::<HeapCellValue>(),
);
self.inner.byte_len += copy_size + heap_index!(1);
} else {
self.inner.byte_len += copy_size;
}
break;
} else if !self.grow() {
@@ -1006,7 +906,7 @@ impl Heap {
}
}
Ok(tail_loc)
Ok(tail_idx)
}
// src is a cell-indexed range.
@@ -1023,7 +923,7 @@ impl Heap {
heap_index!(len),
);
self.pstr_vec.resize(self.cell_len() + len, false);
// self.pstr_vec.resize(self.cell_len() + len, false);
self.inner.byte_len += heap_index!(len);
break;
@@ -1059,10 +959,14 @@ impl Heap {
byte_size += null_idx + pstr_sentinel_length(null_idx);
// each partial string must be buffered from its tail cell
// by at least two null bytes so one of them may be used
// to mark partial strings e.g. during iteration
if (null_idx + 1) % ALIGN == 0 {
byte_size += 2 * mem::size_of::<HeapCellValue>();
byte_size += 2 * size_of::<HeapCellValue>();
} else {
byte_size += mem::size_of::<HeapCellValue>();
byte_size += size_of::<HeapCellValue>();
}
if null_idx + 1 >= src.len() {
@@ -1082,13 +986,13 @@ impl Heap {
while idx < functor.len() {
match &functor[idx] {
&FunctorElement::InnerFunctor(inner_cell_size, ref _inner_functor) => {
byte_size += inner_cell_size as usize * mem::size_of::<HeapCellValue>();
byte_size += inner_cell_size as usize * size_of::<HeapCellValue>();
}
FunctorElement::AbsoluteCell(_cell) | FunctorElement::Cell(_cell) => {
byte_size += mem::size_of::<HeapCellValue>();
byte_size += size_of::<HeapCellValue>();
}
&FunctorElement::String(cell_len, _) => {
byte_size += cell_len as usize * mem::size_of::<HeapCellValue>();
byte_size += cell_len as usize * size_of::<HeapCellValue>();
}
}
@@ -1120,12 +1024,10 @@ impl Heap {
#[inline]
pub(crate) fn truncate(&mut self, cell_offset: usize) {
self.inner.byte_len = heap_index!(cell_offset);
self.pstr_vec.truncate(cell_offset);
// self.pstr_vec.truncate(cell_offset);
}
}
pub(crate) struct PStrSegmentIter<'a> {
string_buf: &'a str,
}
@@ -1153,7 +1055,7 @@ impl<'a> Iterator for PStrSegmentIter<'a> {
if c == '\u{0}' {
None
} else {
self.string_buf = &self.string_buf[c.len_utf8() ..];
self.string_buf = &self.string_buf[c.len_utf8()..];
Some(c)
}
})
@@ -1187,14 +1089,15 @@ pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
fn cell_len(&self) -> usize;
// return a pointer to the heap string and the cell index of its tail
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize);
fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a>;
fn as_slice(&self) -> &[u8];
// return true iff a partial string is stored at cell_offset.
fn pstr_at(&self, cell_offset: usize) -> bool;
// fn pstr_at(&self, cell_offset: usize) -> bool;
}
pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {
}
pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {}
impl Index<usize> for Heap {
type Output = HeapCellValue;
@@ -1215,62 +1118,29 @@ impl SizedHeap for Heap {
self.cell_len()
}
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
let (s, tail_cell_offset) = scan_slice_to_str(
unsafe { self.inner.ptr.add(slice_loc) },
&self.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
);
fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a> {
let HeapStringScan { string, tail_idx } = unsafe {
let slice = std::slice::from_raw_parts(
self.inner.ptr.add(slice_loc),
self.inner.byte_len - slice_loc,
);
(s, cell_index!(slice_loc) + tail_cell_offset)
scan_slice_to_str(slice)
};
HeapStringScan {
string,
tail_idx: cell_index!(slice_loc) + tail_idx,
}
}
fn pstr_at(&self, cell_offset: usize) -> bool {
self.pstr_vec[cell_offset]
fn as_slice(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.inner.ptr, self.inner.byte_len) }
}
}
impl SizedHeapMut for Heap {}
impl<'a> SizedHeap for HeapView<'a> {
fn cell_len(&self) -> usize {
self.slice_cell_len
}
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
let (s, tail_cell_offset) = scan_slice_to_str(
unsafe { self.slice.add(slice_loc) },
&self.pstr_slice[cell_index!(slice_loc) ..],
);
(s, cell_index!(slice_loc) + tail_cell_offset)
}
fn pstr_at(&self, cell_offset: usize) -> bool {
self.pstr_slice[cell_offset]
}
}
impl<'a> SizedHeap for HeapViewMut<'a> {
fn cell_len(&self) -> usize {
self.slice_cell_len
}
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
let (s, tail_cell_offset) = scan_slice_to_str(
unsafe { self.slice.add(slice_loc) },
&self.pstr_slice[cell_index!(slice_loc) ..],
);
(s, cell_index!(slice_loc) + tail_cell_offset)
}
fn pstr_at(&self, cell_offset: usize) -> bool {
self.pstr_slice[cell_offset]
}
}
impl<'a> SizedHeapMut for HeapViewMut<'a> {}
// sometimes we need to dereference variables that are found only in
// the heap without access to the full WAM (e.g., while detecting
// cycles in terms), and which therefore may only point other cells in
@@ -1307,9 +1177,10 @@ pub fn heap_bound_store(heap: &impl SizedHeap, value: HeapCellValue) -> HeapCell
}
#[allow(dead_code)]
pub fn print_heap_terms<'a, I: Iterator<Item = HeapCellValue>>(heap: I, h: usize) {
for (index, term) in heap.enumerate() {
println!("{} : {:?}", h + index, term);
pub fn print_heap_terms(heap: &Heap, h: usize) {
for idx in 0..heap.cell_len() {
let term = heap[idx];
println!("{} : {:?}", h + idx, term);
}
}

View File

@@ -1,4 +1,3 @@
use std::cmp::Ordering;
use std::collections::BTreeMap;
use crate::atom_table;
@@ -442,7 +441,7 @@ impl Iterator for QueryState<'_> {
if let Err(resource_err_loc) = machine
.machine_st
.heap
.append(machine.machine_st.ball.stub.splice(..))
.append(&machine.machine_st.ball.stub)
{
return Some(Err(Term::from_heapcell(
machine,
@@ -530,10 +529,10 @@ impl Machine {
/// Consults a module into the [`Machine`] from a string.
pub fn consult_module_string(&mut self, module_name: &str, program: impl Into<String>) {
let stream = Stream::from_owned_string(program.into(), &mut self.machine_st.arena);
self.machine_st.registers[1] = stream.into();
self.machine_st.registers[2] = atom_as_cell!(&atom_table::AtomTable::build_with(
self.machine_st.registers[1] = stream_as_cell!(stream);
self.machine_st.registers[2] = atom_as_cell!(atom_table::AtomTable::build_with(
&self.machine_st.atom_tbl,
module_name
module_name,
));
self.run_module_predicate(atom!("loader"), (atom!("consult_stream"), 2));

View File

@@ -27,15 +27,14 @@ impl TermWriteResult {
heap[0] = value;
let inverse_var_locs = inverse_var_locs_from_iter(
stackful_preorder_iter::<NonListElider>(
heap,
&mut stack,
0,
),
);
let inverse_var_locs = inverse_var_locs_from_iter(stackful_preorder_iter::<NonListElider>(
heap, &mut stack, 0,
));
Ok(Self { focus, inverse_var_locs })
Ok(Self {
focus,
inverse_var_locs,
})
}
}
@@ -529,9 +528,10 @@ 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
});
let predicate_focus_opt = load_state
.predicates
.first()
.map(|term_write_result| term_write_result.focus);
let machine_st = LS::machine_st(&mut self.payload);
let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus);
@@ -1072,10 +1072,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let cell = machine_st[r];
let focus = machine_st.heap.cell_len();
machine_st.heap.push_cell(cell)
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 = FocusedHeapRefMut {
heap: &mut machine_st.heap,
focus,
};
let export_list = setup_module_export_list(export_list)?;
Ok(export_list.into_iter().collect())
@@ -1129,8 +1134,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
);
Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?)
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(
@@ -1628,18 +1635,15 @@ impl Machine {
};
let value = self.machine_st.registers[2];
let term = resource_error_call_result!(
let term = resource_error_call_result!(
self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value)
);
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((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,
};
@@ -2240,9 +2244,11 @@ 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 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);
@@ -2253,7 +2259,7 @@ impl Machine {
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
(!loader.payload.predicates.is_empty()
&& loader.payload.predicates.compilation_target != compilation_target)
&& loader.payload.predicates.compilation_target != compilation_target)
|| !is_consistent;
let result = LiveLoadAndMachineState::evacuate(loader);

View File

@@ -187,7 +187,11 @@ impl PermissionError for HeapCellValue {
let stub = functor!(
atom!("permission_error"),
[atom_as_cell((perm.as_atom())), atom_as_cell(index_atom), cell(cell)]
[
atom_as_cell((perm.as_atom())),
atom_as_cell(index_atom),
cell(cell)
]
);
MachineError {
@@ -226,7 +230,10 @@ 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_as_cell((error.as_atom())), cell(self)]);
let stub = functor!(
atom!("domain_error"),
[atom_as_cell((error.as_atom())), cell(self)]
);
MachineError {
stub,
@@ -239,7 +246,10 @@ impl DomainError for Number {
fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(
atom!("domain_error"),
[atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))]
[
atom_as_cell((error.as_atom())),
number(self, (&mut machine_st.arena))
]
);
MachineError {
@@ -280,7 +290,10 @@ impl MachineState {
}
pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError {
let stub = functor!(atom!("evaluation_error"), [atom_as_cell((eval_error.as_atom()))]);
let stub = functor!(
atom!("evaluation_error"),
[atom_as_cell((eval_error.as_atom()))]
);
MachineError {
stub,
@@ -297,7 +310,10 @@ impl MachineState {
)
}
ResourceError::OutOfFiles => {
functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))])
functor!(
atom!("resource_error"),
[atom_as_cell((atom!("file_descriptors")))]
)
}
};
@@ -480,12 +496,12 @@ impl MachineState {
SessionError::CannotOverwriteBuiltIn(key) => self.permission_error(
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1)
functor_stub(key.0, key.1),
),
SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1)
functor_stub(key.0, key.1),
),
SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(Permission::Modify, atom!("static_module"), module)
@@ -559,14 +575,14 @@ impl MachineState {
let stub = functor!(atom!("syntax_error"), [functor(stub)]);
MachineError {
stub,
location,
}
MachineError { stub, location }
}
pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]);
let stub = functor!(
atom!("representation_error"),
[atom_as_cell((flag.as_atom()))]
);
MachineError {
stub,
@@ -593,13 +609,19 @@ impl MachineState {
}
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))])])
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 {
functor!(atom!("error"), [functor((err.stub)),
functor(src)])
functor!(atom!("error"), [functor((err.stub)), functor(src)])
}
}
@@ -826,13 +848,29 @@ impl EvalError {
// used by '$skip_max_list'.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CycleSearchResult {
Cyclic { lambda: usize }, // number of steps
Cyclic {
lambda: usize,
}, // number of steps
EmptyList,
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 },
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 {
@@ -856,7 +894,9 @@ 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()))
}
@@ -868,7 +908,9 @@ 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()))
}

View File

@@ -37,7 +37,7 @@ pub(super) enum MachineMode {
pub(super) enum HeapPtr {
HeapCell(usize),
PStr(usize), // Char(usize),
// PStrLocation(usize),
// PStrLocation(usize),
}
impl Default for HeapPtr {
@@ -215,7 +215,8 @@ fn push_var_eq_functors(
let mut writer = heap.reserve(1 + 5 * size)?;
writer.write_with(|section| {
for (var_loc, var) in iter { // (var, binding) in iter {
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);
@@ -224,7 +225,7 @@ fn push_var_eq_functors(
section.push_cell(binding);
}
for idx in 0 .. size {
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));
}
@@ -252,6 +253,7 @@ pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
#[derive(Debug)]
pub struct Ball {
pub(super) boundary: usize,
pub(super) pstr_boundary: usize,
pub(super) stub: Heap,
}
@@ -259,12 +261,14 @@ impl Ball {
pub(super) fn new() -> Self {
Ball {
boundary: 0,
pstr_boundary: 0,
stub: Heap::new(),
}
}
pub(super) fn reset(&mut self) {
self.boundary = 0;
self.pstr_boundary = 0;
self.stub.clear();
}
@@ -272,10 +276,23 @@ impl Ball {
let h = dest.cell_len();
let diff = self.boundary as i64 - h as i64;
dest.append(self.stub.splice(..))?;
let mut dest_writer = dest.reserve(self.stub.cell_len())?;
for cell in &mut dest.splice_mut(h ..) {
*cell = *cell - diff;
dest_writer.write_with(|section| {
for idx in 0..self.pstr_boundary {
section.push_cell(self.stub[idx] - diff);
}
});
let mut pstr_threshold = heap_index!(self.pstr_boundary);
while pstr_threshold < heap_index!(self.stub.cell_len()) {
let HeapStringScan { string, tail_idx } = self.stub.scan_slice_to_str(pstr_threshold);
pstr_threshold += dest_writer.write_with(|section| {
section.push_pstr(string).unwrap();
section.push_cell(self.stub[tail_idx] - diff);
});
}
Ok(h)
@@ -335,32 +352,16 @@ impl<'a> CopierTarget for CopyTerm<'a> {
self.state.heap.cell_len()
}
#[inline(always)]
fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
Box::new(self.state.heap.as_slice()[from..].iter().cloned())
}
#[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)
@@ -469,9 +470,22 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
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);
let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(pstr_loc);
self.stub.allocate_pstr(string)?;
Ok(tail_loc)
Ok(tail_idx)
}
fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
if from < self.heap.byte_len() {
Box::new(
self.heap.as_slice()[from..]
.iter()
.cloned()
.chain(self.stub.as_slice().iter().cloned()),
)
} else {
Box::new(self.stub.as_slice()[from..].iter().cloned())
}
}
#[inline]
@@ -479,41 +493,6 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
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)?;
@@ -699,9 +678,9 @@ impl MachineState {
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())
}),
var_list
.iter()
.map(|(var_name, var, _)| { (var.get_value() as usize, var_name.clone()) }),
&self.atom_tbl,
)
);
@@ -737,7 +716,9 @@ impl MachineState {
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus) {
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() {
@@ -756,9 +737,10 @@ impl MachineState {
singleton_var_set
.iter()
.filter(|(var, is_singleton)| {
**is_singleton && term.inverse_var_locs.contains_key(
&(var.get_value() as usize)
)
**is_singleton
&& term
.inverse_var_locs
.contains_key(&(var.get_value() as usize))
})
.count(),
term.inverse_var_locs
@@ -873,7 +855,8 @@ impl MachineState {
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? {
OnEOF::Return => {
return self.write_read_term_options(vec![], empty_list_as_cell!());
return self
.write_read_term_options(vec![], empty_list_as_cell!());
}
OnEOF::Continue => continue,
}
@@ -1012,11 +995,9 @@ impl MachineState {
let term_loc = self.heap.cell_len();
step_or_resource_error!(
self,
self.heap.push_cell(term_to_be_printed),
{ return Ok(None); }
);
step_or_resource_error!(self, self.heap.push_cell(term_to_be_printed), {
return Ok(None);
});
let mut printer = HCPrinter::new(
&mut self.heap,

View File

@@ -327,9 +327,9 @@ impl MachineState {
self.ball.reset();
let addr = self.registers[1];
let ball_boundary = self.heap.cell_len();
step_or_resource_error!(
self.ball.boundary = self.heap.cell_len();
self.ball.pstr_boundary = step_or_resource_error!(
self,
copy_term(
CopyBallTerm::new(
@@ -342,8 +342,6 @@ impl MachineState {
AttrVarPolicy::DeepCopy,
)
);
self.ball.boundary = ball_boundary;
}
#[inline(always)]
@@ -359,14 +357,14 @@ impl MachineState {
HeapPtr::PStr(h) => {
let mut char_iter = self.heap.char_iter(h);
if self.s_offset == 0 { // read the car of the list
if self.s_offset == 0 {
// read the car of the list
let c = char_iter.next().unwrap();
char_as_cell!(c)
} else { // read the (self.s_offset)^{th} cdr of the list
let byte_offset: usize = char_iter
.take(self.s_offset)
.map(|c| c.len_utf8())
.sum();
} else {
// read the (self.s_offset)^{th} cdr of the list
let byte_offset: usize =
char_iter.take(self.s_offset).map(|c| c.len_utf8()).sum();
let new_h = h + byte_offset;
self.s_offset = 0;
@@ -375,7 +373,7 @@ impl MachineState {
self.s = HeapPtr::PStr(new_h);
pstr_loc_as_cell!(new_h)
} else {
let h = Heap::neighboring_cell_offset(new_h);
let h = Heap::pstr_tail_idx(new_h);
self.s = HeapPtr::HeapCell(h);
self.deref(heap_loc_as_cell!(h))
}
@@ -946,7 +944,7 @@ impl MachineState {
if char_iter.next().is_some() {
unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3);
} else {
let tail_idx = Heap::neighboring_cell_offset(pstr_loc);
let tail_idx = Heap::pstr_tail_idx(pstr_loc);
unify_fn!(*self, self.heap[tail_idx]);
}
@@ -1044,7 +1042,12 @@ impl MachineState {
}
}
fn try_functor_fabricate_struct(&mut self, name: Atom, arity: usize, r: Ref) -> Result<(), usize> {
fn try_functor_fabricate_struct(
&mut self,
name: Atom,
arity: usize,
r: Ref,
) -> Result<(), usize> {
let h = self.heap.cell_len();
let mut writer = self.heap.reserve(arity + 1)?;
@@ -1144,7 +1147,7 @@ impl MachineState {
};
read_heap_cell!(store_name,
(HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char |
(HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char |
HeapCellValueTag::F64) if arity == 0 => {
self.bind(a1.as_var().unwrap(), deref_name);
}

View File

@@ -51,14 +51,12 @@ 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.splice(..), term_write_result.focus);
print_heap_terms(&self.machine_st.heap, term_write_result.focus);
let var_names = term_write_result
.inverse_var_locs
.iter()
.map(|(var_loc, var_name)| {
(self.machine_st.heap[*var_loc], var_name.clone())
})
.map(|(var_loc, var_name)| (self.machine_st.heap[*var_loc], var_name.clone()))
.collect();
let mut printer = HCPrinter::new(
@@ -90,6 +88,7 @@ pub struct TermCopyingMockWAM<'a> {
impl<'a> Index<usize> for TermCopyingMockWAM<'a> {
type Output = HeapCellValue;
#[inline]
fn index(&self, index: usize) -> &HeapCellValue {
&self.wam.machine_st.heap[index]
}
@@ -107,6 +106,7 @@ impl<'a> IndexMut<usize> for TermCopyingMockWAM<'a> {
impl<'a> Deref for TermCopyingMockWAM<'a> {
type Target = MockWAM;
#[inline]
fn deref(&self) -> &Self::Target {
self.wam
}
@@ -114,6 +114,7 @@ impl<'a> Deref for TermCopyingMockWAM<'a> {
#[cfg(test)]
impl<'a> DerefMut for TermCopyingMockWAM<'a> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.wam
}
@@ -170,26 +171,8 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
}
#[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()
fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
Box::new(self.wam.machine_st.heap.as_slice()[from..].iter().cloned())
}
#[inline(always)]
@@ -204,20 +187,9 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
}
#[cfg(test)]
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]
};
pub fn all_cells_marked_and_unforwarded(heap: &Heap, offset: usize) {
for curr_idx in offset..heap.cell_len() {
let cell = heap[curr_idx];
assert!(
cell.get_mark_bit(),
@@ -235,43 +207,21 @@ pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
}
#[cfg(test)]
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;
}
pub fn unmark_all_cells(heap: &mut Heap, offset: usize) {
for idx in offset..heap.cell_len() {
heap[idx].set_mark_bit(false);
}
}
#[cfg(test)]
pub fn all_cells_unmarked(iter: impl SizedHeap) {
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]
};
idx += 1;
let cell = iter[curr_idx];
assert!(
!cell.get_mark_bit(),
@@ -354,7 +304,7 @@ mod tests {
assert!(wam.fail);
}
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.fail = false;
wam.heap.clear();
@@ -375,7 +325,7 @@ mod tests {
assert!(!wam.fail);
}
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.fail = false;
wam.heap.clear();
@@ -396,7 +346,7 @@ mod tests {
assert!(!wam.fail);
}
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.fail = false;
wam.heap.clear();
@@ -417,7 +367,7 @@ mod tests {
assert!(!wam.fail);
}
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.fail = false;
wam.heap.clear();
@@ -438,7 +388,7 @@ mod tests {
assert!(!wam.fail);
}
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.fail = false;
wam.heap.clear();
@@ -450,7 +400,7 @@ 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.splice(..));
all_cells_unmarked(&wam.heap);
unify!(
wam,
@@ -461,7 +411,7 @@ mod tests {
assert!(!wam.fail);
}
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap.clear();
@@ -489,9 +439,15 @@ mod tests {
assert!(!wam.fail);
assert_eq!(wam.heap.slice_to_str(heap_index!(0), "this is a string".len()),
"this is a string");
assert_eq!(wam.heap[3], pstr_loc_as_cell!(heap_index!(8)));
all_cells_unmarked(wam.heap.splice(..));
assert_eq!(wam.heap.slice_to_str(heap_index!(4), "this is a string".len()),
"this is a string");
assert_eq!(wam.heap[7], pstr_loc_as_cell!(heap_index!(8)));
assert_eq!(wam.heap.slice_to_str(heap_index!(8), "this is a string".len()),
"this is a string");
assert_eq!(wam.heap[11], pstr_loc_as_cell!(heap_index!(8)));
wam.heap.clear();
@@ -515,7 +471,7 @@ mod tests {
assert!(!wam.fail);
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap.clear();
@@ -540,7 +496,7 @@ mod tests {
assert!(wam.fail);
wam.fail = false;
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap.clear();
@@ -562,7 +518,7 @@ mod tests {
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(!wam.fail);
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
}
#[test]
@@ -581,7 +537,7 @@ 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.splice(..));
all_cells_unmarked(&wam.heap);
unify_with_occurs_check!(
wam,
@@ -632,11 +588,7 @@ mod tests {
let cstr_cell = wam.allocate_cstr("string").unwrap();
assert_eq!(
compare_term_test!(
wam,
atom_as_cell!(atom!("atom")),
cstr_cell
),
compare_term_test!(wam, atom_as_cell!(atom!("atom")), cstr_cell),
Some(Ordering::Less)
);
@@ -735,11 +687,7 @@ mod tests {
let cstr_cell = wam.allocate_cstr("string").unwrap();
assert_eq!(
compare_term_test!(
wam,
empty_list_as_cell!(),
cstr_cell
),
compare_term_test!(wam, empty_list_as_cell!(), cstr_cell),
Some(Ordering::Less)
);
@@ -782,16 +730,13 @@ mod tests {
assert!(!wam.is_cyclic_term(1));
assert!(!wam.is_cyclic_term(2));
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap.clear();
let mut functor_writer = Heap::functor_writer(
functor!(
atom!("f"),
[atom_as_cell((atom!("a"))),
atom_as_cell((atom!("b")))]
),
);
let mut functor_writer = Heap::functor_writer(functor!(
atom!("f"),
[atom_as_cell((atom!("a"))), atom_as_cell((atom!("b")))]
));
functor_writer(&mut wam.heap).unwrap();
@@ -800,30 +745,30 @@ mod tests {
assert!(!wam.is_cyclic_term(h));
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
assert!(!wam.is_cyclic_term(1));
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
assert!(!wam.is_cyclic_term(2));
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap[2] = str_loc_as_cell!(0);
print_heap_terms(wam.heap.iter(), 0);
print_heap_terms(&wam.heap, 0);
assert!(wam.is_cyclic_term(2));
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap[2] = atom_as_cell!(atom!("b"));
wam.heap[1] = str_loc_as_cell!(0);
assert!(wam.is_cyclic_term(1));
all_cells_unmarked(wam.heap.splice(..));
all_cells_unmarked(&wam.heap);
wam.heap.clear();

View File

@@ -508,7 +508,8 @@ 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);
@@ -1113,6 +1114,7 @@ impl Machine {
if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
self.try_execute(name, arity, idx.get())
} else {
println!("aaand undefined!");
self.undefined_procedure(name, arity)
}
} else if let Some(module) = self.indices.modules.get(&module_name) {

View File

@@ -19,9 +19,17 @@ pub struct HeapPStrIter<'a> {
#[derive(Debug, Clone, Copy)]
pub enum PStrCmpResult<'a> {
ListMatch { list_loc: usize },
CompletePStrMatch { chars_matched: usize, pstr_loc: usize },
PartialPStrMatch { string: &'a str, var_loc: usize },
ListMatch {
list_loc: usize,
},
CompletePStrMatch {
chars_matched: usize,
pstr_loc: usize,
},
PartialPStrMatch {
string: &'a str,
var_loc: usize,
},
}
struct PStrIterStep {
@@ -81,7 +89,7 @@ impl<'a> HeapPStrIter<'a> {
if s.is_empty() {
return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h });
} else {
let next_hare = Heap::neighboring_cell_offset(h + bytes_matched);
let next_hare = Heap::pstr_tail_idx(h + bytes_matched);
curr_hare = next_hare;
}
}
@@ -179,11 +187,11 @@ impl<'a> HeapPStrIter<'a> {
loop {
read_heap_cell!(self.heap[curr_hare],
(HeapCellValueTag::PStrLoc, h) => {
let (s, tail_loc) = self.heap.scan_slice_to_str(h);
let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(h);
return Ok(PStrIterStep {
iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: s.len() },
next_hare: tail_loc,
iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: string.len() },
next_hare: tail_idx,
});
}
(HeapCellValueTag::Lis, h) => {
@@ -319,7 +327,10 @@ impl<'a> Iterator for PStrCharsIter<'a> {
self.item = self.iter.next();
return Some(value);
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
PStrIteratee::PStrSlice {
slice_loc,
slice_len,
} => {
let s = self.iter.heap.slice_to_str(slice_loc, slice_len);
match s.chars().next() {
@@ -353,7 +364,10 @@ mod test {
let mut wam = MockWAM::new();
let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
wam.machine_st.heap.push_cell(empty_list_as_cell!()).unwrap();
wam.machine_st
.heap
.push_cell(empty_list_as_cell!())
.unwrap();
// not overwriting anything! 0 is an interstitial cell
// reserved for use by the runtime
@@ -364,7 +378,10 @@ mod test {
assert_eq!(
iter.next(),
Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }),
Some(PStrIteratee::PStrSlice {
slice_loc: heap_index!(1),
slice_len: "abc ".len()
}),
);
assert_eq!(iter.next(), None);
assert!(!iter.is_cyclic());
@@ -384,7 +401,10 @@ mod test {
assert_eq!(
iter.next(),
Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
Some(PStrIteratee::PStrSlice {
slice_loc: heap_index!(1),
slice_len: "abc ".len()
})
);
assert_eq!(
iter.next(),
@@ -407,7 +427,10 @@ mod test {
assert_eq!(
iter.next(),
Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
Some(PStrIteratee::PStrSlice {
slice_loc: heap_index!(1),
slice_len: "abc ".len()
})
);
assert_eq!(
iter.next(),
@@ -552,7 +575,11 @@ mod test {
section.push_cell(heap_loc_as_cell!(h));
});
unify!(wam.machine_st, pstr_cell, pstr_loc_as_cell!(heap_index!(start)));
unify!(
wam.machine_st,
pstr_cell,
pstr_loc_as_cell!(heap_index!(start))
);
assert!(!wam.machine_st.fail);
@@ -561,7 +588,9 @@ mod test {
"abcdef"
);
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(start), "abc".len()),
wam.machine_st
.heap
.slice_to_str(heap_index!(start), "abc".len()),
"abc"
);
assert_eq!(
@@ -587,7 +616,10 @@ mod test {
assert_eq!(
iter.next(),
Some(PStrIteratee::PStrSlice { slice_loc: 'a'.len_utf8(), slice_len: "bc".len() })
Some(PStrIteratee::PStrSlice {
slice_loc: 'a'.len_utf8(),
slice_len: "bc".len()
})
);
for _ in iter {}
@@ -609,7 +641,11 @@ mod test {
section.push_cell(empty_list_as_cell!());
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert!(!wam.machine_st.fail);
@@ -629,7 +665,11 @@ mod test {
section.push_cell(empty_list_as_cell!());
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert!(!wam.machine_st.fail);
@@ -652,7 +692,11 @@ mod test {
section.push_cell(empty_list_as_cell!());
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b'));
@@ -676,7 +720,11 @@ mod test {
section.push_cell(empty_list_as_cell!());
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert!(!wam.machine_st.fail);
@@ -699,10 +747,17 @@ mod test {
section.push_cell(heap_loc_as_cell!(5 + start));
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert_eq!(wam.machine_st.heap[5 + start], pstr_loc_as_cell!(heap_index!(0) + 3));
assert_eq!(
wam.machine_st.heap[5 + start],
pstr_loc_as_cell!(heap_index!(0) + 3)
);
assert!(!wam.machine_st.fail);
// #2293, test6.
@@ -723,7 +778,11 @@ mod test {
section.push_cell(empty_list_as_cell!());
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c'));
@@ -750,7 +809,11 @@ mod test {
section.push_cell(empty_list_as_cell!());
});
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
unify!(
wam.machine_st,
list_loc_as_cell!(start),
pstr_loc_as_cell!(0)
);
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('b'));
assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d'));

View File

@@ -28,26 +28,26 @@ 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_predicate_key(term.heap, focus+3) {
let name = match term_predicate_key(term.heap, focus + 3) {
Some((name, 0)) => name,
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]),
DirectiveError::InvalidOpDeclNameType(term.heap[focus + 3]),
));
}
};
let spec = match term_predicate_key(term.heap, focus+2) {
let spec = match term_predicate_key(term.heap, focus + 2) {
Some((name, _)) => name,
None => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]),
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]),
));
}
};
let spec = to_op_decl_spec(spec)?;
let prec = term.deref_loc(focus+1);
let prec = term.deref_loc(focus + 1);
let prec = read_heap_cell!(prec,
(HeapCellValueTag::Fixnum, n) => {
@@ -147,34 +147,34 @@ 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,
};
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)?);
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)
@@ -281,7 +281,7 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
* contained in src/lib/ops_and_meta_predicates.pl, which is loaded before
* src/lib/builtins.pl.
*
* Meta-specs have three forms:
* Meta-specs have four forms:
*
* (:) (the argument should be expanded with (:)/2 as described above)
* + (mode declarations under the mode syntax, which currently have no effect)
@@ -334,7 +334,7 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
}
let heap = loader.machine_heap();
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus+1]));
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus + 1]));
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
@@ -506,28 +506,27 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
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_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, arity + supp_args),
qualified_term_loc,
),
None => {
continue;
}
let (module_name, key, term_loc) = 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, arity + supp_args), qualified_term_loc),
None => {
continue;
}
} else {
(module_name, (name, arity + supp_args), subterm_loc)
};
}
} else {
(module_name, (name, arity + supp_args), subterm_loc)
};
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), key.1, term_loc) {
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), term_loc) {
index_ptrs.insert(term_loc, index_ptr);
continue;
}
@@ -642,7 +641,12 @@ impl Preprocessor {
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))
Ok((
Fact {
term_loc: term.focus,
},
var_data,
))
} else {
Err(CompilationError::InadmissibleFact)
}
@@ -660,7 +664,13 @@ impl Preprocessor {
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))
Ok((
Rule {
term_loc: term.focus,
clauses,
},
var_data,
))
} else {
Err(CompilationError::InvalidRuleHead)
}

View File

@@ -181,10 +181,7 @@ fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usi
byte_offset += c.len_utf8();
}
(
char_count,
Heap::neighboring_cell_offset(pstr_loc + byte_offset),
)
(char_count, Heap::pstr_tail_idx(pstr_loc + byte_offset))
}
fn pstr_segment_char_count_up_to(
@@ -217,10 +214,9 @@ fn pstr_segment_char_count_up_to(
pstr_loc: pstr_loc + byte_offset,
}
} else {
let tail_loc = Heap::neighboring_cell_offset(pstr_loc + byte_offset);
PStrSegmentCountResult::End {
char_count,
tail_loc,
tail_loc: Heap::pstr_tail_idx(pstr_loc + byte_offset),
}
}
}
@@ -567,6 +563,12 @@ struct AttrListMatch {
prev_tail: Option<usize>,
}
#[derive(Debug)]
pub(crate) struct FindallCopyInfo {
offset: usize,
pstr_threshold: usize,
}
impl MachineState {
#[inline(always)]
pub(crate) fn unattributed_var(&mut self) {
@@ -648,9 +650,8 @@ impl MachineState {
loop {
read_heap_cell!(value,
(HeapCellValueTag::PStrLoc, h) => {
let (_, tail) = heap.scan_slice_to_str(h);
// let (h_offset, _) = pstr_loc_and_offset(heap, h);
return tail;
let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
return tail_idx;
}
(HeapCellValueTag::Lis, h) => {
return h+1;
@@ -855,17 +856,10 @@ impl MachineState {
&mut self,
lh_offset: usize,
copy_target: HeapCellValue,
) -> Result<usize, usize> {
) -> Result<FindallCopyInfo, usize> {
let threshold = self.lifted_heap.cell_len() - lh_offset;
let mut copy_ball_term = CopyBallTerm::new(
&mut self.attr_var_init.attr_var_queue,
&mut self.stack,
&mut self.heap,
&mut self.lifted_heap,
);
let mut writer = copy_ball_term.reserve(3)?;
let mut writer = self.lifted_heap.reserve(3)?;
writer.write_with(|section| {
section.push_cell(list_loc_as_cell!(threshold + 1));
@@ -873,9 +867,21 @@ impl MachineState {
section.push_cell(heap_loc_as_cell!(threshold + 2));
});
copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?;
let old_lifted_cell_len = self.lifted_heap.cell_len();
Ok(threshold + lh_offset + 2)
let copy_ball_term = CopyBallTerm::new(
&mut self.attr_var_init.attr_var_queue,
&mut self.stack,
&mut self.heap,
&mut self.lifted_heap,
);
let pstr_boundary = copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?;
Ok(FindallCopyInfo {
offset: threshold + lh_offset + 2,
pstr_threshold: pstr_boundary + old_lifted_cell_len,
})
}
#[inline(always)]
@@ -1045,18 +1051,6 @@ impl MachineState {
pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option<AtomOrString> {
read_heap_cell!(value,
/*
(HeapCellValueTag::CStr, cstr_atom) => {
// avoid allocating a String if possible:
// We must be careful to preserve the string "[]" as is,
// instead of turning it into the atom [], i.e., "".
if cstr_atom == atom!("[]") {
Some(AtomOrString::String("[]".to_string()))
} else {
Some(AtomOrString::Atom(cstr_atom))
}
}
*/
(HeapCellValueTag::Atom, (atom, arity)) => {
if arity == 0 {
// ... likewise.
@@ -1389,15 +1383,7 @@ impl Machine {
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity();
(name, arity, if self.machine_st.heap.cell_len() > s + arity + 1 {
if !self.machine_st.heap.pstr_at(s + arity + 1) {
get_structure_index(self.machine_st.heap[s + arity + 1])
} else {
None
}
} else {
None
})
(name, arity, get_structure_index(self.machine_st.heap[s.saturating_sub(1)]))
}
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
@@ -1457,7 +1443,6 @@ impl Machine {
if let Some(code_index) = index_cell {
if !code_index.is_undefined() {
// println!("(fast) calling {}/{}", name.as_str(), arity);
load_registers(&mut self.machine_st, goal, goal_arity);
self.machine_st.neck_cut();
return call_at_index(self, name, arity, code_index.get());
@@ -1481,6 +1466,7 @@ impl Machine {
.variable_set(&mut supp_vars, self.machine_st.registers[2]);
struct GoalAnalysisResult {
index_ptr_loc: usize,
is_simple_goal: bool,
goal: HeapCellValue,
key: PredicateKey,
@@ -1496,7 +1482,7 @@ impl Machine {
// fill expanded_vars with variables of the partial
// goal pre-completion by complete_partial_goal.
for idx in s + 1 .. s + arity - supp_vars.len() + 1 {
for idx in s + 1 ..= s + arity - supp_vars.len() {
self.machine_st.variable_set(&mut expanded_vars, self.machine_st.heap[idx]);
}
@@ -1510,7 +1496,8 @@ impl Machine {
// disjoint from them. if they are not, the
// expanded goal is not simple.
let post_supp_args = self.machine_st.heap.splice(s+arity-supp_vars.len()+1 .. s+arity+1);
let post_supp_args = (s+arity-supp_vars.len()+1 ..= s+arity)
.map(|idx| self.machine_st.heap[idx]);
post_supp_args
.zip(supp_vars.iter())
@@ -1535,27 +1522,33 @@ impl Machine {
false
};
let goal = if is_simple_goal {
let (index_ptr_loc, goal) = if is_simple_goal {
let h = self.machine_st.heap.cell_len();
let arity = arity - supp_vars.len();
resource_error_call_result!(
self.machine_st,
self.machine_st.heap.push_cell(empty_list_as_cell!())
);
resource_error_call_result!(
self.machine_st,
self.machine_st.heap.copy_slice_to_end(
s .. s + arity + 1
s ..= s + arity,
)
);
self.machine_st.heap[h] = atom_as_cell!(name, arity);
self.machine_st.heap[h+1] = atom_as_cell!(name, arity);
// even if arity == 0, goal must be a Str cell,
// since an index is about to appended to it.
str_loc_as_cell!(h)
(h, str_loc_as_cell!(h+1))
} else {
goal
(0, goal)
};
GoalAnalysisResult {
index_ptr_loc,
is_simple_goal,
goal,
key: (name, arity),
@@ -1566,36 +1559,25 @@ impl Machine {
debug_assert_eq!(arity, 0);
let h = self.machine_st.heap.cell_len();
resource_error_call_result!(
let mut writer = resource_error_call_result!(
self.machine_st,
self.machine_st.heap.push_cell(goal)
self.machine_st.heap.reserve(2)
);
writer.write_with(|section| {
section.push_cell(empty_list_as_cell!());
section.push_cell(goal);
});
GoalAnalysisResult {
index_ptr_loc: h,
is_simple_goal: true,
goal: str_loc_as_cell!(h),
goal: str_loc_as_cell!(h+1),
key: (name, 0),
supp_vars,
}
}
/*
(HeapCellValueTag::Char, c) => {
let name = AtomTable::build_with(&self.machine_st.atom_tbl,&c.to_string());
let h = self.machine_st.heap.cell_len();
resource_error_call_result!(
self.machine_st,
self.machine_st.heap.push_cell(atom_as_cell!(name))
);
GoalAnalysisResult {
is_simple_goal: true,
goal: str_loc_as_cell!(h),
key: (name, 0),
supp_vars,
}
}
*/
_ => {
self.machine_st.fail = true;
return Ok(());
@@ -1609,14 +1591,8 @@ impl Machine {
let expanded_term = if result.is_simple_goal {
let idx = self.get_or_insert_qualified_code_index(module_name, result.key);
resource_error_call_result!(
self.machine_st,
self.machine_st
.heap
.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)))
);
self.machine_st.heap[result.index_ptr_loc] =
untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx));
result.goal
} else {
let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
@@ -1648,29 +1624,24 @@ impl Machine {
self.machine_st.heap.reserve(unexpanded_vars.len() + 2)
);
writer.write_with(|section| {
section.push_cell(atom_as_cell!(atom!("$aux"), 0));
for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
section.push_cell(value);
}
section.push_cell(atom_as_cell!(atom!("[]")));
});
let anon_str_arity = self.machine_st.heap.cell_len() - h - 2;
self.machine_st.heap[h] = atom_as_cell!(atom!("$aux"), anon_str_arity);
let idx = CodeIndex::new(
IndexPtr::index(helper_clause_loc),
&mut self.machine_st.arena,
);
self.machine_st.heap.last_cell_mut().map(|cell| {
*cell = untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx));
writer.write_with(|section| {
section.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
section.push_cell(atom_as_cell!(atom!("$aux"), 0));
for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
section.push_cell(value);
}
});
str_loc_as_cell!(h)
let anon_str_arity = self.machine_st.heap.cell_len() - h - 2;
self.machine_st.heap[h + 1] = atom_as_cell!(atom!("$aux"), anon_str_arity);
str_loc_as_cell!(h + 1)
}
}
};
@@ -1688,28 +1659,22 @@ impl Machine {
if HeapCellValueTag::Str == qualified_goal.get_tag() {
let s = qualified_goal.get_value() as usize;
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity();
let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name();
if name == atom!("$call") {
return false;
}
if self.machine_st.heap.cell_len() > s + 1 + arity {
if self.machine_st.heap.pstr_at(s + 1 + arity) {
return false;
}
let idx_cell = self.machine_st.heap[s.saturating_sub(1)];
let idx_cell = self.machine_st.heap[s + 1 + arity];
if HeapCellValueTag::Cons == idx_cell.get_tag() {
match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell),
(ArenaHeaderTag::IndexPtr, _ip) => {
return true;
}
_ => {
}
);
}
if HeapCellValueTag::Cons == idx_cell.get_tag() {
match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell),
(ArenaHeaderTag::IndexPtr, _ip) => {
return true;
}
_ => {
}
);
}
}
@@ -2312,27 +2277,6 @@ impl Machine {
let a1 = self.deref_register(1);
read_heap_cell!(a1,
/*
(HeapCellValueTag::Char) => {
let h = self.machine_st.heap.cell_len();
let mut writer = resource_error_call_result!(
self.machine_st,
self.machine_st.heap.reserve(2)
);
step_or_resource_error!(
self.machine_st,
writer.write_with(|section| {
section.push_cell(a1);
section.push_cell(empty_list_as_cell!());
Ok::<(), usize>(())
})
);
unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
}
*/
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
@@ -2542,7 +2486,7 @@ impl Machine {
self.machine_st.allocate_pstr(&*atom.as_str())
);
let tail_loc = Heap::neighboring_cell_offset(atom.as_str().len() + heap_index!(pstr_h));
let tail_loc = Heap::pstr_tail_idx(atom.as_str().len() + heap_index!(pstr_h));
step_or_resource_error!(
self.machine_st,
@@ -2585,8 +2529,8 @@ impl Machine {
read_heap_cell!(pstr,
(HeapCellValueTag::PStrLoc, h) => {
let (_, tail_loc) = self.machine_st.heap.scan_slice_to_str(h);
unify_fn!(self.machine_st, heap_loc_as_cell!(tail_loc), a2);
let HeapStringScan { tail_idx, .. } = self.machine_st.heap.scan_slice_to_str(h);
unify_fn!(self.machine_st, heap_loc_as_cell!(tail_idx), a2);
}
(HeapCellValueTag::Lis, h) => {
unify_fn!(
@@ -3970,7 +3914,10 @@ impl Machine {
pub(crate) fn copy_to_lifted_heap(&mut self) {
let lh_offset = cell_as_fixnum!(self.deref_register(1)).get_num() as usize;
let copy_target = self.machine_st.registers[2];
let old_threshold = step_or_resource_error!(
let FindallCopyInfo {
offset: old_threshold,
pstr_threshold,
} = step_or_resource_error!(
self.machine_st,
self.machine_st
.copy_findall_solution(lh_offset, copy_target)
@@ -3980,8 +3927,20 @@ impl Machine {
self.machine_st.lifted_heap[old_threshold] = heap_loc_as_cell!(new_threshold);
for addr in &mut self.machine_st.lifted_heap.splice_mut(old_threshold + 1..) {
*addr -= self.machine_st.heap.cell_len() + lh_offset;
for idx in old_threshold + 1..pstr_threshold {
self.machine_st.lifted_heap[idx] -= self.machine_st.heap.cell_len() + lh_offset;
}
let mut pstr_threshold = heap_index!(pstr_threshold);
while pstr_threshold < heap_index!(self.machine_st.lifted_heap.cell_len()) {
let HeapStringScan { tail_idx, .. } = self
.machine_st
.lifted_heap
.scan_slice_to_str(pstr_threshold);
self.machine_st.lifted_heap[tail_idx] -= self.machine_st.heap.cell_len() + lh_offset;
pstr_threshold = heap_index!(tail_idx + 1);
}
}
@@ -5797,17 +5756,18 @@ impl Machine {
unify_fn!(self.machine_st, solutions, diff);
} else {
let h = self.machine_st.heap.cell_len();
let reserve_size = self.machine_st.lifted_heap.cell_len() - lh_offset;
step_or_resource_error!(
let mut writer = step_or_resource_error!(
self.machine_st,
self.machine_st
.heap
.append(self.machine_st.lifted_heap.splice(lh_offset..),)
self.machine_st.heap.reserve(reserve_size)
);
for cell in &mut self.machine_st.heap.splice_mut(h..) {
*cell = *cell + h;
}
writer.write_with(|section| {
for idx in lh_offset..self.machine_st.lifted_heap.cell_len() {
section.push_cell(self.machine_st.lifted_heap[idx] + h);
}
});
let diff = self.machine_st.registers[3];
unify_fn!(
@@ -5834,17 +5794,18 @@ impl Machine {
unify_fn!(self.machine_st, solutions, empty_list_as_cell!());
} else {
let h = self.machine_st.heap.cell_len();
let reserve_size = self.machine_st.lifted_heap.cell_len() - lh_offset;
step_or_resource_error!(
let mut writer = step_or_resource_error!(
self.machine_st,
self.machine_st
.heap
.append(self.machine_st.lifted_heap.splice(lh_offset..),)
self.machine_st.heap.reserve(reserve_size)
);
for cell in &mut self.machine_st.heap.splice_mut(h..) {
*cell = *cell + h;
}
writer.write_with(|section| {
for idx in lh_offset..self.machine_st.lifted_heap.cell_len() {
section.push_cell(self.machine_st.lifted_heap[idx] + h);
}
});
self.machine_st.lifted_heap.truncate(lh_offset);
@@ -7223,8 +7184,7 @@ impl Machine {
let mut ball = Ball::new();
ball.boundary = self.machine_st.heap.cell_len();
step_or_resource_error!(
ball.pstr_boundary = step_or_resource_error!(
self.machine_st,
copy_term(
CopyBallTerm::new(

View File

@@ -44,14 +44,19 @@ impl<'a> BootstrappingTermStream<'a> {
listing_src: ListingSource,
) -> Self {
let lexer_parser = LexerParser::new(stream, machine_st);
Self { lexer_parser, listing_src }
Self {
lexer_parser,
listing_src,
}
}
}
impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline]
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
let result = self.lexer_parser.read_term(op_dir, Tokens::Default)
let result = self
.lexer_parser
.read_term(op_dir, Tokens::Default)
.map_err(CompilationError::from);
result
@@ -125,7 +130,9 @@ pub struct InlineTermStream {}
impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default())))
Err(CompilationError::from(ParserError::unexpected_eof(
ParserErrorSrc::default(),
)))
}
fn eof(&mut self) -> Result<bool, CompilationError> {

View File

@@ -507,11 +507,9 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
if value.is_ref() && !value.is_stack_var() {
machine_st.heap[0] = value;
for cell in stackful_preorder_iter::<NonListElider>(
&mut machine_st.heap,
&mut machine_st.stack,
0,
) {
for cell in
stackful_preorder_iter::<NonListElider>(&mut machine_st.heap, &mut machine_st.stack, 0)
{
let cell = unmark_cell_bits!(cell);
if let Some(inner_r) = cell.as_var() {

View File

@@ -141,7 +141,11 @@ macro_rules! fixnum {
($n:expr, $arena:expr) => {
Fixnum::build_with_checked($n)
.map(|n| fixnum_as_cell!(n))
.unwrap_or_else(|_| typed_arena_ptr_as_cell!(arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>))
.unwrap_or_else(|_| {
typed_arena_ptr_as_cell!(
arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>
)
})
};
($wrapper:ty, $n:expr, $arena:expr) => {
Fixnum::build_with_checked($n)
@@ -619,10 +623,7 @@ impl Literal {
pub type Var = Rc<String>;
pub(crate) fn subterm_index(
heap: &impl SizedHeap,
subterm_loc: usize,
) -> (usize, HeapCellValue) {
pub(crate) fn subterm_index(heap: &impl SizedHeap, subterm_loc: usize) -> (usize, HeapCellValue) {
let subterm = heap[subterm_loc];
if subterm.is_ref() {
@@ -715,16 +716,10 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
}
*/
pub(crate) fn fetch_index_ptr(
heap: &impl SizedHeap,
arity: usize,
term_loc: usize,
) -> Option<CodeIndex> {
if term_loc + arity + 1 >= heap.cell_len() || heap.pstr_at(term_loc + arity + 1) {
return None;
}
pub(crate) fn fetch_index_ptr(heap: &impl SizedHeap, term_loc: usize) -> Option<CodeIndex> {
let index_cell_loc = term_loc.saturating_sub(1);
read_heap_cell!(heap[term_loc + arity + 1],
read_heap_cell!(heap[index_cell_loc],
(HeapCellValueTag::Cons, c) => {
match_untyped_arena_ptr!(c,
(ArenaHeaderTag::IndexPtr, ptr) => {
@@ -744,7 +739,7 @@ pub(crate) fn blunt_index_ptr(
key: PredicateKey,
term_loc: usize,
) -> bool {
if fetch_index_ptr(heap, key.1, term_loc).is_some() {
if fetch_index_ptr(heap, term_loc).is_some() {
heap[term_loc] = atom_as_cell!(key.0, key.1);
true
} else {
@@ -757,10 +752,7 @@ pub(crate) fn unfold_by_str_once(
start_term: HeapCellValue,
atom: Atom,
) -> Option<usize> {
let start_term = heap_bound_store(
heap,
heap_bound_deref(heap, start_term),
);
let start_term = heap_bound_store(heap, heap_bound_deref(heap, start_term));
if let HeapCellValueTag::Str = start_term.get_tag() {
let s = start_term.get_value() as usize;
@@ -769,7 +761,7 @@ pub(crate) fn unfold_by_str_once(
blunt_index_ptr(heap, (s_atom, s_arity), s);
if (s_atom, s_arity) == (atom, 2) {
return Some(s+1);
return Some(s + 1);
}
}
@@ -826,7 +818,7 @@ pub fn unfold_by_str_locs(
let mut current_term = heap[term_loc];
while let Some(fst_loc) = unfold_by_str_once(heap, current_term, atom) {
term_loc = fst_loc+1;
term_loc = fst_loc + 1;
current_term = heap[term_loc];
let fst = heap[fst_loc];
terms.push((fst, fst_loc));
@@ -836,10 +828,7 @@ pub fn unfold_by_str_locs(
terms
}
pub fn term_predicate_key(
heap: &impl SizedHeap,
mut term_loc: usize,
) -> Option<PredicateKey> {
pub fn term_predicate_key(heap: &impl SizedHeap, mut term_loc: usize) -> Option<PredicateKey> {
loop {
read_heap_cell!(heap[term_loc],
(HeapCellValueTag::Atom, (name, arity)) => {
@@ -879,10 +868,7 @@ pub fn inverse_var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) ->
let var_loc = var.get_value() as usize;
if count > 1 {
inverse_var_locs.insert(
var_loc,
Rc::new(format!("_{}", var_loc)),
);
inverse_var_locs.insert(var_loc, Rc::new(format!("_{}", var_loc)));
}
}

View File

@@ -56,22 +56,18 @@ impl Token {
Token::String(string) if flags.double_quotes.is_codes() => {
2 * string.chars().count() + 1
}
Token::String(string) => {
Heap::compute_pstr_size(&string)
}
Token::Literal(_) |
Token::Comma |
Token::HeadTailSeparator |
Token::Open |
Token::OpenCT |
Token::OpenCurly |
Token::OpenList |
Token::Var(_) => {
Token::String(string) => Heap::compute_pstr_size(&string),
Token::Literal(_)
| Token::Comma
| Token::HeadTailSeparator
| Token::Open
| Token::OpenCT
| Token::OpenCurly
| Token::OpenList
| Token::Var(_) => {
heap_index!(1)
}
_ => {
0
}
_ => 0,
}
}
@@ -462,10 +458,7 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
self.skip_char(c);
u32::from_str_radix(&token, radix).map_or_else(
|_| Err(ParserError::ParseBigInt(self.loc_to_err_src())),
|n| {
char::try_from(n)
.map_err(|_| ParserError::Utf8Error(self.loc_to_err_src()))
},
|n| char::try_from(n).map_err(|_| ParserError::Utf8Error(self.loc_to_err_src())),
)
} else {
Err(ParserError::IncompleteReduction(self.loc_to_err_src()))
@@ -657,7 +650,9 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
}
}
} else {
return Err(ParserError::InvalidSingleQuotedCharacter(self.loc_to_err_src()));
return Err(ParserError::InvalidSingleQuotedCharacter(
self.loc_to_err_src(),
));
}
} else {
match self.get_back_quoted_string() {

View File

@@ -187,7 +187,9 @@ struct Parser<'a> {
inverse_var_locs: InverseVarLocs,
}
pub fn read_tokens<R: CharRead>(lexer: &mut LexerParser<R>) -> Result<(Vec<Token>, usize), ParserError> {
pub fn read_tokens<R: CharRead>(
lexer: &mut LexerParser<R>,
) -> Result<(Vec<Token>, usize), ParserError> {
let mut tokens = vec![];
let mut term_size = 0;
@@ -264,9 +266,9 @@ pub(crate) fn as_partial_string(
tail = heap[l+1];
}
(HeapCellValueTag::PStrLoc, l) => {
let (pstr, tail_loc) = heap.scan_slice_to_str(l);
let HeapStringScan { string: pstr, tail_idx } = heap.scan_slice_to_str(l);
string += pstr;
tail = heap[tail_loc];
tail = heap[tail_idx];
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if heap[h] != tail {
@@ -306,8 +308,7 @@ impl<'a> Parser<'a> {
TokenType::Comma => Some(atom!(",")),
TokenType::Term { heap_loc } => {
if heap_loc.is_ref() {
term_predicate_key(&self.terms, heap_loc.get_value() as usize)
.map(|key| key.0)
term_predicate_key(&self.terms, heap_loc.get_value() as usize).map(|key| key.0)
} else {
None
}
@@ -392,7 +393,8 @@ impl<'a> Parser<'a> {
fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
let h = self.terms.cell_len();
self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom)));
self.terms
.write_with(|section| section.push_cell(atom_as_cell!(atom)));
self.stack.push(TokenDesc {
tt: TokenType::Term {
heap_loc: heap_loc_as_cell!(h),
@@ -438,10 +440,12 @@ impl<'a> Parser<'a> {
section.push_cell(list_loc_as_cell!(h));
});
TokenType::Term { heap_loc: heap_loc_as_cell!(h + 2) }
TokenType::Term {
heap_loc: heap_loc_as_cell!(h + 2),
}
} else {
self.terms.write_with(|section| {
match section.push_pstr(&s) {
self.terms
.write_with(|section| match section.push_pstr(&s) {
Some(pstr_loc_cell) => {
section.push_cell(empty_list_as_cell!());
let h = section.cell_len();
@@ -451,10 +455,11 @@ impl<'a> Parser<'a> {
None => {
section.push_cell(empty_list_as_cell!());
}
}
});
});
TokenType::Term { heap_loc: pstr_cell }
TokenType::Term {
heap_loc: pstr_cell,
}
}
}
Token::Literal(c) => {
@@ -478,13 +483,14 @@ impl<'a> Parser<'a> {
if var.trim() != "_" {
self.var_locs.insert(var.clone(), heap_loc);
self.inverse_var_locs.insert(heap_loc.get_value() as usize, var);
self.inverse_var_locs
.insert(heap_loc.get_value() as usize, var);
}
TokenType::Term { heap_loc }
}
}
},
}
Token::Comma => TokenType::Comma,
Token::Open => TokenType::Open,
Token::Close => TokenType::Close,
@@ -619,15 +625,21 @@ impl<'a> Parser<'a> {
let term_idx = self.terms.cell_len();
let push_structure = |parser: &mut Self, name: Atom| -> TokenType {
parser.terms.write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
parser
.terms
.write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
for idx in (stack_len + 2..parser.stack.len()).step_by(2) {
let subterm = parser.term_from_stack(idx).unwrap();
parser.terms.write_with(|section| section.push_cell(subterm));
parser
.terms
.write_with(|section| section.push_cell(subterm));
}
let str_loc_idx = parser.terms.cell_len();
parser.terms.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
parser
.terms
.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
TokenType::Term {
heap_loc: heap_loc_as_cell!(str_loc_idx),
@@ -709,23 +721,20 @@ impl<'a> Parser<'a> {
}
fn loc_to_err_src(&self) -> ParserErrorSrc {
ParserErrorSrc { line_num: *self.line_num, col_num: *self.col_num }
ParserErrorSrc {
line_num: *self.line_num,
col_num: *self.col_num,
}
}
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
if let Some(term) = self.term_from_stack(index - 1) {
let mut op_desc = self.stack[index - 1];
let mut term = heap_bound_store(
&self.terms,
heap_bound_deref(
&self.terms,
term,
),
);
let mut term = heap_bound_store(&self.terms, heap_bound_deref(&self.terms, term));
if term.is_ref() &&
0 < op_desc.priority &&
op_desc.priority < self.stack[index].priority
if term.is_ref()
&& 0 < op_desc.priority
&& op_desc.priority < self.stack[index].priority
{
/* '|' is a head-tail separator here, not
* an operator, so expand the
@@ -740,11 +749,9 @@ impl<'a> Parser<'a> {
} else {
let mut terms = vec![];
while let Some(fst_loc) = unfold_by_str_once(
&mut self.terms,
term,
atom!(","),
) {
while let Some(fst_loc) =
unfold_by_str_once(&mut self.terms, term, atom!(","))
{
let (_, snd) = subterm_index(&self.terms, fst_loc + 1);
let (_, fst) = subterm_index(&self.terms, fst_loc);
@@ -763,14 +770,13 @@ impl<'a> Parser<'a> {
};
let arity = terms.len() - 1;
self.stack.extend(terms.into_iter().map(|heap_loc| {
TokenDesc {
self.stack
.extend(terms.into_iter().map(|heap_loc| TokenDesc {
tt: TokenType::Term { heap_loc },
priority: 0,
spec: 0,
unfold_bounds: 0,
}
}));
}));
return arity;
}
}
@@ -816,7 +822,8 @@ impl<'a> Parser<'a> {
// parsed an empty list token
if td.tt == TokenType::OpenList {
let h = self.terms.cell_len();
self.terms.write_with(|section| section.push_cell(empty_list_as_cell!()));
self.terms
.write_with(|section| section.push_cell(empty_list_as_cell!()));
td.spec = TERM;
td.tt = TokenType::Term {
@@ -845,9 +852,7 @@ impl<'a> Parser<'a> {
let tail_term = match self.term_from_stack(idx + 1) {
Some(term) => term,
None => {
return Err(ParserError::IncompleteReduction(
self.loc_to_err_src(),
));
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
}
};
@@ -863,18 +868,14 @@ impl<'a> Parser<'a> {
};
if arity > self.terms.cell_len() {
return Err(ParserError::IncompleteReduction(
self.loc_to_err_src(),
));
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
}
let pre_terms_len = self.terms.cell_len();
while let Some(token_desc) = self.stack.pop() {
let subterm = match token_desc.tt {
TokenType::Term { heap_loc } => {
heap_loc
}
TokenType::Term { heap_loc } => heap_loc,
_ => {
continue;
}
@@ -942,7 +943,8 @@ impl<'a> Parser<'a> {
if td.tt == TokenType::OpenCurly {
let h = self.terms.cell_len();
self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}"))));
self.terms
.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}"))));
td.tt = TokenType::Term {
heap_loc: heap_loc_as_cell!(h),
@@ -1160,66 +1162,58 @@ impl<'a> Parser<'a> {
Token::String(string) => {
self.shift(Token::String(string), 0, TERM);
}
Token::Literal(c) => {
match Number::try_from(c) {
Ok(Number::Integer(n)) => {
self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n))
}
Ok(Number::Rational(n)) => {
self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r))
}
Ok(Number::Float(n)) if n.is_infinite() => {
return Err(ParserError::InfiniteFloat(
self.lexer.loc_to_err_src(),
));
}
Ok(Number::Float(n)) => {
use ordered_float::OrderedFloat;
Token::Literal(c) => match Number::try_from(c) {
Ok(Number::Integer(n)) => {
self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n))
}
Ok(Number::Rational(n)) => {
self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r))
}
Ok(Number::Float(n)) if n.is_infinite() => {
return Err(ParserError::InfiniteFloat(
self.loc_to_err_src(),
));
}
Ok(Number::Float(n)) => {
use ordered_float::OrderedFloat;
self.negate_number(
n,
|n, _| -n,
|OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)),
)
}
Ok(Number::Fixnum(n)) => {
self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n))
}
Err(_) => {
if let Some(name) = c.to_atom() {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM);
}
} else {
self.negate_number(
n,
|n, _| -n,
|OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)),
)
}
Ok(Number::Fixnum(n)) => {
self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n))
}
Err(_) => {
if let Some(name) = c.to_atom() {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM);
}
} else {
self.shift(Token::Literal(c), 0, TERM);
}
}
}
},
Token::Var(v) => self.shift(Token::Var(v), 0, TERM),
Token::Open => self.shift(Token::Open, 1300, DELIMITER),
Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER),
Token::Close => {
if !self.reduce_term() && !self.reduce_brackets() {
return Err(ParserError::IncompleteReduction(
self.loc_to_err_src(),
));
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
}
}
Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER),
Token::CloseList => {
if !self.reduce_list()? {
return Err(ParserError::IncompleteReduction(
self.loc_to_err_src(),
));
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
}
}
Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER),
Token::CloseCurly => {
if !self.reduce_curly()? {
return Err(ParserError::IncompleteReduction(
self.loc_to_err_src(),
));
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
}
}
Token::HeadTailSeparator => {
@@ -1253,9 +1247,7 @@ impl<'a> Parser<'a> {
| Some(TokenType::OpenCurly)
| Some(TokenType::HeadTailSeparator)
| Some(TokenType::Comma) => {
return Err(ParserError::IncompleteReduction(
self.loc_to_err_src(),
))
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()))
}
_ => {}
},
@@ -1272,7 +1264,10 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
}
pub fn loc_to_err_src(&self) -> ParserErrorSrc {
ParserErrorSrc { line_num: self.line_num, col_num: self.col_num }
ParserErrorSrc {
line_num: self.line_num,
col_num: self.col_num,
}
}
// on success, returns the parsed term and the number of lines read.
@@ -1289,7 +1284,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
// the parser uses conditional indirection in many places so
// the reserved size should be at least 4 * term_byte_size
// so all cells are accounted for.
let writer = match self.machine_st.heap.reserve(cell_index!(4 * term_byte_size)) {
let writer = match self
.machine_st
.heap
.reserve(cell_index!(4 * term_byte_size))
{
Ok(term) => term,
Err(_err_loc) => {
return Err(ParserError::ResourceError(self.loc_to_err_src()));

View File

@@ -58,7 +58,7 @@ impl MachineState {
let op_dir = CompositeOpDir::new(op_dir, None);
let term_result = lexer_parser.read_term(&op_dir, Tokens::Default);
let lines_read = lexer_parser.line_num();
let lines_read = lexer_parser.line_num();
term_result.map(|term| (term, lines_read))
}

View File

@@ -369,8 +369,8 @@ impl HeapCellValue {
name == atom!("[]") && arity == 0
}
(HeapCellValueTag::PStrLoc, h) => {
let (_s, tail_loc) = heap.scan_slice_to_str(h);
self = heap[tail_loc];
let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
self = heap[tail_idx];
continue;
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
@@ -399,8 +399,7 @@ impl HeapCellValue {
| HeapCellValueTag::Var
| HeapCellValueTag::StackVar
| HeapCellValueTag::AttrVar
| HeapCellValueTag::PStrLoc
// | HeapCellValueTag::PStrOffset
| HeapCellValueTag::PStrLoc // | HeapCellValueTag::PStrOffset
)
}
@@ -503,9 +502,7 @@ impl HeapCellValue {
#[inline]
pub fn to_atom(self) -> Option<Atom> {
match self.get_tag() {
HeapCellValueTag::Atom => {
Some(AtomCell::from_bytes(self.into_bytes()).get_name())
}
HeapCellValueTag::Atom => Some(AtomCell::from_bytes(self.into_bytes()).get_name()),
_ => None,
}
}
@@ -775,7 +772,8 @@ impl Sub<i64> for HeapCellValue {
HeapCellValue::build_with(tag, self.get_value() + rhs.unsigned_abs())
}
tag @ HeapCellValueTag::PStrLoc => {
let value = self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
let value =
self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
HeapCellValue::build_with(tag, value as u64)
}
_ => self,

View File

@@ -1,5 +1,5 @@
use crate::parser::ast::*;
use crate::forms::GenContext;
use crate::parser::ast::*;
use bit_set::*;
use fxhash::FxBuildHasher;
@@ -88,7 +88,10 @@ pub enum VarAlloc {
safety: VarSafetyStatus,
to_perm_var_num: Option<usize>,
},
Perm { reg: usize, allocation: PermVarAllocation }, // stack offset, allocation info
Perm {
reg: usize,
allocation: PermVarAllocation,
}, // stack offset, allocation info
}
impl VarAlloc {
@@ -152,7 +155,10 @@ pub struct VariableRecord {
impl Default for VariableRecord {
fn default() -> Self {
VariableRecord {
allocation: VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending },
allocation: VarAlloc::Perm {
reg: 0,
allocation: PermVarAllocation::Pending,
},
num_occurrences: 0,
running_count: 0,
}