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

@@ -89,7 +89,7 @@ const INLINED_ATOM_MAX_LEN: usize = 6;
fn static_string_index(string: &str, index: usize) -> u64 { fn static_string_index(string: &str, index: usize) -> u64 {
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN { if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN {
let mut string_buf: [u8; 8] = [0u8; 8]; 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());
(u64::from_le_bytes(string_buf) << 1) | 1 (u64::from_le_bytes(string_buf) << 1) | 1
} else { } else {
(index << 1) as u64 (index << 1) as u64
@@ -165,22 +165,26 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
let mut static_strs = vec![]; let mut static_strs = vec![];
let mut static_str_indices = vec![]; let mut static_str_indices = vec![];
let indices: Vec<u64> = visitor.static_strs.iter().map(|string| { let indices: Vec<u64> = visitor
let index = static_string_index(string, static_strs.len()); .static_strs
.iter()
.map(|string| {
let index = static_string_index(string, static_strs.len());
static_str_keys.push(string); static_str_keys.push(string);
if index & 1 == 1 { if index & 1 == 1 {
index index
} else { } else {
static_str_indices.push(index); static_str_indices.push(index);
static_strs.push(string); static_strs.push(string);
index index
} }
}).collect(); })
.collect();
let static_strs_len = static_strs.len(); // visitor.static_strs.len(); let static_strs_len = static_strs.len(); // visitor.static_strs.len();
//let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect(); //let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
quote! { quote! {
static STRINGS: [&str; #static_strs_len] = [ static STRINGS: [&str; #static_strs_len] = [

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::instructions::*;
use crate::functor_macro::*; use crate::functor_macro::*;
use crate::instructions::*;
use crate::machine::disjuncts::VarData; use crate::machine::disjuncts::VarData;
use crate::machine::heap::*; use crate::machine::heap::*;
// use crate::machine::loader::PredicateQueue; // use crate::machine::loader::PredicateQueue;
@@ -80,8 +80,8 @@ impl GenContext {
#[inline] #[inline]
pub fn chunk_type(&self) -> ChunkType { pub fn chunk_type(&self) -> ChunkType {
match self { match self {
GenContext::Head => ChunkType::Head, GenContext::Head => ChunkType::Head,
GenContext::Mid(_) => ChunkType::Mid, GenContext::Mid(_) => ChunkType::Mid,
GenContext::Last(_) => ChunkType::Last, GenContext::Last(_) => ChunkType::Last,
} }
} }
@@ -118,7 +118,10 @@ impl ChunkType {
#[derive(Debug)] #[derive(Debug)]
pub enum ChunkedTerms { pub enum ChunkedTerms {
Branch(Vec<VecDeque<ChunkedTerms>>), Branch(Vec<VecDeque<ChunkedTerms>>),
Chunk { chunk_num: usize, terms: VecDeque<QueryTerm> }, Chunk {
chunk_num: usize,
terms: VecDeque<QueryTerm>,
},
} }
#[derive(Debug)] #[derive(Debug)]
@@ -190,7 +193,8 @@ impl ChunkedTermVec {
} }
pub fn current_gen_context(&self) -> GenContext { 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) { 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); let key_opt = term_predicate_key(heap, term_loc);
if Some((atom!(":-"), 2)) == key_opt { if Some((atom!(":-"), 2)) == key_opt {
term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| { term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| term_predicate_key(heap, arg_loc))
term_predicate_key(heap, arg_loc)
})
} else { } else {
key_opt 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::atom_table::*;
use crate::instructions::IndexingCodePtr; use crate::instructions::IndexingCodePtr;
use crate::machine::heap::Heap; use crate::machine::heap::Heap;
@@ -5,7 +8,7 @@ use crate::parser::ast::Fixnum;
use crate::types::*; use crate::types::*;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum FunctorElement { pub(crate) enum FunctorElement {
AbsoluteCell(HeapCellValue), AbsoluteCell(HeapCellValue),
Cell(HeapCellValue), Cell(HeapCellValue),
InnerFunctor(u64, Vec<FunctorElement>), InnerFunctor(u64, Vec<FunctorElement>),
@@ -190,19 +193,19 @@ pub(crate) fn variadic_functor(
let num_items = key_value_pairs.len(); let num_items = key_value_pairs.len();
for (idx, _) in key_value_pairs.iter().enumerate() { 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.push(FunctorElement::Cell(list_loc_as_cell!(5 + idx)));
} }
arg_vec.pop(); arg_vec.pop();
arg_vec.push(FunctorElement::Cell(empty_list_as_cell!())); arg_vec.push(FunctorElement::Cell(empty_list_as_cell!()));
arg_vec.extend(key_value_pairs arg_vec.extend(key_value_pairs.into_iter().map(|kv_func| {
.into_iter() let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
.map(|kv_func| { FunctorElement::InnerFunctor(inner_functor_size as u64, 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 arg_vec
} }
@@ -211,13 +214,15 @@ pub(crate) fn variadic_functor(
#[allow(unused_parens)] #[allow(unused_parens)]
mod tests { mod tests {
use super::*; use super::*;
use FunctorElement::*;
use std::string::String; use std::string::String;
use FunctorElement::*;
#[test] #[test]
fn basic_terms() { fn basic_terms() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), let functor = functor!(
char_as_cell('c')]); atom!("first"),
[atom_as_cell((atom!("a"))), char_as_cell('c')]
);
assert_eq!(functor.len(), 3); assert_eq!(functor.len(), 3);
@@ -225,10 +230,14 @@ mod tests {
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a")))); assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(char_as_cell!('c'))); assert_eq!(functor[2], Cell(char_as_cell!('c')));
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))), let functor = functor!(
functor((atom!("b")), [fixnum(1), atom!("second"),
fixnum(2)]), [
char_as_cell('c')]); atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
char_as_cell('c')
]
);
assert_eq!(functor.len(), 5); assert_eq!(functor.len(), 5);
@@ -236,13 +245,20 @@ mod tests {
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a")))); assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(str_loc_as_cell!(4))); assert_eq!(functor[2], Cell(str_loc_as_cell!(4)));
assert_eq!(functor[3], Cell(char_as_cell!('c'))); assert_eq!(functor[3], Cell(char_as_cell!('c')));
assert_eq!(functor[4], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), assert_eq!(
fixnum(2)]))); functor[4],
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
);
let functor = functor!(atom!("third"), [atom_as_cell((atom!("a"))), let functor = functor!(
functor((atom!("b")), [fixnum(1), fixnum(2)]), atom!("third"),
functor((atom!("c")), [fixnum(1), fixnum(2)]), [
char_as_cell('c')]); 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); assert_eq!(functor.len(), 7);
@@ -251,14 +267,25 @@ mod tests {
assert_eq!(functor[2], Cell(str_loc_as_cell!(5))); assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(8))); assert_eq!(functor[3], Cell(str_loc_as_cell!(8)));
assert_eq!(functor[4], Cell(char_as_cell!('c'))); assert_eq!(functor[4], Cell(char_as_cell!('c')));
assert_eq!(functor[5], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))); assert_eq!(
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)]))); 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"))), let functor = functor!(
functor((atom!("b")), [fixnum(1), fixnum(2)]), atom!("fourth"),
functor((atom!("c")), [fixnum(1)]), [
functor((atom!("d")), [fixnum(453), fixnum(2)]), atom_as_cell((atom!("a"))),
char_as_cell('c')]); 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); assert_eq!(functor.len(), 9);
@@ -268,14 +295,26 @@ mod tests {
assert_eq!(functor[3], Cell(str_loc_as_cell!(9))); assert_eq!(functor[3], Cell(str_loc_as_cell!(9)));
assert_eq!(functor[4], Cell(str_loc_as_cell!(11))); assert_eq!(functor[4], Cell(str_loc_as_cell!(11)));
assert_eq!(functor[5], Cell(char_as_cell!('c'))); assert_eq!(functor[5], Cell(char_as_cell!('c')));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))); assert_eq!(
assert_eq!(functor[7], InnerFunctor(2, functor!(atom!("c"), [fixnum(1)]))); functor[6],
assert_eq!(functor[8], InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)]))); 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] #[test]
fn basic_terms_in_heap() { 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); assert_eq!(functor.len(), 3);
@@ -291,10 +330,15 @@ mod tests {
heap.truncate(2); heap.truncate(2);
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))), let functor = functor!(
functor((atom!("b")), [fixnum(1), fixnum(2)]), atom!("second"),
functor((atom!("c")), [fixnum(1), fixnum(2)]), [
char_as_cell('b')]); 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); assert_eq!(functor.len(), 7);
@@ -318,14 +362,24 @@ mod tests {
#[test] #[test]
fn nested_functors() { fn nested_functors() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), let functor = functor!(
functor((atom!("d")), [fixnum(1), atom!("first"),
functor((atom!("b")), [
[atom_as_cell((atom!("c"))), atom_as_cell((atom!("a"))),
char_as_cell('c')])]), functor(
functor((atom!("e")), [fixnum(453), (atom!("d")),
fixnum(2)]), [
char_as_cell('b')]); 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); assert_eq!(functor.len(), 7);
@@ -334,24 +388,47 @@ mod tests {
assert_eq!(functor[2], Cell(str_loc_as_cell!(5))); assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(11))); assert_eq!(functor[3], Cell(str_loc_as_cell!(11)));
assert_eq!(functor[4], Cell(char_as_cell!('b'))); assert_eq!(functor[4], Cell(char_as_cell!('b')));
assert_eq!(functor[5], InnerFunctor(6, vec![Cell(atom_as_cell!(atom!("d"), 2)), assert_eq!(
Cell(fixnum_as_cell!(Fixnum::build_with(1))), functor[5],
Cell(str_loc_as_cell!(3)), InnerFunctor(
InnerFunctor(3, functor!(atom!("b"), [atom_as_cell((atom!("c"))), 6,
char_as_cell('c')]))])); vec![
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("e"), [fixnum(453), Cell(atom_as_cell!(atom!("d"), 2)),
fixnum(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] #[test]
fn nested_functors_in_heap() { fn nested_functors_in_heap() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), let functor = functor!(
functor((atom!("second")), [fixnum(1), atom!("first"),
functor((atom!("third")), [atom_as_cell((atom!("b"))), [
char_as_cell('c')])]), atom_as_cell((atom!("a"))),
functor((atom!("fourth")), [fixnum(453), fixnum(2)]), functor(
char_as_cell('b')]); (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 heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor); 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[0], atom_as_cell!(atom!("first"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2))); 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!()); assert_eq!(heap[4], empty_list_as_cell!());
heap.truncate(0); 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); let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap(); 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[0], atom_as_cell!(atom!("second"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2))); 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[4], pstr_loc_as_cell!(heap_index!(5)));
assert_eq!(heap.slice_to_str(heap_index!(5), " string".len()), " string"); assert_eq!(
assert_eq!(heap[6], empty_list_as_cell!()); heap.slice_to_str(heap_index!(5), " string".len()),
" string"
);
assert_eq!(heap[7], empty_list_as_cell!());
} }
#[test] #[test]
fn functors_with_lists_in_heap() { fn functors_with_lists_in_heap() {
let functor = functor!( let functor = functor!(
atom!("first"), atom!("first"),
[list([fixnum(1), [list([fixnum(1), atom_as_cell((atom!("a"))), fixnum(2)])]
atom_as_cell((atom!("a"))),
fixnum(2)])]
); );
assert_eq!(functor.len(), 3); assert_eq!(functor.len(), 3);
@@ -462,8 +549,10 @@ mod tests {
let code_ptr = IndexingCodePtr::Internal(0); let code_ptr = IndexingCodePtr::Internal(0);
let functor = functor!( let functor = functor!(
atom!("first"), 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(); let mut heap = Heap::new();
@@ -476,18 +565,30 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2)); assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3))); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6)); 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[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1)); assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0))); assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0)));
heap.truncate(0); heap.truncate(0);
let functor = functor!(atom!("second"), let functor = functor!(
[string((String::from("a string"))), atom!("second"),
functor((atom!("third")), [atom_as_cell((atom!("a"))), [
string((String::from("another string"))), string((String::from("a string"))),
indexing_code_ptr(code_ptr)])]); 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); let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap(); functor_writer(&mut heap).unwrap();
@@ -497,24 +598,43 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2)); assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3))); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6)); 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[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3)); assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3));
assert_eq!(heap[7], atom_as_cell!(atom!("a"))); assert_eq!(heap[7], atom_as_cell!(atom!("a")));
assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10))); assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10)));
assert_eq!(heap[9], str_loc_as_cell!(13)); 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[12], empty_list_as_cell!());
assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1)); assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0))); assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0)));
let functor = functor!(atom!("fourth"), let functor = functor!(
[string((String::from("a string"))), atom!("fourth"),
functor((atom!("a")), [
[functor((atom!("fifth")), [fixnum(5), string((String::from("a string"))),
string((String::from("another string"))), functor(
indexing_code_ptr(code_ptr)]), (atom!("a")),
string((String::from("and another")))])]); [
functor(
(atom!("fifth")),
[
fixnum(5),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)
]
),
string((String::from("and another")))
]
)
]
);
heap.truncate(0); heap.truncate(0);
@@ -526,7 +646,10 @@ mod tests {
assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2)); assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3))); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6)); 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[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2)); assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2));
assert_eq!(heap[7], str_loc_as_cell!(9)); 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[10], fixnum_as_cell!(Fixnum::build_with(5)));
assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13))); assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13)));
assert_eq!(heap[12], str_loc_as_cell!(16)); 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[15], empty_list_as_cell!());
assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1)); assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[17], fixnum_as_cell!(Fixnum::build_with(0))); 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!()); assert_eq!(heap[20], empty_list_as_cell!());
} }
@@ -550,17 +679,16 @@ mod tests {
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom_as_cell((atom!("procedure"))), functor((culprit.clone()))] [
atom_as_cell((atom!("procedure"))),
functor((culprit.clone()))
]
); );
println!("{:?}", stub); println!("{:?}", stub);
// now the error form // now the error form
let lineless_error_form = functor!( let lineless_error_form = functor!(atom!("error"), [functor(stub), functor(culprit)]);
atom!("error"),
[functor(stub),
functor(culprit)]
);
println!("{:?}", lineless_error_form); println!("{:?}", lineless_error_form);

