From: Mark Thom Date: Sat, 7 Dec 2024 05:47:36 +0000 (-0800) Subject: remove pstr_vec X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=62dda7414b06d5adeb57e612dc651fc4aa90eeab;p=scryer-prolog.git remove pstr_vec --- diff --git a/build/static_string_indexing.rs b/build/static_string_indexing.rs index 62e06f46..5135ab77 100644 --- a/build/static_string_indexing.rs +++ b/build/static_string_indexing.rs @@ -89,7 +89,7 @@ const INLINED_ATOM_MAX_LEN: usize = 6; fn static_string_index(string: &str, index: usize) -> u64 { if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN { let mut string_buf: [u8; 8] = [0u8; 8]; - string_buf[.. string.len()].copy_from_slice(string.as_bytes()); + string_buf[..string.len()].copy_from_slice(string.as_bytes()); (u64::from_le_bytes(string_buf) << 1) | 1 } else { (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_str_indices = vec![]; - let indices: Vec = visitor.static_strs.iter().map(|string| { - let index = static_string_index(string, static_strs.len()); + let indices: Vec = visitor + .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 { - index - } else { - static_str_indices.push(index); - static_strs.push(string); - index - } - }).collect(); + if index & 1 == 1 { + index + } else { + static_str_indices.push(index); + static_strs.push(string); + index + } + }) + .collect(); 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! { static STRINGS: [&str; #static_strs_len] = [ diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 8cb11743..dc03c8db 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -479,7 +479,6 @@ impl Div for Number { } } - impl PartialEq for Number { fn eq(&self, rhs: &Self) -> bool { match (self, rhs) { @@ -563,7 +562,6 @@ impl PartialOrd for Number { } } - impl Ord for Number { fn cmp(&self, rhs: &Number) -> Ordering { match (self, rhs) { diff --git a/src/atom_table.rs b/src/atom_table.rs index 7c23349d..67aaa966 100644 --- a/src/atom_table.rs +++ b/src/atom_table.rs @@ -66,7 +66,7 @@ impl AtomCell { debug_assert!(string.len() <= INLINED_ATOM_MAX_LEN); let mut string_buf: [u8; 8] = [0u8; 8]; - string_buf[.. string.len()].copy_from_slice(string.as_bytes()); + string_buf[..string.len()].copy_from_slice(string.as_bytes()); let encoding = u64::from_le_bytes(string_buf); AtomCell::new() @@ -80,7 +80,7 @@ impl AtomCell { #[inline] pub fn new_char_inlined(c: char) -> Self { - let mut char_buf = [0u8;8]; + let mut char_buf = [0u8; 8]; c.encode_utf8(&mut char_buf); let encoding = u64::from_le_bytes(char_buf); @@ -109,7 +109,9 @@ impl AtomCell { #[inline] pub fn get_name(self) -> Atom { - Atom { index: (self.name() << 1) | self.is_inlined() as u64 } + Atom { + index: (self.name() << 1) | self.is_inlined() as u64, + } } #[inline] @@ -216,21 +218,22 @@ impl Hash for Atom { pub enum AtomString<'a> { Static(&'a str), - Inlined([u8;8]), + Inlined([u8; 8]), Dynamic(AtomTableRef), } -fn inlined_to_str<'a>(bytes: &'a [u8;8]) -> &'a str { +fn inlined_to_str<'a>(bytes: &'a [u8; 8]) -> &'a str { // allow the '\0\' atom to be represented as the 0-valued inlined atom let slice_len = if bytes[0] == 0 { 1 } else { - bytes.iter().position(|&b| b == 0u8).unwrap_or(INLINED_ATOM_MAX_LEN) + bytes + .iter() + .position(|&b| b == 0u8) + .unwrap_or(INLINED_ATOM_MAX_LEN) }; - unsafe { - str::from_utf8_unchecked(&bytes[..slice_len]) - } + unsafe { str::from_utf8_unchecked(&bytes[..slice_len]) } } impl std::fmt::Debug for AtomString<'_> { diff --git a/src/codegen.rs b/src/codegen.rs index 4b27e448..3118d649 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -295,8 +295,10 @@ impl DebrayAllocator { self.mark_var::(var_num, Level::Shallow, context, code); temp_v!(arg) } else { - if let VarAlloc::Perm { allocation: PermVarAllocation::Pending, .. } = - &self.var_data.records[var_num].allocation + if let VarAlloc::Perm { + allocation: PermVarAllocation::Pending, + .. + } = &self.var_data.records[var_num].allocation { self.mark_var::(var_num, Level::Shallow, context, code); } else { @@ -337,22 +339,16 @@ impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator { fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>( index_ptrs: &IndexMap, heap: &Heap, - arity: usize, heap_loc: usize, ) -> Option { - match fetch_index_ptr(heap, arity, heap_loc) { - Some(index_ptr) => { + if let Some(index_ptr) = index_ptrs.get(&heap_loc) { + let subterm = HeapCellValue::from(*index_ptr); + return Some(Target::constant_subterm(subterm)); + } else if !heap[heap_loc.saturating_sub(1)].get_mark_bit() { + if let Some(index_ptr) = fetch_index_ptr(heap, heap_loc) { let subterm = HeapCellValue::from(index_ptr); return Some(Target::constant_subterm(subterm)); } - None => { - // if Level::Shallow == lvl { - if let Some(index_ptr) = index_ptrs.get(&heap_loc) { - let subterm = HeapCellValue::from(*index_ptr); - return Some(Target::constant_subterm(subterm)); - } - // } - } } None @@ -495,23 +491,28 @@ impl CodeGenerator { let (heap_loc, _) = subterm_index(iter.deref(), heap_loc); if arity == 0 { - if let Some(instr) = add_index_ptr::(index_ptrs, &iter, arity, heap_loc) { + if let Some(instr) = add_index_ptr::(index_ptrs, &iter, heap_loc) { let r = self.marker.mark_non_var::(lvl, heap_loc, context, &mut target); - target.push_back(Target::to_structure(lvl, name, 0, r)); target.push_back(instr); + target.push_back(Target::to_structure(lvl, name, 0, r)); } else if lvl == Level::Shallow { let r = self.marker.mark_non_var::(lvl, heap_loc, context, &mut target); target.push_back(Target::to_constant(lvl, atom_as_cell!(name), r)); } } else { let r = self.marker.mark_non_var::(lvl, heap_loc, context, &mut target); - target.push_back(Target::to_structure(lvl, name, arity, r)); >::add_term_to_free_list( self, r, ); + if let Some(instr) = add_index_ptr::(index_ptrs, &iter, heap_loc) { + target.push_back(instr); + } + + target.push_back(Target::to_structure(lvl, name, arity, r)); + let free_list_regs: Vec<_> = (heap_loc + 1 ..= heap_loc + arity) .map(|subterm_loc| { let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc); @@ -522,10 +523,6 @@ impl CodeGenerator { }) .collect(); - if let Some(instr) = add_index_ptr::(index_ptrs, &iter, arity, heap_loc) { - target.push_back(instr); - } - for r_opt in free_list_regs { if let Some(r) = r_opt { >::add_subterm_to_free_list( @@ -583,11 +580,11 @@ impl CodeGenerator { let heap_loc = iter.focus().value() as usize; let (heap_loc, _) = subterm_index(iter.deref(), heap_loc); let r = self.marker.mark_non_var::(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::( tail, tail_loc, context, index_ptrs, &mut target, ); @@ -676,12 +673,11 @@ impl CodeGenerator { &InlinedClauseType::CompareNumber(mut cmp) => { self.marker.reset_arg(2); - let (mut lcode, at_1) = - if let Some(r) = variable_marker(&mut self.marker) { - (CodeDeque::default(), Some(ArithmeticTerm::Reg(r))) - } else { - self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)? - }; + let (mut lcode, at_1) = if let Some(r) = variable_marker(&mut self.marker) { + (CodeDeque::default(), Some(ArithmeticTerm::Reg(r))) + } else { + self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)? + }; let (mut rcode, at_2) = self.compile_arith_expr(terms, first_arg_loc + 1, 2, context, 2)?; @@ -720,41 +716,41 @@ impl CodeGenerator { if let Some(r) = variable_marker(&mut self.marker) { instr!("atomic", r) } else { - read_heap_cell!(first_arg, - (HeapCellValueTag::Fixnum | - HeapCellValueTag::F64) => { - instr!("$succeed") - } - (HeapCellValueTag::Cons, cons_ptr) => { - match cons_ptr.get_tag() { - ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => { - instr!("$succeed") - } - _ => { - instr!("$fail") - } - } - } - (HeapCellValueTag::Atom, (_name, arity)) => { - if arity == 0 { - instr!("$succeed") - } else { - instr!("$fail") - } - } - (HeapCellValueTag::Lis - | HeapCellValueTag::Str - | HeapCellValueTag::PStrLoc) => { - instr!("$fail") - } - _ => { - if first_arg.is_constant() { - instr!("$succeed") - } else { - instr!("$fail") - } - } - ) + read_heap_cell!(first_arg, + (HeapCellValueTag::Fixnum | + HeapCellValueTag::F64) => { + instr!("$succeed") + } + (HeapCellValueTag::Cons, cons_ptr) => { + match cons_ptr.get_tag() { + ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => { + instr!("$succeed") + } + _ => { + instr!("$fail") + } + } + } + (HeapCellValueTag::Atom, (_name, arity)) => { + if arity == 0 { + instr!("$succeed") + } else { + instr!("$fail") + } + } + (HeapCellValueTag::Lis + | HeapCellValueTag::Str + | HeapCellValueTag::PStrLoc) => { + instr!("$fail") + } + _ => { + if first_arg.is_constant() { + instr!("$succeed") + } else { + instr!("$fail") + } + } + ) } } InlinedClauseType::IsCompound(..) => { @@ -860,7 +856,7 @@ impl CodeGenerator { } } } - }, + } InlinedClauseType::IsVar(..) => { self.marker.reset_arg(1); @@ -871,7 +867,7 @@ impl CodeGenerator { } else { instr!("$fail") } - }, + } }; // inlined predicates are never counted, so this overrides nothing. @@ -901,8 +897,7 @@ impl CodeGenerator { ) -> Result<(), CompilationError> { macro_rules! compile_expr { ($self:expr, $terms:expr, $context:expr, $code:expr) => {{ - let (acode, at) = - $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?; + let (acode, at) = $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?; $code.extend(acode.into_iter()); at }}; @@ -1067,13 +1062,11 @@ impl CodeGenerator { code.push_back(instr!("deallocate")); } - code.push_back( - if self.marker.in_tail_position { - instr!("$succeed").into_execute() - } else { - instr!("$succeed") - }, - ); + code.push_back(if self.marker.in_tail_position { + instr!("$succeed").into_execute() + } else { + instr!("$succeed") + }); } QueryTerm::Clause(clause) => { self.compile_query_line( @@ -1145,7 +1138,10 @@ impl CodeGenerator { self.marker.var_data = var_data; - let term = FocusedHeapRefMut { heap, focus: *term_loc }; + let term = FocusedHeapRefMut { + heap, + focus: *term_loc, + }; let mut code = VecDeque::new(); let head_loc = term.nth_arg(term.focus, 1).unwrap(); @@ -1216,11 +1212,7 @@ impl CodeGenerator { let mut stack = Stack::uninitialized(); let iter = query_iterator::(&mut term.heap, &mut stack, clause.term_loc()); - let query = self.compile_target::( - iter, - &clause.code_indices, - context, - ); + let query = self.compile_target::(iter, &clause.code_indices, context); code.extend(query); self.add_call(code, clause.ct.to_instr(), clause.call_policy); @@ -1342,20 +1334,14 @@ impl CodeGenerator { skip_stub_try_me_else = !self.settings.is_dynamic(); } - let arg = clause.args(heap) - .map(|r| heap[r.start() + optimal_index]); + let arg = clause.args(heap).map(|r| heap[r.start() + optimal_index]); if let Some(arg) = arg { let index = code.len(); if clauses_len > 1 || self.settings.is_extensible { let arg = heap_bound_store(heap, heap_bound_deref(heap, arg)); - code_offsets.index_term( - heap, - arg, - index, - &mut clause_index_info, - ); + code_offsets.index_term(heap, arg, index, &mut clause_index_info); } } diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index d1d01aa8..7c86bb88 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -172,7 +172,9 @@ impl DebrayAllocator { for var_num in subsumed_hits { match &mut self.var_data.records[var_num].allocation { - VarAlloc::Perm { ref mut allocation, .. } => { + VarAlloc::Perm { + ref mut allocation, .. + } => { if let PermVarAllocation::Done { shallow_safety, deep_safety, @@ -233,7 +235,7 @@ impl DebrayAllocator { let num_occurrences = self.var_data.records[var_num].num_occurrences; match &mut self.var_data.records[var_num].allocation { - VarAlloc::Perm { allocation, ..} => { + VarAlloc::Perm { allocation, .. } => { let shallow_safety = VarSafetyStatus::needed_if( shallow_safety.contains(var_num), branch_designator, @@ -514,10 +516,12 @@ impl DebrayAllocator { self.perm_free_list.pop_front(); match &mut self.var_data.records[var_num].allocation { - VarAlloc::Perm { reg: p, allocation: PermVarAllocation::Pending } - if *p > 0 => { - return Some(std::mem::replace(p, 0)); - } + VarAlloc::Perm { + reg: p, + allocation: PermVarAllocation::Pending, + } if *p > 0 => { + return Some(std::mem::replace(p, 0)); + } _ => {} } } else { @@ -543,11 +547,12 @@ impl DebrayAllocator { match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm { - allocation: PermVarAllocation::Done { - deep_safety, - shallow_safety, - .. - }, + allocation: + PermVarAllocation::Done { + deep_safety, + shallow_safety, + .. + }, .. } => { *deep_safety = VarSafetyStatus::unneeded(branch_designator); @@ -568,11 +573,12 @@ impl DebrayAllocator { match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm { - allocation: PermVarAllocation::Done { - deep_safety, - shallow_safety, - .. - }, + allocation: + PermVarAllocation::Done { + deep_safety, + shallow_safety, + .. + }, .. } => { // GetVariable in head chunk is considered safe. @@ -612,10 +618,11 @@ impl DebrayAllocator { match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm { - allocation: PermVarAllocation::Done { - ref mut shallow_safety, - .. - }, + allocation: + PermVarAllocation::Done { + ref mut shallow_safety, + .. + }, .. } => { if !self.in_tail_position @@ -648,10 +655,11 @@ impl DebrayAllocator { match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm { - allocation: PermVarAllocation::Done { - ref mut deep_safety, - .. - }, + allocation: + PermVarAllocation::Done { + ref mut deep_safety, + .. + }, .. } => { if self @@ -921,10 +929,7 @@ impl Allocator for DebrayAllocator { } fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) { - let head_cell = heap_bound_store( - heap, - heap_bound_deref(heap, heap_loc_as_cell!(head_loc)), - ); + let head_cell = heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(head_loc))); read_heap_cell!(head_cell, (HeapCellValueTag::Str, s) => { @@ -933,7 +938,9 @@ impl Allocator for DebrayAllocator { self.reset_arg(arity); self.arity = arity; - for (idx, arg) in heap.splice(s+1 ..= s+arity).enumerate() { + for (c_idx, heap_idx) in (s+1 ..= s+arity).enumerate() { + let arg = heap[heap_idx]; + if arg.is_var() { let var = heap_bound_store( heap, @@ -953,11 +960,11 @@ impl Allocator for DebrayAllocator { let r = self.get_var_binding(var_num); if !r.is_perm() && r.reg_num() == 0 { - self.in_use.insert(idx + 1); - self.shallow_temp_mappings.insert(idx + 1, var_num); + self.in_use.insert(c_idx + 1); + self.shallow_temp_mappings.insert(c_idx + 1, var_num); self.var_data.records[var_num] .allocation - .set_register(idx + 1); + .set_register(c_idx + 1); } } VarPtr::Anon => {} diff --git a/src/forms.rs b/src/forms.rs index 4053b5a9..6e9608df 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,7 +1,7 @@ use crate::arena::*; use crate::atom_table::*; -use crate::instructions::*; use crate::functor_macro::*; +use crate::instructions::*; use crate::machine::disjuncts::VarData; use crate::machine::heap::*; // use crate::machine::loader::PredicateQueue; @@ -80,8 +80,8 @@ impl GenContext { #[inline] pub fn chunk_type(&self) -> ChunkType { match self { - GenContext::Head => ChunkType::Head, - GenContext::Mid(_) => ChunkType::Mid, + GenContext::Head => ChunkType::Head, + GenContext::Mid(_) => ChunkType::Mid, GenContext::Last(_) => ChunkType::Last, } } @@ -118,7 +118,10 @@ impl ChunkType { #[derive(Debug)] pub enum ChunkedTerms { Branch(Vec>), - Chunk { chunk_num: usize, terms: VecDeque }, + Chunk { + chunk_num: usize, + terms: VecDeque, + }, } #[derive(Debug)] @@ -190,7 +193,8 @@ impl ChunkedTermVec { } pub fn current_gen_context(&self) -> GenContext { - self.current_chunk_type.to_gen_context(self.current_chunk_num) + self.current_chunk_type + .to_gen_context(self.current_chunk_num) } pub fn push_chunk_term(&mut self, term: QueryTerm) { @@ -290,9 +294,7 @@ pub fn clause_predicate_key(heap: &impl SizedHeap, term_loc: usize) -> Option), @@ -190,19 +193,19 @@ pub(crate) fn variadic_functor( let num_items = key_value_pairs.len(); for (idx, _) in key_value_pairs.iter().enumerate() { - arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(2 + num_items * 2 + idx))); + arg_vec.push(FunctorElement::Cell(str_loc_as_cell!( + 2 + num_items * 2 + idx + ))); arg_vec.push(FunctorElement::Cell(list_loc_as_cell!(5 + idx))); } arg_vec.pop(); arg_vec.push(FunctorElement::Cell(empty_list_as_cell!())); - arg_vec.extend(key_value_pairs - .into_iter() - .map(|kv_func| { - let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func)); - FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func) - })); + arg_vec.extend(key_value_pairs.into_iter().map(|kv_func| { + let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func)); + FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func) + })); arg_vec } @@ -211,13 +214,15 @@ pub(crate) fn variadic_functor( #[allow(unused_parens)] mod tests { use super::*; - use FunctorElement::*; use std::string::String; + use FunctorElement::*; #[test] fn basic_terms() { - let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), - char_as_cell('c')]); + let functor = functor!( + atom!("first"), + [atom_as_cell((atom!("a"))), char_as_cell('c')] + ); assert_eq!(functor.len(), 3); @@ -225,10 +230,14 @@ mod tests { assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a")))); assert_eq!(functor[2], Cell(char_as_cell!('c'))); - let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))), - functor((atom!("b")), [fixnum(1), - fixnum(2)]), - char_as_cell('c')]); + let functor = functor!( + atom!("second"), + [ + atom_as_cell((atom!("a"))), + functor((atom!("b")), [fixnum(1), fixnum(2)]), + char_as_cell('c') + ] + ); assert_eq!(functor.len(), 5); @@ -236,13 +245,20 @@ mod tests { assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a")))); assert_eq!(functor[2], Cell(str_loc_as_cell!(4))); assert_eq!(functor[3], Cell(char_as_cell!('c'))); - assert_eq!(functor[4], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), - fixnum(2)]))); + assert_eq!( + functor[4], + InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])) + ); - let functor = functor!(atom!("third"), [atom_as_cell((atom!("a"))), - functor((atom!("b")), [fixnum(1), fixnum(2)]), - functor((atom!("c")), [fixnum(1), fixnum(2)]), - char_as_cell('c')]); + let functor = functor!( + atom!("third"), + [ + atom_as_cell((atom!("a"))), + functor((atom!("b")), [fixnum(1), fixnum(2)]), + functor((atom!("c")), [fixnum(1), fixnum(2)]), + char_as_cell('c') + ] + ); assert_eq!(functor.len(), 7); @@ -251,14 +267,25 @@ mod tests { assert_eq!(functor[2], Cell(str_loc_as_cell!(5))); assert_eq!(functor[3], Cell(str_loc_as_cell!(8))); assert_eq!(functor[4], Cell(char_as_cell!('c'))); - assert_eq!(functor[5], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))); - assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)]))); + assert_eq!( + functor[5], + InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])) + ); + assert_eq!( + functor[6], + InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)])) + ); - let functor = functor!(atom!("fourth"), [atom_as_cell((atom!("a"))), - functor((atom!("b")), [fixnum(1), fixnum(2)]), - functor((atom!("c")), [fixnum(1)]), - functor((atom!("d")), [fixnum(453), fixnum(2)]), - char_as_cell('c')]); + let functor = functor!( + atom!("fourth"), + [ + atom_as_cell((atom!("a"))), + functor((atom!("b")), [fixnum(1), fixnum(2)]), + functor((atom!("c")), [fixnum(1)]), + functor((atom!("d")), [fixnum(453), fixnum(2)]), + char_as_cell('c') + ] + ); assert_eq!(functor.len(), 9); @@ -268,14 +295,26 @@ mod tests { assert_eq!(functor[3], Cell(str_loc_as_cell!(9))); assert_eq!(functor[4], Cell(str_loc_as_cell!(11))); assert_eq!(functor[5], Cell(char_as_cell!('c'))); - assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))); - assert_eq!(functor[7], InnerFunctor(2, functor!(atom!("c"), [fixnum(1)]))); - assert_eq!(functor[8], InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)]))); + assert_eq!( + functor[6], + InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])) + ); + assert_eq!( + functor[7], + InnerFunctor(2, functor!(atom!("c"), [fixnum(1)])) + ); + assert_eq!( + functor[8], + InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)])) + ); } #[test] fn basic_terms_in_heap() { - let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), char_as_cell('b')]); + let functor = functor!( + atom!("first"), + [atom_as_cell((atom!("a"))), char_as_cell('b')] + ); assert_eq!(functor.len(), 3); @@ -291,10 +330,15 @@ mod tests { heap.truncate(2); - let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))), - functor((atom!("b")), [fixnum(1), fixnum(2)]), - functor((atom!("c")), [fixnum(1), fixnum(2)]), - char_as_cell('b')]); + let functor = functor!( + atom!("second"), + [ + atom_as_cell((atom!("a"))), + functor((atom!("b")), [fixnum(1), fixnum(2)]), + functor((atom!("c")), [fixnum(1), fixnum(2)]), + char_as_cell('b') + ] + ); assert_eq!(functor.len(), 7); @@ -318,14 +362,24 @@ mod tests { #[test] fn nested_functors() { - let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), - functor((atom!("d")), [fixnum(1), - functor((atom!("b")), - [atom_as_cell((atom!("c"))), - char_as_cell('c')])]), - functor((atom!("e")), [fixnum(453), - fixnum(2)]), - char_as_cell('b')]); + let functor = functor!( + atom!("first"), + [ + atom_as_cell((atom!("a"))), + functor( + (atom!("d")), + [ + fixnum(1), + functor( + (atom!("b")), + [atom_as_cell((atom!("c"))), char_as_cell('c')] + ) + ] + ), + functor((atom!("e")), [fixnum(453), fixnum(2)]), + char_as_cell('b') + ] + ); assert_eq!(functor.len(), 7); @@ -334,24 +388,47 @@ mod tests { assert_eq!(functor[2], Cell(str_loc_as_cell!(5))); assert_eq!(functor[3], Cell(str_loc_as_cell!(11))); assert_eq!(functor[4], Cell(char_as_cell!('b'))); - assert_eq!(functor[5], InnerFunctor(6, vec![Cell(atom_as_cell!(atom!("d"), 2)), - Cell(fixnum_as_cell!(Fixnum::build_with(1))), - Cell(str_loc_as_cell!(3)), - InnerFunctor(3, functor!(atom!("b"), [atom_as_cell((atom!("c"))), - char_as_cell('c')]))])); - assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("e"), [fixnum(453), - fixnum(2)]))); + assert_eq!( + functor[5], + InnerFunctor( + 6, + vec![ + Cell(atom_as_cell!(atom!("d"), 2)), + Cell(fixnum_as_cell!(Fixnum::build_with(1))), + Cell(str_loc_as_cell!(3)), + InnerFunctor( + 3, + functor!(atom!("b"), [atom_as_cell((atom!("c"))), char_as_cell('c')]) + ) + ] + ) + ); + assert_eq!( + functor[6], + InnerFunctor(3, functor!(atom!("e"), [fixnum(453), fixnum(2)])) + ); } - #[test] fn nested_functors_in_heap() { - let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), - functor((atom!("second")), [fixnum(1), - functor((atom!("third")), [atom_as_cell((atom!("b"))), - char_as_cell('c')])]), - functor((atom!("fourth")), [fixnum(453), fixnum(2)]), - char_as_cell('b')]); + let functor = functor!( + atom!("first"), + [ + atom_as_cell((atom!("a"))), + functor( + (atom!("second")), + [ + fixnum(1), + functor( + (atom!("third")), + [atom_as_cell((atom!("b"))), char_as_cell('c')] + ) + ] + ), + functor((atom!("fourth")), [fixnum(453), fixnum(2)]), + char_as_cell('b') + ] + ); let mut heap = Heap::new(); let mut functor_writer = Heap::functor_writer(functor); @@ -392,33 +469,43 @@ mod tests { assert_eq!(heap[0], atom_as_cell!(atom!("first"), 1)); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2))); - assert_eq!(heap.slice_to_str(heap_index!(2), "a string".len()), "a string"); + assert_eq!( + heap.slice_to_str(heap_index!(2), "a string".len()), + "a string" + ); assert_eq!(heap[4], empty_list_as_cell!()); heap.truncate(0); - let functor = functor!(atom!("second"), [string((String::from("a stuttered\0 string")))]); + let functor = functor!( + atom!("second"), + [string((String::from("a stuttered\0 string")))] + ); let mut functor_writer = Heap::functor_writer(functor); functor_writer(&mut heap).unwrap(); - assert_eq!(heap.cell_len(), 7); + assert_eq!(heap.cell_len(), 8); assert_eq!(heap[0], atom_as_cell!(atom!("second"), 1)); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2))); - assert_eq!(heap.slice_to_str(heap_index!(2), "a stuttered".len()), "a stuttered"); + assert_eq!( + heap.slice_to_str(heap_index!(2), "a stuttered".len()), + "a stuttered" + ); assert_eq!(heap[4], pstr_loc_as_cell!(heap_index!(5))); - assert_eq!(heap.slice_to_str(heap_index!(5), " string".len()), " string"); - assert_eq!(heap[6], empty_list_as_cell!()); + assert_eq!( + heap.slice_to_str(heap_index!(5), " string".len()), + " string" + ); + assert_eq!(heap[7], empty_list_as_cell!()); } #[test] fn functors_with_lists_in_heap() { let functor = functor!( atom!("first"), - [list([fixnum(1), - atom_as_cell((atom!("a"))), - fixnum(2)])] + [list([fixnum(1), atom_as_cell((atom!("a"))), fixnum(2)])] ); assert_eq!(functor.len(), 3); @@ -462,8 +549,10 @@ mod tests { let code_ptr = IndexingCodePtr::Internal(0); let functor = functor!( atom!("first"), - [string((String::from("a string"))), - indexing_code_ptr(code_ptr)] + [ + string((String::from("a string"))), + indexing_code_ptr(code_ptr) + ] ); let mut heap = Heap::new(); @@ -476,18 +565,30 @@ mod tests { assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2)); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3))); assert_eq!(heap[2], str_loc_as_cell!(6)); - assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string"); + assert_eq!( + heap.slice_to_str(heap_index!(3), "a string".len()), + "a string" + ); assert_eq!(heap[5], empty_list_as_cell!()); assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1)); assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0))); heap.truncate(0); - let functor = functor!(atom!("second"), - [string((String::from("a string"))), - functor((atom!("third")), [atom_as_cell((atom!("a"))), - string((String::from("another string"))), - indexing_code_ptr(code_ptr)])]); + let functor = functor!( + atom!("second"), + [ + string((String::from("a string"))), + functor( + (atom!("third")), + [ + atom_as_cell((atom!("a"))), + string((String::from("another string"))), + indexing_code_ptr(code_ptr) + ] + ) + ] + ); let mut functor_writer = Heap::functor_writer(functor); functor_writer(&mut heap).unwrap(); @@ -497,24 +598,43 @@ mod tests { assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2)); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3))); assert_eq!(heap[2], str_loc_as_cell!(6)); - assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string"); + assert_eq!( + heap.slice_to_str(heap_index!(3), "a string".len()), + "a string" + ); assert_eq!(heap[5], empty_list_as_cell!()); assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3)); assert_eq!(heap[7], atom_as_cell!(atom!("a"))); assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10))); assert_eq!(heap[9], str_loc_as_cell!(13)); - assert_eq!(heap.slice_to_str(heap_index!(10), "another string".len()), "another string"); + assert_eq!( + heap.slice_to_str(heap_index!(10), "another string".len()), + "another string" + ); assert_eq!(heap[12], empty_list_as_cell!()); assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1)); assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0))); - let functor = functor!(atom!("fourth"), - [string((String::from("a string"))), - functor((atom!("a")), - [functor((atom!("fifth")), [fixnum(5), - string((String::from("another string"))), - indexing_code_ptr(code_ptr)]), - string((String::from("and another")))])]); + let functor = functor!( + atom!("fourth"), + [ + string((String::from("a string"))), + functor( + (atom!("a")), + [ + functor( + (atom!("fifth")), + [ + fixnum(5), + string((String::from("another string"))), + indexing_code_ptr(code_ptr) + ] + ), + string((String::from("and another"))) + ] + ) + ] + ); heap.truncate(0); @@ -526,7 +646,10 @@ mod tests { assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2)); assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3))); assert_eq!(heap[2], str_loc_as_cell!(6)); - assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string"); + assert_eq!( + heap.slice_to_str(heap_index!(3), "a string".len()), + "a string" + ); assert_eq!(heap[5], empty_list_as_cell!()); assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2)); assert_eq!(heap[7], str_loc_as_cell!(9)); @@ -535,11 +658,17 @@ mod tests { assert_eq!(heap[10], fixnum_as_cell!(Fixnum::build_with(5))); assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13))); assert_eq!(heap[12], str_loc_as_cell!(16)); - assert_eq!(heap.slice_to_str(heap_index!(13), "another string".len()), "another string"); + assert_eq!( + heap.slice_to_str(heap_index!(13), "another string".len()), + "another string" + ); assert_eq!(heap[15], empty_list_as_cell!()); assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1)); assert_eq!(heap[17], fixnum_as_cell!(Fixnum::build_with(0))); - assert_eq!(heap.slice_to_str(heap_index!(18), "and another".len()), "and another"); + assert_eq!( + heap.slice_to_str(heap_index!(18), "and another".len()), + "and another" + ); assert_eq!(heap[20], empty_list_as_cell!()); } @@ -550,17 +679,16 @@ mod tests { let stub = functor!( atom!("existence_error"), - [atom_as_cell((atom!("procedure"))), functor((culprit.clone()))] + [ + atom_as_cell((atom!("procedure"))), + functor((culprit.clone())) + ] ); println!("{:?}", stub); // now the error form - let lineless_error_form = functor!( - atom!("error"), - [functor(stub), - functor(culprit)] - ); + let lineless_error_form = functor!(atom!("error"), [functor(stub), functor(culprit)]); println!("{:?}", lineless_error_form); diff --git a/src/heap_iter.rs b/src/heap_iter.rs index 62e02f9f..fd9b1b0c 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -116,10 +116,10 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> { } } (HeapCellValueTag::PStrLoc, h) => { - let (_, tail_loc) = self.heap.scan_slice_to_str(h); + let tail_idx = self.heap.scan_slice_to_str(h).tail_idx; - self.heap[tail_loc].set_mark_bit(self.mark_phase); - self.iter_stack.push(self.heap[tail_loc]); + self.heap[tail_idx].set_mark_bit(self.mark_phase); + self.iter_stack.push(self.heap[tail_idx]); } _ => { } @@ -452,12 +452,12 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> } (HeapCellValueTag::PStrLoc, vh) => { let cell = *cell; - let (_, tail_loc) = self.heap.scan_slice_to_str(vh); + let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx; // forward the current PStrLoc cell if the zero // byte at the end of the string buffer // is marked - let buf_bytes = self.heap[tail_loc - 1].into_bytes(); + let buf_bytes = self.heap[tail_idx - 1].into_bytes(); if buf_bytes[7] != 0u8 { let cell = self.read_cell_mut(h); @@ -469,9 +469,9 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> // is never inspected, which it isn't. self.push_if_unmarked( - IterStackLoc::iterable_loc(tail_loc - 1, HeapOrStackTag::Heap), + IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap), ); - self.stack.push(IterStackLoc::mark_loc(tail_loc, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::mark_loc(tail_idx, HeapOrStackTag::Heap)); return Some(cell); } @@ -502,7 +502,6 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> } } - impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> { type Item = HeapCellValue; @@ -707,9 +706,8 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom)]), - ); + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); wam.machine_st.heap.push_cell(cell).unwrap(); @@ -733,7 +731,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -758,10 +756,7 @@ mod tests { unmark_cell_bits!(iter.next().unwrap()), atom_as_cell!(f_atom, 4) ); - assert_eq!( - unmark_cell_bits!(iter.next().unwrap()), - str_loc_as_cell!(0) - ); + assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0)); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), atom_as_cell!(a_atom) @@ -778,7 +773,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -794,7 +789,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -837,7 +832,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); // now make the list cyclic. wam.machine_st.heap[4] = heap_loc_as_cell!(0); @@ -939,8 +934,6 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); - wam.machine_st.heap.clear(); let mut writer = wam.machine_st.heap.reserve(96).unwrap(); @@ -955,9 +948,11 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom), - atom_as_cell(b_atom)] + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(b_atom) + ] )); functor_writer(&mut wam.machine_st.heap).unwrap(); @@ -1003,7 +998,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); { let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0); @@ -1044,7 +1039,7 @@ mod tests { // instance. } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5)); @@ -1074,7 +1069,7 @@ mod tests { // instance. } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5)); @@ -1126,7 +1121,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1147,7 +1142,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1193,7 +1188,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1427,7 +1422,10 @@ mod tests { wam.machine_st.heap.clear(); { - wam.machine_st.heap.push_cell(fixnum_as_cell!(Fixnum::build_with(0))).unwrap(); + wam.machine_st + .heap + .push_cell(fixnum_as_cell!(Fixnum::build_with(0))) + .unwrap(); let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0); @@ -1439,7 +1437,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1473,7 +1471,7 @@ mod tests { assert!(iter.next().is_none()); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1504,7 +1502,7 @@ mod tests { assert!(iter.next().is_none()); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1564,7 +1562,7 @@ mod tests { assert!(iter.next().is_none()); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(wam.machine_st.heap[0], str_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2)); @@ -1634,13 +1632,6 @@ mod tests { { let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 9); - /* - while let Some(_) = iter.next() { - print_heap_terms(iter.heap.iter(), 0); - println!(""); - } - */ - assert_eq!( unmark_cell_bits!(iter.next().unwrap()), list_loc_as_cell!(7) @@ -1693,9 +1684,8 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom)]), - ); + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let h = wam.machine_st.heap.cell_len(); @@ -1924,7 +1914,7 @@ mod tests { ); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); @@ -2021,7 +2011,11 @@ mod tests { let functor = functor!( f_atom, - [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)] + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(b_atom) + ] ); let mut writer = wam.machine_st.heap.reserve(96).unwrap(); @@ -2098,7 +2092,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap[4] = list_loc_as_cell!(1); @@ -2163,7 +2157,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -2202,7 +2196,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -2221,18 +2215,18 @@ mod tests { 2, ); - assert_eq!( - iter.heap.slice_to_str(0, "a string".len()), - "a string" - ); - assert_eq!( - iter.next().unwrap(), - empty_list_as_cell!() - ); + assert_eq!(iter.heap.slice_to_str(0, "a string".len()), "a string"); + assert_eq!(iter.next().unwrap(), empty_list_as_cell!()); assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + assert_eq!(wam.machine_st.heap.slice_to_str(0, "a string".len()), "a string"); + assert_eq!(wam.machine_st.heap[1], HeapCellValue::build_with(HeapCellValueTag::Cons, 0)); + + for idx in 2 ..= 3 { + assert!(!wam.machine_st.heap[idx].get_mark_bit()); + assert!(!wam.machine_st.heap[idx].get_forwarding_bit()); + } wam.machine_st.heap.clear(); @@ -2291,9 +2285,8 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom)]), - ); + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let h = wam.machine_st.heap.cell_len(); @@ -2325,7 +2318,6 @@ mod tests { wam.machine_st.heap.clear(); - let mut functor_writer = Heap::functor_writer(functor!( f_atom, [ @@ -2361,10 +2353,7 @@ mod tests { unmark_cell_bits!(iter.next().unwrap()), atom_as_cell!(a_atom) ); - assert_eq!( - unmark_cell_bits!(iter.next().unwrap()), - str_loc_as_cell!(0) - ); + assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0)); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), atom_as_cell!(f_atom, 4) @@ -2519,7 +2508,7 @@ mod tests { ); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); @@ -2616,7 +2605,11 @@ mod tests { let functor = functor!( f_atom, - [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)] + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(b_atom) + ] ); let mut writer = wam.machine_st.heap.reserve(96).unwrap(); @@ -2694,7 +2687,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap[4] = list_loc_as_cell!(1); @@ -2761,7 +2754,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); } @@ -2778,9 +2771,8 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom)]), - ); + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); wam.machine_st.heap.push_cell(cell).unwrap(); @@ -2969,7 +2961,7 @@ mod tests { ); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); @@ -3039,7 +3031,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2); @@ -3053,11 +3045,18 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); - let functor = functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]); + let functor = functor!( + f_atom, + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(b_atom) + ] + ); let mut writer = wam.machine_st.heap.reserve(96).unwrap(); @@ -3116,7 +3115,7 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap[4] = list_loc_as_cell!(1); @@ -3164,6 +3163,6 @@ mod tests { assert_eq!(iter.next(), None); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); } } diff --git a/src/heap_print.rs b/src/heap_print.rs index 2bc1706b..cdd166c8 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -486,7 +486,12 @@ pub struct HCPrinter<'a, Outputter> { pub double_quotes: bool, } -fn ambiguity_check(outputter: &impl HCValueOutputter, quoted: bool, last_item_idx: usize, atom: &str) -> bool { +fn ambiguity_check( + outputter: &impl HCValueOutputter, + quoted: bool, + last_item_idx: usize, + atom: &str, +) -> bool { let tail = &outputter.as_str()[last_item_idx..]; if atom == "," || !quoted || non_quoted_token(atom.chars()) { @@ -1132,7 +1137,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } macro_rules! emit_char { - ($c:expr) => ({ + ($c:expr) => {{ append_str!(self, "'.'"); push_char!(self, '('); @@ -1141,14 +1146,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.state_stack.push(TokenOrRedirect::Close); char_count += 1; - }); + }}; } match iteratee { PStrIteratee::Char { value, .. } => { emit_char!(value); } - PStrIteratee::PStrSlice { slice_loc, slice_len } => { + PStrIteratee::PStrSlice { + slice_loc, + slice_len, + } => { let s = iter.heap.slice_to_str(slice_loc, slice_len); for c in s.chars() { @@ -1181,10 +1189,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { if max_depth == 0 { while let Some(iteratee) = iter.next() { let iter: Box> = match iteratee { - PStrIteratee::Char { value: c, .. } => { - Box::new(std::iter::once(c)) - } - PStrIteratee::PStrSlice { slice_loc, slice_len } => { + PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)), + PStrIteratee::PStrSlice { + slice_loc, + slice_len, + } => { let s = iter.heap.slice_to_str(slice_loc, slice_len); Box::new(s.chars()) } @@ -1201,10 +1210,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { while let Some(iteratee) = iter.next() { let iter: Box> = match iteratee { - PStrIteratee::Char { value: c, .. } => { - Box::new(std::iter::once(c)) - } - PStrIteratee::PStrSlice { slice_loc, slice_len } => { + PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)), + PStrIteratee::PStrSlice { + slice_loc, + slice_len, + } => { let s = iter.heap.slice_to_str(slice_loc, slice_len); Box::new(s.chars()) } @@ -1583,22 +1593,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::HeadTailSeparator); } else { - /* - let end_cell_h = Heap::neighboring_cell_offset(pstr_loc); - let end_cell = self.iter.heap[end_cell_h]; - let end_cell = heap_bound_store( - self.iter.heap, - heap_bound_deref(self.iter.heap, end_cell), - ); - - if end_cell != empty_list_as_cell!() { - self.iter.push_stack( - IterStackLoc::iterable_loc(end_cell_h, HeapOrStackTag::Heap), - ); - } - */ - - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1)); + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth + 1)); self.state_stack.push(TokenOrRedirect::HeadTailSeparator); } } @@ -1872,9 +1868,8 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom)]), - ); + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); wam.machine_st.heap.push_cell(cell).unwrap(); @@ -1893,7 +1888,7 @@ mod tests { assert_eq!(output.result(), "f(a,b)"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1925,7 +1920,7 @@ mod tests { assert_eq!(output.result(), "f(a,b,a,...)"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1968,7 +1963,7 @@ mod tests { assert_eq!(output.result(), "[L|L]"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -1984,9 +1979,11 @@ mod tests { let mut functor_writer = Heap::functor_writer(functor!( f_atom, - [atom_as_cell(a_atom), - atom_as_cell(b_atom), - atom_as_cell(b_atom)] + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(b_atom) + ] )); functor_writer(&mut wam.machine_st.heap).unwrap(); @@ -2005,7 +2002,7 @@ mod tests { assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)]"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap[4] = list_loc_as_cell!(1); @@ -2023,7 +2020,7 @@ mod tests { assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|...]"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); { let mut printer = HCPrinter::new( @@ -2043,7 +2040,7 @@ mod tests { assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); // issue #382 wam.machine_st.heap.clear(); @@ -2077,7 +2074,7 @@ mod tests { assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -2100,7 +2097,7 @@ mod tests { assert_eq!(output.result(), "[a,b,c|_1]"); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); let mut writer = wam.machine_st.heap.reserve(96).unwrap(); @@ -2131,7 +2128,7 @@ mod tests { assert_eq!(output.result(), "\"abcabc\""); } - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.machine_st.heap.clear(); @@ -2140,14 +2137,14 @@ mod tests { "=(X,[a,b,c|X])" ); - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!( &wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(), "[a,b,[a],[a,b,c]]" ); - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!( &wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].") @@ -2155,11 +2152,11 @@ mod tests { "[[a,b,c],e,f,[g,e,h,Y,v,X,Y]]" ); - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!(&wam.parse_and_print_term("f((a,b)).").unwrap(), "f((a,b))"); - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.op_dir .insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX)); @@ -2171,14 +2168,14 @@ mod tests { "[a|[]+b]" ); - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); assert_eq!( &wam.parse_and_print_term("[a|[b|c]*d].").unwrap(), "[a|[b|c]*d]" ); - all_cells_unmarked(wam.machine_st.heap.splice(..)); + all_cells_unmarked(&wam.machine_st.heap); wam.op_dir .insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY)); diff --git a/src/indexing.rs b/src/indexing.rs index d9a4f036..344155d8 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1110,12 +1110,11 @@ pub(crate) fn constant_key_alternatives( constants.push( Fixnum::build_with_checked(value) .map(|n| fixnum_as_cell!(n)) - .unwrap() + .unwrap(), ); } } - _ => { - } + _ => {} } /* @@ -1465,11 +1464,7 @@ impl CodeOffsets { self.indices.lists().push_back(index); } - fn index_constant( - &mut self, - constant: HeapCellValue, - index: usize, - ) -> Vec { + fn index_constant(&mut self, constant: HeapCellValue, index: usize) -> Vec { let overlapping_constants = constant_key_alternatives(constant); let code = self.indices.constants().entry(constant).or_default(); diff --git a/src/iterators.rs b/src/iterators.rs index b641c756..1de7541b 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -14,7 +14,9 @@ use std::iter::*; use std::ops::Deref; use std::vec::Vec; -pub(crate) trait TermIterator: Deref + Iterator { +pub(crate) trait TermIterator: + Deref + Iterator +{ fn focus(&self) -> IterStackLoc; fn level(&mut self) -> Level; } @@ -45,9 +47,9 @@ fn record_path( } } (HeapCellValueTag::Lis) => { - root_terms.insert(root_loc); - break; - } + root_terms.insert(root_loc); + break; + } _ => { if cell.is_ref() { root_terms.insert(cell.get_value() as usize); @@ -228,7 +230,10 @@ pub(crate) enum ClauseItem<'a> { FirstBranch(usize), NextBranch, BranchEnd(usize), - Chunk { chunk_num: usize, terms: &'a VecDeque }, + Chunk { + chunk_num: usize, + terms: &'a VecDeque, + }, } #[derive(Debug)] @@ -271,10 +276,9 @@ impl<'a> ClauseIterator<'a> { while let Some(state) = self.state_stack.pop() { match state { - ClauseIteratorState::RemainingBranches(terms, focus) - if terms.len() == focus => { - depth += 1; - } + ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => { + depth += 1; + } _ => { self.state_stack.push(state); break; @@ -292,25 +296,27 @@ impl<'a> Iterator for ClauseIterator<'a> { fn next(&mut self) -> Option { while let Some(state) = self.state_stack.pop() { match state { - ClauseIteratorState::RemainingChunks(chunks, focus) - if focus < chunks.len() => { - if focus + 1 < chunks.len() { + ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => { + if focus + 1 < chunks.len() { + self.state_stack + .push(ClauseIteratorState::RemainingChunks(chunks, focus + 1)); + } else { + self.remaining_chunks_on_stack -= 1; + } + + match &chunks[focus] { + ChunkedTerms::Branch(branches) => { self.state_stack - .push(ClauseIteratorState::RemainingChunks(chunks, focus + 1)); - } else { - self.remaining_chunks_on_stack -= 1; + .push(ClauseIteratorState::RemainingBranches(branches, 0)); } - - match &chunks[focus] { - ChunkedTerms::Branch(branches) => { - self.state_stack - .push(ClauseIteratorState::RemainingBranches(branches, 0)); - } - &ChunkedTerms::Chunk { chunk_num, ref terms } => { - return Some(ClauseItem::Chunk { chunk_num, terms }); - } + &ChunkedTerms::Chunk { + chunk_num, + ref terms, + } => { + return Some(ClauseItem::Chunk { chunk_num, terms }); } } + } ClauseIteratorState::RemainingChunks(chunks, focus) => { debug_assert_eq!(chunks.len(), focus); } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 2b974228..4e8cb44e 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -568,6 +568,7 @@ parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :- % maplist isn't % declared as a % meta-predicate yet + '$debug_hook', catch(lists:maplist(Selector, Options, OptionPairs0), error(E, _), builtins:throw(error(E, Stub))) -> diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index a779411d..86470097 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1165,9 +1165,8 @@ impl MachineState { return Err(self.error_form(type_error, stub_gen())); }; - let mut iter = stackful_post_order_iter::( - &mut self.heap, &mut self.stack, root_loc, - ); + let mut iter = + stackful_post_order_iter::(&mut self.heap, &mut self.stack, root_loc); while let Some(value) = iter.next() { if value.get_forwarding_bit() { diff --git a/src/machine/attributed_variables.pl b/src/machine/attributed_variables.pl index 584abc80..c288511b 100644 --- a/src/machine/attributed_variables.pl +++ b/src/machine/attributed_variables.pl @@ -38,7 +38,6 @@ verify_attrs([], _, _, []). call_goals([ListOfGoalLists | ListsCubed]) :- - '$debug_hook', call_goals_0(ListOfGoalLists), call_goals(ListsCubed). call_goals([]). diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index 6b5ae9b3..368152f5 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -145,7 +145,9 @@ impl MachineState { }; let mut iter = stackful_preorder_iter::( - &mut self.heap, &mut self.stack, root_loc, // cell, + &mut self.heap, + &mut self.stack, + root_loc, // cell, ); while let Some(value) = iter.next() { diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 71beaa47..84b89c39 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -2102,19 +2102,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { } pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> { - let key = match self - .payload - .predicates - .first() - .map(|term| term.focus) { - Some(focus) => { - clause_predicate_key(self.machine_heap(), focus) - .ok_or(SessionError::NamelessEntry)? - } - None => { - return Err(SessionError::NamelessEntry); - } - }; + let key = match self.payload.predicates.first().map(|term| term.focus) { + Some(focus) => clause_predicate_key(self.machine_heap(), focus) + .ok_or(SessionError::NamelessEntry)?, + None => { + return Err(SessionError::NamelessEntry); + } + }; let listing_src_file_name = self.listing_src_file_name(); @@ -2290,13 +2284,18 @@ impl Machine { term_reg: RegType, vars: Vec, ) -> Result<(), SessionError> { - let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg])); + let body_cell = self + .machine_st + .store(self.machine_st.deref(self.machine_st[term_reg])); let new_header_loc = self.machine_st.heap.cell_len(); let arity = vars.len(); let term_loc = self.machine_st.heap.cell_len() + 1 + arity; - let mut writer = self.machine_st.heap.reserve(4 + arity) + let mut writer = self + .machine_st + .heap + .reserve(4 + arity) .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?; writer.write_with(move |section| { diff --git a/src/machine/copier.rs b/src/machine/copier.rs index 5bb2fe90..57e034af 100644 --- a/src/machine/copier.rs +++ b/src/machine/copier.rs @@ -1,13 +1,71 @@ +use fxhash::FxBuildHasher; +use indexmap::IndexSet; + use crate::atom_table::*; use crate::machine::get_structure_index; use crate::machine::heap::*; use crate::machine::stack::*; use crate::types::*; +use scryer_modular_bitfield::specifiers::*; +use scryer_modular_bitfield::*; + +use std::collections::BTreeMap; use std::mem; use std::ops::{IndexMut, Range}; -type Trail = Vec<(Ref, HeapCellValue)>; +#[derive(BitfieldSpecifier, Copy, Clone, Debug)] +#[bits = 6] +enum TrailRefTag { + HeapCell = 0b001011, + StackCell = 0b001101, + AttrVar = 0b010001, + PStrLoc = 0b001111, +} + +#[bitfield] +#[repr(u64)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +struct TrailRef { + val: B56, + #[allow(unused)] + m: bool, + #[allow(unused)] + f: bool, + tag: TrailRefTag, +} + +impl TrailRef { + #[inline(always)] + fn heap_cell(h: usize) -> Self { + TrailRef::new() + .with_tag(TrailRefTag::HeapCell) + .with_val(h as u64) + } + + #[inline(always)] + fn stack_cell(h: usize) -> Self { + TrailRef::new() + .with_tag(TrailRefTag::StackCell) + .with_val(h as u64) + } + + #[inline(always)] + fn attr_var(h: usize) -> Self { + TrailRef::new() + .with_tag(TrailRefTag::AttrVar) + .with_val(h as u64) + } + + #[inline(always)] + fn pstr_loc(h: usize) -> Self { + TrailRef::new() + .with_tag(TrailRefTag::PStrLoc) + .with_val(h as u64) + } +} + +type Trail = Vec<(TrailRef, HeapCellValue)>; #[derive(Debug, Clone, Copy)] pub enum AttrVarPolicy { @@ -18,15 +76,12 @@ pub enum AttrVarPolicy { pub trait CopierTarget: IndexMut { fn store(&self, value: HeapCellValue) -> HeapCellValue; fn deref(&self, value: HeapCellValue) -> HeapCellValue; - // fn push_cell(&mut self, value: HeapCellValue) -> Result<(), usize>; fn push_attr_var_queue(&mut self, attr_var_loc: usize); fn stack(&mut self) -> &mut Stack; fn threshold(&self) -> usize; // returns the tail location of the pstr on success + fn as_slice_from<'a>(&'a self, from: usize) -> Box + 'a>; fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result; - 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; fn copy_slice_to_end(&mut self, bounds: Range) -> Result<(), usize>; } @@ -35,14 +90,25 @@ pub(crate) fn copy_term( target: T, addr: HeapCellValue, attr_var_policy: AttrVarPolicy, -) -> Result<(), usize> { +) -> Result { let mut copy_term_state = CopyTermState::new(target, attr_var_policy); + let old_threshold = copy_term_state.target.threshold(); copy_term_state.copy_term_impl(addr)?; copy_term_state.copy_attr_var_lists()?; copy_term_state.unwind_trail(); - Ok(()) + let new_threshold = copy_term_state.target.threshold(); + copy_term_state.copy_pstrs()?; + + Ok(new_threshold - old_threshold) +} + +#[derive(Debug)] +pub struct PStrData { + pre_old_h_tail_loc: usize, + post_old_h_tail_loc: usize, + post_old_h_pstr_loc_locs: IndexSet, } #[derive(Debug)] @@ -53,6 +119,9 @@ struct CopyTermState { target: T, attr_var_policy: AttrVarPolicy, attr_var_list_locs: Vec<(usize, HeapCellValue)>, + // keys of pstr_loc_locs are byte indices rounded down to the + // nearest cell boundary + pstr_loc_locs: BTreeMap, } impl CopyTermState { @@ -64,6 +133,7 @@ impl CopyTermState { target, attr_var_policy, attr_var_list_locs: vec![], + pstr_loc_locs: BTreeMap::new(), } } @@ -74,7 +144,7 @@ impl CopyTermState { fn trail_list_cell(&mut self, addr: usize, threshold: usize) { let trail_item = mem::replace(&mut self.target[addr], list_loc_as_cell!(threshold)); - self.trail.push((Ref::heap_cell(addr), trail_item)); + self.trail.push((TrailRef::heap_cell(addr), trail_item)); } fn copy_list(&mut self, addr: usize) -> Result<(), usize> { @@ -93,7 +163,7 @@ impl CopyTermState { } let threshold = self.target.threshold(); - self.target.copy_slice_to_end(addr .. addr + 2)?; + self.target.copy_slice_to_end(addr..addr + 2)?; *self.value_at_scan() = list_loc_as_cell!(threshold); @@ -122,54 +192,90 @@ impl CopyTermState { Ok(()) } - /* - * write a null byte to the first word of a partial string to - * flag that it has been copied followed by the copied - * string's index in the next 7 bytes. write the bytes in big - * endian order so that the null byte is at index 0. - */ - fn write_pstr_index(&mut self, head_cell_idx: usize, threshold: usize) { - let bytes = u64::to_be_bytes(threshold as u64); - debug_assert_eq!(bytes[0], 0); - self.target[head_cell_idx] = HeapCellValue::from_bytes(bytes); - } - fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> { - let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc); - let head_byte_idx = heap_index!(head_cell_idx); - let pstr_offset = pstr_loc - head_byte_idx; + match self.pstr_loc_locs.range_mut(..=pstr_loc).next_back() { + Some(( + _prev_pstr_loc, + &mut PStrData { + pre_old_h_tail_loc, + ref mut post_old_h_pstr_loc_locs, + .. + }, + )) if pre_old_h_tail_loc >= cell_index!(pstr_loc) => { + post_old_h_pstr_loc_locs.insert(self.scan); + self.scan += 1; + return Ok(()); + } + _ => {} + } - // if a partial string has been copied previously, we - // track it by writing a null byte to its first word, which is trailed, - // and then the new pstr_loc in the word's remaining 7 bytes. see write_pstr_index - // comment. + let offset = self + .target + .as_slice_from(pstr_loc) + .take_while(|b| *b != 0u8) + .count(); + + 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); + + if flag == 1 { + if left_pstr_boundary != pstr_loc_idx { + let mut pstr_data = self + .pstr_loc_locs + .remove(&heap_index!(left_pstr_boundary)) + .unwrap(); + + pstr_data.post_old_h_pstr_loc_locs.insert(self.scan); + self.pstr_loc_locs + .insert(heap_index!(cell_index!(pstr_loc)), pstr_data); + + let old_cell = self.target[pstr_loc_idx]; + self.target[pstr_loc_idx] = HeapCellValue::from_bytes(u64::to_be_bytes(1)); + self.trail + .push((TrailRef::pstr_loc(pstr_loc_idx), old_cell)); + } else { + let pstr_data = self + .pstr_loc_locs + .get_mut(&heap_index!(left_pstr_boundary)) + .unwrap(); + pstr_data.post_old_h_pstr_loc_locs.insert(self.scan); + } + } else { + let old_cell = self.target[pstr_loc_idx]; + self.target[pstr_loc_idx] = HeapCellValue::from_bytes(u64::to_be_bytes(1)); + self.trail + .push((TrailRef::pstr_loc(pstr_loc_idx), old_cell)); - if self.target[head_cell_idx].into_bytes()[0] == 0u8 { - let head_bytes = self.target[head_cell_idx].into_bytes(); - let new_pstr_loc = u64::from_be_bytes(head_bytes) as usize; + 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 + }; - *self.value_at_scan() = pstr_loc_as_cell!(heap_index!(new_pstr_loc) + pstr_offset); - self.scan += 1; - return Ok(()); - } + let tail_cell = self.target[old_tail_idx]; - let threshold = self.target.threshold(); - let tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?; + let new_tail_idx = self.target.threshold(); + let mut writer = self.target.reserve(1)?; - *self.value_at_scan() = pstr_loc_as_cell!(heap_index!(threshold) + pstr_offset); + writer.write_with(|section| { + section.push_cell(tail_cell); + }); - self.trail.push((Ref::heap_cell(head_cell_idx), self.target[head_cell_idx])); - self.write_pstr_index(head_cell_idx, threshold); + let mut post_old_h_pstr_loc_locs = IndexSet::with_hasher(FxBuildHasher::default()); + post_old_h_pstr_loc_locs.insert(self.scan); - let tail_cell = self.target[tail_loc]; - let mut writer = self.target.reserve(1)?; + 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, + }; - writer.write_with(|section| { - section.push_cell(tail_cell); - }); + self.pstr_loc_locs + .insert(heap_index!(pstr_loc_idx), pstr_data); + } self.scan += 1; - Ok(()) } @@ -210,6 +316,7 @@ impl CopyTermState { }); debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str); + self.copy_term_impl(str_cell)?; list_addr = self.target[heap_loc + 1]; @@ -227,13 +334,13 @@ impl CopyTermState { self.target[frontier] = heap_loc_as_cell!(frontier); self.target[h] = heap_loc_as_cell!(frontier); - self.trail.push((Ref::heap_cell(h), heap_loc_as_cell!(h))); + self.trail.push((TrailRef::heap_cell(h), heap_loc_as_cell!(h))); } (HeapCellValueTag::StackVar, s) => { self.target[frontier] = heap_loc_as_cell!(frontier); self.target.stack()[s] = heap_loc_as_cell!(frontier); - self.trail.push((Ref::stack_cell(s), stack_loc_as_cell!(s))); + self.trail.push((TrailRef::stack_cell(s), stack_loc_as_cell!(s))); } (HeapCellValueTag::AttrVar, h) => { let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy { @@ -245,10 +352,10 @@ impl CopyTermState { self.target[frontier] = heap_loc_as_cell!(threshold); self.target[h] = heap_loc_as_cell!(threshold); - self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h))); + self.trail.push((TrailRef::attr_var(h), attr_var_as_cell!(h))); if let AttrVarPolicy::DeepCopy = self.attr_var_policy { - let mut writer = self.target.reserve(2).unwrap(); + let mut writer = self.target.reserve(2)?; writer.write_with(|section| { section.push_cell(attr_var_as_cell!(threshold)); @@ -256,7 +363,7 @@ impl CopyTermState { }); let old_list_link = self.target[h + 1]; - self.trail.push((Ref::heap_cell(h + 1), old_list_link)); + self.trail.push((TrailRef::heap_cell(h + 1), old_list_link)); self.target[h + 1] = heap_loc_as_cell!(threshold + 1); if old_list_link.get_tag() == HeapCellValueTag::Lis { @@ -317,7 +424,21 @@ impl CopyTermState { (HeapCellValueTag::Atom, (_name, arity)) => { let threshold = self.target.threshold(); - *self.value_at_scan() = str_loc_as_cell!(threshold); + let index_cell = self.target[addr.saturating_sub(1)]; + + *self.value_at_scan() = if get_structure_index(index_cell).is_some() { + // copy the index pointer trailing this + // inlined or expanded goal. + let mut writer = self.target.reserve(1).unwrap(); + + writer.write_with(|section| { + section.push_cell(index_cell); + }); + + str_loc_as_cell!(threshold + 1) + } else { + str_loc_as_cell!(threshold) + }; self.target.copy_slice_to_end(addr .. addr + 1 + arity)?; @@ -326,28 +447,7 @@ impl CopyTermState { str_loc_as_cell!(threshold), ); - self.trail.push((Ref::heap_cell(addr), trail_item)); -/* - self.target.push(atom_as_cell!(name, arity)); - - for i in 0..arity { - let hcv = self.target[addr + 1 + i]; - self.target.push(hcv); - } -*/ - if !self.target.pstr_at(addr + 1 + arity) { - let index_cell = self.target[addr + 1 + arity]; - - if get_structure_index(index_cell).is_some() { - // copy the index pointer trailing this - // inlined or expanded goal. - let mut writer = self.target.reserve(1).unwrap(); - - writer.write_with(|section| { - section.push_cell(index_cell); - }); - } - } + self.trail.push((TrailRef::heap_cell(addr), trail_item)); } (HeapCellValueTag::Str, h) => { *self.value_at_scan() = str_loc_as_cell!(h); @@ -370,11 +470,6 @@ impl CopyTermState { }); while self.scan < self.target.threshold() { - if self.target.pstr_at(self.scan) { - self.scan = self.target.next_non_pstr_cell_index(self.scan); - continue; - } - let addr = *self.value_at_scan(); read_heap_cell!(addr, @@ -405,17 +500,40 @@ impl CopyTermState { Ok(()) } - fn unwind_trail(mut self) { - for (r, value) in self.trail { - let index = r.get_value() as usize; + fn copy_pstrs(&mut self) -> Result<(), usize> { + while let Some((least_pstr_loc, pstr_data)) = self.pstr_loc_locs.pop_first() { + let threshold = heap_index!(self.target.threshold()); + + for pstr_loc_loc in pstr_data.post_old_h_pstr_loc_locs { + let pstr_loc = self.target[pstr_loc_loc].get_value() as usize; + self.target[pstr_loc_loc] = + pstr_loc_as_cell!(threshold + pstr_loc - least_pstr_loc); + } + + self.target.copy_pstr_to_threshold(least_pstr_loc)?; + + let mut writer = self.target.reserve(1)?; + + writer.write_with(|section| { + section.push_cell(heap_loc_as_cell!(pstr_data.post_old_h_tail_loc)); + }); + } + + Ok(()) + } + + fn unwind_trail(&mut self) { + for (r, value) in self.trail.drain(..) { + let index = r.val() as usize; - match r.get_tag() { - RefTag::AttrVar | RefTag::HeapCell => { + match r.tag() { + TrailRefTag::AttrVar | TrailRefTag::HeapCell => { self.target[index] = value; self.target[index].set_mark_bit(false); self.target[index].set_forwarding_bit(false); } - RefTag::StackCell => self.target.stack()[index] = value, + TrailRefTag::StackCell => self.target.stack()[index] = value, + TrailRefTag::PStrLoc => self.target[index] = value, } } } @@ -438,9 +556,10 @@ mod tests { let a_atom = atom!("a"); let b_atom = atom!("b"); - let mut functor_writer = Heap::functor_writer( - functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]), - ); + let mut functor_writer = Heap::functor_writer(functor!( + f_atom, + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); functor_writer(&mut wam.machine_st.heap).unwrap(); @@ -480,29 +599,233 @@ mod tests { copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap(); } - assert_eq!( - wam.machine_st.heap.slice_to_str(0, "abc ".len()), - "abc " - ); + assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc "); assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(2))); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(2), "def".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(2), "def".len()), "def" ); assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(0)); - assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(5))); + assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(7))); + assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(9))); + assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7))); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(5), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(7), "abc ".len()), "abc " ); - assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7))); + assert_eq!(wam.machine_st.heap[8], heap_loc_as_cell!(5)); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(7), "def".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(9), "def".len()), "def" ); - assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(heap_index!(5))); + assert_eq!(wam.machine_st.heap[10], heap_loc_as_cell!(6)); + + wam.machine_st.heap.clear(); + + let mut writer = wam.machine_st.heap.reserve(4).unwrap(); + + writer.write_with(|section| { + section.push_pstr("abc "); + section.push_cell(pstr_loc_as_cell!(heap_index!(2) + 9)); + + section.push_pstr("defdefdefdef"); + section.push_cell(pstr_loc_as_cell!(0)); + }); + + { + let wam = TermCopyingMockWAM { wam: &mut wam }; + copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap(); + } + + assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc "); + assert_eq!( + wam.machine_st.heap[1], + pstr_loc_as_cell!(heap_index!(2) + 9) + ); + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(2), "defdefdefdef".len()), + "defdefdefdef" + ); + assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(0)); + + assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(8))); + assert_eq!( + wam.machine_st.heap[6], + pstr_loc_as_cell!(heap_index!(10) + 1) + ); + assert_eq!(wam.machine_st.heap[7], pstr_loc_as_cell!(heap_index!(8))); + + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(8), "abc ".len()), + "abc " + ); + assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(6)); + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(10), "fdef".len()), + "fdef" + ); + assert_eq!(wam.machine_st.heap[11], heap_loc_as_cell!(7)); + + wam.machine_st.heap.clear(); + + let mut writer = wam.machine_st.heap.reserve(4).unwrap(); + + writer.write_with(|section| { + section.push_pstr("012345678912345"); + section.push_cell(pstr_loc_as_cell!(heap_index!(0))); + }); + + { + let wam = TermCopyingMockWAM { wam: &mut wam }; + copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap(); + } + + assert_eq!( + wam.machine_st.heap.slice_to_str(0, "012345678912345".len()), + "012345678912345" + ); + assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(heap_index!(0))); + + assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(6))); + + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(6), "012345678912345".len()), + "012345678912345" + ); + assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(6))); + + wam.machine_st.heap.clear(); + + let mut writer = wam.machine_st.heap.reserve(4).unwrap(); + + writer.write_with(|section| { + section.push_pstr("012345678912345"); + section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 9)); + }); + + { + let wam = TermCopyingMockWAM { wam: &mut wam }; + copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap(); + } + + assert_eq!( + wam.machine_st.heap.slice_to_str(0, "012345678912345".len()), + "012345678912345" + ); + assert_eq!( + wam.machine_st.heap[3], + pstr_loc_as_cell!(heap_index!(0) + 9) + ); + + assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(6))); + assert_eq!( + wam.machine_st.heap[5], + pstr_loc_as_cell!(heap_index!(6) + 9) + ); + + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(6), "012345678912345".len()), + "012345678912345" + ); + assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(5)); + + wam.machine_st.heap.clear(); + + let mut writer = wam.machine_st.heap.reserve(4).unwrap(); + + writer.write_with(|section| { + section.push_pstr("012345678912345"); + section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 7)); + }); + + { + let wam = TermCopyingMockWAM { wam: &mut wam }; + copy_term(wam, pstr_loc_as_cell!(11), AttrVarPolicy::DeepCopy).unwrap(); + } + + assert_eq!( + wam.machine_st.heap.slice_to_str(0, "012345678912345".len()), + "012345678912345" + ); + assert_eq!( + wam.machine_st.heap[3], + pstr_loc_as_cell!(heap_index!(0) + 7) + ); + + assert_eq!( + wam.machine_st.heap[4], + pstr_loc_as_cell!(heap_index!(6) + 11) + ); + assert_eq!( + wam.machine_st.heap[5], + pstr_loc_as_cell!(heap_index!(6) + 7) + ); + + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(6), "012345678912345".len()), + "012345678912345" + ); + assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(5)); + + wam.machine_st.heap.clear(); + + let mut writer = wam.machine_st.heap.reserve(4).unwrap(); + + writer.write_with(|section| { + section.push_pstr("012345678912345"); + section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 12)); + }); + + { + let wam = TermCopyingMockWAM { wam: &mut wam }; + copy_term(wam, pstr_loc_as_cell!(11), AttrVarPolicy::DeepCopy).unwrap(); + } + + assert_eq!( + wam.machine_st.heap.slice_to_str(0, "012345678912345".len()), + "012345678912345" + ); + assert_eq!( + wam.machine_st.heap[3], + pstr_loc_as_cell!(heap_index!(0) + 12) + ); + + assert_eq!( + wam.machine_st.heap[4], + pstr_loc_as_cell!(heap_index!(6) + 3) + ); + assert_eq!( + wam.machine_st.heap[5], + pstr_loc_as_cell!(heap_index!(6) + 4) + ); + + assert_eq!( + wam.machine_st + .heap + .slice_to_str(heap_index!(6), "8912345".len()), + "8912345" + ); + assert_eq!(wam.machine_st.heap[8], heap_loc_as_cell!(5)); wam.machine_st.heap.clear(); @@ -528,7 +851,6 @@ mod tests { assert_eq!(wam.machine_st.heap[2], atom_as_cell!(b_atom)); assert_eq!(wam.machine_st.heap[3], atom_as_cell!(a_atom)); assert_eq!(wam.machine_st.heap[4], str_loc_as_cell!(0)); - assert_eq!(wam.machine_st.heap[5], str_loc_as_cell!(6)); assert_eq!(wam.machine_st.heap[6], atom_as_cell!(f_atom, 4)); assert_eq!(wam.machine_st.heap[7], atom_as_cell!(a_atom)); diff --git a/src/machine/cycle_detection.rs b/src/machine/cycle_detection.rs index 99ae40b4..da125518 100644 --- a/src/machine/cycle_detection.rs +++ b/src/machine/cycle_detection.rs @@ -206,9 +206,9 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> { } HeapCellValueTag::PStrLoc => { let h = self.next as usize; - let (_, last_cell_loc) = self.heap.scan_slice_to_str(h); + let tail_idx = self.heap.scan_slice_to_str(h).tail_idx; - if self.heap[last_cell_loc].get_forwarding_bit() { + if self.heap[tail_idx].get_forwarding_bit() { if self.cycle_detection_active() { self.cycle_found = true; return None; @@ -219,11 +219,11 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> { continue; } - self.heap[last_cell_loc].set_forwarding_bit(true); + self.heap[tail_idx].set_forwarding_bit(true); - self.next = self.heap[last_cell_loc].get_value(); - self.heap[last_cell_loc].set_value(self.current as u64); - self.current = last_cell_loc; + self.next = self.heap[tail_idx].get_value(); + self.heap[tail_idx].set_value(self.current as u64); + self.current = tail_idx; return Some(pstr_loc_as_cell!(h)); } diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index a7b2a128..ad4460d4 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -2,11 +2,11 @@ use crate::atom_table::*; use crate::forms::*; use crate::instructions::*; use crate::iterators::fact_iterator; -use crate::machine::Stack; use crate::machine::heap::*; use crate::machine::loader::*; use crate::machine::machine_errors::CompilationError; use crate::machine::preprocessor::*; +use crate::machine::Stack; use crate::parser::ast::*; use crate::parser::dashu::Rational; use crate::types::*; @@ -229,7 +229,8 @@ impl VarLocsToNums { } pub fn get(&self, idx: VarPtrIndex) -> VarPtr { - self.map.get(&idx) + self.map + .get(&idx) .cloned() .map(VarPtr::Numbered) .unwrap_or_else(|| VarPtr::Anon) @@ -260,8 +261,10 @@ impl VarData { if let Some(global_cut_var_num) = global_cut_var_num { let term = QueryTerm::GetLevel(global_cut_var_num); - self.records[global_cut_var_num].allocation = - VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending }; + self.records[global_cut_var_num].allocation = VarAlloc::Perm { + reg: 0, + allocation: PermVarAllocation::Pending, + }; match build_stack.front_mut() { Some(ChunkedTerms::Branch(_)) => { @@ -395,11 +398,7 @@ impl VariableClassifier { let mut lvl = Level::Shallow; let mut stack = Stack::uninitialized(); - let mut iter = fact_iterator::( - term.heap, - &mut stack, - term.focus, - ); + let mut iter = fact_iterator::(term.heap, &mut stack, term.focus); // second arg is true to iterate the root, which may be a variable while let Some(subterm) = iter.next() { @@ -425,8 +424,7 @@ impl VariableClassifier { fn probe_body_var(&mut self, context: GenContext, var_info: VarInfo) { let chunk_num = context.chunk_num(); - let branch_info_v = self.branch_map.entry(var_info.var) - .or_default(); + let branch_info_v = self.branch_map.entry(var_info.var).or_default(); let needs_new_branch = if let Some(last_bi) = branch_info_v.last() { !self.root_set.contains(&last_bi.branch_num) @@ -489,14 +487,10 @@ impl VariableClassifier { debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str); - for idx in str_offset + 1 ..= str_offset + arity { + for idx in str_offset + 1..=str_offset + arity { let mut lvl = Level::Shallow; let mut stack = Stack::uninitialized(); - let mut iter = fact_iterator::( - heap, - &mut stack, - idx, - ); + let mut iter = fact_iterator::(heap, &mut stack, idx); while let Some(subterm) = iter.next() { if !subterm.is_var() { @@ -661,13 +655,14 @@ impl VariableClassifier { mut term_loc, } => { // return true iff new chunk should be added. - let update_chunk_data = |build_stack: &mut ChunkedTermVec, key: PredicateKey| { - if ClauseType::is_inlined(key.0, key.1) { - build_stack.try_set_chunk_at_inlined_boundary() - } else { - build_stack.try_set_chunk_at_call_boundary() - } - }; + let update_chunk_data = + |build_stack: &mut ChunkedTermVec, key: PredicateKey| { + if ClauseType::is_inlined(key.0, key.1) { + build_stack.try_set_chunk_at_inlined_boundary() + } else { + build_stack.try_set_chunk_at_call_boundary() + } + }; macro_rules! add_chunk { ($key:expr, $tag:expr, $term_loc:expr) => {{ @@ -678,9 +673,10 @@ impl VariableClassifier { let context = build_stack.current_gen_context(); for (arg_c, term_loc) in - ($term_loc + 1 ..= $term_loc + $key.1).enumerate() + ($term_loc + 1..=$term_loc + $key.1).enumerate() { - let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc); + let mut term = + FocusedHeapRefMut::from(loader.machine_heap(), term_loc); self.probe_body_term( arg_c + 1, @@ -710,9 +706,10 @@ impl VariableClassifier { let context = build_stack.current_gen_context(); for (arg_c, term_loc) in - ($term_loc + 1 ..= $term_loc + $key.1).enumerate() + ($term_loc + 1..=$term_loc + $key.1).enumerate() { - let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc); + let mut term = + FocusedHeapRefMut::from(loader.machine_heap(), term_loc); self.probe_body_term( arg_c + 1, @@ -1043,8 +1040,8 @@ impl BranchMap { for (var, branches) in self.iter_mut() { let (mut var_num, var_num_incr) = match var { - &ClassifiedVar::InSitu { var_num} => (var_num, false), - _ => (var_data.records.len(), true) + &ClassifiedVar::InSitu { var_num } => (var_num, false), + _ => (var_data.records.len(), true), }; for branch in branches.iter_mut() { @@ -1088,7 +1085,10 @@ impl BranchMap { let chunk_num = chunk.term_loc.chunk_num(); var_data.var_locs_to_nums.insert( - VarPtrIndex { chunk_num, term_loc }, + VarPtrIndex { + chunk_num, + term_loc, + }, var_num, ); } diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index ad0ebc7d..cd672320 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -140,10 +140,7 @@ impl MachineState { let a1 = self.registers[1]; let a2 = self.registers[2]; - step_or_resource_error!( - self, - copy_term(CopyTerm::new(self), a1, attr_var_policy) - ); + step_or_resource_error!(self, copy_term(CopyTerm::new(self), a1, attr_var_policy)); unify_fn!(*self, heap_loc_as_cell!(old_h), a2); } @@ -162,11 +159,7 @@ impl MachineState { let heap_addr = resource_error_call_result!( self, - sized_iter_to_heap_list( - &mut self.heap, - list.len(), - list.into_iter(), - ) + sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter(),) ); let target_addr = self.registers[2]; @@ -5155,9 +5148,8 @@ impl Machine { let r = self.machine_st.registers[2]; let r = self.machine_st.store(self.machine_st.deref(r)); - let mut writer = Heap::functor_writer( - functor!(atom!("-"), [fixnum(n), fixnum(p)]), - ); + let mut writer = + Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)])); let str_cell = backtrack_on_resource_error!( &mut self.machine_st, @@ -5178,9 +5170,8 @@ impl Machine { let r = self.machine_st.registers[2]; let r = self.machine_st.store(self.machine_st.deref(r)); - let mut writer = Heap::functor_writer( - functor!(atom!("-"), [fixnum(n), fixnum(p)]), - ); + let mut writer = + Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)])); let str_cell = backtrack_on_resource_error!( &mut self.machine_st, diff --git a/src/machine/gc.rs b/src/machine/gc.rs index f0f480f3..b18b5300 100644 --- a/src/machine/gc.rs +++ b/src/machine/gc.rs @@ -6,15 +6,18 @@ use crate::machine::heap::*; use crate::types::*; #[cfg(test)] -use fxhash::FxBuildHasher; +use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc}; + #[cfg(test)] -use indexmap::IndexMap; +use std::collections::BTreeMap; +#[cfg(test)] +use std::ops::Deref; #[cfg(test)] -use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc}; +use fxhash::FxBuildHasher; #[cfg(test)] -use std::ops::Deref; +use indexmap::IndexMap; #[cfg(test)] pub(crate) trait UnmarkPolicy { @@ -36,7 +39,8 @@ pub(crate) trait UnmarkPolicy { fn record_focus(_iter: &mut StacklessPreOrderHeapIter) where Self: Sized, - {} + { + } } #[cfg(test)] @@ -109,7 +113,63 @@ impl UnmarkPolicy for MarkerUMP { } #[cfg(test)] -type PStrLocValuesMap = IndexMap; +#[derive(Debug)] +struct PStrLocValuesMap { + hit_set: BTreeMap, + pstr_loc_locs: IndexMap, +} + +#[cfg(test)] +impl PStrLocValuesMap { + #[inline] + fn new() -> Self { + Self { + hit_set: BTreeMap::default(), + pstr_loc_locs: IndexMap::with_hasher(FxBuildHasher::default()), + } + } + + fn progress_pstr_marking(&mut self, heap_slice: &[u8], pstr_loc: usize) -> usize { + match self.hit_set.range(..= pstr_loc).next_back() { + Some((_prev_pstr_loc, &tail_idx)) if pstr_loc < heap_index!(tail_idx) => { + return tail_idx; + } + _ => {} + } + + let delimiter = match self.hit_set.range(pstr_loc + 1..).next() { + Some((&prev_pstr_loc, _)) => prev_pstr_loc, + None => heap_slice.len(), + }; + + match heap_slice[pstr_loc..delimiter].iter().position(|b| *b == 0u8) { + Some(zero_byte_offset) => { + let tail_idx = if (zero_byte_offset + 1) % Heap::heap_cell_alignment() == 0 { + cell_index!(pstr_loc + zero_byte_offset) + 2 + } else { + cell_index!(pstr_loc + zero_byte_offset) + 1 + }; + self.hit_set.insert(pstr_loc, tail_idx); + tail_idx + } + None => { + let tail_idx = self.hit_set.remove(&delimiter).unwrap(); + self.hit_set.insert(pstr_loc, tail_idx); + tail_idx //None + } + } + } + + #[inline] + fn pstr_loc_loc_value(&self, pstr_loc_loc: usize) -> Option { + self.pstr_loc_locs.get(&pstr_loc_loc).cloned() + } + + #[inline] + fn insert_pstr_loc_value(&mut self, pstr_loc_loc: usize, pstr_loc: usize) { + self.pstr_loc_locs.insert(pstr_loc_loc, pstr_loc); + } +} #[cfg(test)] #[derive(Debug)] @@ -164,7 +224,7 @@ impl<'a> StacklessPreOrderHeapIter<'a, MarkerUMP> { current: start, next, iter_state: MarkerUMP {}, - pstr_loc_values: PStrLocValuesMap::with_hasher(FxBuildHasher::default()), + pstr_loc_values: PStrLocValuesMap::new(), } } } @@ -182,7 +242,7 @@ impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> { current: start, next, iter_state: IteratorUMP { mark_phase: true }, - pstr_loc_values: PStrLocValuesMap::with_hasher(FxBuildHasher::default()), + pstr_loc_values: PStrLocValuesMap::new(), } } } @@ -260,8 +320,8 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { let arity = cell_as_atom_cell!(self.heap[h]).get_arity(); - for cell in &mut self.heap.splice_mut(h + 1..h + arity + 1) { - cell.set_forwarding_bit(true); + for idx in h + 1..=h + arity { + self.heap[idx].set_forwarding_bit(true); } let last_cell_loc = h + arity; @@ -288,22 +348,25 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { return Some(list_loc_as_cell!(last_cell_loc - 1)); } HeapCellValueTag::PStrLoc => { - let h = self.next as usize; - let (_, last_cell_loc) = self.heap.scan_slice_to_str(h); + let pstr_loc = self.next as usize; - self.pstr_loc_values.insert(self.current, h); + let tail_idx = self + .pstr_loc_values + .progress_pstr_marking(self.heap.as_slice(), pstr_loc); - if self.heap[last_cell_loc].get_forwarding_bit() { + self.pstr_loc_values.insert_pstr_loc_value(self.current, pstr_loc); + + if self.heap[tail_idx].get_forwarding_bit() { return Some(self.backward_and_return()); } - self.next = self.heap[last_cell_loc].get_value(); - self.heap[last_cell_loc].set_value(self.current as u64); - self.current = last_cell_loc; + self.next = self.heap[tail_idx].get_value(); + self.heap[tail_idx].set_value(self.current as u64); + self.current = tail_idx; - self.heap[last_cell_loc].set_forwarding_bit(true); + self.heap[tail_idx].set_forwarding_bit(true); - return Some(pstr_loc_as_cell!(h)); + return Some(pstr_loc_as_cell!(pstr_loc)); } tag @ HeapCellValueTag::Atom => { let cell = HeapCellValue::build_with(tag, self.next); @@ -315,17 +378,24 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { return None; } } - HeapCellValueTag::Cons if self.heap.pstr_at(self.current) => { - let pstr_loc_loc = self.heap[self.current].get_value() as usize; - let pstr_loc_val = self.pstr_loc_values.get(&pstr_loc_loc).unwrap(); - - self.heap[self.current].set_value(self.next); - - self.next = *pstr_loc_val as u64; - self.current = pstr_loc_loc; - - if self.backward() { - return None; + HeapCellValueTag::Cons => { + match self.pstr_loc_values.hit_set.range(.. heap_index!(self.current + 1)).next_back() { + Some((_prev_pstr_loc, &tail_idx)) if self.current + 1 == tail_idx => { + let pstr_loc_loc = self.heap[self.current].get_value() as usize; + let pstr_loc_val = self.pstr_loc_values.pstr_loc_loc_value(pstr_loc_loc).unwrap(); + + self.heap[self.current].set_value(self.next); + + self.next = pstr_loc_val as u64; + self.current = pstr_loc_loc; + + if self.backward() { + return None; + } + } + _ => { + return Some(self.backward_and_return()); + } } } _ => { @@ -398,9 +468,10 @@ mod tests { let a_atom = atom!("a"); let b_atom = atom!("b"); - let mut functor_writer = Heap::functor_writer( - functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]), - ); + let mut functor_writer = Heap::functor_writer(functor!( + f_atom, + [atom_as_cell(a_atom), atom_as_cell(b_atom)] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let h = wam.machine_st.heap.cell_len(); @@ -409,7 +480,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, h); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), @@ -431,17 +502,15 @@ mod tests { wam.machine_st.heap.clear(); - let mut functor_writer = Heap::functor_writer( - functor!( - f_atom, - [ - atom_as_cell(a_atom), - atom_as_cell(b_atom), - atom_as_cell(a_atom), - str_loc_as_cell(1) - ] - ), - ); + let mut functor_writer = Heap::functor_writer(functor!( + f_atom, + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(a_atom), + str_loc_as_cell(1) + ] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let h = wam.machine_st.heap.cell_len(); @@ -449,7 +518,7 @@ mod tests { wam.machine_st.heap.push_cell(cell).unwrap(); mark_cells(&mut wam.machine_st.heap, h); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), @@ -473,28 +542,26 @@ mod tests { atom_as_cell!(a_atom) ); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); // make the structure doubly cyclic. wam.machine_st.heap[1] = str_loc_as_cell!(0); mark_cells(&mut wam.machine_st.heap, h); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); wam.machine_st.heap.clear(); - let mut functor_writer = Heap::functor_writer( - functor!( - f_atom, - [ - atom_as_cell(a_atom), - atom_as_cell(b_atom), - atom_as_cell(a_atom), - str_loc_as_cell(0) - ] - ), - ); + let mut functor_writer = Heap::functor_writer(functor!( + f_atom, + [ + atom_as_cell(a_atom), + atom_as_cell(b_atom), + atom_as_cell(a_atom), + str_loc_as_cell(0) + ] + )); let cell = functor_writer(&mut wam.machine_st.heap).unwrap(); let h = wam.machine_st.heap.cell_len(); @@ -503,7 +570,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, h); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), @@ -536,7 +603,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -558,7 +625,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -581,14 +648,14 @@ mod tests { empty_list_as_cell!() ); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); // now make the list cyclic. wam.machine_st.heap[4] = heap_loc_as_cell!(0); mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -611,24 +678,21 @@ mod tests { heap_loc_as_cell!(0) ); - for cell in &mut wam.machine_st.heap.splice_mut(..) { - cell.set_mark_bit(false); - } + unmark_all_cells(&mut wam.machine_st.heap, 0); // make the list doubly cyclic. wam.machine_st.heap[3] = heap_loc_as_cell!(0); mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); wam.machine_st.heap.clear(); // term is: [a, ] let stream = Stream::from_static_string("test", &mut wam.machine_st.arena); - let stream_cell = HeapCellValue::from( - ConsPtr::build_with(stream.as_ptr(), ConsPtrMaskTag::Cons), - ); + let stream_cell = + HeapCellValue::from(ConsPtr::build_with(stream.as_ptr(), ConsPtrMaskTag::Cons)); let mut writer = wam.machine_st.heap.reserve(16).unwrap(); @@ -642,7 +706,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -677,7 +741,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -708,19 +772,27 @@ mod tests { let pstr_cell_loc = wam.machine_st.heap.cell_len(); - wam.machine_st.heap.push_cell(pstr_loc_as_cell!(heap_index!(0))).unwrap(); + wam.machine_st + .heap + .push_cell(pstr_loc_as_cell!(heap_index!(0))) + .unwrap(); mark_cells(&mut wam.machine_st.heap, pstr_cell_loc); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 1); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 1); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(0), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(0), "abc ".len()), "abc " ); - assert_eq!(unmark_cell_bits!(wam.machine_st.heap[pstr_cell_loc]), pstr_cell); + assert_eq!( + unmark_cell_bits!(wam.machine_st.heap[pstr_cell_loc]), + pstr_cell + ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1) @@ -728,135 +800,155 @@ mod tests { wam.machine_st.heap[1] = pstr_loc_as_cell!(heap_index!(3)); - wam.machine_st.allocate_pstr("abc ").unwrap(); - wam.machine_st.heap.push_cell(heap_loc_as_cell!(4)).unwrap(); + wam.machine_st.allocate_pstr("abcdef ").unwrap(); + wam.machine_st.heap.push_cell(heap_loc_as_cell!(5)).unwrap(); mark_cells(&mut wam.machine_st.heap, 2); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + assert!(wam.machine_st.heap[0].get_mark_bit()); + assert!(!wam.machine_st.heap[0].get_forwarding_bit()); + assert!(wam.machine_st.heap[1].get_mark_bit()); + assert!(!wam.machine_st.heap[1].get_forwarding_bit()); + assert!(wam.machine_st.heap[2].get_mark_bit()); + assert!(!wam.machine_st.heap[2].get_forwarding_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + assert!(wam.machine_st.heap[4].get_mark_bit()); + assert!(!wam.machine_st.heap[4].get_forwarding_bit()); + assert!(wam.machine_st.heap[5].get_mark_bit()); + assert!(!wam.machine_st.heap[5].get_forwarding_bit()); + + unmark_all_cells(&mut wam.machine_st.heap, 0); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(0), "abc ".len()), - "abc " - ); - assert_eq!( - wam.machine_st.heap[1], - pstr_loc_as_cell!(heap_index!(3)) - ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(0)) - ); - assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(0), "abc ".len()), "abc " ); + assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(3))); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(0))); assert_eq!( - wam.machine_st.heap[4], - heap_loc_as_cell!(4) + wam.machine_st + .heap + .slice_to_str(heap_index!(3), "abcdef ".len()), + "abcdef " ); + assert_eq!(wam.machine_st.heap[5], heap_loc_as_cell!(5)); // create a cycle offset two characters into the partial string at 0 - wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(0) + 2); + wam.machine_st.heap[5] = pstr_loc_as_cell!(heap_index!(0) + 2); mark_cells(&mut wam.machine_st.heap, 2); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + assert!(wam.machine_st.heap[0].get_mark_bit()); + assert!(!wam.machine_st.heap[0].get_forwarding_bit()); + assert!(wam.machine_st.heap[1].get_mark_bit()); + assert!(!wam.machine_st.heap[1].get_forwarding_bit()); + assert!(wam.machine_st.heap[2].get_mark_bit()); + assert!(!wam.machine_st.heap[2].get_forwarding_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + assert!(wam.machine_st.heap[4].get_mark_bit()); + assert!(!wam.machine_st.heap[4].get_forwarding_bit()); + assert!(wam.machine_st.heap[5].get_mark_bit()); + assert!(!wam.machine_st.heap[5].get_forwarding_bit()); + wam.machine_st.heap[0].set_mark_bit(false); + wam.machine_st.heap[1].set_mark_bit(false); + wam.machine_st.heap[2].set_mark_bit(false); + wam.machine_st.heap[4].set_mark_bit(false); + wam.machine_st.heap[5].set_mark_bit(false); + + 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!(3))); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(0))); 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!(3)) - ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(0)) + wam.machine_st + .heap + .slice_to_str(heap_index!(3), "abcdef ".len()), + "abcdef " ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()), - "abc " - ); - assert_eq!( - wam.machine_st.heap[4], + wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(0) + 2) ); - wam.machine_st.heap[4] = heap_loc_as_cell!(2); - + wam.machine_st.heap[5] = heap_loc_as_cell!(2); wam.machine_st.heap.push_cell(heap_loc_as_cell!(2)).unwrap(); - mark_cells(&mut wam.machine_st.heap, 5); + mark_cells(&mut wam.machine_st.heap, 6); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + assert!(wam.machine_st.heap[0].get_mark_bit()); + assert!(!wam.machine_st.heap[0].get_forwarding_bit()); + assert!(wam.machine_st.heap[1].get_mark_bit()); + assert!(!wam.machine_st.heap[1].get_forwarding_bit()); + assert!(wam.machine_st.heap[2].get_mark_bit()); + assert!(!wam.machine_st.heap[2].get_forwarding_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + assert!(wam.machine_st.heap[4].get_mark_bit()); + assert!(!wam.machine_st.heap[4].get_forwarding_bit()); + assert!(wam.machine_st.heap[5].get_mark_bit()); + assert!(!wam.machine_st.heap[5].get_forwarding_bit()); + assert!(wam.machine_st.heap[6].get_mark_bit()); + assert!(!wam.machine_st.heap[6].get_forwarding_bit()); + wam.machine_st.heap[0].set_mark_bit(false); + wam.machine_st.heap[1].set_mark_bit(false); + wam.machine_st.heap[2].set_mark_bit(false); + wam.machine_st.heap[4].set_mark_bit(false); + wam.machine_st.heap[5].set_mark_bit(false); + wam.machine_st.heap[6].set_mark_bit(false); + + 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!(3))); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(0))); 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!(3)) - ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(0)) - ); - assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()), - "abc " - ); - assert_eq!( - wam.machine_st.heap[4], - heap_loc_as_cell!(2) - ); - assert_eq!( - wam.machine_st.heap[5], - heap_loc_as_cell!(2) + wam.machine_st + .heap + .slice_to_str(heap_index!(3), "abcdef ".len()), + "abcdef " ); + assert_eq!(wam.machine_st.heap[5], heap_loc_as_cell!(2)); + assert_eq!(wam.machine_st.heap[6], heap_loc_as_cell!(2)); - wam.machine_st.heap[4] = pstr_loc_as_cell!(0); + wam.machine_st.heap[5] = pstr_loc_as_cell!(0); mark_cells(&mut wam.machine_st.heap, 2); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(.. 5)); + assert!(wam.machine_st.heap[0].get_mark_bit()); + assert!(wam.machine_st.heap[1].get_mark_bit()); + assert!(wam.machine_st.heap[2].get_mark_bit()); + assert!(!wam.machine_st.heap[3].get_mark_bit()); + assert!(wam.machine_st.heap[4].get_mark_bit()); + assert!(wam.machine_st.heap[5].get_mark_bit()); + assert!(!wam.machine_st.heap[6].get_mark_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(.. 5)); + assert!(!wam.machine_st.heap[0].get_forwarding_bit()); + assert!(!wam.machine_st.heap[1].get_forwarding_bit()); + assert!(!wam.machine_st.heap[2].get_forwarding_bit()); + assert!(!wam.machine_st.heap[3].get_forwarding_bit()); + assert!(!wam.machine_st.heap[4].get_forwarding_bit()); + assert!(!wam.machine_st.heap[5].get_forwarding_bit()); + assert!(!wam.machine_st.heap[6].get_forwarding_bit()); + wam.machine_st.heap[0].set_mark_bit(false); + wam.machine_st.heap[1].set_mark_bit(false); + wam.machine_st.heap[2].set_mark_bit(false); + wam.machine_st.heap[4].set_mark_bit(false); + wam.machine_st.heap[5].set_mark_bit(false); + + 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!(3))); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(0))); 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!(3)) - ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(0)) - ); - assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()), - "abc " - ); - assert_eq!( - wam.machine_st.heap[4], - pstr_loc_as_cell!(heap_index!(0)) - ); - assert_eq!( - wam.machine_st.heap[5], - heap_loc_as_cell!(2) + wam.machine_st + .heap + .slice_to_str(heap_index!(3), "abcdef ".len()), + "abcdef " ); + assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(0))); + assert_eq!(wam.machine_st.heap[6], heap_loc_as_cell!(2)); - wam.machine_st.heap.truncate(4); + wam.machine_st.heap.truncate(5); let mut writer = wam.machine_st.heap.reserve(2).unwrap(); @@ -865,51 +957,42 @@ mod tests { section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 2)); // offset two chars into pstr at 0 }); - wam.machine_st.heap.push_cell(heap_loc_as_cell!(5)).unwrap(); + wam.machine_st.heap.push_cell(heap_loc_as_cell!(6)).unwrap(); - mark_cells(&mut wam.machine_st.heap, 6); + mark_cells(&mut wam.machine_st.heap, 7); - // indices 0 and 3 are the beginning of one-cell partial - // strings, and they should be marked! despite the HeapCellValue casts - // otherwise not being sensible. + // indices 0 and 3 - 4 are the beginning of one-cell partial + // strings, and they should be marked! despite the + // HeapCellValue casts otherwise not being sensible. assert!(wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(!wam.machine_st.heap[2].get_mark_bit()); - assert!(wam.machine_st.heap[3].get_mark_bit()); + assert!(!wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(wam.machine_st.heap[6].get_mark_bit()); + assert!(wam.machine_st.heap[7].get_mark_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); + 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!(3))); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(0))); 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!(3)) - ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(0)) - ); - assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()), - "abc " - ); - assert_eq!( - wam.machine_st.heap[4], - atom_as_cell!(atom!("irrelevant stuff")) + wam.machine_st + .heap + .slice_to_str(heap_index!(3), "abcdef ".len()), + "abcdef " ); assert_eq!( wam.machine_st.heap[5], - pstr_loc_as_cell!(heap_index!(0) + 2) + atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( wam.machine_st.heap[6], - heap_loc_as_cell!(5) + pstr_loc_as_cell!(heap_index!(0) + 2) ); + assert_eq!(wam.machine_st.heap[7], heap_loc_as_cell!(6)); wam.machine_st.heap.clear(); @@ -944,26 +1027,27 @@ mod tests { assert!(!wam.machine_st.heap[5].get_forwarding_bit()); assert!(!wam.machine_st.heap[6].get_forwarding_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); assert_eq!( wam.machine_st.heap[0], atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(1), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(1), "abc ".len()), "abc " ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(4)) - ); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(4))); assert_eq!( wam.machine_st.heap[3], atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(4), "def".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(4), "def".len()), "def" ); assert_eq!( @@ -988,34 +1072,31 @@ mod tests { assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); - assert!(!wam.machine_st.heap[0].get_forwarding_bit()); - assert!(!wam.machine_st.heap[1].get_forwarding_bit()); - assert!(!wam.machine_st.heap[2].get_forwarding_bit()); - assert!(!wam.machine_st.heap[3].get_forwarding_bit()); - assert!(!wam.machine_st.heap[4].get_forwarding_bit()); - assert!(!wam.machine_st.heap[5].get_forwarding_bit()); - assert!(!wam.machine_st.heap[6].get_forwarding_bit()); + for idx in 0..=6 { + assert!(!wam.machine_st.heap[idx].get_forwarding_bit()); + } assert_eq!( wam.machine_st.heap[0], atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(1), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(1), "abc ".len()), "abc " ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(4)) - ); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(4))); assert_eq!( wam.machine_st.heap[3], atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(4), "def".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(4), "def".len()), "def" ); assert_eq!( @@ -1040,34 +1121,31 @@ mod tests { assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); - assert!(!wam.machine_st.heap[0].get_forwarding_bit()); - assert!(!wam.machine_st.heap[1].get_forwarding_bit()); - assert!(!wam.machine_st.heap[2].get_forwarding_bit()); - assert!(!wam.machine_st.heap[3].get_forwarding_bit()); - assert!(!wam.machine_st.heap[4].get_forwarding_bit()); - assert!(!wam.machine_st.heap[5].get_forwarding_bit()); - assert!(!wam.machine_st.heap[6].get_forwarding_bit()); + for idx in 0..=6 { + assert!(!wam.machine_st.heap[idx].get_forwarding_bit()); + } assert_eq!( wam.machine_st.heap[0], atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(1), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(1), "abc ".len()), "abc " ); - assert_eq!( - wam.machine_st.heap[2], - pstr_loc_as_cell!(heap_index!(4)) - ); + assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(heap_index!(4))); assert_eq!( wam.machine_st.heap[3], atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(4), "def".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(4), "def".len()), "def" ); assert_eq!( @@ -1096,34 +1174,24 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 5); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(0), "abc ".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(0), "abc ".len()), "abc " ); assert_eq!( wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(0) + 3) ); - assert_eq!( - wam.machine_st.heap[2], - list_loc_as_cell!(3) - ); - assert_eq!( - wam.machine_st.heap[3], - pstr_loc_as_cell!(0) - ); - assert_eq!( - wam.machine_st.heap[4], - empty_list_as_cell!() - ); - assert_eq!( - wam.machine_st.heap[5], - heap_loc_as_cell!(2) - ); + assert_eq!(wam.machine_st.heap[2], list_loc_as_cell!(3)); + assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(0)); + assert_eq!(wam.machine_st.heap[4], empty_list_as_cell!()); + assert_eq!(wam.machine_st.heap[5], heap_loc_as_cell!(2)); wam.machine_st.heap.clear(); @@ -1140,26 +1208,14 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); - unmark_all_cells(wam.machine_st.heap.splice_mut(..)); + unmark_all_cells(&mut wam.machine_st.heap, 0); - assert_eq!( - wam.machine_st.heap[0], - heap_loc_as_cell!(1) - ); - assert_eq!( - wam.machine_st.heap[1], - heap_loc_as_cell!(2) - ); - assert_eq!( - wam.machine_st.heap[2], - heap_loc_as_cell!(3) - ); - assert_eq!( - wam.machine_st.heap[3], - heap_loc_as_cell!(3) - ); + assert_eq!(wam.machine_st.heap[0], heap_loc_as_cell!(1)); + assert_eq!(wam.machine_st.heap[1], heap_loc_as_cell!(2)); + assert_eq!(wam.machine_st.heap[2], heap_loc_as_cell!(3)); + assert_eq!(wam.machine_st.heap[3], heap_loc_as_cell!(3)); wam.machine_st.heap.clear(); @@ -1175,7 +1231,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1215,7 +1271,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1274,7 +1330,8 @@ mod tests { let clpz_atom = atom!("clpz"); let p_atom = atom!("p"); - for cell in &mut wam.machine_st.heap.splice_mut(..) { + for idx in 0..wam.machine_st.heap.cell_len() { + let cell = &mut wam.machine_st.heap[idx]; cell.set_mark_bit(false); cell.set_forwarding_bit(false); } @@ -1299,7 +1356,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1398,7 +1455,9 @@ mod tests { heap_loc_as_cell!(23) ); - for cell in &mut wam.machine_st.heap.splice_mut(..) { + for idx in 0..wam.machine_st.heap.cell_len() { + let cell = &mut wam.machine_st.heap[idx]; + cell.set_mark_bit(false); cell.set_forwarding_bit(false); } @@ -1415,10 +1474,13 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(0..24)); + for idx in 0..24 { + assert!(wam.machine_st.heap[idx].get_mark_bit()); + assert!(!wam.machine_st.heap[idx].get_forwarding_bit()); + } - for cell in wam.machine_st.heap.splice(24..) { - assert!(!cell.get_mark_bit()); + for idx in 24..wam.machine_st.heap.cell_len() { + assert!(!wam.machine_st.heap[idx].get_mark_bit()); } assert_eq!( @@ -1540,7 +1602,7 @@ mod tests { assert_eq!(wam.machine_st.heap.cell_len(), 1); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); wam.machine_st.heap.clear(); @@ -1563,7 +1625,7 @@ mod tests { assert_eq!(wam.machine_st.heap.cell_len(), 10); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1619,7 +1681,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 3); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1653,7 +1715,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 7); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1708,7 +1770,7 @@ mod tests { assert!(wam.machine_st.heap[0].get_mark_bit()); assert!(!wam.machine_st.heap[1].get_mark_bit()); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(2..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 2); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), @@ -1770,7 +1832,7 @@ mod tests { mark_cells(&mut wam.machine_st.heap, 0); - all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..)); + all_cells_marked_and_unforwarded(&wam.machine_st.heap, 0); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 8f4d4a6c..fc517740 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -5,22 +5,17 @@ use crate::types::*; use std::alloc; use std::convert::TryFrom; -use std::mem; use std::ops::{Bound, Index, IndexMut, Range, RangeBounds}; use std::ptr; use std::sync::Once; use super::MachineState; -use bitvec::prelude::*; -use bitvec::slice::BitSlice; - const ALIGN: usize = Heap::heap_cell_alignment(); #[derive(Debug)] pub struct Heap { inner: InnerHeap, - pstr_vec: BitVec, resource_err_loc: usize, } @@ -90,40 +85,51 @@ unsafe impl Sync for Heap {} static RESOURCE_ERROR_OFFSET_INIT: Once = Once::new(); +#[derive(Debug)] +pub struct HeapStringScan<'a> { + pub string: &'a str, + pub tail_idx: usize, +} + // return the string at ptr and the tail location relative to ptr. -// pstr_vec records the location of each string cell starting at index -// 0. -fn scan_slice_to_str(orig_ptr: *const u8, pstr_vec: &BitSlice) -> (&str, usize) { - unsafe { - debug_assert_eq!(pstr_vec[0], true); - - let tail_cell_offset = pstr_vec[0..].first_zero().unwrap(); - let offset = (ALIGN - orig_ptr.align_offset(ALIGN)) % 8; - let buf_len = heap_index!(tail_cell_offset) - offset; - let slice = std::slice::from_raw_parts(orig_ptr, buf_len); - - // skip the final buffer byte which may not be 0 depending on - // the context, i.e. marking by an iterator. it is counted by - // the initial 1 as part of the padding but for this reason - // mustn't be allowed to stop the count. - - let padding_len = 1 + slice.iter() - .rev() - .skip(1) - .position(|b| *b != 0u8) - .unwrap(); - - let s_len = slice.len() - padding_len; - (std::str::from_utf8_unchecked(&slice[0 .. s_len]), tail_cell_offset) +unsafe fn scan_slice_to_str<'a>(heap_slice: &'a [u8]) -> HeapStringScan<'a> { + let string_len = heap_slice.iter().position(|b| *b == 0u8).unwrap(); + let zero_byte_addr = heap_slice.as_ptr().add(string_len); + let sentinel_len = pstr_sentinel_length(zero_byte_addr as usize); + let tail_idx = cell_index!( + (string_len + sentinel_len).next_multiple_of(ALIGN) + + if sentinel_len <= 1 { heap_index!(1) } else { 0 } + ); + + let str_slice = &heap_slice[..string_len]; + + HeapStringScan { + string: std::str::from_utf8_unchecked(str_slice), + tail_idx, } } #[derive(Debug, Clone, Copy)] pub(crate) enum PStrSegmentCmpResult { - Mismatch { c1: char, c2: char }, - FirstMatch { pstr_loc1: usize, pstr_loc2: usize, l1_offset: usize }, - SecondMatch { pstr_loc1: usize, pstr_loc2: usize, l2_offset: usize }, - BothMatch { pstr_loc1: usize, pstr_loc2: usize, null_offset: usize }, + Mismatch { + c1: char, + c2: char, + }, + FirstMatch { + pstr_loc1: usize, + pstr_loc2: usize, + l1_offset: usize, + }, + SecondMatch { + pstr_loc1: usize, + pstr_loc2: usize, + l2_offset: usize, + }, + BothMatch { + pstr_loc1: usize, + pstr_loc2: usize, + null_offset: usize, + }, } impl PStrSegmentCmpResult { @@ -132,24 +138,36 @@ impl PStrSegmentCmpResult { pdl: &mut Vec, ) -> Option { match self { - PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset } => { - let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + l1_offset); + PStrSegmentCmpResult::FirstMatch { + pstr_loc1, + pstr_loc2, + l1_offset, + } => { + let tail1 = Heap::pstr_tail_idx(pstr_loc1 + l1_offset); let rest_of_l2 = pstr_loc_as_cell!(pstr_loc2 + l1_offset); pdl.push(heap_loc_as_cell!(tail1)); pdl.push(rest_of_l2); } - PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset } => { - let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + l2_offset); + PStrSegmentCmpResult::SecondMatch { + pstr_loc1, + pstr_loc2, + l2_offset, + } => { + let tail2 = Heap::pstr_tail_idx(pstr_loc2 + l2_offset); let rest_of_l1 = pstr_loc_as_cell!(pstr_loc1 + l2_offset); pdl.push(rest_of_l1); pdl.push(heap_loc_as_cell!(tail2)); } - PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset } => { + PStrSegmentCmpResult::BothMatch { + pstr_loc1, + pstr_loc2, + null_offset, + } => { // exhaustive match - let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + null_offset); - let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + null_offset); + let tail1 = Heap::pstr_tail_idx(pstr_loc1 + null_offset); + let tail2 = Heap::pstr_tail_idx(pstr_loc2 + null_offset); pdl.push(heap_loc_as_cell!(tail1)); pdl.push(heap_loc_as_cell!(tail2)); @@ -163,162 +181,18 @@ impl PStrSegmentCmpResult { } } -#[derive(Debug)] -pub(crate) struct HeapView<'a> { - slice: *const u8, - cell_offset: usize, - slice_cell_len: usize, - pstr_slice: &'a BitSlice, -} - -impl<'a> HeapView<'a> { - /* - pub fn get(&self, idx: usize) -> Option { - if idx < self.slice_cell_len { - Some(*self.index(idx)) - } else { - None - } - } - */ - - fn iter_follow(&mut self) -> Option { - 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.iter_follow() - } -} - -impl<'a> Index 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 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 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.iter_follow() - } -} - #[derive(Debug)] pub struct PStrWriteInfo { pstr_loc: usize, } #[derive(Debug)] -pub(crate) struct ReservedHeapSection<'a> { +pub(crate) struct ReservedHeapSection { heap_ptr: *mut u8, heap_cell_len: usize, - pstr_vec: &'a mut BitVec, } -impl<'a> ReservedHeapSection<'a> { +impl ReservedHeapSection { #[inline] pub(crate) fn cell_len(&self) -> usize { self.heap_cell_len @@ -326,16 +200,16 @@ impl<'a> ReservedHeapSection<'a> { pub(crate) fn push_cell(&mut self, cell: HeapCellValue) { unsafe { - ptr::write(self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _, cell); + ptr::write( + self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _, + cell, + ); } - self.pstr_vec.push(false); + // self.pstr_vec.push(false); self.heap_cell_len += 1; } - fn push_pstr_segment( - &mut self, - src: &str, - ) -> usize { + fn push_pstr_segment(&mut self, src: &str) -> usize { if src.is_empty() { return 0; } @@ -354,23 +228,30 @@ impl<'a> ReservedHeapSection<'a> { let align_offset = pstr_sentinel_length(zero_region_idx); - ptr::write_bytes( - self.heap_ptr.add(zero_region_idx), - 0u8, - align_offset, - ); + ptr::write_bytes(self.heap_ptr.add(zero_region_idx), 0u8, align_offset); + + cells_written = if align_offset == 1 { + ptr::write_bytes( + self.heap_ptr.add(zero_region_idx + 1), + 0u8, + size_of::(), + ); + + // 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::()) + } else { + cell_index!(src.len() + align_offset) + }; - cells_written = cell_index!(src.len() + align_offset); self.heap_cell_len += cells_written; } cells_written } - pub(crate) fn push_pstr( - &mut self, - mut src: &str, - ) -> Option { + pub(crate) fn push_pstr(&mut self, mut src: &str) -> Option { let orig_h = self.cell_len(); if src.is_empty() { @@ -386,18 +267,14 @@ impl<'a> ReservedHeapSection<'a> { loop { let null_char_idx = src.find('\u{0}').unwrap_or_else(|| src.len()); - - let cell_len = self.cell_len(); let cells_written = self.push_pstr_segment(&src[0..null_char_idx]); let tail_idx = self.cell_len(); - self.pstr_vec.resize(cell_len + cells_written, true); - if cells_written == 0 { return None; } else if null_char_idx + 1 < src.len() { self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1))); - src = &src[null_char_idx + 1 ..]; + src = &src[null_char_idx + 1..]; } else { return Some(pstr_loc_as_cell!(heap_index!(orig_h))); } @@ -420,7 +297,12 @@ impl<'a> ReservedHeapSection<'a> { cursor: 0, }]; - while let Some(FunctorData { functor, cell_offset, mut cursor }) = functor_stack.pop() { + while let Some(FunctorData { + functor, + cell_offset, + mut cursor, + }) = functor_stack.pop() + { while cursor < functor.len() { match &functor[cursor] { &FunctorElement::AbsoluteCell(cell) => { @@ -460,15 +342,13 @@ impl<'a> ReservedHeapSection<'a> { } } -impl<'a> Index for ReservedHeapSection<'a> { +impl Index for ReservedHeapSection { type Output = HeapCellValue; #[inline] fn index(&self, idx: usize) -> &Self::Output { debug_assert!(idx < self.heap_cell_len); - unsafe { - &*(self.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) - } + unsafe { &*(self.heap_ptr as *const HeapCellValue).add(idx) } } } @@ -489,7 +369,7 @@ fn pstr_sentinel_length(chunk_len: usize) -> usize { #[must_use] #[derive(Debug)] pub struct HeapWriter<'a> { - section: ReservedHeapSection<'a>, + section: ReservedHeapSection, heap_byte_len: &'a mut usize, } @@ -504,13 +384,12 @@ impl<'a> HeapWriter<'a> { *self.heap_byte_len = heap_index!(self.section.heap_cell_len); // return the number of bytes written - Ok(heap_index!(self.section.heap_cell_len - old_section_cell_len)) + Ok(heap_index!( + self.section.heap_cell_len - old_section_cell_len + )) } - pub(crate) fn write_with( - &mut self, - writer: impl FnOnce(&mut ReservedHeapSection), - ) -> usize { + pub(crate) fn write_with(&mut self, writer: impl FnOnce(&mut ReservedHeapSection)) -> usize { let old_section_cell_len = self.section.heap_cell_len; writer(&mut self.section); *self.heap_byte_len = heap_index!(self.section.heap_cell_len); @@ -522,7 +401,7 @@ impl<'a> HeapWriter<'a> { #[inline] pub(crate) fn truncate(&mut self, cell_offset: usize) { self.section.heap_cell_len = cell_offset; - self.section.pstr_vec.truncate(cell_offset); + // self.section.pstr_vec.truncate(cell_offset); *self.heap_byte_len = heap_index!(cell_offset); } @@ -543,9 +422,7 @@ impl<'a> Index for HeapWriter<'a> { #[inline] fn index(&self, idx: usize) -> &Self::Output { debug_assert!(heap_index!(idx) < *self.heap_byte_len); - unsafe { - &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) - } + unsafe { &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) } } } @@ -553,9 +430,7 @@ impl<'a> IndexMut for HeapWriter<'a> { #[inline] fn index_mut(&mut self, idx: usize) -> &mut Self::Output { debug_assert!(heap_index!(idx) < *self.heap_byte_len); - unsafe { - &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue) - } + unsafe { &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue) } } } @@ -564,17 +439,29 @@ impl<'a> SizedHeap for HeapWriter<'a> { self.section.cell_len() } - fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) { - let (s, tail_cell_offset) = scan_slice_to_str( - unsafe { self.section.heap_ptr.add(slice_loc) }, - &self.section.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..], - ); + fn scan_slice_to_str(&self, slice_loc: usize) -> HeapStringScan { + let HeapStringScan { string, tail_idx } = unsafe { + let slice = std::slice::from_raw_parts( + self.section.heap_ptr.byte_add(slice_loc), + heap_index!(self.section.heap_cell_len) - slice_loc, + ); + + scan_slice_to_str(slice) + }; - (s, cell_index!(slice_loc) + tail_cell_offset) + HeapStringScan { + string, + tail_idx: cell_index!(slice_loc) + tail_idx, + } } - fn pstr_at(&self, cell_offset: usize) -> bool { - self.section.pstr_vec[cell_offset] + fn as_slice(&self) -> &[u8] { + unsafe { + std::slice::from_raw_parts( + self.section.heap_ptr, + heap_index!(self.section.heap_cell_len), + ) + } } } @@ -588,20 +475,23 @@ impl Heap { byte_len: 0, byte_cap: 0, }, - pstr_vec: bitvec![], resource_err_loc: 0, } } - #[inline(always)] - unsafe fn grow(&mut self) -> bool { - let result = self.inner.grow(); - - if result { - self.pstr_vec.reserve(cell_index!(self.inner.byte_cap)); + // 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 } + } - result + #[inline(always)] + unsafe fn grow(&mut self) -> bool { + self.inner.grow() } #[inline] @@ -624,7 +514,7 @@ impl Heap { byte_len: 0, byte_cap: heap_index!(cap), }, - pstr_vec: bitvec![], + // pstr_vec: bitvec![], resource_err_loc: 0, }) } @@ -641,7 +531,6 @@ impl Heap { section = ReservedHeapSection { heap_ptr: self.inner.ptr, heap_cell_len: self.cell_len(), - pstr_vec: &mut self.pstr_vec, }; break; } else if !self.grow() { @@ -656,26 +545,40 @@ impl Heap { }) } - pub(crate) fn last_cell_mut(&mut self) -> Option<&mut HeapCellValue> { + pub(crate) fn last_cell(&mut self) -> Option { 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)) + Some(ptr::read( + self.inner.ptr.add(self.inner.byte_len - heap_index!(1)) + as *const HeapCellValue, + )) } } } - pub(crate) fn last_cell(&mut self) -> Option { - if self.inner.byte_len == 0 { - None - } else { - unsafe { - Some(ptr::read(self.inner.ptr.add(self.inner.byte_len - heap_index!(1)) - as *const HeapCellValue)) + 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] @@ -703,31 +606,31 @@ impl Heap { self.inner.byte_len = 0; self.inner.byte_cap = 0; - self.pstr_vec.clear(); + // self.pstr_vec.clear(); } - pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> { - unsafe { - loop { - if self.free_space() >= heap_index!(heap_slice.slice_cell_len) { - ptr::copy_nonoverlapping( - heap_slice.slice, - self.inner.ptr.add(self.inner.byte_len), - heap_index!(heap_slice.slice_cell_len), - ); + // pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> { + // unsafe { + // loop { + // if self.free_space() >= heap_index!(heap_slice.slice_cell_len) { + // ptr::copy_nonoverlapping( + // heap_slice.slice, + // self.inner.ptr.add(self.inner.byte_len), + // heap_index!(heap_slice.slice_cell_len), + // ); - self.inner.byte_len += heap_index!(heap_slice.slice_cell_len); - self.pstr_vec.extend(heap_slice.pstr_slice.iter()); + // self.inner.byte_len += heap_index!(heap_slice.slice_cell_len); + // // self.pstr_vec.extend(heap_slice.pstr_slice.iter()); - break; - } else if !self.grow() { - return Err(self.resource_error_offset()); - } - } - } + // break; + // } else if !self.grow() { + // return Err(self.resource_error_offset()); + // } + // } + // } - Ok(()) - } + // Ok(()) + // } pub(crate) fn store_resource_error(&mut self) { RESOURCE_ERROR_OFFSET_INIT.call_once(move || { @@ -763,11 +666,23 @@ impl Heap { for ((idx, c1), c2) in str1.char_indices().zip(str2.chars()) { if c1 == '\u{0}' && c2 == '\u{0}' { - return PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset: idx }; + return PStrSegmentCmpResult::BothMatch { + pstr_loc1, + pstr_loc2, + null_offset: idx, + }; } else if c1 == '\u{0}' { - return PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset: idx }; + return PStrSegmentCmpResult::FirstMatch { + pstr_loc1, + pstr_loc2, + l1_offset: idx, + }; } else if c2 == '\u{0}' { - return PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset: idx }; + return PStrSegmentCmpResult::SecondMatch { + pstr_loc1, + pstr_loc2, + l2_offset: idx, + }; } else if c1 != c2 { return PStrSegmentCmpResult::Mismatch { c1, c2 }; } @@ -822,7 +737,7 @@ impl Heap { // - Invariant: from `InnerHeap`, `self.inner.byte_cap < isize::MAX`. let cell_ptr = (self.inner.ptr as *mut HeapCellValue).add(self.cell_len()); cell_ptr.write(cell); - self.pstr_vec.push(false); + // self.pstr_vec.push(false); self.inner.byte_len += heap_index!(1); } @@ -866,6 +781,7 @@ impl Heap { Range { start, end } } + /* pub(crate) fn splice>( &self, range: R, @@ -876,7 +792,7 @@ impl Heap { slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) }, cell_offset: range.start, slice_cell_len: range.end - range.start, - pstr_slice: &self.pstr_vec.as_bitslice()[range], + // pstr_slice: &self.pstr_vec.as_bitslice()[range], } } @@ -890,9 +806,10 @@ impl Heap { slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) }, cell_offset: range.start, slice_cell_len: range.end - range.start, - pstr_slice: &self.pstr_vec.as_bitslice()[range], + // pstr_slice: &self.pstr_vec.as_bitslice()[range], } } + */ pub fn allocate_pstr(&mut self, src: &str) -> Result, usize> { let size_in_heap = Self::compute_pstr_size(src); @@ -911,39 +828,18 @@ impl Heap { }) } - const fn heap_cell_alignment() -> usize { + pub const fn heap_cell_alignment() -> usize { // yes, size_of, not align_of. the alignment of HeapCellValue // is 1 byte. In the heap, though, its alignment must be its // size. - mem::size_of::() - } - - // 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 { - self.pstr_vec.as_bitslice() + size_of::() } #[inline] pub(crate) fn char_at(&self, byte_idx: usize) -> char { let s = unsafe { let char_ptr = self.inner.ptr.add(byte_idx); - let slice = std::slice::from_raw_parts(char_ptr, mem::size_of::()); + let slice = std::slice::from_raw_parts(char_ptr, size_of::()); std::str::from_utf8_unchecked(&slice) }; @@ -961,7 +857,7 @@ impl Heap { let succ_len = loc + c.len_utf8(); if chars_iter.next() == Some('\u{0}') { - (c, heap_loc_as_cell!(Self::neighboring_cell_offset(succ_len))) + (c, heap_loc_as_cell!(Self::pstr_tail_idx(succ_len))) } else { (c, pstr_loc_as_cell!(succ_len)) } @@ -971,8 +867,8 @@ impl Heap { // copies only the string, not its tail. returns the cell index of // the tail location pub(crate) fn copy_pstr_within(&mut self, pstr_loc: usize) -> Result { - let (s, tail_loc) = self.scan_slice_to_str(pstr_loc); - let s_len = s.len(); + let HeapStringScan { string, tail_idx } = self.scan_slice_to_str(pstr_loc); + let s_len = string.len(); let align_offset = pstr_sentinel_length(s_len); let copy_size = s_len + align_offset; @@ -980,15 +876,10 @@ impl Heap { unsafe { loop { if self.free_space() >= copy_size { - let slice = std::slice::from_raw_parts_mut( - self.inner.ptr, - self.inner.byte_len + s_len, - ); + let slice = + std::slice::from_raw_parts_mut(self.inner.ptr, self.inner.byte_len + s_len); - slice.copy_within( - pstr_loc .. pstr_loc + s_len, - self.inner.byte_len, - ); + slice.copy_within(pstr_loc..pstr_loc + s_len, self.inner.byte_len); ptr::write_bytes( self.inner.ptr.add(self.inner.byte_len + s_len), @@ -996,8 +887,17 @@ impl Heap { align_offset, ); - self.inner.byte_len += copy_size; - self.pstr_vec.resize(self.cell_len(), true); + if align_offset == 1 { + ptr::write_bytes( + self.inner.ptr.add(self.inner.byte_len + copy_size), + 0u8, + size_of::(), + ); + + self.inner.byte_len += copy_size + heap_index!(1); + } else { + self.inner.byte_len += copy_size; + } break; } else if !self.grow() { @@ -1006,7 +906,7 @@ impl Heap { } } - Ok(tail_loc) + Ok(tail_idx) } // src is a cell-indexed range. @@ -1023,7 +923,7 @@ impl Heap { heap_index!(len), ); - self.pstr_vec.resize(self.cell_len() + len, false); + // self.pstr_vec.resize(self.cell_len() + len, false); self.inner.byte_len += heap_index!(len); break; @@ -1059,10 +959,14 @@ impl Heap { byte_size += null_idx + pstr_sentinel_length(null_idx); + // each partial string must be buffered from its tail cell + // by at least two null bytes so one of them may be used + // to mark partial strings e.g. during iteration + if (null_idx + 1) % ALIGN == 0 { - byte_size += 2 * mem::size_of::(); + byte_size += 2 * size_of::(); } else { - byte_size += mem::size_of::(); + byte_size += size_of::(); } if null_idx + 1 >= src.len() { @@ -1082,13 +986,13 @@ impl Heap { while idx < functor.len() { match &functor[idx] { &FunctorElement::InnerFunctor(inner_cell_size, ref _inner_functor) => { - byte_size += inner_cell_size as usize * mem::size_of::(); + byte_size += inner_cell_size as usize * size_of::(); } FunctorElement::AbsoluteCell(_cell) | FunctorElement::Cell(_cell) => { - byte_size += mem::size_of::(); + byte_size += size_of::(); } &FunctorElement::String(cell_len, _) => { - byte_size += cell_len as usize * mem::size_of::(); + byte_size += cell_len as usize * size_of::(); } } @@ -1120,12 +1024,10 @@ impl Heap { #[inline] pub(crate) fn truncate(&mut self, cell_offset: usize) { self.inner.byte_len = heap_index!(cell_offset); - self.pstr_vec.truncate(cell_offset); + // self.pstr_vec.truncate(cell_offset); } } - - pub(crate) struct PStrSegmentIter<'a> { string_buf: &'a str, } @@ -1153,7 +1055,7 @@ impl<'a> Iterator for PStrSegmentIter<'a> { if c == '\u{0}' { None } else { - self.string_buf = &self.string_buf[c.len_utf8() ..]; + self.string_buf = &self.string_buf[c.len_utf8()..]; Some(c) } }) @@ -1187,14 +1089,15 @@ pub trait SizedHeap: Index { fn cell_len(&self) -> usize; // return a pointer to the heap string and the cell index of its tail - fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize); + fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a>; + + fn as_slice(&self) -> &[u8]; // return true iff a partial string is stored at cell_offset. - fn pstr_at(&self, cell_offset: usize) -> bool; + // fn pstr_at(&self, cell_offset: usize) -> bool; } -pub trait SizedHeapMut: IndexMut + SizedHeap { -} +pub trait SizedHeapMut: IndexMut + SizedHeap {} impl Index for Heap { type Output = HeapCellValue; @@ -1215,61 +1118,28 @@ impl SizedHeap for Heap { self.cell_len() } - fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) { - let (s, tail_cell_offset) = scan_slice_to_str( - unsafe { self.inner.ptr.add(slice_loc) }, - &self.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..], - ); - - (s, cell_index!(slice_loc) + tail_cell_offset) - } - - fn pstr_at(&self, cell_offset: usize) -> bool { - self.pstr_vec[cell_offset] - } -} - -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<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a> { + let HeapStringScan { string, tail_idx } = unsafe { + let slice = std::slice::from_raw_parts( + self.inner.ptr.add(slice_loc), + self.inner.byte_len - slice_loc, + ); - 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) ..], - ); + scan_slice_to_str(slice) + }; - (s, cell_index!(slice_loc) + tail_cell_offset) + HeapStringScan { + string, + tail_idx: cell_index!(slice_loc) + tail_idx, + } } - fn pstr_at(&self, cell_offset: usize) -> bool { - self.pstr_slice[cell_offset] + fn as_slice(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.inner.ptr, self.inner.byte_len) } } } -impl<'a> SizedHeapMut for HeapViewMut<'a> {} +impl SizedHeapMut for Heap {} // sometimes we need to dereference variables that are found only in // the heap without access to the full WAM (e.g., while detecting @@ -1307,9 +1177,10 @@ pub fn heap_bound_store(heap: &impl SizedHeap, value: HeapCellValue) -> HeapCell } #[allow(dead_code)] -pub fn print_heap_terms<'a, I: Iterator>(heap: I, h: usize) { - for (index, term) in heap.enumerate() { - println!("{} : {:?}", h + index, term); +pub fn print_heap_terms(heap: &Heap, h: usize) { + for idx in 0..heap.cell_len() { + let term = heap[idx]; + println!("{} : {:?}", h + idx, term); } } diff --git a/src/machine/lib_machine/mod.rs b/src/machine/lib_machine/mod.rs index eef64f96..c139bc12 100644 --- a/src/machine/lib_machine/mod.rs +++ b/src/machine/lib_machine/mod.rs @@ -1,4 +1,3 @@ -use std::cmp::Ordering; use std::collections::BTreeMap; use crate::atom_table; @@ -442,7 +441,7 @@ impl Iterator for QueryState<'_> { if let Err(resource_err_loc) = machine .machine_st .heap - .append(machine.machine_st.ball.stub.splice(..)) + .append(&machine.machine_st.ball.stub) { return Some(Err(Term::from_heapcell( machine, @@ -531,9 +530,9 @@ impl Machine { pub fn consult_module_string(&mut self, module_name: &str, program: impl Into) { let stream = Stream::from_owned_string(program.into(), &mut self.machine_st.arena); 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, - module_name + module_name, )); self.run_module_predicate(atom!("loader"), (atom!("consult_stream"), 2)); diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 34499ced..0d850150 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -27,15 +27,14 @@ impl TermWriteResult { heap[0] = value; - let inverse_var_locs = inverse_var_locs_from_iter( - stackful_preorder_iter::( - heap, - &mut stack, - 0, - ), - ); + let inverse_var_locs = inverse_var_locs_from_iter(stackful_preorder_iter::( + heap, &mut stack, 0, + )); - Ok(Self { focus, inverse_var_locs }) + Ok(Self { + focus, + inverse_var_locs, + }) } } @@ -529,9 +528,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target); let mut term = load_state.term_stream.next(&composite_op_dir)?; - let predicate_focus_opt = load_state.predicates.first().map(|term_write_result| { - term_write_result.focus - }); + let predicate_focus_opt = load_state + .predicates + .first() + .map(|term_write_result| term_write_result.focus); let machine_st = LS::machine_st(&mut self.payload); let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus); @@ -1072,10 +1072,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let cell = machine_st[r]; let focus = machine_st.heap.cell_len(); - machine_st.heap.push_cell(cell) + machine_st + .heap + .push_cell(cell) .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?; - let export_list = FocusedHeapRefMut { heap: &mut machine_st.heap, focus }; + let export_list = FocusedHeapRefMut { + heap: &mut machine_st.heap, + focus, + }; let export_list = setup_module_export_list(export_list)?; Ok(export_list.into_iter().collect()) @@ -1129,8 +1134,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { } ); - Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus)) - .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?) + Ok( + TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus)) + .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?, + ) } fn add_extensible_predicate_declaration( @@ -1628,18 +1635,15 @@ impl Machine { }; let value = self.machine_st.registers[2]; - let term = resource_error_call_result!( + let term = resource_error_call_result!( self.machine_st, TermWriteResult::from(&mut self.machine_st.heap, value) ); let add_clause = || { let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) { - Some((atom!(":-"), _)) => { - term_nth_arg(&self.machine_st.heap, term.focus, 1).and_then(|h| { - term_nth_arg(&self.machine_st.heap, h, 1) - }) - } + Some((atom!(":-"), _)) => term_nth_arg(&self.machine_st.heap, term.focus, 1) + .and_then(|h| term_nth_arg(&self.machine_st.heap, h, 1)), Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1), None => None, }; @@ -2240,9 +2244,11 @@ impl Machine { }; let mut loader = self.loader_from_heap_evacuable(temp_v!(4)); - let predicate_focus_opt = loader.payload.predicates.first().map(|term_write_result| { - term_write_result.focus - }); + let predicate_focus_opt = loader + .payload + .predicates + .first() + .map(|term_write_result| term_write_result.focus); let is_consistent = if let Some(predicate_focus) = predicate_focus_opt { let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload); @@ -2253,7 +2259,7 @@ impl Machine { LiveLoadAndMachineState::machine_st(&mut loader.payload).fail = (!loader.payload.predicates.is_empty() - && loader.payload.predicates.compilation_target != compilation_target) + && loader.payload.predicates.compilation_target != compilation_target) || !is_consistent; let result = LiveLoadAndMachineState::evacuate(loader); diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 5017cb78..1a4e8487 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -187,7 +187,11 @@ impl PermissionError for HeapCellValue { let stub = functor!( atom!("permission_error"), - [atom_as_cell((perm.as_atom())), atom_as_cell(index_atom), cell(cell)] + [ + atom_as_cell((perm.as_atom())), + atom_as_cell(index_atom), + cell(cell) + ] ); MachineError { @@ -226,7 +230,10 @@ pub(super) trait DomainError { impl DomainError for HeapCellValue { fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { - let stub = functor!(atom!("domain_error"), [atom_as_cell((error.as_atom())), cell(self)]); + let stub = functor!( + atom!("domain_error"), + [atom_as_cell((error.as_atom())), cell(self)] + ); MachineError { stub, @@ -239,7 +246,10 @@ impl DomainError for Number { fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { let stub = functor!( atom!("domain_error"), - [atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))] + [ + atom_as_cell((error.as_atom())), + number(self, (&mut machine_st.arena)) + ] ); MachineError { @@ -280,7 +290,10 @@ impl MachineState { } pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError { - let stub = functor!(atom!("evaluation_error"), [atom_as_cell((eval_error.as_atom()))]); + let stub = functor!( + atom!("evaluation_error"), + [atom_as_cell((eval_error.as_atom()))] + ); MachineError { stub, @@ -297,7 +310,10 @@ impl MachineState { ) } ResourceError::OutOfFiles => { - functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))]) + functor!( + atom!("resource_error"), + [atom_as_cell((atom!("file_descriptors")))] + ) } }; @@ -480,12 +496,12 @@ impl MachineState { SessionError::CannotOverwriteBuiltIn(key) => self.permission_error( Permission::Modify, atom!("static_procedure"), - functor_stub(key.0, key.1) + functor_stub(key.0, key.1), ), SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error( Permission::Modify, atom!("static_procedure"), - functor_stub(key.0, key.1) + functor_stub(key.0, key.1), ), SessionError::CannotOverwriteBuiltInModule(module) => { self.permission_error(Permission::Modify, atom!("static_module"), module) @@ -559,14 +575,14 @@ impl MachineState { let stub = functor!(atom!("syntax_error"), [functor(stub)]); - MachineError { - stub, - location, - } + MachineError { stub, location } } pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError { - let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]); + let stub = functor!( + atom!("representation_error"), + [atom_as_cell((flag.as_atom()))] + ); MachineError { stub, @@ -593,13 +609,19 @@ impl MachineState { } pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub { - if let Some(ParserErrorSrc { line_num, .. }) = err.location { - functor!(atom!("error"), [functor((err.stub)), - functor((atom!(":")), [functor(src), - number(line_num, (&mut self.arena))])]) + if let Some(ParserErrorSrc { line_num, .. }) = err.location { + functor!( + atom!("error"), + [ + functor((err.stub)), + functor( + (atom!(":")), + [functor(src), number(line_num, (&mut self.arena))] + ) + ] + ) } else { - functor!(atom!("error"), [functor((err.stub)), - functor(src)]) + functor!(atom!("error"), [functor((err.stub)), functor(src)]) } } @@ -826,13 +848,29 @@ impl EvalError { // used by '$skip_max_list'. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CycleSearchResult { - Cyclic { lambda: usize }, // number of steps + Cyclic { + lambda: usize, + }, // number of steps EmptyList, - NotList { num_steps: usize, heap_loc: HeapCellValue }, - PartialList { num_steps: usize, heap_loc: HeapCellValue }, - ProperList { num_steps: usize }, - PStrLocation { num_steps: usize, pstr_loc: HeapCellValue }, - UntouchedList { num_steps: usize, list_loc: usize }, + NotList { + num_steps: usize, + heap_loc: HeapCellValue, + }, + PartialList { + num_steps: usize, + heap_loc: HeapCellValue, + }, + ProperList { + num_steps: usize, + }, + PStrLocation { + num_steps: usize, + pstr_loc: HeapCellValue, + }, + UntouchedList { + num_steps: usize, + list_loc: usize, + }, } impl MachineState { @@ -856,7 +894,9 @@ impl MachineState { }; match BrentAlgState::detect_cycles(&self.heap, sorted) { - CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !sorted.is_var() => { + CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } + if !sorted.is_var() => + { let err = self.type_error(ValidType::List, sorted); Err(self.error_form(err, stub_gen())) } @@ -868,7 +908,9 @@ impl MachineState { let stub_gen = || functor_stub(atom!("keysort"), 2); match BrentAlgState::detect_cycles(&self.heap, list) { - CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !list.is_var() => { + CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } + if !list.is_var() => + { let err = self.type_error(ValidType::List, list); Err(self.error_form(err, stub_gen())) } diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index b5fdc1c0..dcf7a920 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -37,7 +37,7 @@ pub(super) enum MachineMode { pub(super) enum HeapPtr { HeapCell(usize), PStr(usize), // Char(usize), - // PStrLocation(usize), + // PStrLocation(usize), } impl Default for HeapPtr { @@ -215,7 +215,8 @@ fn push_var_eq_functors( let mut writer = heap.reserve(1 + 5 * size)?; writer.write_with(|section| { - for (var_loc, var) in iter { // (var, binding) in iter { + for (var_loc, var) in iter { + // (var, binding) in iter { let var_atom = AtomTable::build_with(atom_tbl, &var.to_string()); let binding = heap_loc_as_cell!(var_loc); @@ -224,7 +225,7 @@ fn push_var_eq_functors( section.push_cell(binding); } - for idx in 0 .. size { + for idx in 0..size { section.push_cell(list_loc_as_cell!(section.cell_len() + 1)); section.push_cell(str_loc_as_cell!(src_h + 3 * idx)); } @@ -252,6 +253,7 @@ pub(crate) fn copy_and_align_iter>( #[derive(Debug)] pub struct Ball { pub(super) boundary: usize, + pub(super) pstr_boundary: usize, pub(super) stub: Heap, } @@ -259,12 +261,14 @@ impl Ball { pub(super) fn new() -> Self { Ball { boundary: 0, + pstr_boundary: 0, stub: Heap::new(), } } pub(super) fn reset(&mut self) { self.boundary = 0; + self.pstr_boundary = 0; self.stub.clear(); } @@ -272,10 +276,23 @@ impl Ball { let h = dest.cell_len(); let diff = self.boundary as i64 - h as i64; - dest.append(self.stub.splice(..))?; + let mut dest_writer = dest.reserve(self.stub.cell_len())?; - for cell in &mut dest.splice_mut(h ..) { - *cell = *cell - diff; + dest_writer.write_with(|section| { + for idx in 0..self.pstr_boundary { + section.push_cell(self.stub[idx] - diff); + } + }); + + let mut pstr_threshold = heap_index!(self.pstr_boundary); + + while pstr_threshold < heap_index!(self.stub.cell_len()) { + let HeapStringScan { string, tail_idx } = self.stub.scan_slice_to_str(pstr_threshold); + + pstr_threshold += dest_writer.write_with(|section| { + section.push_pstr(string).unwrap(); + section.push_cell(self.stub[tail_idx] - diff); + }); } Ok(h) @@ -336,29 +353,13 @@ impl<'a> CopierTarget for CopyTerm<'a> { } #[inline(always)] - fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result { - 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) + fn as_slice_from<'b>(&'b self, from: usize) -> Box + 'b> { + Box::new(self.state.heap.as_slice()[from..].iter().cloned()) } #[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() + fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result { + self.state.heap.copy_pstr_within(pstr_loc) } #[inline(always)] @@ -469,49 +470,27 @@ impl<'a> CopierTarget for CopyBallTerm<'a> { fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result { debug_assert!(pstr_loc < self.heap.byte_len()); - let (string, tail_loc) = self.heap.scan_slice_to_str(pstr_loc); + let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(pstr_loc); self.stub.allocate_pstr(string)?; - Ok(tail_loc) + Ok(tail_idx) } - #[inline] - fn reserve(&mut self, num_cells: usize) -> Result { - 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()] + fn as_slice_from<'b>(&'b self, from: usize) -> Box + 'b> { + if from < self.heap.byte_len() { + Box::new( + self.heap.as_slice()[from..] + .iter() + .cloned() + .chain(self.stub.as_slice().iter().cloned()), + ) } else { - self.heap.pstr_vec()[loc] + Box::new(self.stub.as_slice()[from..].iter().cloned()) } } #[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 reserve(&mut self, num_cells: usize) -> Result { + self.stub.reserve(num_cells) } fn copy_slice_to_end(&mut self, bounds: Range) -> Result<(), usize> { @@ -699,9 +678,9 @@ impl MachineState { push_var_eq_functors( &mut self.heap, var_list.len(), - var_list.iter().map(|(var_name, var, _)| { - (var.get_value() as usize, var_name.clone()) - }), + var_list + .iter() + .map(|(var_name, var, _)| { (var.get_value() as usize, var_name.clone()) }), &self.atom_tbl, ) ); @@ -737,7 +716,9 @@ impl MachineState { let mut singleton_var_set: IndexMap = IndexMap::new(); - for cell in stackful_preorder_iter::(&mut self.heap, &mut self.stack, term.focus) { + for cell in + stackful_preorder_iter::(&mut self.heap, &mut self.stack, term.focus) + { let cell = unmark_cell_bits!(cell); if let Some(var) = cell.as_var() { @@ -756,9 +737,10 @@ impl MachineState { singleton_var_set .iter() .filter(|(var, is_singleton)| { - **is_singleton && term.inverse_var_locs.contains_key( - &(var.get_value() as usize) - ) + **is_singleton + && term + .inverse_var_locs + .contains_key(&(var.get_value() as usize)) }) .count(), term.inverse_var_locs @@ -873,7 +855,8 @@ impl MachineState { CompilationError::ParserError(e) if e.is_unexpected_eof() => { match eof_handler(self, stream)? { OnEOF::Return => { - return self.write_read_term_options(vec![], empty_list_as_cell!()); + return self + .write_read_term_options(vec![], empty_list_as_cell!()); } OnEOF::Continue => continue, } @@ -1012,11 +995,9 @@ impl MachineState { let term_loc = self.heap.cell_len(); - step_or_resource_error!( - self, - self.heap.push_cell(term_to_be_printed), - { return Ok(None); } - ); + step_or_resource_error!(self, self.heap.push_cell(term_to_be_printed), { + return Ok(None); + }); let mut printer = HCPrinter::new( &mut self.heap, diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 34fbe5ca..a7dc5d9e 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -327,9 +327,9 @@ impl MachineState { self.ball.reset(); let addr = self.registers[1]; - let ball_boundary = self.heap.cell_len(); - step_or_resource_error!( + self.ball.boundary = self.heap.cell_len(); + self.ball.pstr_boundary = step_or_resource_error!( self, copy_term( CopyBallTerm::new( @@ -342,8 +342,6 @@ impl MachineState { AttrVarPolicy::DeepCopy, ) ); - - self.ball.boundary = ball_boundary; } #[inline(always)] @@ -359,14 +357,14 @@ impl MachineState { HeapPtr::PStr(h) => { let mut char_iter = self.heap.char_iter(h); - if self.s_offset == 0 { // read the car of the list + if self.s_offset == 0 { + // read the car of the list let c = char_iter.next().unwrap(); char_as_cell!(c) - } else { // read the (self.s_offset)^{th} cdr of the list - let byte_offset: usize = char_iter - .take(self.s_offset) - .map(|c| c.len_utf8()) - .sum(); + } else { + // read the (self.s_offset)^{th} cdr of the list + let byte_offset: usize = + char_iter.take(self.s_offset).map(|c| c.len_utf8()).sum(); let new_h = h + byte_offset; self.s_offset = 0; @@ -375,7 +373,7 @@ impl MachineState { self.s = HeapPtr::PStr(new_h); pstr_loc_as_cell!(new_h) } else { - let h = Heap::neighboring_cell_offset(new_h); + let h = Heap::pstr_tail_idx(new_h); self.s = HeapPtr::HeapCell(h); self.deref(heap_loc_as_cell!(h)) } @@ -946,7 +944,7 @@ impl MachineState { if char_iter.next().is_some() { unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3); } else { - let tail_idx = Heap::neighboring_cell_offset(pstr_loc); + let tail_idx = Heap::pstr_tail_idx(pstr_loc); unify_fn!(*self, self.heap[tail_idx]); } @@ -1044,7 +1042,12 @@ impl MachineState { } } - fn try_functor_fabricate_struct(&mut self, name: Atom, arity: usize, r: Ref) -> Result<(), usize> { + fn try_functor_fabricate_struct( + &mut self, + name: Atom, + arity: usize, + r: Ref, + ) -> Result<(), usize> { let h = self.heap.cell_len(); let mut writer = self.heap.reserve(arity + 1)?; @@ -1144,7 +1147,7 @@ impl MachineState { }; read_heap_cell!(store_name, - (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char | + (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char | HeapCellValueTag::F64) if arity == 0 => { self.bind(a1.as_var().unwrap(), deref_name); } diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index e0551a60..71f74f0c 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -51,14 +51,12 @@ impl MockWAM { ) -> Result { let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?; - print_heap_terms(self.machine_st.heap.splice(..), term_write_result.focus); + print_heap_terms(&self.machine_st.heap, term_write_result.focus); let var_names = term_write_result .inverse_var_locs .iter() - .map(|(var_loc, var_name)| { - (self.machine_st.heap[*var_loc], var_name.clone()) - }) + .map(|(var_loc, var_name)| (self.machine_st.heap[*var_loc], var_name.clone())) .collect(); let mut printer = HCPrinter::new( @@ -90,6 +88,7 @@ pub struct TermCopyingMockWAM<'a> { impl<'a> Index for TermCopyingMockWAM<'a> { type Output = HeapCellValue; + #[inline] fn index(&self, index: usize) -> &HeapCellValue { &self.wam.machine_st.heap[index] } @@ -107,6 +106,7 @@ impl<'a> IndexMut for TermCopyingMockWAM<'a> { impl<'a> Deref for TermCopyingMockWAM<'a> { type Target = MockWAM; + #[inline] fn deref(&self) -> &Self::Target { self.wam } @@ -114,6 +114,7 @@ impl<'a> Deref for TermCopyingMockWAM<'a> { #[cfg(test)] impl<'a> DerefMut for TermCopyingMockWAM<'a> { + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.wam } @@ -170,26 +171,8 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> { } #[inline(always)] - fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize { - self.wam.machine_st.heap.pstr_vec()[0 .. cell_index!(pstr_loc)] - .last_zero() - .map(|idx| idx + 1) - .unwrap_or(0) - } - - #[inline(always)] - fn pstr_at(&self, loc: usize) -> bool { - self.wam.machine_st.heap.pstr_vec()[loc] - } - - #[inline(always)] - fn next_non_pstr_cell_index(&self, loc: usize) -> usize { - // unwrap is safe here because a partial string is always - // followed by a tail cell, i.e. a non-pstr cell, supposing - // self.machine_st.heap[loc] is a pstr cell - self.wam.machine_st.heap.pstr_vec()[loc ..].first_zero() - .map(|idx| idx + loc) - .unwrap() + fn as_slice_from<'b>(&'b self, from: usize) -> Box + 'b> { + Box::new(self.wam.machine_st.heap.as_slice()[from..].iter().cloned()) } #[inline(always)] @@ -204,20 +187,9 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> { } #[cfg(test)] -pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) { - let mut idx = 0; - let cell_len = iter.cell_len(); - - while idx < cell_len { - let curr_idx = idx; - let cell = if iter.pstr_at(idx) { - let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx)); - idx = last_cell_loc; - iter[last_cell_loc - 1] - } else { - idx += 1; - iter[curr_idx] - }; +pub fn all_cells_marked_and_unforwarded(heap: &Heap, offset: usize) { + for curr_idx in offset..heap.cell_len() { + let cell = heap[curr_idx]; assert!( cell.get_mark_bit(), @@ -235,43 +207,21 @@ pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) { } #[cfg(test)] -pub fn unmark_all_cells(mut iter: impl SizedHeapMut) { - let mut idx = 0; - let cell_len = iter.cell_len(); - - while idx < cell_len { - if iter.pstr_at(idx) { - iter[idx].set_mark_bit(false); - - let last_cell_loc = { - let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx)); - last_cell_loc - }; - - iter[last_cell_loc].set_mark_bit(false); - idx = last_cell_loc; - } else { - iter[idx].set_mark_bit(false); - idx += 1; - } +pub fn unmark_all_cells(heap: &mut Heap, offset: usize) { + for idx in offset..heap.cell_len() { + heap[idx].set_mark_bit(false); } } #[cfg(test)] -pub fn all_cells_unmarked(iter: impl SizedHeap) { +pub fn all_cells_unmarked(iter: &impl SizedHeap) { let mut idx = 0; let cell_len = iter.cell_len(); while idx < cell_len { let curr_idx = idx; - let cell = if iter.pstr_at(idx) { - let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx)); - idx = last_cell_loc; - iter[last_cell_loc - 1] - } else { - idx += 1; - iter[curr_idx] - }; + idx += 1; + let cell = iter[curr_idx]; assert!( !cell.get_mark_bit(), @@ -354,7 +304,7 @@ mod tests { assert!(wam.fail); } - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.fail = false; wam.heap.clear(); @@ -375,7 +325,7 @@ mod tests { assert!(!wam.fail); } - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.fail = false; wam.heap.clear(); @@ -396,7 +346,7 @@ mod tests { assert!(!wam.fail); } - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.fail = false; wam.heap.clear(); @@ -417,7 +367,7 @@ mod tests { assert!(!wam.fail); } - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.fail = false; wam.heap.clear(); @@ -438,7 +388,7 @@ mod tests { assert!(!wam.fail); } - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.fail = false; wam.heap.clear(); @@ -450,7 +400,7 @@ mod tests { let term_write_result_2 = parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap(); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); unify!( wam, @@ -461,7 +411,7 @@ mod tests { assert!(!wam.fail); } - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap.clear(); @@ -489,9 +439,15 @@ mod tests { assert!(!wam.fail); + assert_eq!(wam.heap.slice_to_str(heap_index!(0), "this is a string".len()), + "this is a string"); assert_eq!(wam.heap[3], pstr_loc_as_cell!(heap_index!(8))); - - all_cells_unmarked(wam.heap.splice(..)); + assert_eq!(wam.heap.slice_to_str(heap_index!(4), "this is a string".len()), + "this is a string"); + assert_eq!(wam.heap[7], pstr_loc_as_cell!(heap_index!(8))); + assert_eq!(wam.heap.slice_to_str(heap_index!(8), "this is a string".len()), + "this is a string"); + assert_eq!(wam.heap[11], pstr_loc_as_cell!(heap_index!(8))); wam.heap.clear(); @@ -515,7 +471,7 @@ mod tests { assert!(!wam.fail); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap.clear(); @@ -540,7 +496,7 @@ mod tests { assert!(wam.fail); wam.fail = false; - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap.clear(); @@ -562,7 +518,7 @@ mod tests { unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5)); assert!(!wam.fail); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); } #[test] @@ -581,7 +537,7 @@ mod tests { let term_write_result_2 = parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap(); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); unify_with_occurs_check!( wam, @@ -632,11 +588,7 @@ mod tests { let cstr_cell = wam.allocate_cstr("string").unwrap(); assert_eq!( - compare_term_test!( - wam, - atom_as_cell!(atom!("atom")), - cstr_cell - ), + compare_term_test!(wam, atom_as_cell!(atom!("atom")), cstr_cell), Some(Ordering::Less) ); @@ -735,11 +687,7 @@ mod tests { let cstr_cell = wam.allocate_cstr("string").unwrap(); assert_eq!( - compare_term_test!( - wam, - empty_list_as_cell!(), - cstr_cell - ), + compare_term_test!(wam, empty_list_as_cell!(), cstr_cell), Some(Ordering::Less) ); @@ -782,16 +730,13 @@ mod tests { assert!(!wam.is_cyclic_term(1)); assert!(!wam.is_cyclic_term(2)); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap.clear(); - let mut functor_writer = Heap::functor_writer( - functor!( - atom!("f"), - [atom_as_cell((atom!("a"))), - atom_as_cell((atom!("b")))] - ), - ); + let mut functor_writer = Heap::functor_writer(functor!( + atom!("f"), + [atom_as_cell((atom!("a"))), atom_as_cell((atom!("b")))] + )); functor_writer(&mut wam.heap).unwrap(); @@ -800,30 +745,30 @@ mod tests { assert!(!wam.is_cyclic_term(h)); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); assert!(!wam.is_cyclic_term(1)); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); assert!(!wam.is_cyclic_term(2)); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap[2] = str_loc_as_cell!(0); - print_heap_terms(wam.heap.iter(), 0); + print_heap_terms(&wam.heap, 0); assert!(wam.is_cyclic_term(2)); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap[2] = atom_as_cell!(atom!("b")); wam.heap[1] = str_loc_as_cell!(0); assert!(wam.is_cyclic_term(1)); - all_cells_unmarked(wam.heap.splice(..)); + all_cells_unmarked(&wam.heap); wam.heap.clear(); diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 18cb7427..873d3ceb 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -528,7 +528,8 @@ impl Machine { s, )) => { cell = self.deref_register(arg); - self.machine_st.select_switch_on_term_index(cell, v, c, l, s) + self.machine_st + .select_switch_on_term_index(cell, v, c, l, s) } IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => { // let lit = self.machine_st.constant_to_literal(cell); @@ -1133,6 +1134,7 @@ impl Machine { if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() { self.try_execute(name, arity, idx.get()) } else { + println!("aaand undefined!"); self.undefined_procedure(name, arity) } } else if let Some(module) = self.indices.modules.get(&module_name) { diff --git a/src/machine/partial_string.rs b/src/machine/partial_string.rs index 6176e73a..9484bf40 100644 --- a/src/machine/partial_string.rs +++ b/src/machine/partial_string.rs @@ -19,9 +19,17 @@ pub struct HeapPStrIter<'a> { #[derive(Debug, Clone, Copy)] pub enum PStrCmpResult<'a> { - ListMatch { list_loc: usize }, - CompletePStrMatch { chars_matched: usize, pstr_loc: usize }, - PartialPStrMatch { string: &'a str, var_loc: usize }, + ListMatch { + list_loc: usize, + }, + CompletePStrMatch { + chars_matched: usize, + pstr_loc: usize, + }, + PartialPStrMatch { + string: &'a str, + var_loc: usize, + }, } struct PStrIterStep { @@ -81,7 +89,7 @@ impl<'a> HeapPStrIter<'a> { if s.is_empty() { return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h }); } else { - let next_hare = Heap::neighboring_cell_offset(h + bytes_matched); + let next_hare = Heap::pstr_tail_idx(h + bytes_matched); curr_hare = next_hare; } } @@ -179,11 +187,11 @@ impl<'a> HeapPStrIter<'a> { loop { read_heap_cell!(self.heap[curr_hare], (HeapCellValueTag::PStrLoc, h) => { - let (s, tail_loc) = self.heap.scan_slice_to_str(h); + let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(h); return Ok(PStrIterStep { - iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: s.len() }, - next_hare: tail_loc, + iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: string.len() }, + next_hare: tail_idx, }); } (HeapCellValueTag::Lis, h) => { @@ -319,7 +327,10 @@ impl<'a> Iterator for PStrCharsIter<'a> { self.item = self.iter.next(); return Some(value); } - PStrIteratee::PStrSlice { slice_loc, slice_len } => { + PStrIteratee::PStrSlice { + slice_loc, + slice_len, + } => { let s = self.iter.heap.slice_to_str(slice_loc, slice_len); match s.chars().next() { @@ -353,7 +364,10 @@ mod test { let mut wam = MockWAM::new(); let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap(); - wam.machine_st.heap.push_cell(empty_list_as_cell!()).unwrap(); + wam.machine_st + .heap + .push_cell(empty_list_as_cell!()) + .unwrap(); // not overwriting anything! 0 is an interstitial cell // reserved for use by the runtime @@ -364,7 +378,10 @@ mod test { assert_eq!( iter.next(), - Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }), + Some(PStrIteratee::PStrSlice { + slice_loc: heap_index!(1), + slice_len: "abc ".len() + }), ); assert_eq!(iter.next(), None); assert!(!iter.is_cyclic()); @@ -384,7 +401,10 @@ mod test { assert_eq!( iter.next(), - Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }) + Some(PStrIteratee::PStrSlice { + slice_loc: heap_index!(1), + slice_len: "abc ".len() + }) ); assert_eq!( iter.next(), @@ -407,7 +427,10 @@ mod test { assert_eq!( iter.next(), - Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }) + Some(PStrIteratee::PStrSlice { + slice_loc: heap_index!(1), + slice_len: "abc ".len() + }) ); assert_eq!( iter.next(), @@ -552,7 +575,11 @@ mod test { section.push_cell(heap_loc_as_cell!(h)); }); - unify!(wam.machine_st, pstr_cell, pstr_loc_as_cell!(heap_index!(start))); + unify!( + wam.machine_st, + pstr_cell, + pstr_loc_as_cell!(heap_index!(start)) + ); assert!(!wam.machine_st.fail); @@ -561,7 +588,9 @@ mod test { "abcdef" ); assert_eq!( - wam.machine_st.heap.slice_to_str(heap_index!(start), "abc".len()), + wam.machine_st + .heap + .slice_to_str(heap_index!(start), "abc".len()), "abc" ); assert_eq!( @@ -587,7 +616,10 @@ mod test { assert_eq!( iter.next(), - Some(PStrIteratee::PStrSlice { slice_loc: 'a'.len_utf8(), slice_len: "bc".len() }) + Some(PStrIteratee::PStrSlice { + slice_loc: 'a'.len_utf8(), + slice_len: "bc".len() + }) ); for _ in iter {} @@ -609,7 +641,11 @@ mod test { section.push_cell(empty_list_as_cell!()); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert!(!wam.machine_st.fail); @@ -629,7 +665,11 @@ mod test { section.push_cell(empty_list_as_cell!()); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a')); assert!(!wam.machine_st.fail); @@ -652,7 +692,11 @@ mod test { section.push_cell(empty_list_as_cell!()); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert_eq!(wam.machine_st.heap[start], char_as_cell!('a')); assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b')); @@ -676,7 +720,11 @@ mod test { section.push_cell(empty_list_as_cell!()); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a')); assert!(!wam.machine_st.fail); @@ -699,10 +747,17 @@ mod test { section.push_cell(heap_loc_as_cell!(5 + start)); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a')); - assert_eq!(wam.machine_st.heap[5 + start], pstr_loc_as_cell!(heap_index!(0) + 3)); + assert_eq!( + wam.machine_st.heap[5 + start], + pstr_loc_as_cell!(heap_index!(0) + 3) + ); assert!(!wam.machine_st.fail); // #2293, test6. @@ -723,7 +778,11 @@ mod test { section.push_cell(empty_list_as_cell!()); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert_eq!(wam.machine_st.heap[start], char_as_cell!('a')); assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c')); @@ -750,7 +809,11 @@ mod test { section.push_cell(empty_list_as_cell!()); }); - unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0)); + unify!( + wam.machine_st, + list_loc_as_cell!(start), + pstr_loc_as_cell!(0) + ); assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('b')); assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d')); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 751b55b6..51e45a4a 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -28,26 +28,26 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result Result { let (focus, _cell) = subterm_index(term.heap, term.focus); - let name = match term_predicate_key(term.heap, focus+3) { + let name = match term_predicate_key(term.heap, focus + 3) { Some((name, 0)) => name, _ => { return Err(CompilationError::InvalidDirective( - DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]), + DirectiveError::InvalidOpDeclNameType(term.heap[focus + 3]), )); } }; - let spec = match term_predicate_key(term.heap, focus+2) { + let spec = match term_predicate_key(term.heap, focus + 2) { Some((name, _)) => name, None => { return Err(CompilationError::InvalidDirective( - DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]), + DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]), )); } }; let spec = to_op_decl_spec(spec)?; - let prec = term.deref_loc(focus+1); + let prec = term.deref_loc(focus + 1); let prec = read_heap_cell!(prec, (HeapCellValueTag::Fixnum, n) => { @@ -147,34 +147,34 @@ pub(super) fn setup_module_export_list( let mut focus = term.focus; loop { - read_heap_cell!(term.heap[focus], - (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { - if h == focus { - break; - } else { - focus = h; - } - } - (HeapCellValueTag::Lis, l) => { - let term = FocusedHeapRefMut { - heap: term.heap, - focus: l, - }; - - exports.push(setup_module_export(&term)?); - focus = l + 1; - } - (HeapCellValueTag::Atom, (name, _arity)) => { - if name == atom!("[]") { - return Ok(exports); - } else { - break; - } - } - _ => { - break; - } - ); + read_heap_cell!(term.heap[focus], + (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { + if h == focus { + break; + } else { + focus = h; + } + } + (HeapCellValueTag::Lis, l) => { + let term = FocusedHeapRefMut { + heap: term.heap, + focus: l, + }; + + exports.push(setup_module_export(&term)?); + focus = l + 1; + } + (HeapCellValueTag::Atom, (name, _arity)) => { + if name == atom!("[]") { + return Ok(exports); + } else { + break; + } + } + _ => { + break; + } + ); } Err(CompilationError::InvalidModuleDecl) @@ -281,7 +281,7 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result>( } let heap = loader.machine_heap(); - let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus+1])); + let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus + 1])); read_heap_cell!(cell, (HeapCellValueTag::Str, s) => { @@ -506,28 +506,27 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>( let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc); let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc); - let (module_name, key, term_loc) = - if subterm_key_opt == Some((atom!(":"), 2)) { - match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) { - Some(QualifiedNameInfo { - module_name, - name, - arity, - qualified_term_loc, - }) => ( - module_name, - (name, arity + supp_args), - qualified_term_loc, - ), - None => { - continue; - } + let (module_name, key, term_loc) = if subterm_key_opt == Some((atom!(":"), 2)) { + match get_qualified_name( + loader.machine_heap(), + subterm_loc + 1, + subterm_loc + 2, + ) { + Some(QualifiedNameInfo { + module_name, + name, + arity, + qualified_term_loc, + }) => (module_name, (name, arity + supp_args), qualified_term_loc), + None => { + continue; } - } else { - (module_name, (name, arity + supp_args), subterm_loc) - }; + } + } else { + (module_name, (name, arity + supp_args), subterm_loc) + }; - if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), key.1, term_loc) { + if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), term_loc) { index_ptrs.insert(term_loc, index_ptr); continue; } @@ -642,7 +641,12 @@ impl Preprocessor { let classifier = VariableClassifier::new(self.settings.default_call_policy()); let var_data = classifier.classify_fact(loader, &term)?; - Ok((Fact { term_loc: term.focus }, var_data)) + Ok(( + Fact { + term_loc: term.focus, + }, + var_data, + )) } else { Err(CompilationError::InadmissibleFact) } @@ -660,7 +664,13 @@ impl Preprocessor { let head_loc = term_nth_arg(heap, term.focus, 1).unwrap(); if term_predicate_key(heap, head_loc).is_some() { - Ok((Rule { term_loc: term.focus, clauses }, var_data)) + Ok(( + Rule { + term_loc: term.focus, + clauses, + }, + var_data, + )) } else { Err(CompilationError::InvalidRuleHead) } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 2dccc87d..1dfd8f46 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -181,10 +181,7 @@ fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usi byte_offset += c.len_utf8(); } - ( - char_count, - Heap::neighboring_cell_offset(pstr_loc + byte_offset), - ) + (char_count, Heap::pstr_tail_idx(pstr_loc + byte_offset)) } fn pstr_segment_char_count_up_to( @@ -217,10 +214,9 @@ fn pstr_segment_char_count_up_to( pstr_loc: pstr_loc + byte_offset, } } else { - let tail_loc = Heap::neighboring_cell_offset(pstr_loc + byte_offset); PStrSegmentCountResult::End { char_count, - tail_loc, + tail_loc: Heap::pstr_tail_idx(pstr_loc + byte_offset), } } } @@ -567,6 +563,12 @@ struct AttrListMatch { prev_tail: Option, } +#[derive(Debug)] +pub(crate) struct FindallCopyInfo { + offset: usize, + pstr_threshold: usize, +} + impl MachineState { #[inline(always)] pub(crate) fn unattributed_var(&mut self) { @@ -648,9 +650,8 @@ impl MachineState { loop { read_heap_cell!(value, (HeapCellValueTag::PStrLoc, h) => { - let (_, tail) = heap.scan_slice_to_str(h); - // let (h_offset, _) = pstr_loc_and_offset(heap, h); - return tail; + let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h); + return tail_idx; } (HeapCellValueTag::Lis, h) => { return h+1; @@ -855,17 +856,10 @@ impl MachineState { &mut self, lh_offset: usize, copy_target: HeapCellValue, - ) -> Result { + ) -> Result { let threshold = self.lifted_heap.cell_len() - lh_offset; - let mut copy_ball_term = CopyBallTerm::new( - &mut self.attr_var_init.attr_var_queue, - &mut self.stack, - &mut self.heap, - &mut self.lifted_heap, - ); - - let mut writer = copy_ball_term.reserve(3)?; + let mut writer = self.lifted_heap.reserve(3)?; writer.write_with(|section| { section.push_cell(list_loc_as_cell!(threshold + 1)); @@ -873,9 +867,21 @@ impl MachineState { section.push_cell(heap_loc_as_cell!(threshold + 2)); }); - copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?; + let old_lifted_cell_len = self.lifted_heap.cell_len(); + + let copy_ball_term = CopyBallTerm::new( + &mut self.attr_var_init.attr_var_queue, + &mut self.stack, + &mut self.heap, + &mut self.lifted_heap, + ); - Ok(threshold + lh_offset + 2) + 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)] @@ -1059,18 +1065,6 @@ impl MachineState { pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option { read_heap_cell!(value, - /* - (HeapCellValueTag::CStr, cstr_atom) => { - // avoid allocating a String if possible: - // We must be careful to preserve the string "[]" as is, - // instead of turning it into the atom [], i.e., "". - if cstr_atom == atom!("[]") { - Some(AtomOrString::String("[]".to_string())) - } else { - Some(AtomOrString::Atom(cstr_atom)) - } - } - */ (HeapCellValueTag::Atom, (atom, arity)) => { if arity == 0 { // ... likewise. @@ -1403,15 +1397,7 @@ impl Machine { let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]) .get_name_and_arity(); - (name, arity, if self.machine_st.heap.cell_len() > s + arity + 1 { - if !self.machine_st.heap.pstr_at(s + arity + 1) { - get_structure_index(self.machine_st.heap[s + arity + 1]) - } else { - None - } - } else { - None - }) + (name, arity, get_structure_index(self.machine_st.heap[s.saturating_sub(1)])) } (HeapCellValueTag::Atom, (name, arity)) => { debug_assert_eq!(arity, 0); @@ -1471,7 +1457,6 @@ impl Machine { if let Some(code_index) = index_cell { if !code_index.is_undefined() { - // println!("(fast) calling {}/{}", name.as_str(), arity); load_registers(&mut self.machine_st, goal, goal_arity); self.machine_st.neck_cut(); return call_at_index(self, name, arity, code_index.get()); @@ -1495,6 +1480,7 @@ impl Machine { .variable_set(&mut supp_vars, self.machine_st.registers[2]); struct GoalAnalysisResult { + index_ptr_loc: usize, is_simple_goal: bool, goal: HeapCellValue, key: PredicateKey, @@ -1510,7 +1496,7 @@ impl Machine { // fill expanded_vars with variables of the partial // goal pre-completion by complete_partial_goal. - for idx in s + 1 .. s + arity - supp_vars.len() + 1 { + for idx in s + 1 ..= s + arity - supp_vars.len() { self.machine_st.variable_set(&mut expanded_vars, self.machine_st.heap[idx]); } @@ -1524,7 +1510,8 @@ impl Machine { // disjoint from them. if they are not, the // expanded goal is not simple. - let post_supp_args = self.machine_st.heap.splice(s+arity-supp_vars.len()+1 .. s+arity+1); + let post_supp_args = (s+arity-supp_vars.len()+1 ..= s+arity) + .map(|idx| self.machine_st.heap[idx]); post_supp_args .zip(supp_vars.iter()) @@ -1549,27 +1536,33 @@ impl Machine { false }; - let goal = if is_simple_goal { + let (index_ptr_loc, goal) = if is_simple_goal { let h = self.machine_st.heap.cell_len(); let arity = arity - supp_vars.len(); + resource_error_call_result!( + self.machine_st, + self.machine_st.heap.push_cell(empty_list_as_cell!()) + ); + resource_error_call_result!( self.machine_st, self.machine_st.heap.copy_slice_to_end( - s .. s + arity + 1 + s ..= s + arity, ) ); - self.machine_st.heap[h] = atom_as_cell!(name, arity); + self.machine_st.heap[h+1] = atom_as_cell!(name, arity); // even if arity == 0, goal must be a Str cell, // since an index is about to appended to it. - str_loc_as_cell!(h) + (h, str_loc_as_cell!(h+1)) } else { - goal + (0, goal) }; GoalAnalysisResult { + index_ptr_loc, is_simple_goal, goal, key: (name, arity), @@ -1579,37 +1572,26 @@ impl Machine { (HeapCellValueTag::Atom, (name, arity)) => { debug_assert_eq!(arity, 0); - let h = self.machine_st.heap.cell_len(); - resource_error_call_result!( - self.machine_st, - self.machine_st.heap.push_cell(goal) - ); - - GoalAnalysisResult { - is_simple_goal: true, - goal: str_loc_as_cell!(h), - key: (name, 0), - supp_vars, - } - } - /* - (HeapCellValueTag::Char, c) => { - let name = AtomTable::build_with(&self.machine_st.atom_tbl,&c.to_string()); let h = self.machine_st.heap.cell_len(); - resource_error_call_result!( + let mut writer = resource_error_call_result!( self.machine_st, - self.machine_st.heap.push_cell(atom_as_cell!(name)) + self.machine_st.heap.reserve(2) ); + writer.write_with(|section| { + section.push_cell(empty_list_as_cell!()); + section.push_cell(goal); + }); + GoalAnalysisResult { + index_ptr_loc: h, is_simple_goal: true, - goal: str_loc_as_cell!(h), + goal: str_loc_as_cell!(h+1), key: (name, 0), supp_vars, } } - */ _ => { self.machine_st.fail = true; return Ok(()); @@ -1623,14 +1605,8 @@ impl Machine { let expanded_term = if result.is_simple_goal { let idx = self.get_or_insert_qualified_code_index(module_name, result.key); - - resource_error_call_result!( - self.machine_st, - self.machine_st - .heap - .push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx))) - ); - + self.machine_st.heap[result.index_ptr_loc] = + untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)); result.goal } else { let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default()); @@ -1662,29 +1638,24 @@ impl Machine { self.machine_st.heap.reserve(unexpanded_vars.len() + 2) ); + let idx = CodeIndex::new( + IndexPtr::index(helper_clause_loc), + &mut self.machine_st.arena, + ); + writer.write_with(|section| { + section.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx))); section.push_cell(atom_as_cell!(atom!("$aux"), 0)); for value in unexpanded_vars.difference(&result.supp_vars).cloned() { section.push_cell(value); } - - section.push_cell(atom_as_cell!(atom!("[]"))); }); let anon_str_arity = self.machine_st.heap.cell_len() - h - 2; - self.machine_st.heap[h] = atom_as_cell!(atom!("$aux"), anon_str_arity); - - let idx = CodeIndex::new( - IndexPtr::index(helper_clause_loc), - &mut self.machine_st.arena, - ); + self.machine_st.heap[h + 1] = atom_as_cell!(atom!("$aux"), anon_str_arity); - self.machine_st.heap.last_cell_mut().map(|cell| { - *cell = untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)); - }); - - str_loc_as_cell!(h) + str_loc_as_cell!(h + 1) } } }; @@ -1702,28 +1673,22 @@ impl Machine { if HeapCellValueTag::Str == qualified_goal.get_tag() { let s = qualified_goal.get_value() as usize; - let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity(); + let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name(); if name == atom!("$call") { return false; } - if self.machine_st.heap.cell_len() > s + 1 + arity { - if self.machine_st.heap.pstr_at(s + 1 + arity) { - return false; - } + let idx_cell = self.machine_st.heap[s.saturating_sub(1)]; - let idx_cell = self.machine_st.heap[s + 1 + arity]; - - if HeapCellValueTag::Cons == idx_cell.get_tag() { - match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell), - (ArenaHeaderTag::IndexPtr, _ip) => { - return true; - } - _ => { - } - ); - } + if HeapCellValueTag::Cons == idx_cell.get_tag() { + match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell), + (ArenaHeaderTag::IndexPtr, _ip) => { + return true; + } + _ => { + } + ); } } @@ -2326,27 +2291,6 @@ impl Machine { let a1 = self.deref_register(1); read_heap_cell!(a1, - /* - (HeapCellValueTag::Char) => { - let h = self.machine_st.heap.cell_len(); - - let mut writer = resource_error_call_result!( - self.machine_st, - self.machine_st.heap.reserve(2) - ); - - step_or_resource_error!( - self.machine_st, - writer.write_with(|section| { - section.push_cell(a1); - section.push_cell(empty_list_as_cell!()); - Ok::<(), usize>(()) - }) - ); - - unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h)); - } - */ (HeapCellValueTag::Atom, (name, arity)) => { debug_assert_eq!(arity, 0); @@ -2556,7 +2500,7 @@ impl Machine { self.machine_st.allocate_pstr(&*atom.as_str()) ); - let tail_loc = Heap::neighboring_cell_offset(atom.as_str().len() + heap_index!(pstr_h)); + let tail_loc = Heap::pstr_tail_idx(atom.as_str().len() + heap_index!(pstr_h)); step_or_resource_error!( self.machine_st, @@ -2599,8 +2543,8 @@ impl Machine { read_heap_cell!(pstr, (HeapCellValueTag::PStrLoc, h) => { - let (_, tail_loc) = self.machine_st.heap.scan_slice_to_str(h); - unify_fn!(self.machine_st, heap_loc_as_cell!(tail_loc), a2); + let HeapStringScan { tail_idx, .. } = self.machine_st.heap.scan_slice_to_str(h); + unify_fn!(self.machine_st, heap_loc_as_cell!(tail_idx), a2); } (HeapCellValueTag::Lis, h) => { unify_fn!( @@ -3985,7 +3929,10 @@ impl Machine { pub(crate) fn copy_to_lifted_heap(&mut self) { let lh_offset = cell_as_fixnum!(self.deref_register(1)).get_num() as usize; let copy_target = self.machine_st.registers[2]; - let old_threshold = step_or_resource_error!( + let FindallCopyInfo { + offset: old_threshold, + pstr_threshold, + } = step_or_resource_error!( self.machine_st, self.machine_st .copy_findall_solution(lh_offset, copy_target) @@ -3995,8 +3942,20 @@ impl Machine { self.machine_st.lifted_heap[old_threshold] = heap_loc_as_cell!(new_threshold); - for addr in &mut self.machine_st.lifted_heap.splice_mut(old_threshold + 1..) { - *addr -= self.machine_st.heap.cell_len() + lh_offset; + for idx in old_threshold + 1..pstr_threshold { + self.machine_st.lifted_heap[idx] -= self.machine_st.heap.cell_len() + lh_offset; + } + + let mut pstr_threshold = heap_index!(pstr_threshold); + + while pstr_threshold < heap_index!(self.machine_st.lifted_heap.cell_len()) { + let HeapStringScan { tail_idx, .. } = self + .machine_st + .lifted_heap + .scan_slice_to_str(pstr_threshold); + + self.machine_st.lifted_heap[tail_idx] -= self.machine_st.heap.cell_len() + lh_offset; + pstr_threshold = heap_index!(tail_idx + 1); } } @@ -5815,17 +5774,18 @@ impl Machine { unify_fn!(self.machine_st, solutions, diff); } else { let h = self.machine_st.heap.cell_len(); + let reserve_size = self.machine_st.lifted_heap.cell_len() - lh_offset; - step_or_resource_error!( + let mut writer = step_or_resource_error!( self.machine_st, - self.machine_st - .heap - .append(self.machine_st.lifted_heap.splice(lh_offset..),) + self.machine_st.heap.reserve(reserve_size) ); - for cell in &mut self.machine_st.heap.splice_mut(h..) { - *cell = *cell + h; - } + writer.write_with(|section| { + for idx in lh_offset..self.machine_st.lifted_heap.cell_len() { + section.push_cell(self.machine_st.lifted_heap[idx] + h); + } + }); let diff = self.machine_st.registers[3]; unify_fn!( @@ -5852,17 +5812,18 @@ impl Machine { unify_fn!(self.machine_st, solutions, empty_list_as_cell!()); } else { let h = self.machine_st.heap.cell_len(); + let reserve_size = self.machine_st.lifted_heap.cell_len() - lh_offset; - step_or_resource_error!( + let mut writer = step_or_resource_error!( self.machine_st, - self.machine_st - .heap - .append(self.machine_st.lifted_heap.splice(lh_offset..),) + self.machine_st.heap.reserve(reserve_size) ); - for cell in &mut self.machine_st.heap.splice_mut(h..) { - *cell = *cell + h; - } + writer.write_with(|section| { + for idx in lh_offset..self.machine_st.lifted_heap.cell_len() { + section.push_cell(self.machine_st.lifted_heap[idx] + h); + } + }); self.machine_st.lifted_heap.truncate(lh_offset); @@ -7243,8 +7204,7 @@ impl Machine { let mut ball = Ball::new(); ball.boundary = self.machine_st.heap.cell_len(); - - step_or_resource_error!( + ball.pstr_boundary = step_or_resource_error!( self.machine_st, copy_term( CopyBallTerm::new( diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index 9a1f9fa6..f8488af7 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -44,14 +44,19 @@ impl<'a> BootstrappingTermStream<'a> { listing_src: ListingSource, ) -> Self { let lexer_parser = LexerParser::new(stream, machine_st); - Self { lexer_parser, listing_src } + Self { + lexer_parser, + listing_src, + } } } impl<'a> TermStream for BootstrappingTermStream<'a> { #[inline] fn next(&mut self, op_dir: &CompositeOpDir) -> Result { - let result = self.lexer_parser.read_term(op_dir, Tokens::Default) + let result = self + .lexer_parser + .read_term(op_dir, Tokens::Default) .map_err(CompilationError::from); result @@ -125,7 +130,9 @@ pub struct InlineTermStream {} impl TermStream for InlineTermStream { fn next(&mut self, _: &CompositeOpDir) -> Result { - Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default()))) + Err(CompilationError::from(ParserError::unexpected_eof( + ParserErrorSrc::default(), + ))) } fn eof(&mut self) -> Result { diff --git a/src/machine/unify.rs b/src/machine/unify.rs index 5b7c23e8..899fc3ac 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -507,11 +507,9 @@ fn bind_with_occurs_check(unifier: &mut U, r: Ref, value: HeapCellVa if value.is_ref() && !value.is_stack_var() { machine_st.heap[0] = value; - for cell in stackful_preorder_iter::( - &mut machine_st.heap, - &mut machine_st.stack, - 0, - ) { + for cell in + stackful_preorder_iter::(&mut machine_st.heap, &mut machine_st.stack, 0) + { let cell = unmark_cell_bits!(cell); if let Some(inner_r) = cell.as_var() { diff --git a/src/macros.rs b/src/macros.rs index 5463c0c8..eb8a48b4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -40,15 +40,10 @@ macro_rules! empty_list_as_cell { macro_rules! atom_as_cell { ($atom:expr) => { - HeapCellValue::from_bytes( - AtomCell::build_with($atom.index, 0).into_bytes(), - ) + HeapCellValue::from_bytes(AtomCell::build_with($atom.index, 0).into_bytes()) }; ($atom:expr, $arity:expr) => { - HeapCellValue::from_bytes( - AtomCell::build_with($atom.index, $arity as u8) - .into_bytes(), - ) + HeapCellValue::from_bytes(AtomCell::build_with($atom.index, $arity as u8).into_bytes()) }; } @@ -499,9 +494,13 @@ macro_rules! resource_error_call_result { } macro_rules! heap_index { - ($idx:expr) => {($idx) * std::mem::size_of::()}; + ($idx:expr) => { + ($idx) * std::mem::size_of::() + }; } macro_rules! cell_index { - ($idx:expr) => {(($idx) / std::mem::size_of::())}; + ($idx:expr) => { + (($idx) / std::mem::size_of::()) + }; } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 45335c88..b873e61b 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -141,7 +141,11 @@ macro_rules! fixnum { ($n:expr, $arena:expr) => { Fixnum::build_with_checked($n) .map(|n| fixnum_as_cell!(n)) - .unwrap_or_else(|_| typed_arena_ptr_as_cell!(arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr)) + .unwrap_or_else(|_| { + typed_arena_ptr_as_cell!( + arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr + ) + }) }; ($wrapper:ty, $n:expr, $arena:expr) => { Fixnum::build_with_checked($n) @@ -614,10 +618,7 @@ impl Literal { pub type Var = Rc; -pub(crate) fn subterm_index( - heap: &impl SizedHeap, - subterm_loc: usize, -) -> (usize, HeapCellValue) { +pub(crate) fn subterm_index(heap: &impl SizedHeap, subterm_loc: usize) -> (usize, HeapCellValue) { let subterm = heap[subterm_loc]; if subterm.is_ref() { @@ -710,16 +711,10 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec { } */ -pub(crate) fn fetch_index_ptr( - heap: &impl SizedHeap, - arity: usize, - term_loc: usize, -) -> Option { - if term_loc + arity + 1 >= heap.cell_len() || heap.pstr_at(term_loc + arity + 1) { - return None; - } +pub(crate) fn fetch_index_ptr(heap: &impl SizedHeap, term_loc: usize) -> Option { + let index_cell_loc = term_loc.saturating_sub(1); - read_heap_cell!(heap[term_loc + arity + 1], + read_heap_cell!(heap[index_cell_loc], (HeapCellValueTag::Cons, c) => { match_untyped_arena_ptr!(c, (ArenaHeaderTag::IndexPtr, ptr) => { @@ -739,7 +734,7 @@ pub(crate) fn blunt_index_ptr( key: PredicateKey, term_loc: usize, ) -> bool { - if fetch_index_ptr(heap, key.1, term_loc).is_some() { + if fetch_index_ptr(heap, term_loc).is_some() { heap[term_loc] = atom_as_cell!(key.0, key.1); true } else { @@ -752,10 +747,7 @@ pub(crate) fn unfold_by_str_once( start_term: HeapCellValue, atom: Atom, ) -> Option { - let start_term = heap_bound_store( - heap, - heap_bound_deref(heap, start_term), - ); + let start_term = heap_bound_store(heap, heap_bound_deref(heap, start_term)); if let HeapCellValueTag::Str = start_term.get_tag() { let s = start_term.get_value() as usize; @@ -764,7 +756,7 @@ pub(crate) fn unfold_by_str_once( blunt_index_ptr(heap, (s_atom, s_arity), s); if (s_atom, s_arity) == (atom, 2) { - return Some(s+1); + return Some(s + 1); } } @@ -821,7 +813,7 @@ pub fn unfold_by_str_locs( let mut current_term = heap[term_loc]; while let Some(fst_loc) = unfold_by_str_once(heap, current_term, atom) { - term_loc = fst_loc+1; + term_loc = fst_loc + 1; current_term = heap[term_loc]; let fst = heap[fst_loc]; terms.push((fst, fst_loc)); @@ -831,10 +823,7 @@ pub fn unfold_by_str_locs( terms } -pub fn term_predicate_key( - heap: &impl SizedHeap, - mut term_loc: usize, -) -> Option { +pub fn term_predicate_key(heap: &impl SizedHeap, mut term_loc: usize) -> Option { loop { read_heap_cell!(heap[term_loc], (HeapCellValueTag::Atom, (name, arity)) => { @@ -874,10 +863,7 @@ pub fn inverse_var_locs_from_iter>(iter: I) -> let var_loc = var.get_value() as usize; if count > 1 { - inverse_var_locs.insert( - var_loc, - Rc::new(format!("_{}", var_loc)), - ); + inverse_var_locs.insert(var_loc, Rc::new(format!("_{}", var_loc))); } } diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 800e5f44..b357c3e8 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -1,4 +1,4 @@ -use lexical::{FromLexical, parse}; +use lexical::{parse, FromLexical}; use crate::arena::*; use crate::atom_table::*; @@ -54,22 +54,18 @@ impl Token { Token::String(string) if flags.double_quotes.is_codes() => { 2 * string.chars().count() + 1 } - Token::String(string) => { - Heap::compute_pstr_size(&string) - } - Token::Literal(_) | - Token::Comma | - Token::HeadTailSeparator | - Token::Open | - Token::OpenCT | - Token::OpenCurly | - Token::OpenList | - Token::Var(_) => { + Token::String(string) => Heap::compute_pstr_size(&string), + Token::Literal(_) + | Token::Comma + | Token::HeadTailSeparator + | Token::Open + | Token::OpenCT + | Token::OpenCurly + | Token::OpenList + | Token::Var(_) => { heap_index!(1) } - _ => { - 0 - } + _ => 0, } } @@ -411,10 +407,7 @@ impl<'a, R: CharRead> LexerParser<'a, R> { self.skip_char(c); u32::from_str_radix(&token, radix).map_or_else( |_| Err(ParserError::ParseBigInt(self.loc_to_err_src())), - |n| { - char::try_from(n) - .map_err(|_| ParserError::Utf8Error(self.loc_to_err_src())) - }, + |n| char::try_from(n).map_err(|_| ParserError::Utf8Error(self.loc_to_err_src())), ) } else { Err(ParserError::IncompleteReduction(self.loc_to_err_src())) @@ -486,12 +479,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { .or_else(|_| { Integer::from_str_radix(&token, 16) .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) @@ -523,12 +515,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { .or_else(|_| { Integer::from_str_radix(&token, 8) .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) @@ -560,12 +551,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { .or_else(|_| { Integer::from_str_radix(&token, 2) .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) @@ -642,7 +632,9 @@ impl<'a, R: CharRead> LexerParser<'a, R> { } } } else { - return Err(ParserError::InvalidSingleQuotedCharacter(self.loc_to_err_src())); + return Err(ParserError::InvalidSingleQuotedCharacter( + self.loc_to_err_src(), + )); } } else { match self.get_back_quoted_string() { @@ -721,12 +713,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) @@ -815,12 +806,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) @@ -831,23 +821,18 @@ impl<'a, R: CharRead> LexerParser<'a, R> { if let ParserError::ParseBigInt(..) = e { token .parse::() - .map(|n| { - Token::Literal(fixnum!(n, &mut self.machine_st.arena)) - }) + .map(|n| Token::Literal(fixnum!(n, &mut self.machine_st.arena))) .or_else(|_| { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) - }) - .map_err(|_| { - ParserError::ParseBigInt(self.loc_to_err_src()) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) + .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) } else { Err(e) @@ -858,23 +843,18 @@ impl<'a, R: CharRead> LexerParser<'a, R> { if let ParserError::ParseBigInt(..) = e { token .parse::() - .map(|n| { - Token::Literal(fixnum!(n, &mut self.machine_st.arena)) - }) + .map(|n| Token::Literal(fixnum!(n, &mut self.machine_st.arena))) .or_else(|_| { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) - }) - .map_err(|_| { - ParserError::ParseBigInt(self.loc_to_err_src()) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) + .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) } else { Err(e) @@ -885,23 +865,18 @@ impl<'a, R: CharRead> LexerParser<'a, R> { if let ParserError::ParseBigInt(..) = e { token .parse::() - .map(|n| { - Token::Literal(fixnum!(n, &mut self.machine_st.arena)) - }) + .map(|n| Token::Literal(fixnum!(n, &mut self.machine_st.arena))) .or_else(|_| { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) - }) - .map_err(|_| { - ParserError::ParseBigInt(self.loc_to_err_src()) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) + .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) } else { Err(e) @@ -937,23 +912,18 @@ impl<'a, R: CharRead> LexerParser<'a, R> { token .parse::() - .map(|n| { - Token::Literal(fixnum!(n, &mut self.machine_st.arena)) - }) + .map(|n| Token::Literal(fixnum!(n, &mut self.machine_st.arena))) .or_else(|_| { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) - }) - .map_err(|_| { - ParserError::ParseBigInt(self.loc_to_err_src()) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) + .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) }) } else { @@ -964,12 +934,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) @@ -982,12 +951,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { token .parse::() .map(|n| { - Token::Literal(typed_arena_ptr_as_cell!( - arena_alloc!( - n, - &mut self.machine_st.arena - ) as TypedArenaPtr - )) + Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!( + n, + &mut self.machine_st.arena + ) + as TypedArenaPtr)) }) .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src())) }) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index c726ced2..00c1d101 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -187,7 +187,9 @@ struct Parser<'a> { inverse_var_locs: InverseVarLocs, } -pub fn read_tokens(lexer: &mut LexerParser) -> Result<(Vec, usize), ParserError> { +pub fn read_tokens( + lexer: &mut LexerParser, +) -> Result<(Vec, usize), ParserError> { let mut tokens = vec![]; let mut term_size = 0; @@ -264,9 +266,9 @@ pub(crate) fn as_partial_string( tail = heap[l+1]; } (HeapCellValueTag::PStrLoc, l) => { - let (pstr, tail_loc) = heap.scan_slice_to_str(l); + let HeapStringScan { string: pstr, tail_idx } = heap.scan_slice_to_str(l); string += pstr; - tail = heap[tail_loc]; + tail = heap[tail_idx]; } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { if heap[h] != tail { @@ -306,8 +308,7 @@ impl<'a> Parser<'a> { TokenType::Comma => Some(atom!(",")), TokenType::Term { heap_loc } => { if heap_loc.is_ref() { - term_predicate_key(&self.terms, heap_loc.get_value() as usize) - .map(|key| key.0) + term_predicate_key(&self.terms, heap_loc.get_value() as usize).map(|key| key.0) } else { None } @@ -392,7 +393,8 @@ impl<'a> Parser<'a> { fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) { let h = self.terms.cell_len(); - self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom))); + self.terms + .write_with(|section| section.push_cell(atom_as_cell!(atom))); self.stack.push(TokenDesc { tt: TokenType::Term { heap_loc: heap_loc_as_cell!(h), @@ -438,10 +440,12 @@ impl<'a> Parser<'a> { section.push_cell(list_loc_as_cell!(h)); }); - TokenType::Term { heap_loc: heap_loc_as_cell!(h + 2) } + TokenType::Term { + heap_loc: heap_loc_as_cell!(h + 2), + } } else { - self.terms.write_with(|section| { - match section.push_pstr(&s) { + self.terms + .write_with(|section| match section.push_pstr(&s) { Some(pstr_loc_cell) => { section.push_cell(empty_list_as_cell!()); let h = section.cell_len(); @@ -451,10 +455,11 @@ impl<'a> Parser<'a> { None => { section.push_cell(empty_list_as_cell!()); } - } - }); + }); - TokenType::Term { heap_loc: pstr_cell } + TokenType::Term { + heap_loc: pstr_cell, + } } } Token::Literal(c) => { @@ -478,13 +483,14 @@ impl<'a> Parser<'a> { if var.trim() != "_" { self.var_locs.insert(var.clone(), heap_loc); - self.inverse_var_locs.insert(heap_loc.get_value() as usize, var); + self.inverse_var_locs + .insert(heap_loc.get_value() as usize, var); } TokenType::Term { heap_loc } } } - }, + } Token::Comma => TokenType::Comma, Token::Open => TokenType::Open, Token::Close => TokenType::Close, @@ -619,15 +625,21 @@ impl<'a> Parser<'a> { let term_idx = self.terms.cell_len(); let push_structure = |parser: &mut Self, name: Atom| -> TokenType { - parser.terms.write_with(|section| section.push_cell(atom_as_cell!(name, arity))); + parser + .terms + .write_with(|section| section.push_cell(atom_as_cell!(name, arity))); for idx in (stack_len + 2..parser.stack.len()).step_by(2) { let subterm = parser.term_from_stack(idx).unwrap(); - parser.terms.write_with(|section| section.push_cell(subterm)); + parser + .terms + .write_with(|section| section.push_cell(subterm)); } let str_loc_idx = parser.terms.cell_len(); - parser.terms.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx))); + parser + .terms + .write_with(|section| section.push_cell(str_loc_as_cell!(term_idx))); TokenType::Term { heap_loc: heap_loc_as_cell!(str_loc_idx), @@ -709,23 +721,20 @@ impl<'a> Parser<'a> { } fn loc_to_err_src(&self) -> ParserErrorSrc { - ParserErrorSrc { line_num: *self.line_num, col_num: *self.col_num } + ParserErrorSrc { + line_num: *self.line_num, + col_num: *self.col_num, + } } fn expand_comma_compacted_terms(&mut self, index: usize) -> usize { if let Some(term) = self.term_from_stack(index - 1) { let mut op_desc = self.stack[index - 1]; - let mut term = heap_bound_store( - &self.terms, - heap_bound_deref( - &self.terms, - term, - ), - ); - - if term.is_ref() && - 0 < op_desc.priority && - op_desc.priority < self.stack[index].priority + let mut term = heap_bound_store(&self.terms, heap_bound_deref(&self.terms, term)); + + if term.is_ref() + && 0 < op_desc.priority + && op_desc.priority < self.stack[index].priority { /* '|' is a head-tail separator here, not * an operator, so expand the @@ -740,11 +749,9 @@ impl<'a> Parser<'a> { } else { let mut terms = vec![]; - while let Some(fst_loc) = unfold_by_str_once( - &mut self.terms, - term, - atom!(","), - ) { + while let Some(fst_loc) = + unfold_by_str_once(&mut self.terms, term, atom!(",")) + { let (_, snd) = subterm_index(&self.terms, fst_loc + 1); let (_, fst) = subterm_index(&self.terms, fst_loc); @@ -763,14 +770,13 @@ impl<'a> Parser<'a> { }; let arity = terms.len() - 1; - self.stack.extend(terms.into_iter().map(|heap_loc| { - TokenDesc { + self.stack + .extend(terms.into_iter().map(|heap_loc| TokenDesc { tt: TokenType::Term { heap_loc }, priority: 0, spec: 0, unfold_bounds: 0, - } - })); + })); return arity; } } @@ -816,7 +822,8 @@ impl<'a> Parser<'a> { // parsed an empty list token if td.tt == TokenType::OpenList { let h = self.terms.cell_len(); - self.terms.write_with(|section| section.push_cell(empty_list_as_cell!())); + self.terms + .write_with(|section| section.push_cell(empty_list_as_cell!())); td.spec = TERM; td.tt = TokenType::Term { @@ -845,9 +852,7 @@ impl<'a> Parser<'a> { let tail_term = match self.term_from_stack(idx + 1) { Some(term) => term, None => { - return Err(ParserError::IncompleteReduction( - self.loc_to_err_src(), - )); + return Err(ParserError::IncompleteReduction(self.loc_to_err_src())); } }; @@ -863,18 +868,14 @@ impl<'a> Parser<'a> { }; if arity > self.terms.cell_len() { - return Err(ParserError::IncompleteReduction( - self.loc_to_err_src(), - )); + return Err(ParserError::IncompleteReduction(self.loc_to_err_src())); } let pre_terms_len = self.terms.cell_len(); while let Some(token_desc) = self.stack.pop() { let subterm = match token_desc.tt { - TokenType::Term { heap_loc } => { - heap_loc - } + TokenType::Term { heap_loc } => heap_loc, _ => { continue; } @@ -942,7 +943,8 @@ impl<'a> Parser<'a> { if td.tt == TokenType::OpenCurly { let h = self.terms.cell_len(); - self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}")))); + self.terms + .write_with(|section| section.push_cell(atom_as_cell!(atom!("{}")))); td.tt = TokenType::Term { heap_loc: heap_loc_as_cell!(h), @@ -1160,61 +1162,53 @@ impl<'a> Parser<'a> { Token::String(string) => { self.shift(Token::String(string), 0, TERM); } - Token::Literal(c) => { - match Number::try_from(c) { - Ok(Number::Integer(n)) => { - self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n)) - } - Ok(Number::Rational(n)) => { - self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r)) - } - Ok(Number::Float(n)) => { - use ordered_float::OrderedFloat; - - self.negate_number( - n, - |n, _| -n, - |OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)), - ) - } - Ok(Number::Fixnum(n)) => { - self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n)) - } - Err(_) => { - if let Some(name) = c.to_atom() { - if !self.shift_op(name, op_dir)? { - self.shift(Token::Literal(c), 0, TERM); - } - } else { + Token::Literal(c) => match Number::try_from(c) { + Ok(Number::Integer(n)) => { + self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n)) + } + Ok(Number::Rational(n)) => { + self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r)) + } + Ok(Number::Float(n)) => { + use ordered_float::OrderedFloat; + + self.negate_number( + n, + |n, _| -n, + |OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)), + ) + } + Ok(Number::Fixnum(n)) => { + self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n)) + } + Err(_) => { + if let Some(name) = c.to_atom() { + if !self.shift_op(name, op_dir)? { self.shift(Token::Literal(c), 0, TERM); } + } else { + self.shift(Token::Literal(c), 0, TERM); } } - } + }, Token::Var(v) => self.shift(Token::Var(v), 0, TERM), Token::Open => self.shift(Token::Open, 1300, DELIMITER), Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER), Token::Close => { if !self.reduce_term() && !self.reduce_brackets() { - return Err(ParserError::IncompleteReduction( - self.loc_to_err_src(), - )); + return Err(ParserError::IncompleteReduction(self.loc_to_err_src())); } } Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER), Token::CloseList => { if !self.reduce_list()? { - return Err(ParserError::IncompleteReduction( - self.loc_to_err_src(), - )); + return Err(ParserError::IncompleteReduction(self.loc_to_err_src())); } } Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER), Token::CloseCurly => { if !self.reduce_curly()? { - return Err(ParserError::IncompleteReduction( - self.loc_to_err_src(), - )); + return Err(ParserError::IncompleteReduction(self.loc_to_err_src())); } } Token::HeadTailSeparator => { @@ -1248,9 +1242,7 @@ impl<'a> Parser<'a> { | Some(TokenType::OpenCurly) | Some(TokenType::HeadTailSeparator) | Some(TokenType::Comma) => { - return Err(ParserError::IncompleteReduction( - self.loc_to_err_src(), - )) + return Err(ParserError::IncompleteReduction(self.loc_to_err_src())) } _ => {} }, @@ -1267,7 +1259,10 @@ impl<'a, R: CharRead> LexerParser<'a, R> { } pub fn loc_to_err_src(&self) -> ParserErrorSrc { - ParserErrorSrc { line_num: self.line_num, col_num: self.col_num } + ParserErrorSrc { + line_num: self.line_num, + col_num: self.col_num, + } } // on success, returns the parsed term and the number of lines read. @@ -1284,7 +1279,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> { // the parser uses conditional indirection in many places so // the reserved size should be at least 4 * term_byte_size // so all cells are accounted for. - let writer = match self.machine_st.heap.reserve(cell_index!(4 * term_byte_size)) { + let writer = match self + .machine_st + .heap + .reserve(cell_index!(4 * term_byte_size)) + { Ok(term) => term, Err(_err_loc) => { return Err(ParserError::ResourceError(self.loc_to_err_src())); diff --git a/src/read.rs b/src/read.rs index e0b5d7d9..549cdef0 100644 --- a/src/read.rs +++ b/src/read.rs @@ -58,7 +58,7 @@ impl MachineState { let op_dir = CompositeOpDir::new(op_dir, None); let term_result = lexer_parser.read_term(&op_dir, Tokens::Default); - let lines_read = lexer_parser.line_num(); + let lines_read = lexer_parser.line_num(); term_result.map(|term| (term, lines_read)) } diff --git a/src/types.rs b/src/types.rs index e9caa4a7..5eee7fcc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -369,8 +369,8 @@ impl HeapCellValue { name == atom!("[]") && arity == 0 } (HeapCellValueTag::PStrLoc, h) => { - let (_s, tail_loc) = heap.scan_slice_to_str(h); - self = heap[tail_loc]; + let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h); + self = heap[tail_idx]; continue; } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { @@ -399,8 +399,7 @@ impl HeapCellValue { | HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar - | HeapCellValueTag::PStrLoc - // | HeapCellValueTag::PStrOffset + | HeapCellValueTag::PStrLoc // | HeapCellValueTag::PStrOffset ) } @@ -503,9 +502,7 @@ impl HeapCellValue { #[inline] pub fn to_atom(self) -> Option { match self.get_tag() { - HeapCellValueTag::Atom => { - Some(AtomCell::from_bytes(self.into_bytes()).get_name()) - } + HeapCellValueTag::Atom => Some(AtomCell::from_bytes(self.into_bytes()).get_name()), _ => None, } } @@ -773,7 +770,8 @@ impl Sub for HeapCellValue { HeapCellValue::build_with(tag, self.get_value() + rhs.unsigned_abs()) } tag @ HeapCellValueTag::PStrLoc => { - let value = self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize); + let value = + self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize); HeapCellValue::build_with(tag, value as u64) } _ => self, diff --git a/src/variable_records.rs b/src/variable_records.rs index a2b98918..a22e5be1 100644 --- a/src/variable_records.rs +++ b/src/variable_records.rs @@ -1,5 +1,5 @@ -use crate::parser::ast::*; use crate::forms::GenContext; +use crate::parser::ast::*; use bit_set::*; use fxhash::FxBuildHasher; @@ -88,7 +88,10 @@ pub enum VarAlloc { safety: VarSafetyStatus, to_perm_var_num: Option, }, - Perm { reg: usize, allocation: PermVarAllocation }, // stack offset, allocation info + Perm { + reg: usize, + allocation: PermVarAllocation, + }, // stack offset, allocation info } impl VarAlloc { @@ -152,7 +155,10 @@ pub struct VariableRecord { impl Default for VariableRecord { fn default() -> Self { VariableRecord { - allocation: VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending }, + allocation: VarAlloc::Perm { + reg: 0, + allocation: PermVarAllocation::Pending, + }, num_occurrences: 0, running_count: 0, }