View File

@@ -116,10 +116,10 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> {
} }
} }
(HeapCellValueTag::PStrLoc, h) => { (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.heap[tail_idx].set_mark_bit(self.mark_phase);
self.iter_stack.push(self.heap[tail_loc]); self.iter_stack.push(self.heap[tail_idx]);
} }
_ => { _ => {
} }
@@ -452,12 +452,12 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
} }
(HeapCellValueTag::PStrLoc, vh) => { (HeapCellValueTag::PStrLoc, vh) => {
let cell = *cell; 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 // forward the current PStrLoc cell if the zero
// byte at the end of the string buffer // byte at the end of the string buffer
// is marked // 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 { if buf_bytes[7] != 0u8 {
let cell = self.read_cell_mut(h); 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. // is never inspected, which it isn't.
self.push_if_unmarked( 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); return Some(cell);
} }
@@ -502,7 +502,6 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
} }
} }
impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> { impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
type Item = HeapCellValue; type Item = HeapCellValue;
@@ -707,9 +706,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [atom_as_cell(a_atom), atom_as_cell(b_atom)]
atom_as_cell(b_atom)]), ));
);
let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).unwrap(); wam.machine_st.heap.push_cell(cell).unwrap();
@@ -733,7 +731,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -758,10 +756,7 @@ mod tests {
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(f_atom, 4) atom_as_cell!(f_atom, 4)
); );
assert_eq!( assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(0)
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(a_atom) atom_as_cell!(a_atom)
@@ -778,7 +773,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -794,7 +789,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -837,7 +832,7 @@ mod tests {
assert_eq!(iter.next(), None); 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. // now make the list cyclic.
wam.machine_st.heap[4] = heap_loc_as_cell!(0); wam.machine_st.heap[4] = heap_loc_as_cell!(0);
@@ -939,8 +934,6 @@ mod tests {
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(96).unwrap(); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -955,9 +948,11 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [
atom_as_cell(b_atom), atom_as_cell(a_atom),
atom_as_cell(b_atom)] atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
)); ));
functor_writer(&mut wam.machine_st.heap).unwrap(); functor_writer(&mut wam.machine_st.heap).unwrap();
@@ -1003,7 +998,7 @@ mod tests {
assert_eq!(iter.next(), None); 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); let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
@@ -1044,7 +1039,7 @@ mod tests {
// instance. // 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[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5)); assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
@@ -1074,7 +1069,7 @@ mod tests {
// instance. // 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[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5)); assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
@@ -1126,7 +1121,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -1147,7 +1142,7 @@ mod tests {
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
all_cells_unmarked(wam.machine_st.heap.splice(..)); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!( assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]), unmark_cell_bits!(wam.machine_st.heap[0]),
@@ -1193,7 +1188,7 @@ mod tests {
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
all_cells_unmarked(wam.machine_st.heap.splice(..)); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!( assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]), unmark_cell_bits!(wam.machine_st.heap[0]),
@@ -1427,7 +1422,10 @@ mod tests {
wam.machine_st.heap.clear(); 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); let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
@@ -1439,7 +1437,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -1473,7 +1471,7 @@ mod tests {
assert!(iter.next().is_none()); 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(); wam.machine_st.heap.clear();
@@ -1504,7 +1502,7 @@ mod tests {
assert!(iter.next().is_none()); 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(); wam.machine_st.heap.clear();
@@ -1564,7 +1562,7 @@ mod tests {
assert!(iter.next().is_none()); 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[0], str_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2)); 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); 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!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
list_loc_as_cell!(7) list_loc_as_cell!(7)
@@ -1693,9 +1684,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [atom_as_cell(a_atom), atom_as_cell(b_atom)]
atom_as_cell(b_atom)]), ));
);
let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
let h = wam.machine_st.heap.cell_len(); 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[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -2021,7 +2011,11 @@ mod tests {
let functor = functor!( let functor = functor!(
f_atom, 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(); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2098,7 +2092,7 @@ mod tests {
assert_eq!(iter.next(), None); 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); wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -2163,7 +2157,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -2202,7 +2196,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -2221,18 +2215,18 @@ mod tests {
2, 2,
); );
assert_eq!( assert_eq!(iter.heap.slice_to_str(0, "a string".len()), "a string");
iter.heap.slice_to_str(0, "a string".len()), assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
"a string"
);
assert_eq!(
iter.next().unwrap(),
empty_list_as_cell!()
);
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
@@ -2291,9 +2285,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [atom_as_cell(a_atom), atom_as_cell(b_atom)]
atom_as_cell(b_atom)]), ));
);
let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
let h = wam.machine_st.heap.cell_len(); let h = wam.machine_st.heap.cell_len();
@@ -2325,7 +2318,6 @@ mod tests {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[ [
@@ -2361,10 +2353,7 @@ mod tests {
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(a_atom) atom_as_cell!(a_atom)
); );
assert_eq!( assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(0)
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(f_atom, 4) 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[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -2616,7 +2605,11 @@ mod tests {
let functor = functor!( let functor = functor!(
f_atom, 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(); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2694,7 +2687,7 @@ mod tests {
assert_eq!(iter.next(), None); 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); wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -2761,7 +2754,7 @@ mod tests {
assert_eq!(iter.next(), None); 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(); wam.machine_st.heap.clear();
} }
@@ -2778,9 +2771,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [atom_as_cell(a_atom), atom_as_cell(b_atom)]
atom_as_cell(b_atom)]), ));
);
let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).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[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -3039,7 +3031,7 @@ mod tests {
assert_eq!(iter.next(), None); 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); wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
@@ -3053,11 +3045,18 @@ mod tests {
assert_eq!(iter.next(), None); 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(); 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(); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -3116,7 +3115,7 @@ mod tests {
assert_eq!(iter.next(), None); 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); wam.machine_st.heap[4] = list_loc_as_cell!(1);
@@ -3164,6 +3163,6 @@ mod tests {
assert_eq!(iter.next(), None); 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, 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..]; let tail = &outputter.as_str()[last_item_idx..];
if atom == "," || !quoted || non_quoted_token(atom.chars()) { if atom == "," || !quoted || non_quoted_token(atom.chars()) {
@@ -1132,7 +1137,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} }
macro_rules! emit_char { macro_rules! emit_char {
($c:expr) => ({ ($c:expr) => {{
append_str!(self, "'.'"); append_str!(self, "'.'");
push_char!(self, '('); push_char!(self, '(');
@@ -1141,14 +1146,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Close); self.state_stack.push(TokenOrRedirect::Close);
char_count += 1; char_count += 1;
}); }};
} }
match iteratee { match iteratee {
PStrIteratee::Char { value, .. } => { PStrIteratee::Char { value, .. } => {
emit_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); let s = iter.heap.slice_to_str(slice_loc, slice_len);
for c in s.chars() { for c in s.chars() {
@@ -1181,10 +1189,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if max_depth == 0 { if max_depth == 0 {
while let Some(iteratee) = iter.next() { while let Some(iteratee) = iter.next() {
let iter: Box<dyn Iterator<Item = char>> = match iteratee { let iter: Box<dyn Iterator<Item = char>> = match iteratee {
PStrIteratee::Char { value: c, .. } => { PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
Box::new(std::iter::once(c)) PStrIteratee::PStrSlice {
} slice_loc,
PStrIteratee::PStrSlice { slice_loc, slice_len } => { slice_len,
} => {
let s = iter.heap.slice_to_str(slice_loc, slice_len); let s = iter.heap.slice_to_str(slice_loc, slice_len);
Box::new(s.chars()) Box::new(s.chars())
} }
@@ -1201,10 +1210,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
while let Some(iteratee) = iter.next() { while let Some(iteratee) = iter.next() {
let iter: Box<dyn Iterator<Item = char>> = match iteratee { let iter: Box<dyn Iterator<Item = char>> = match iteratee {
PStrIteratee::Char { value: c, .. } => { PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
Box::new(std::iter::once(c)) PStrIteratee::PStrSlice {
} slice_loc,
PStrIteratee::PStrSlice { slice_loc, slice_len } => { slice_len,
} => {
let s = iter.heap.slice_to_str(slice_loc, slice_len); let s = iter.heap.slice_to_str(slice_loc, slice_len);
Box::new(s.chars()) 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::Atom(atom!("...")));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
} else { } else {
/* self.state_stack
let end_cell_h = Heap::neighboring_cell_offset(pstr_loc); .push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
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::HeadTailSeparator); self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
} }
} }
@@ -1872,9 +1868,8 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [atom_as_cell(a_atom), atom_as_cell(b_atom)]
atom_as_cell(b_atom)]), ));
);
let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).unwrap(); wam.machine_st.heap.push_cell(cell).unwrap();
@@ -1893,7 +1888,7 @@ mod tests {
assert_eq!(output.result(), "f(a,b)"); 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(); wam.machine_st.heap.clear();
@@ -1925,7 +1920,7 @@ mod tests {
assert_eq!(output.result(), "f(a,b,a,...)"); 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(); wam.machine_st.heap.clear();
@@ -1968,7 +1963,7 @@ mod tests {
assert_eq!(output.result(), "[L|L]"); 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(); wam.machine_st.heap.clear();
@@ -1984,9 +1979,11 @@ mod tests {
let mut functor_writer = Heap::functor_writer(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[atom_as_cell(a_atom), [
atom_as_cell(b_atom), atom_as_cell(a_atom),
atom_as_cell(b_atom)] atom_as_cell(b_atom),
atom_as_cell(b_atom)
]
)); ));
functor_writer(&mut wam.machine_st.heap).unwrap(); 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)]"); 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); 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)|...]"); 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( let mut printer = HCPrinter::new(
@@ -2043,7 +2040,7 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]"); 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 // issue #382
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
@@ -2077,7 +2074,7 @@ mod tests {
assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]"); 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(); wam.machine_st.heap.clear();
@@ -2100,7 +2097,7 @@ mod tests {
assert_eq!(output.result(), "[a,b,c|_1]"); 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(); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2131,7 +2128,7 @@ mod tests {
assert_eq!(output.result(), "\"abcabc\""); 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(); wam.machine_st.heap.clear();
@@ -2140,14 +2137,14 @@ mod tests {
"=(X,[a,b,c|X])" "=(X,[a,b,c|X])"
); );
all_cells_unmarked(wam.machine_st.heap.splice(..)); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(), &wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(),
"[a,b,[a],[a,b,c]]" "[a,b,[a],[a,b,c]]"
); );
all_cells_unmarked(wam.machine_st.heap.splice(..)); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].") &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]]" "[[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))"); 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 wam.op_dir
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX)); .insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
@@ -2171,14 +2168,14 @@ mod tests {
"[a|[]+b]" "[a|[]+b]"
); );
all_cells_unmarked(wam.machine_st.heap.splice(..)); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(), &wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
"[a|[b|c]*d]" "[a|[b|c]*d]"
); );
all_cells_unmarked(wam.machine_st.heap.splice(..)); all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir wam.op_dir
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY)); .insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -145,7 +145,9 @@ impl MachineState {
}; };
let mut iter = stackful_preorder_iter::<NonListElider>( 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() { 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> { pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
let key = match self let key = match self.payload.predicates.first().map(|term| term.focus) {
.payload Some(focus) => clause_predicate_key(self.machine_heap(), focus)
.predicates .ok_or(SessionError::NamelessEntry)?,
.first() None => {
.map(|term| term.focus) { return Err(SessionError::NamelessEntry);
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(); let listing_src_file_name = self.listing_src_file_name();
@@ -2290,13 +2284,18 @@ impl Machine {
term_reg: RegType, term_reg: RegType,
vars: Vec<HeapCellValue>, vars: Vec<HeapCellValue>,
) -> Result<(), SessionError> { ) -> 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 new_header_loc = self.machine_st.heap.cell_len();
let arity = vars.len(); let arity = vars.len();
let term_loc = self.machine_st.heap.cell_len() + 1 + arity; 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()))?; .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
writer.write_with(move |section| { writer.write_with(move |section| {

View File

@@ -1,13 +1,71 @@
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::get_structure_index; use crate::machine::get_structure_index;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::stack::*; use crate::machine::stack::*;
use crate::types::*; use crate::types::*;
use scryer_modular_bitfield::specifiers::*;
use scryer_modular_bitfield::*;
use std::collections::BTreeMap;
use std::mem; use std::mem;
use std::ops::{IndexMut, Range}; 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)] #[derive(Debug, Clone, Copy)]
pub enum AttrVarPolicy { pub enum AttrVarPolicy {
@@ -18,15 +76,12 @@ pub enum AttrVarPolicy {
pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> { pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
fn store(&self, value: HeapCellValue) -> HeapCellValue; fn store(&self, value: HeapCellValue) -> HeapCellValue;
fn deref(&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 push_attr_var_queue(&mut self, attr_var_loc: usize);
fn stack(&mut self) -> &mut Stack; fn stack(&mut self) -> &mut Stack;
fn threshold(&self) -> usize; fn threshold(&self) -> usize;
// returns the tail location of the pstr on success // 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 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 reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize>;
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), 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, target: T,
addr: HeapCellValue, addr: HeapCellValue,
attr_var_policy: AttrVarPolicy, attr_var_policy: AttrVarPolicy,
) -> Result<(), usize> { ) -> Result<usize, usize> {
let mut copy_term_state = CopyTermState::new(target, attr_var_policy); 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_term_impl(addr)?;
copy_term_state.copy_attr_var_lists()?; copy_term_state.copy_attr_var_lists()?;
copy_term_state.unwind_trail(); 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)] #[derive(Debug)]
@@ -53,6 +119,9 @@ struct CopyTermState<T: CopierTarget> {
target: T, target: T,
attr_var_policy: AttrVarPolicy, attr_var_policy: AttrVarPolicy,
attr_var_list_locs: Vec<(usize, HeapCellValue)>, 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> { impl<T: CopierTarget> CopyTermState<T> {
@@ -64,6 +133,7 @@ impl<T: CopierTarget> CopyTermState<T> {
target, target,
attr_var_policy, attr_var_policy,
attr_var_list_locs: vec![], 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) { fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
let trail_item = mem::replace(&mut self.target[addr], list_loc_as_cell!(threshold)); 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> { fn copy_list(&mut self, addr: usize) -> Result<(), usize> {
@@ -93,7 +163,7 @@ impl<T: CopierTarget> CopyTermState<T> {
} }
let threshold = self.target.threshold(); 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); *self.value_at_scan() = list_loc_as_cell!(threshold);
@@ -122,54 +192,90 @@ impl<T: CopierTarget> CopyTermState<T> {
Ok(()) 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> { fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> {
let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc); match self.pstr_loc_locs.range_mut(..=pstr_loc).next_back() {
let head_byte_idx = heap_index!(head_cell_idx); Some((
let pstr_offset = pstr_loc - head_byte_idx; _prev_pstr_loc,
&mut PStrData {
// if a partial string has been copied previously, we pre_old_h_tail_loc,
// track it by writing a null byte to its first word, which is trailed, ref mut post_old_h_pstr_loc_locs,
// and then the new pstr_loc in the word's remaining 7 bytes. see write_pstr_index ..
// comment. },
)) if pre_old_h_tail_loc >= cell_index!(pstr_loc) => {
if self.target[head_cell_idx].into_bytes()[0] == 0u8 { post_old_h_pstr_loc_locs.insert(self.scan);
let head_bytes = self.target[head_cell_idx].into_bytes(); self.scan += 1;
let new_pstr_loc = u64::from_be_bytes(head_bytes) as usize; return Ok(());
}
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(new_pstr_loc) + pstr_offset); _ => {}
self.scan += 1;
return Ok(());
} }
let threshold = self.target.threshold(); let offset = self
let tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?; .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])); if flag == 1 {
self.write_pstr_index(head_cell_idx, threshold); 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]; pstr_data.post_old_h_pstr_loc_locs.insert(self.scan);
let mut writer = self.target.reserve(1)?; self.pstr_loc_locs
.insert(heap_index!(cell_index!(pstr_loc)), pstr_data);
writer.write_with(|section| { let old_cell = self.target[pstr_loc_idx];
section.push_cell(tail_cell); 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; self.scan += 1;
Ok(()) Ok(())
} }
@@ -210,6 +316,7 @@ impl<T: CopierTarget> CopyTermState<T> {
}); });
debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str); debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
self.copy_term_impl(str_cell)?; self.copy_term_impl(str_cell)?;
list_addr = self.target[heap_loc + 1]; 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[frontier] = heap_loc_as_cell!(frontier);
self.target[h] = 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) => { (HeapCellValueTag::StackVar, s) => {
self.target[frontier] = heap_loc_as_cell!(frontier); self.target[frontier] = heap_loc_as_cell!(frontier);
self.target.stack()[s] = 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) => { (HeapCellValueTag::AttrVar, h) => {
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy { 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[frontier] = heap_loc_as_cell!(threshold);
self.target[h] = 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 { 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| { writer.write_with(|section| {
section.push_cell(attr_var_as_cell!(threshold)); 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]; 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); self.target[h + 1] = heap_loc_as_cell!(threshold + 1);
if old_list_link.get_tag() == HeapCellValueTag::Lis { if old_list_link.get_tag() == HeapCellValueTag::Lis {
@@ -317,7 +424,21 @@ impl<T: CopierTarget> CopyTermState<T> {
(HeapCellValueTag::Atom, (_name, arity)) => { (HeapCellValueTag::Atom, (_name, arity)) => {
let threshold = self.target.threshold(); 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)?; self.target.copy_slice_to_end(addr .. addr + 1 + arity)?;
@@ -326,28 +447,7 @@ impl<T: CopierTarget> CopyTermState<T> {
str_loc_as_cell!(threshold), str_loc_as_cell!(threshold),
); );
self.trail.push((Ref::heap_cell(addr), trail_item)); self.trail.push((TrailRef::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);
});
}
}
} }
(HeapCellValueTag::Str, h) => { (HeapCellValueTag::Str, h) => {
*self.value_at_scan() = str_loc_as_cell!(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() { 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(); let addr = *self.value_at_scan();
read_heap_cell!(addr, read_heap_cell!(addr,
@@ -405,17 +500,40 @@ impl<T: CopierTarget> CopyTermState<T> {
Ok(()) Ok(())
} }
fn unwind_trail(mut self) { fn copy_pstrs(&mut self) -> Result<(), usize> {
for (r, value) in self.trail { while let Some((least_pstr_loc, pstr_data)) = self.pstr_loc_locs.pop_first() {
let index = r.get_value() as usize; let threshold = heap_index!(self.target.threshold());
match r.get_tag() { for pstr_loc_loc in pstr_data.post_old_h_pstr_loc_locs {
RefTag::AttrVar | RefTag::HeapCell => { 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] = value;
self.target[index].set_mark_bit(false); self.target[index].set_mark_bit(false);
self.target[index].set_forwarding_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 a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
let mut functor_writer = Heap::functor_writer( let mut functor_writer = Heap::functor_writer(functor!(
functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]), f_atom,
); [atom_as_cell(a_atom), atom_as_cell(b_atom)]
));
functor_writer(&mut wam.machine_st.heap).unwrap(); 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(); copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
} }
assert_eq!( assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc ");
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[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!( 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" "def"
); );
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(0)); 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!( 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 " "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!( 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" "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(); 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[2], atom_as_cell!(b_atom));
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(a_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[4], str_loc_as_cell!(0));
assert_eq!(wam.machine_st.heap[5], str_loc_as_cell!(6)); 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[6], atom_as_cell!(f_atom, 4));
assert_eq!(wam.machine_st.heap[7], atom_as_cell!(a_atom)); assert_eq!(wam.machine_st.heap[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 => { HeapCellValueTag::PStrLoc => {
let h = self.next as usize; 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() { if self.cycle_detection_active() {
self.cycle_found = true; self.cycle_found = true;
return None; return None;
@@ -219,11 +219,11 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
continue; 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.next = self.heap[tail_idx].get_value();
self.heap[last_cell_loc].set_value(self.current as u64); self.heap[tail_idx].set_value(self.current as u64);
self.current = last_cell_loc; self.current = tail_idx;
return Some(pstr_loc_as_cell!(h)); return Some(pstr_loc_as_cell!(h));
} }

View File

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

View File

@@ -140,10 +140,7 @@ impl MachineState {
let a1 = self.registers[1]; let a1 = self.registers[1];
let a2 = self.registers[2]; let a2 = self.registers[2];
step_or_resource_error!( step_or_resource_error!(self, copy_term(CopyTerm::new(self), a1, attr_var_policy));
self,
copy_term(CopyTerm::new(self), a1, attr_var_policy)
);
unify_fn!(*self, heap_loc_as_cell!(old_h), a2); unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
} }
@@ -162,11 +159,7 @@ impl MachineState {
let heap_addr = resource_error_call_result!( let heap_addr = resource_error_call_result!(
self, self,
sized_iter_to_heap_list( sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter(),)
&mut self.heap,
list.len(),
list.into_iter(),
)
); );
let target_addr = self.registers[2]; let target_addr = self.registers[2];
@@ -5155,9 +5148,8 @@ impl Machine {
let r = self.machine_st.registers[2]; let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r)); let r = self.machine_st.store(self.machine_st.deref(r));
let mut writer = Heap::functor_writer( let mut writer =
functor!(atom!("-"), [fixnum(n), fixnum(p)]), Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
);
let str_cell = backtrack_on_resource_error!( let str_cell = backtrack_on_resource_error!(
&mut self.machine_st, &mut self.machine_st,
@@ -5178,9 +5170,8 @@ impl Machine {
let r = self.machine_st.registers[2]; let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r)); let r = self.machine_st.store(self.machine_st.deref(r));
let mut writer = Heap::functor_writer( let mut writer =
functor!(atom!("-"), [fixnum(n), fixnum(p)]), Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
);
let str_cell = backtrack_on_resource_error!( let str_cell = backtrack_on_resource_error!(
&mut self.machine_st, &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::alloc;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::mem;
use std::ops::{Bound, Index, IndexMut, Range, RangeBounds}; use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
use std::ptr; use std::ptr;
use std::sync::Once; use std::sync::Once;
use super::MachineState; use super::MachineState;
use bitvec::prelude::*;
use bitvec::slice::BitSlice;
const ALIGN: usize = Heap::heap_cell_alignment(); const ALIGN: usize = Heap::heap_cell_alignment();
#[derive(Debug)] #[derive(Debug)]
pub struct Heap { pub struct Heap {
inner: InnerHeap, inner: InnerHeap,
pstr_vec: BitVec,
resource_err_loc: usize, resource_err_loc: usize,
} }
@@ -90,40 +85,51 @@ unsafe impl Sync for Heap {}
static RESOURCE_ERROR_OFFSET_INIT: Once = Once::new(); 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. // return the string at ptr and the tail location relative to ptr.
// pstr_vec records the location of each string cell starting at index unsafe fn scan_slice_to_str<'a>(heap_slice: &'a [u8]) -> HeapStringScan<'a> {
// 0. let string_len = heap_slice.iter().position(|b| *b == 0u8).unwrap();
fn scan_slice_to_str(orig_ptr: *const u8, pstr_vec: &BitSlice) -> (&str, usize) { let zero_byte_addr = heap_slice.as_ptr().add(string_len);
unsafe { let sentinel_len = pstr_sentinel_length(zero_byte_addr as usize);
debug_assert_eq!(pstr_vec[0], true); 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 str_slice = &heap_slice[..string_len];
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);
// skip the final buffer byte which may not be 0 depending on HeapStringScan {
// the context, i.e. marking by an iterator. it is counted by string: std::str::from_utf8_unchecked(str_slice),
// the initial 1 as part of the padding but for this reason tail_idx,
// 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)
} }
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) enum PStrSegmentCmpResult { pub(crate) enum PStrSegmentCmpResult {
Mismatch { c1: char, c2: char }, Mismatch {
FirstMatch { pstr_loc1: usize, pstr_loc2: usize, l1_offset: usize }, c1: char,
SecondMatch { pstr_loc1: usize, pstr_loc2: usize, l2_offset: usize }, c2: char,
BothMatch { pstr_loc1: usize, pstr_loc2: usize, null_offset: usize }, },
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 { impl PStrSegmentCmpResult {
@@ -132,24 +138,36 @@ impl PStrSegmentCmpResult {
pdl: &mut Vec<HeapCellValue>, pdl: &mut Vec<HeapCellValue>,
) -> Option<std::cmp::Ordering> { ) -> Option<std::cmp::Ordering> {
match self { match self {
PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset } => { PStrSegmentCmpResult::FirstMatch {
let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + l1_offset); 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); let rest_of_l2 = pstr_loc_as_cell!(pstr_loc2 + l1_offset);
pdl.push(heap_loc_as_cell!(tail1)); pdl.push(heap_loc_as_cell!(tail1));
pdl.push(rest_of_l2); pdl.push(rest_of_l2);
} }
PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset } => { PStrSegmentCmpResult::SecondMatch {
let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + l2_offset); 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); let rest_of_l1 = pstr_loc_as_cell!(pstr_loc1 + l2_offset);
pdl.push(rest_of_l1); pdl.push(rest_of_l1);
pdl.push(heap_loc_as_cell!(tail2)); 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 // exhaustive match
let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + null_offset); let tail1 = Heap::pstr_tail_idx(pstr_loc1 + null_offset);
let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + 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!(tail1));
pdl.push(heap_loc_as_cell!(tail2)); 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)] #[derive(Debug)]
pub struct PStrWriteInfo { pub struct PStrWriteInfo {
pstr_loc: usize, pstr_loc: usize,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ReservedHeapSection<'a> { pub(crate) struct ReservedHeapSection {
heap_ptr: *mut u8, heap_ptr: *mut u8,
heap_cell_len: usize, heap_cell_len: usize,
pstr_vec: &'a mut BitVec,
} }
impl<'a> ReservedHeapSection<'a> { impl ReservedHeapSection {
#[inline] #[inline]
pub(crate) fn cell_len(&self) -> usize { pub(crate) fn cell_len(&self) -> usize {
self.heap_cell_len self.heap_cell_len
@@ -326,16 +200,16 @@ impl<'a> ReservedHeapSection<'a> {
pub(crate) fn push_cell(&mut self, cell: HeapCellValue) { pub(crate) fn push_cell(&mut self, cell: HeapCellValue) {
unsafe { 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; self.heap_cell_len += 1;
} }
fn push_pstr_segment( fn push_pstr_segment(&mut self, src: &str) -> usize {
&mut self,
src: &str,
) -> usize {
if src.is_empty() { if src.is_empty() {
return 0; return 0;
} }
@@ -354,23 +228,30 @@ impl<'a> ReservedHeapSection<'a> {
let align_offset = pstr_sentinel_length(zero_region_idx); let align_offset = pstr_sentinel_length(zero_region_idx);
ptr::write_bytes( ptr::write_bytes(self.heap_ptr.add(zero_region_idx), 0u8, align_offset);
self.heap_ptr.add(zero_region_idx),
0u8, cells_written = if align_offset == 1 {
align_offset, 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; self.heap_cell_len += cells_written;
} }
cells_written cells_written
} }
pub(crate) fn push_pstr( pub(crate) fn push_pstr(&mut self, mut src: &str) -> Option<HeapCellValue> {
&mut self,
mut src: &str,
) -> Option<HeapCellValue> {
let orig_h = self.cell_len(); let orig_h = self.cell_len();
if src.is_empty() { if src.is_empty() {
@@ -386,18 +267,14 @@ impl<'a> ReservedHeapSection<'a> {
loop { loop {
let null_char_idx = src.find('\u{0}').unwrap_or_else(|| src.len()); 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 cells_written = self.push_pstr_segment(&src[0..null_char_idx]);
let tail_idx = self.cell_len(); let tail_idx = self.cell_len();
self.pstr_vec.resize(cell_len + cells_written, true);
if cells_written == 0 { if cells_written == 0 {
return None; return None;
} else if null_char_idx + 1 < src.len() { } else if null_char_idx + 1 < src.len() {
self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1))); 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 { } else {
return Some(pstr_loc_as_cell!(heap_index!(orig_h))); return Some(pstr_loc_as_cell!(heap_index!(orig_h)));
} }
@@ -420,7 +297,12 @@ impl<'a> ReservedHeapSection<'a> {
cursor: 0, 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() { while cursor < functor.len() {
match &functor[cursor] { match &functor[cursor] {
&FunctorElement::AbsoluteCell(cell) => { &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; type Output = HeapCellValue;
#[inline] #[inline]
fn index(&self, idx: usize) -> &Self::Output { fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(idx < self.heap_cell_len); debug_assert!(idx < self.heap_cell_len);
unsafe { unsafe { &*(self.heap_ptr as *const HeapCellValue).add(idx) }
&*(self.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
}
} }
} }
@@ -489,7 +369,7 @@ fn pstr_sentinel_length(chunk_len: usize) -> usize {
#[must_use] #[must_use]
#[derive(Debug)] #[derive(Debug)]
pub struct HeapWriter<'a> { pub struct HeapWriter<'a> {
section: ReservedHeapSection<'a>, section: ReservedHeapSection,
heap_byte_len: &'a mut usize, 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); *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
// return the number of bytes written // 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( pub(crate) fn write_with(&mut self, writer: impl FnOnce(&mut ReservedHeapSection)) -> usize {
&mut self,
writer: impl FnOnce(&mut ReservedHeapSection),
) -> usize {
let old_section_cell_len = self.section.heap_cell_len; let old_section_cell_len = self.section.heap_cell_len;
writer(&mut self.section); writer(&mut self.section);
*self.heap_byte_len = heap_index!(self.section.heap_cell_len); *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
@@ -522,7 +401,7 @@ impl<'a> HeapWriter<'a> {
#[inline] #[inline]
pub(crate) fn truncate(&mut self, cell_offset: usize) { pub(crate) fn truncate(&mut self, cell_offset: usize) {
self.section.heap_cell_len = cell_offset; 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); *self.heap_byte_len = heap_index!(cell_offset);
} }
@@ -543,9 +422,7 @@ impl<'a> Index<usize> for HeapWriter<'a> {
#[inline] #[inline]
fn index(&self, idx: usize) -> &Self::Output { fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(heap_index!(idx) < *self.heap_byte_len); debug_assert!(heap_index!(idx) < *self.heap_byte_len);
unsafe { unsafe { &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) }
&*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
}
} }
} }
@@ -553,9 +430,7 @@ impl<'a> IndexMut<usize> for HeapWriter<'a> {
#[inline] #[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output { fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
debug_assert!(heap_index!(idx) < *self.heap_byte_len); debug_assert!(heap_index!(idx) < *self.heap_byte_len);
unsafe { unsafe { &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue) }
&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() self.section.cell_len()
} }
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) { fn scan_slice_to_str(&self, slice_loc: usize) -> HeapStringScan {
let (s, tail_cell_offset) = scan_slice_to_str( let HeapStringScan { string, tail_idx } = unsafe {
unsafe { self.section.heap_ptr.add(slice_loc) }, let slice = std::slice::from_raw_parts(
&self.section.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..], 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 { fn as_slice(&self) -> &[u8] {
self.section.pstr_vec[cell_offset] 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_len: 0,
byte_cap: 0, byte_cap: 0,
}, },
pstr_vec: bitvec![],
resource_err_loc: 0, 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)] #[inline(always)]
unsafe fn grow(&mut self) -> bool { unsafe fn grow(&mut self) -> bool {
let result = self.inner.grow(); self.inner.grow()
if result {
self.pstr_vec.reserve(cell_index!(self.inner.byte_cap));
}
result
} }
#[inline] #[inline]
@@ -624,7 +514,7 @@ impl Heap {
byte_len: 0, byte_len: 0,
byte_cap: heap_index!(cap), byte_cap: heap_index!(cap),
}, },
pstr_vec: bitvec![], // pstr_vec: bitvec![],
resource_err_loc: 0, resource_err_loc: 0,
}) })
} }
@@ -641,7 +531,6 @@ impl Heap {
section = ReservedHeapSection { section = ReservedHeapSection {
heap_ptr: self.inner.ptr, heap_ptr: self.inner.ptr,
heap_cell_len: self.cell_len(), heap_cell_len: self.cell_len(),
pstr_vec: &mut self.pstr_vec,
}; };
break; break;
} else if !self.grow() { } 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> { pub(crate) fn last_cell(&mut self) -> Option<HeapCellValue> {
if self.inner.byte_len == 0 { if self.inner.byte_len == 0 {
None None
} else { } else {
unsafe { unsafe {
Some(ptr::read(self.inner.ptr.add(self.inner.byte_len - heap_index!(1)) Some(ptr::read(
as *const HeapCellValue)) 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] #[inline]
pub(crate) fn is_empty(&self) -> bool { pub(crate) fn is_empty(&self) -> bool {
self.inner.byte_len == 0 self.inner.byte_len == 0
@@ -703,31 +606,31 @@ impl Heap {
self.inner.byte_len = 0; self.inner.byte_len = 0;
self.inner.byte_cap = 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> { // pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> {
unsafe { // unsafe {
loop { // loop {
if self.free_space() >= heap_index!(heap_slice.slice_cell_len) { // if self.free_space() >= heap_index!(heap_slice.slice_cell_len) {
ptr::copy_nonoverlapping( // ptr::copy_nonoverlapping(
heap_slice.slice, // heap_slice.slice,
self.inner.ptr.add(self.inner.byte_len), // self.inner.ptr.add(self.inner.byte_len),
heap_index!(heap_slice.slice_cell_len), // heap_index!(heap_slice.slice_cell_len),
); // );
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.pstr_vec.extend(heap_slice.pstr_slice.iter());
break; // break;
} else if !self.grow() { // } else if !self.grow() {
return Err(self.resource_error_offset()); // return Err(self.resource_error_offset());
} // }
} // }
} // }
Ok(()) // Ok(())
} // }
pub(crate) fn store_resource_error(&mut self) { pub(crate) fn store_resource_error(&mut self) {
RESOURCE_ERROR_OFFSET_INIT.call_once(move || { RESOURCE_ERROR_OFFSET_INIT.call_once(move || {
@@ -763,11 +666,23 @@ impl Heap {
for ((idx, c1), c2) in str1.char_indices().zip(str2.chars()) { for ((idx, c1), c2) in str1.char_indices().zip(str2.chars()) {
if c1 == '\u{0}' && c2 == '\u{0}' { 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}' { } 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}' { } 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 { } else if c1 != c2 {
return PStrSegmentCmpResult::Mismatch { c1, c2 }; return PStrSegmentCmpResult::Mismatch { c1, c2 };
} }
@@ -822,7 +737,7 @@ impl Heap {
// - Invariant: from `InnerHeap`, `self.inner.byte_cap < isize::MAX`. // - Invariant: from `InnerHeap`, `self.inner.byte_cap < isize::MAX`.
let cell_ptr = (self.inner.ptr as *mut HeapCellValue).add(self.cell_len()); let cell_ptr = (self.inner.ptr as *mut HeapCellValue).add(self.cell_len());
cell_ptr.write(cell); cell_ptr.write(cell);
self.pstr_vec.push(false); // self.pstr_vec.push(false);
self.inner.byte_len += heap_index!(1); self.inner.byte_len += heap_index!(1);
} }
@@ -866,6 +781,7 @@ impl Heap {
Range { start, end } Range { start, end }
} }
/*
pub(crate) fn splice<R: RangeBounds<usize>>( pub(crate) fn splice<R: RangeBounds<usize>>(
&self, &self,
range: R, range: R,
@@ -876,7 +792,7 @@ impl Heap {
slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) }, slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
cell_offset: range.start, cell_offset: range.start,
slice_cell_len: range.end - 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)) }, slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
cell_offset: range.start, cell_offset: range.start,
slice_cell_len: range.end - 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> { pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
let size_in_heap = Self::compute_pstr_size(src); 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 // yes, size_of, not align_of. the alignment of HeapCellValue
// is 1 byte. In the heap, though, its alignment must be its // is 1 byte. In the heap, though, its alignment must be its
// size. // size.
mem::size_of::<HeapCellValue>() 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()
} }
#[inline] #[inline]
pub(crate) fn char_at(&self, byte_idx: usize) -> char { pub(crate) fn char_at(&self, byte_idx: usize) -> char {
let s = unsafe { let s = unsafe {
let char_ptr = self.inner.ptr.add(byte_idx); 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) std::str::from_utf8_unchecked(&slice)
}; };
@@ -961,7 +857,7 @@ impl Heap {
let succ_len = loc + c.len_utf8(); let succ_len = loc + c.len_utf8();
if chars_iter.next() == Some('\u{0}') { 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 { } else {
(c, pstr_loc_as_cell!(succ_len)) (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 // copies only the string, not its tail. returns the cell index of
// the tail location // the tail location
pub(crate) fn copy_pstr_within(&mut self, pstr_loc: usize) -> Result<usize, usize> { 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 HeapStringScan { string, tail_idx } = self.scan_slice_to_str(pstr_loc);
let s_len = s.len(); let s_len = string.len();
let align_offset = pstr_sentinel_length(s_len); let align_offset = pstr_sentinel_length(s_len);
let copy_size = s_len + align_offset; let copy_size = s_len + align_offset;
@@ -980,15 +876,10 @@ impl Heap {
unsafe { unsafe {
loop { loop {
if self.free_space() >= copy_size { if self.free_space() >= copy_size {
let slice = std::slice::from_raw_parts_mut( let slice =
self.inner.ptr, std::slice::from_raw_parts_mut(self.inner.ptr, self.inner.byte_len + s_len);
self.inner.byte_len + s_len,
);
slice.copy_within( slice.copy_within(pstr_loc..pstr_loc + s_len, self.inner.byte_len);
pstr_loc .. pstr_loc + s_len,
self.inner.byte_len,
);
ptr::write_bytes( ptr::write_bytes(
self.inner.ptr.add(self.inner.byte_len + s_len), self.inner.ptr.add(self.inner.byte_len + s_len),
@@ -996,8 +887,17 @@ impl Heap {
align_offset, align_offset,
); );
self.inner.byte_len += copy_size; if align_offset == 1 {
self.pstr_vec.resize(self.cell_len(), true); 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; break;
} else if !self.grow() { } else if !self.grow() {
@@ -1006,7 +906,7 @@ impl Heap {
} }
} }
Ok(tail_loc) Ok(tail_idx)
} }
// src is a cell-indexed range. // src is a cell-indexed range.
@@ -1023,7 +923,7 @@ impl Heap {
heap_index!(len), 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); self.inner.byte_len += heap_index!(len);
break; break;
@@ -1059,10 +959,14 @@ impl Heap {
byte_size += null_idx + pstr_sentinel_length(null_idx); 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 { if (null_idx + 1) % ALIGN == 0 {
byte_size += 2 * mem::size_of::<HeapCellValue>(); byte_size += 2 * size_of::<HeapCellValue>();
} else { } else {
byte_size += mem::size_of::<HeapCellValue>(); byte_size += size_of::<HeapCellValue>();
} }
if null_idx + 1 >= src.len() { if null_idx + 1 >= src.len() {
@@ -1082,13 +986,13 @@ impl Heap {
while idx < functor.len() { while idx < functor.len() {
match &functor[idx] { match &functor[idx] {
&FunctorElement::InnerFunctor(inner_cell_size, ref _inner_functor) => { &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) => { FunctorElement::AbsoluteCell(_cell) | FunctorElement::Cell(_cell) => {
byte_size += mem::size_of::<HeapCellValue>(); byte_size += size_of::<HeapCellValue>();
} }
&FunctorElement::String(cell_len, _) => { &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] #[inline]
pub(crate) fn truncate(&mut self, cell_offset: usize) { pub(crate) fn truncate(&mut self, cell_offset: usize) {
self.inner.byte_len = heap_index!(cell_offset); 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> { pub(crate) struct PStrSegmentIter<'a> {
string_buf: &'a str, string_buf: &'a str,
} }
@@ -1153,7 +1055,7 @@ impl<'a> Iterator for PStrSegmentIter<'a> {
if c == '\u{0}' { if c == '\u{0}' {
None None
} else { } else {
self.string_buf = &self.string_buf[c.len_utf8() ..]; self.string_buf = &self.string_buf[c.len_utf8()..];
Some(c) Some(c)
} }
}) })
@@ -1187,14 +1089,15 @@ pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
fn cell_len(&self) -> usize; fn cell_len(&self) -> usize;
// return a pointer to the heap string and the cell index of its tail // 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. // 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 { impl Index<usize> for Heap {
type Output = HeapCellValue; type Output = HeapCellValue;
@@ -1215,62 +1118,29 @@ impl SizedHeap for Heap {
self.cell_len() self.cell_len()
} }
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) { fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a> {
let (s, tail_cell_offset) = scan_slice_to_str( let HeapStringScan { string, tail_idx } = unsafe {
unsafe { self.inner.ptr.add(slice_loc) }, let slice = std::slice::from_raw_parts(
&self.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..], 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 { fn as_slice(&self) -> &[u8] {
self.pstr_vec[cell_offset] unsafe { std::slice::from_raw_parts(self.inner.ptr, self.inner.byte_len) }
} }
} }
impl SizedHeapMut for Heap {} 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 // sometimes we need to dereference variables that are found only in
// the heap without access to the full WAM (e.g., while detecting // the heap without access to the full WAM (e.g., while detecting
// cycles in terms), and which therefore may only point other cells in // 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)] #[allow(dead_code)]
pub fn print_heap_terms<'a, I: Iterator<Item = HeapCellValue>>(heap: I, h: usize) { pub fn print_heap_terms(heap: &Heap, h: usize) {
for (index, term) in heap.enumerate() { for idx in 0..heap.cell_len() {
println!("{} : {:?}", h + index, term); let term = heap[idx];
println!("{} : {:?}", h + idx, term);
} }
} }

View File

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

View File

@@ -27,15 +27,14 @@ impl TermWriteResult {
heap[0] = value; heap[0] = value;
let inverse_var_locs = inverse_var_locs_from_iter( let inverse_var_locs = inverse_var_locs_from_iter(stackful_preorder_iter::<NonListElider>(
stackful_preorder_iter::<NonListElider>( heap, &mut stack, 0,
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 composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
let mut term = load_state.term_stream.next(&composite_op_dir)?; let mut term = load_state.term_stream.next(&composite_op_dir)?;
let predicate_focus_opt = load_state.predicates.first().map(|term_write_result| { let predicate_focus_opt = load_state
term_write_result.focus .predicates
}); .first()
.map(|term_write_result| term_write_result.focus);
let machine_st = LS::machine_st(&mut self.payload); let machine_st = LS::machine_st(&mut self.payload);
let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus); 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 cell = machine_st[r];
let focus = machine_st.heap.cell_len(); 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()))?; .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)?; let export_list = setup_module_export_list(export_list)?;
Ok(export_list.into_iter().collect()) 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)) Ok(
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?) TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?,
)
} }
fn add_extensible_predicate_declaration( fn add_extensible_predicate_declaration(
@@ -1628,18 +1635,15 @@ impl Machine {
}; };
let value = self.machine_st.registers[2]; let value = self.machine_st.registers[2];
let term = resource_error_call_result!( let term = resource_error_call_result!(
self.machine_st, self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value) TermWriteResult::from(&mut self.machine_st.heap, value)
); );
let add_clause = || { let add_clause = || {
let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) { let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) {
Some((atom!(":-"), _)) => { Some((atom!(":-"), _)) => term_nth_arg(&self.machine_st.heap, term.focus, 1)
term_nth_arg(&self.machine_st.heap, term.focus, 1).and_then(|h| { .and_then(|h| term_nth_arg(&self.machine_st.heap, h, 1)),
term_nth_arg(&self.machine_st.heap, h, 1)
})
}
Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1), Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1),
None => None, None => None,
}; };
@@ -2240,9 +2244,11 @@ impl Machine {
}; };
let mut loader = self.loader_from_heap_evacuable(temp_v!(4)); let mut loader = self.loader_from_heap_evacuable(temp_v!(4));
let predicate_focus_opt = loader.payload.predicates.first().map(|term_write_result| { let predicate_focus_opt = loader
term_write_result.focus .payload
}); .predicates
.first()
.map(|term_write_result| term_write_result.focus);
let is_consistent = if let Some(predicate_focus) = predicate_focus_opt { let is_consistent = if let Some(predicate_focus) = predicate_focus_opt {
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload); let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
@@ -2253,7 +2259,7 @@ impl Machine {
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail = LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
(!loader.payload.predicates.is_empty() (!loader.payload.predicates.is_empty()
&& loader.payload.predicates.compilation_target != compilation_target) && loader.payload.predicates.compilation_target != compilation_target)
|| !is_consistent; || !is_consistent;
let result = LiveLoadAndMachineState::evacuate(loader); let result = LiveLoadAndMachineState::evacuate(loader);

View File

@@ -187,7 +187,11 @@ impl PermissionError for HeapCellValue {
let stub = functor!( let stub = functor!(
atom!("permission_error"), 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 { MachineError {
@@ -226,7 +230,10 @@ pub(super) trait DomainError {
impl DomainError for HeapCellValue { impl DomainError for HeapCellValue {
fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { 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 { MachineError {
stub, stub,
@@ -239,7 +246,10 @@ impl DomainError for Number {
fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!( let stub = functor!(
atom!("domain_error"), 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 { MachineError {
@@ -280,7 +290,10 @@ impl MachineState {
} }
pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError { 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 { MachineError {
stub, stub,
@@ -297,7 +310,10 @@ impl MachineState {
) )
} }
ResourceError::OutOfFiles => { 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( SessionError::CannotOverwriteBuiltIn(key) => self.permission_error(
Permission::Modify, Permission::Modify,
atom!("static_procedure"), atom!("static_procedure"),
functor_stub(key.0, key.1) functor_stub(key.0, key.1),
), ),
SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error( SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
Permission::Modify, Permission::Modify,
atom!("static_procedure"), atom!("static_procedure"),
functor_stub(key.0, key.1) functor_stub(key.0, key.1),
), ),
SessionError::CannotOverwriteBuiltInModule(module) => { SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(Permission::Modify, atom!("static_module"), module) self.permission_error(Permission::Modify, atom!("static_module"), module)
@@ -559,14 +575,14 @@ impl MachineState {
let stub = functor!(atom!("syntax_error"), [functor(stub)]); let stub = functor!(atom!("syntax_error"), [functor(stub)]);
MachineError { MachineError { stub, location }
stub,
location,
}
} }
pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError { 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 { MachineError {
stub, stub,
@@ -593,13 +609,19 @@ impl MachineState {
} }
pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub { pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
if let Some(ParserErrorSrc { line_num, .. }) = err.location { if let Some(ParserErrorSrc { line_num, .. }) = err.location {
functor!(atom!("error"), [functor((err.stub)), functor!(
functor((atom!(":")), [functor(src), atom!("error"),
number(line_num, (&mut self.arena))])]) [
functor((err.stub)),
functor(
(atom!(":")),
[functor(src), number(line_num, (&mut self.arena))]
)
]
)
} else { } else {
functor!(atom!("error"), [functor((err.stub)), functor!(atom!("error"), [functor((err.stub)), functor(src)])
functor(src)])
} }
} }
@@ -826,13 +848,29 @@ impl EvalError {
// used by '$skip_max_list'. // used by '$skip_max_list'.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CycleSearchResult { pub enum CycleSearchResult {
Cyclic { lambda: usize }, // number of steps Cyclic {
lambda: usize,
}, // number of steps
EmptyList, EmptyList,
NotList { num_steps: usize, heap_loc: HeapCellValue }, NotList {
PartialList { num_steps: usize, heap_loc: HeapCellValue }, num_steps: usize,
ProperList { num_steps: usize }, heap_loc: HeapCellValue,
PStrLocation { num_steps: usize, pstr_loc: HeapCellValue }, },
UntouchedList { num_steps: usize, list_loc: usize }, 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 { impl MachineState {
@@ -856,7 +894,9 @@ impl MachineState {
}; };
match BrentAlgState::detect_cycles(&self.heap, sorted) { 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); let err = self.type_error(ValidType::List, sorted);
Err(self.error_form(err, stub_gen())) Err(self.error_form(err, stub_gen()))
} }
@@ -868,7 +908,9 @@ impl MachineState {
let stub_gen = || functor_stub(atom!("keysort"), 2); let stub_gen = || functor_stub(atom!("keysort"), 2);
match BrentAlgState::detect_cycles(&self.heap, list) { 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); let err = self.type_error(ValidType::List, list);
Err(self.error_form(err, stub_gen())) Err(self.error_form(err, stub_gen()))
} }

View File

@@ -37,7 +37,7 @@ pub(super) enum MachineMode {
pub(super) enum HeapPtr { pub(super) enum HeapPtr {
HeapCell(usize), HeapCell(usize),
PStr(usize), // Char(usize), PStr(usize), // Char(usize),
// PStrLocation(usize), // PStrLocation(usize),
} }
impl Default for HeapPtr { impl Default for HeapPtr {
@@ -215,7 +215,8 @@ fn push_var_eq_functors(
let mut writer = heap.reserve(1 + 5 * size)?; let mut writer = heap.reserve(1 + 5 * size)?;
writer.write_with(|section| { 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 var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let binding = heap_loc_as_cell!(var_loc); let binding = heap_loc_as_cell!(var_loc);
@@ -224,7 +225,7 @@ fn push_var_eq_functors(
section.push_cell(binding); 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(list_loc_as_cell!(section.cell_len() + 1));
section.push_cell(str_loc_as_cell!(src_h + 3 * idx)); 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)] #[derive(Debug)]
pub struct Ball { pub struct Ball {
pub(super) boundary: usize, pub(super) boundary: usize,
pub(super) pstr_boundary: usize,
pub(super) stub: Heap, pub(super) stub: Heap,
} }
@@ -259,12 +261,14 @@ impl Ball {
pub(super) fn new() -> Self { pub(super) fn new() -> Self {
Ball { Ball {
boundary: 0, boundary: 0,
pstr_boundary: 0,
stub: Heap::new(), stub: Heap::new(),
} }
} }
pub(super) fn reset(&mut self) { pub(super) fn reset(&mut self) {
self.boundary = 0; self.boundary = 0;
self.pstr_boundary = 0;
self.stub.clear(); self.stub.clear();
} }
@@ -272,10 +276,23 @@ impl Ball {
let h = dest.cell_len(); let h = dest.cell_len();
let diff = self.boundary as i64 - h as i64; 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 ..) { dest_writer.write_with(|section| {
*cell = *cell - diff; 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) Ok(h)
@@ -335,32 +352,16 @@ impl<'a> CopierTarget for CopyTerm<'a> {
self.state.heap.cell_len() 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)] #[inline(always)]
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> { fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
self.state.heap.copy_pstr_within(pstr_loc) 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)] #[inline(always)]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> { fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.state.heap.reserve(num_cells) 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> { fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
debug_assert!(pstr_loc < self.heap.byte_len()); 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)?; 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] #[inline]
@@ -479,41 +493,6 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
self.stub.reserve(num_cells) 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> { fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
let len = bounds.end - bounds.start; let len = bounds.end - bounds.start;
let mut stub_writer = self.stub.reserve(len)?; let mut stub_writer = self.stub.reserve(len)?;
@@ -699,9 +678,9 @@ impl MachineState {
push_var_eq_functors( push_var_eq_functors(
&mut self.heap, &mut self.heap,
var_list.len(), var_list.len(),
var_list.iter().map(|(var_name, var, _)| { var_list
(var.get_value() as usize, var_name.clone()) .iter()
}), .map(|(var_name, var, _)| { (var.get_value() as usize, var_name.clone()) }),
&self.atom_tbl, &self.atom_tbl,
) )
); );
@@ -737,7 +716,9 @@ impl MachineState {
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new(); 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); let cell = unmark_cell_bits!(cell);
if let Some(var) = cell.as_var() { if let Some(var) = cell.as_var() {
@@ -756,9 +737,10 @@ impl MachineState {
singleton_var_set singleton_var_set
.iter() .iter()
.filter(|(var, is_singleton)| { .filter(|(var, is_singleton)| {
**is_singleton && term.inverse_var_locs.contains_key( **is_singleton
&(var.get_value() as usize) && term
) .inverse_var_locs
.contains_key(&(var.get_value() as usize))
}) })
.count(), .count(),
term.inverse_var_locs term.inverse_var_locs
@@ -873,7 +855,8 @@ impl MachineState {
CompilationError::ParserError(e) if e.is_unexpected_eof() => { CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? { match eof_handler(self, stream)? {
OnEOF::Return => { 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, OnEOF::Continue => continue,
} }
@@ -1012,11 +995,9 @@ impl MachineState {
let term_loc = self.heap.cell_len(); let term_loc = self.heap.cell_len();
step_or_resource_error!( step_or_resource_error!(self, self.heap.push_cell(term_to_be_printed), {
self, return Ok(None);
self.heap.push_cell(term_to_be_printed), });
{ return Ok(None); }
);
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut self.heap, &mut self.heap,

View File

@@ -327,9 +327,9 @@ impl MachineState {
self.ball.reset(); self.ball.reset();
let addr = self.registers[1]; 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, self,
copy_term( copy_term(
CopyBallTerm::new( CopyBallTerm::new(
@@ -342,8 +342,6 @@ impl MachineState {
AttrVarPolicy::DeepCopy, AttrVarPolicy::DeepCopy,
) )
); );
self.ball.boundary = ball_boundary;
} }
#[inline(always)] #[inline(always)]
@@ -359,14 +357,14 @@ impl MachineState {
HeapPtr::PStr(h) => { HeapPtr::PStr(h) => {
let mut char_iter = self.heap.char_iter(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(); let c = char_iter.next().unwrap();
char_as_cell!(c) char_as_cell!(c)
} else { // read the (self.s_offset)^{th} cdr of the list } else {
let byte_offset: usize = char_iter // read the (self.s_offset)^{th} cdr of the list
.take(self.s_offset) let byte_offset: usize =
.map(|c| c.len_utf8()) char_iter.take(self.s_offset).map(|c| c.len_utf8()).sum();
.sum();
let new_h = h + byte_offset; let new_h = h + byte_offset;
self.s_offset = 0; self.s_offset = 0;
@@ -375,7 +373,7 @@ impl MachineState {
self.s = HeapPtr::PStr(new_h); self.s = HeapPtr::PStr(new_h);
pstr_loc_as_cell!(new_h) pstr_loc_as_cell!(new_h)
} else { } else {
let h = Heap::neighboring_cell_offset(new_h); let h = Heap::pstr_tail_idx(new_h);
self.s = HeapPtr::HeapCell(h); self.s = HeapPtr::HeapCell(h);
self.deref(heap_loc_as_cell!(h)) self.deref(heap_loc_as_cell!(h))
} }
@@ -946,7 +944,7 @@ impl MachineState {
if char_iter.next().is_some() { if char_iter.next().is_some() {
unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3); unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3);
} else { } 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]); 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 h = self.heap.cell_len();
let mut writer = self.heap.reserve(arity + 1)?; let mut writer = self.heap.reserve(arity + 1)?;

View File

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

View File

@@ -508,7 +508,8 @@ impl Machine {
s, s,
)) => { )) => {
cell = self.deref_register(arg); 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)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
// let lit = self.machine_st.constant_to_literal(cell); // 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() { if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
self.try_execute(name, arity, idx.get()) self.try_execute(name, arity, idx.get())
} else { } else {
println!("aaand undefined!");
self.undefined_procedure(name, arity) self.undefined_procedure(name, arity)
} }
} else if let Some(module) = self.indices.modules.get(&module_name) { } 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)] #[derive(Debug, Clone, Copy)]
pub enum PStrCmpResult<'a> { pub enum PStrCmpResult<'a> {
ListMatch { list_loc: usize }, ListMatch {
CompletePStrMatch { chars_matched: usize, pstr_loc: usize }, list_loc: usize,
PartialPStrMatch { string: &'a str, var_loc: usize }, },
CompletePStrMatch {
chars_matched: usize,
pstr_loc: usize,
},
PartialPStrMatch {
string: &'a str,
var_loc: usize,
},
} }
struct PStrIterStep { struct PStrIterStep {
@@ -81,7 +89,7 @@ impl<'a> HeapPStrIter<'a> {
if s.is_empty() { if s.is_empty() {
return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h }); return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h });
} else { } 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; curr_hare = next_hare;
} }
} }
@@ -179,11 +187,11 @@ impl<'a> HeapPStrIter<'a> {
loop { loop {
read_heap_cell!(self.heap[curr_hare], read_heap_cell!(self.heap[curr_hare],
(HeapCellValueTag::PStrLoc, h) => { (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 { return Ok(PStrIterStep {
iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: s.len() }, iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: string.len() },
next_hare: tail_loc, next_hare: tail_idx,
}); });
} }
(HeapCellValueTag::Lis, h) => { (HeapCellValueTag::Lis, h) => {
@@ -319,7 +327,10 @@ impl<'a> Iterator for PStrCharsIter<'a> {
self.item = self.iter.next(); self.item = self.iter.next();
return Some(value); 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); let s = self.iter.heap.slice_to_str(slice_loc, slice_len);
match s.chars().next() { match s.chars().next() {
@@ -353,7 +364,10 @@ mod test {
let mut wam = MockWAM::new(); let mut wam = MockWAM::new();
let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap(); 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 // not overwriting anything! 0 is an interstitial cell
// reserved for use by the runtime // reserved for use by the runtime
@@ -364,7 +378,10 @@ mod test {
assert_eq!( assert_eq!(
iter.next(), 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_eq!(iter.next(), None);
assert!(!iter.is_cyclic()); assert!(!iter.is_cyclic());
@@ -384,7 +401,10 @@ mod test {
assert_eq!( assert_eq!(
iter.next(), 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!( assert_eq!(
iter.next(), iter.next(),
@@ -407,7 +427,10 @@ mod test {
assert_eq!( assert_eq!(
iter.next(), 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!( assert_eq!(
iter.next(), iter.next(),
@@ -552,7 +575,11 @@ mod test {
section.push_cell(heap_loc_as_cell!(h)); 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); assert!(!wam.machine_st.fail);
@@ -561,7 +588,9 @@ mod test {
"abcdef" "abcdef"
); );
assert_eq!( 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" "abc"
); );
assert_eq!( assert_eq!(
@@ -587,7 +616,10 @@ mod test {
assert_eq!( assert_eq!(
iter.next(), 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 {} for _ in iter {}
@@ -609,7 +641,11 @@ mod test {
section.push_cell(empty_list_as_cell!()); 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); assert!(!wam.machine_st.fail);
@@ -629,7 +665,11 @@ mod test {
section.push_cell(empty_list_as_cell!()); 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_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert!(!wam.machine_st.fail); assert!(!wam.machine_st.fail);
@@ -652,7 +692,11 @@ mod test {
section.push_cell(empty_list_as_cell!()); 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[start], char_as_cell!('a'));
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b')); 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!()); 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_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert!(!wam.machine_st.fail); assert!(!wam.machine_st.fail);
@@ -699,10 +747,17 @@ mod test {
section.push_cell(heap_loc_as_cell!(5 + start)); 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[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); assert!(!wam.machine_st.fail);
// #2293, test6. // #2293, test6.
@@ -723,7 +778,11 @@ mod test {
section.push_cell(empty_list_as_cell!()); 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[start], char_as_cell!('a'));
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c')); 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!()); 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[2 + start], char_as_cell!('b'));
assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d')); 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> { fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
let (focus, _cell) = subterm_index(term.heap, term.focus); 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, Some((name, 0)) => name,
_ => { _ => {
return Err(CompilationError::InvalidDirective( 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, Some((name, _)) => name,
None => { None => {
return Err(CompilationError::InvalidDirective( return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]), DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]),
)); ));
} }
}; };
let spec = to_op_decl_spec(spec)?; 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, let prec = read_heap_cell!(prec,
(HeapCellValueTag::Fixnum, n) => { (HeapCellValueTag::Fixnum, n) => {
@@ -147,34 +147,34 @@ pub(super) fn setup_module_export_list(
let mut focus = term.focus; let mut focus = term.focus;
loop { loop {
read_heap_cell!(term.heap[focus], read_heap_cell!(term.heap[focus],
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == focus { if h == focus {
break; break;
} else { } else {
focus = h; focus = h;
} }
} }
(HeapCellValueTag::Lis, l) => { (HeapCellValueTag::Lis, l) => {
let term = FocusedHeapRefMut { let term = FocusedHeapRefMut {
heap: term.heap, heap: term.heap,
focus: l, focus: l,
}; };
exports.push(setup_module_export(&term)?); exports.push(setup_module_export(&term)?);
focus = l + 1; focus = l + 1;
} }
(HeapCellValueTag::Atom, (name, _arity)) => { (HeapCellValueTag::Atom, (name, _arity)) => {
if name == atom!("[]") { if name == atom!("[]") {
return Ok(exports); return Ok(exports);
} else { } else {
break; break;
} }
} }
_ => { _ => {
break; break;
} }
); );
} }
Err(CompilationError::InvalidModuleDecl) 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 * contained in src/lib/ops_and_meta_predicates.pl, which is loaded before
* src/lib/builtins.pl. * src/lib/builtins.pl.
* *
* Meta-specs have three forms: * Meta-specs have four forms:
* *
* (:) (the argument should be expanded with (:)/2 as described above) * (:) (the argument should be expanded with (:)/2 as described above)
* + (mode declarations under the mode syntax, which currently have no effect) * + (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 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, read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => { (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_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc); let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
let (module_name, key, term_loc) = let (module_name, key, term_loc) = if subterm_key_opt == Some((atom!(":"), 2)) {
if subterm_key_opt == Some((atom!(":"), 2)) { match get_qualified_name(
match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) { loader.machine_heap(),
Some(QualifiedNameInfo { subterm_loc + 1,
module_name, subterm_loc + 2,
name, ) {
arity, Some(QualifiedNameInfo {
qualified_term_loc, module_name,
}) => ( name,
module_name, arity,
(name, arity + supp_args), qualified_term_loc,
qualified_term_loc, }) => (module_name, (name, arity + supp_args), qualified_term_loc),
), None => {
None => { continue;
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); index_ptrs.insert(term_loc, index_ptr);
continue; continue;
} }
@@ -642,7 +641,12 @@ impl Preprocessor {
let classifier = VariableClassifier::new(self.settings.default_call_policy()); let classifier = VariableClassifier::new(self.settings.default_call_policy());
let var_data = classifier.classify_fact(loader, &term)?; 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 { } else {
Err(CompilationError::InadmissibleFact) Err(CompilationError::InadmissibleFact)
} }
@@ -660,7 +664,13 @@ impl Preprocessor {
let head_loc = term_nth_arg(heap, term.focus, 1).unwrap(); let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
if term_predicate_key(heap, head_loc).is_some() { 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 { } else {
Err(CompilationError::InvalidRuleHead) 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(); byte_offset += c.len_utf8();
} }
( (char_count, Heap::pstr_tail_idx(pstr_loc + byte_offset))
char_count,
Heap::neighboring_cell_offset(pstr_loc + byte_offset),
)
} }
fn pstr_segment_char_count_up_to( fn pstr_segment_char_count_up_to(
@@ -217,10 +214,9 @@ fn pstr_segment_char_count_up_to(
pstr_loc: pstr_loc + byte_offset, pstr_loc: pstr_loc + byte_offset,
} }
} else { } else {
let tail_loc = Heap::neighboring_cell_offset(pstr_loc + byte_offset);
PStrSegmentCountResult::End { PStrSegmentCountResult::End {
char_count, char_count,
tail_loc, tail_loc: Heap::pstr_tail_idx(pstr_loc + byte_offset),
} }
} }
} }
@@ -567,6 +563,12 @@ struct AttrListMatch {
prev_tail: Option<usize>, prev_tail: Option<usize>,
} }
#[derive(Debug)]
pub(crate) struct FindallCopyInfo {
offset: usize,
pstr_threshold: usize,
}
impl MachineState { impl MachineState {
#[inline(always)] #[inline(always)]
pub(crate) fn unattributed_var(&mut self) { pub(crate) fn unattributed_var(&mut self) {
@@ -648,9 +650,8 @@ impl MachineState {
loop { loop {
read_heap_cell!(value, read_heap_cell!(value,
(HeapCellValueTag::PStrLoc, h) => { (HeapCellValueTag::PStrLoc, h) => {
let (_, tail) = heap.scan_slice_to_str(h); let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
// let (h_offset, _) = pstr_loc_and_offset(heap, h); return tail_idx;
return tail;
} }
(HeapCellValueTag::Lis, h) => { (HeapCellValueTag::Lis, h) => {
return h+1; return h+1;
@@ -855,17 +856,10 @@ impl MachineState {
&mut self, &mut self,
lh_offset: usize, lh_offset: usize,
copy_target: HeapCellValue, copy_target: HeapCellValue,
) -> Result<usize, usize> { ) -> Result<FindallCopyInfo, usize> {
let threshold = self.lifted_heap.cell_len() - lh_offset; let threshold = self.lifted_heap.cell_len() - lh_offset;
let mut copy_ball_term = CopyBallTerm::new( let mut writer = self.lifted_heap.reserve(3)?;
&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)?;
writer.write_with(|section| { writer.write_with(|section| {
section.push_cell(list_loc_as_cell!(threshold + 1)); section.push_cell(list_loc_as_cell!(threshold + 1));
@@ -873,9 +867,21 @@ impl MachineState {
section.push_cell(heap_loc_as_cell!(threshold + 2)); 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)] #[inline(always)]
@@ -1045,18 +1051,6 @@ impl MachineState {
pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option<AtomOrString> { pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option<AtomOrString> {
read_heap_cell!(value, 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)) => { (HeapCellValueTag::Atom, (atom, arity)) => {
if arity == 0 { if arity == 0 {
// ... likewise. // ... likewise.
@@ -1389,15 +1383,7 @@ impl Machine {
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]) let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity(); .get_name_and_arity();
(name, arity, if self.machine_st.heap.cell_len() > s + arity + 1 { (name, arity, get_structure_index(self.machine_st.heap[s.saturating_sub(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
})
} }
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0); debug_assert_eq!(arity, 0);
@@ -1457,7 +1443,6 @@ impl Machine {
if let Some(code_index) = index_cell { if let Some(code_index) = index_cell {
if !code_index.is_undefined() { if !code_index.is_undefined() {
// println!("(fast) calling {}/{}", name.as_str(), arity);
load_registers(&mut self.machine_st, goal, goal_arity); load_registers(&mut self.machine_st, goal, goal_arity);
self.machine_st.neck_cut(); self.machine_st.neck_cut();
return call_at_index(self, name, arity, code_index.get()); 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]); .variable_set(&mut supp_vars, self.machine_st.registers[2]);
struct GoalAnalysisResult { struct GoalAnalysisResult {
index_ptr_loc: usize,
is_simple_goal: bool, is_simple_goal: bool,
goal: HeapCellValue, goal: HeapCellValue,
key: PredicateKey, key: PredicateKey,
@@ -1496,7 +1482,7 @@ impl Machine {
// fill expanded_vars with variables of the partial // fill expanded_vars with variables of the partial
// goal pre-completion by complete_partial_goal. // 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]); 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 // disjoint from them. if they are not, the
// expanded goal is not simple. // 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 post_supp_args
.zip(supp_vars.iter()) .zip(supp_vars.iter())
@@ -1535,27 +1522,33 @@ impl Machine {
false 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 h = self.machine_st.heap.cell_len();
let arity = arity - supp_vars.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!( resource_error_call_result!(
self.machine_st, self.machine_st,
self.machine_st.heap.copy_slice_to_end( 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, // even if arity == 0, goal must be a Str cell,
// since an index is about to appended to it. // since an index is about to appended to it.
str_loc_as_cell!(h) (h, str_loc_as_cell!(h+1))
} else { } else {
goal (0, goal)
}; };
GoalAnalysisResult { GoalAnalysisResult {
index_ptr_loc,
is_simple_goal, is_simple_goal,
goal, goal,
key: (name, arity), key: (name, arity),
@@ -1566,36 +1559,25 @@ impl Machine {
debug_assert_eq!(arity, 0); debug_assert_eq!(arity, 0);
let h = self.machine_st.heap.cell_len(); 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,
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 { GoalAnalysisResult {
index_ptr_loc: h,
is_simple_goal: true, is_simple_goal: true,
goal: str_loc_as_cell!(h), goal: str_loc_as_cell!(h+1),
key: (name, 0), key: (name, 0),
supp_vars, 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; self.machine_st.fail = true;
return Ok(()); return Ok(());
@@ -1609,14 +1591,8 @@ impl Machine {
let expanded_term = if result.is_simple_goal { let expanded_term = if result.is_simple_goal {
let idx = self.get_or_insert_qualified_code_index(module_name, result.key); let idx = self.get_or_insert_qualified_code_index(module_name, result.key);
self.machine_st.heap[result.index_ptr_loc] =
resource_error_call_result!( untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx));
self.machine_st,
self.machine_st
.heap
.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)))
);
result.goal result.goal
} else { } else {
let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default()); let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
@@ -1648,29 +1624,24 @@ impl Machine {
self.machine_st.heap.reserve(unexpanded_vars.len() + 2) 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( let idx = CodeIndex::new(
IndexPtr::index(helper_clause_loc), IndexPtr::index(helper_clause_loc),
&mut self.machine_st.arena, &mut self.machine_st.arena,
); );
self.machine_st.heap.last_cell_mut().map(|cell| { writer.write_with(|section| {
*cell = untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)); 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() { if HeapCellValueTag::Str == qualified_goal.get_tag() {
let s = qualified_goal.get_value() as usize; 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") { if name == atom!("$call") {
return false; return false;
} }
if self.machine_st.heap.cell_len() > s + 1 + arity { let idx_cell = self.machine_st.heap[s.saturating_sub(1)];
if self.machine_st.heap.pstr_at(s + 1 + arity) {
return false;
}
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),
if HeapCellValueTag::Cons == idx_cell.get_tag() { (ArenaHeaderTag::IndexPtr, _ip) => {
match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell), return true;
(ArenaHeaderTag::IndexPtr, _ip) => { }
return true; _ => {
} }
_ => { );
}
);
}
} }
} }
@@ -2312,27 +2277,6 @@ impl Machine {
let a1 = self.deref_register(1); let a1 = self.deref_register(1);
read_heap_cell!(a1, 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)) => { (HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0); debug_assert_eq!(arity, 0);
@@ -2542,7 +2486,7 @@ impl Machine {
self.machine_st.allocate_pstr(&*atom.as_str()) 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!( step_or_resource_error!(
self.machine_st, self.machine_st,
@@ -2585,8 +2529,8 @@ impl Machine {
read_heap_cell!(pstr, read_heap_cell!(pstr,
(HeapCellValueTag::PStrLoc, h) => { (HeapCellValueTag::PStrLoc, h) => {
let (_, tail_loc) = self.machine_st.heap.scan_slice_to_str(h); let HeapStringScan { tail_idx, .. } = self.machine_st.heap.scan_slice_to_str(h);
unify_fn!(self.machine_st, heap_loc_as_cell!(tail_loc), a2); unify_fn!(self.machine_st, heap_loc_as_cell!(tail_idx), a2);
} }
(HeapCellValueTag::Lis, h) => { (HeapCellValueTag::Lis, h) => {
unify_fn!( unify_fn!(
@@ -3970,7 +3914,10 @@ impl Machine {
pub(crate) fn copy_to_lifted_heap(&mut self) { pub(crate) fn copy_to_lifted_heap(&mut self) {
let lh_offset = cell_as_fixnum!(self.deref_register(1)).get_num() as usize; let lh_offset = cell_as_fixnum!(self.deref_register(1)).get_num() as usize;
let copy_target = self.machine_st.registers[2]; 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,
self.machine_st self.machine_st
.copy_findall_solution(lh_offset, copy_target) .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); 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..) { for idx in old_threshold + 1..pstr_threshold {
*addr -= self.machine_st.heap.cell_len() + lh_offset; 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); unify_fn!(self.machine_st, solutions, diff);
} else { } else {
let h = self.machine_st.heap.cell_len(); 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,
self.machine_st self.machine_st.heap.reserve(reserve_size)
.heap
.append(self.machine_st.lifted_heap.splice(lh_offset..),)
); );
for cell in &mut self.machine_st.heap.splice_mut(h..) { writer.write_with(|section| {
*cell = *cell + h; 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]; let diff = self.machine_st.registers[3];
unify_fn!( unify_fn!(
@@ -5834,17 +5794,18 @@ impl Machine {
unify_fn!(self.machine_st, solutions, empty_list_as_cell!()); unify_fn!(self.machine_st, solutions, empty_list_as_cell!());
} else { } else {
let h = self.machine_st.heap.cell_len(); 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,
self.machine_st self.machine_st.heap.reserve(reserve_size)
.heap
.append(self.machine_st.lifted_heap.splice(lh_offset..),)
); );
for cell in &mut self.machine_st.heap.splice_mut(h..) { writer.write_with(|section| {
*cell = *cell + h; 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); self.machine_st.lifted_heap.truncate(lh_offset);
@@ -7223,8 +7184,7 @@ impl Machine {
let mut ball = Ball::new(); let mut ball = Ball::new();
ball.boundary = self.machine_st.heap.cell_len(); ball.boundary = self.machine_st.heap.cell_len();
ball.pstr_boundary = step_or_resource_error!(
step_or_resource_error!(
self.machine_st, self.machine_st,
copy_term( copy_term(
CopyBallTerm::new( CopyBallTerm::new(

View File

@@ -44,14 +44,19 @@ impl<'a> BootstrappingTermStream<'a> {
listing_src: ListingSource, listing_src: ListingSource,
) -> Self { ) -> Self {
let lexer_parser = LexerParser::new(stream, machine_st); let lexer_parser = LexerParser::new(stream, machine_st);
Self { lexer_parser, listing_src } Self {
lexer_parser,
listing_src,
}
} }
} }
impl<'a> TermStream for BootstrappingTermStream<'a> { impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline] #[inline]
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> { 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); .map_err(CompilationError::from);
result result
@@ -125,7 +130,9 @@ pub struct InlineTermStream {}
impl TermStream for InlineTermStream { impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> { 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> { 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() { if value.is_ref() && !value.is_stack_var() {
machine_st.heap[0] = value; machine_st.heap[0] = value;
for cell in stackful_preorder_iter::<NonListElider>( for cell in
&mut machine_st.heap, stackful_preorder_iter::<NonListElider>(&mut machine_st.heap, &mut machine_st.stack, 0)
&mut machine_st.stack, {
0,
) {
let cell = unmark_cell_bits!(cell); let cell = unmark_cell_bits!(cell);
if let Some(inner_r) = cell.as_var() { if let Some(inner_r) = cell.as_var() {

View File

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

View File

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

View File

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

View File

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

View File

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