]> Repositorios git - scryer-prolog.git/commitdiff
remove pstr_vec
authorMark Thom <[email protected]>
Sat, 7 Dec 2024 05:47:36 +0000 (21:47 -0800)
committerMark Thom <[email protected]>
Wed, 23 Apr 2025 06:32:32 +0000 (23:32 -0700)
41 files changed:
build/static_string_indexing.rs
src/arithmetic.rs
src/atom_table.rs
src/codegen.rs
src/debray_allocator.rs
src/forms.rs
src/functor_macro.rs
src/heap_iter.rs
src/heap_print.rs
src/indexing.rs
src/iterators.rs
src/lib/builtins.pl
src/machine/arithmetic_ops.rs
src/machine/attributed_variables.pl
src/machine/attributed_variables.rs
src/machine/compile.rs
src/machine/copier.rs
src/machine/cycle_detection.rs
src/machine/disjuncts.rs
src/machine/dispatch.rs
src/machine/gc.rs
src/machine/heap.rs
src/machine/lib_machine/mod.rs
src/machine/loader.rs
src/machine/machine_errors.rs
src/machine/machine_state.rs
src/machine/machine_state_impl.rs
src/machine/mock_wam.rs
src/machine/mod.rs
src/machine/partial_string.rs
src/machine/preprocessor.rs
src/machine/system_calls.rs
src/machine/term_stream.rs
src/machine/unify.rs
src/macros.rs
src/parser/ast.rs
src/parser/lexer.rs
src/parser/parser.rs
src/read.rs
src/types.rs
src/variable_records.rs

index 62e06f46c4acf33f20d345639742ed644603af26..5135ab771bcbc09a78dcbf90effed8a4e94922c4 100644 (file)
@@ -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<u64> = visitor.static_strs.iter().map(|string| {
-        let index = static_string_index(string, static_strs.len());
+    let indices: Vec<u64> = 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] = [
index 8cb11743c0ab33d2d7e2a072b1a34ccc28520ee1..dc03c8db8a66f7e5787a4e8ffbe4c704f62d53df 100644 (file)
@@ -479,7 +479,6 @@ impl Div<Number> for Number {
     }
 }
 
-
 impl PartialEq for Number {
     fn eq(&self, rhs: &Self) -> bool {
         match (self, rhs) {
@@ -563,7 +562,6 @@ impl PartialOrd for Number {
     }
 }
 
-
 impl Ord for Number {
     fn cmp(&self, rhs: &Number) -> Ordering {
         match (self, rhs) {
index 7c23349d3adafd73e0210681c0468780c27acf47..67aaa966c785c292c6510c982c1bbc7c0372ee91 100644 (file)
@@ -66,7 +66,7 @@ impl AtomCell {
         debug_assert!(string.len() <= INLINED_ATOM_MAX_LEN);
 
         let mut string_buf: [u8; 8] = [0u8; 8];
-        string_buf[.. string.len()].copy_from_slice(string.as_bytes());
+        string_buf[..string.len()].copy_from_slice(string.as_bytes());
         let encoding = u64::from_le_bytes(string_buf);
 
         AtomCell::new()
@@ -80,7 +80,7 @@ impl AtomCell {
 
     #[inline]
     pub fn new_char_inlined(c: char) -> Self {
-        let mut char_buf = [0u8;8];
+        let mut char_buf = [0u8; 8];
         c.encode_utf8(&mut char_buf);
 
         let encoding = u64::from_le_bytes(char_buf);
@@ -109,7 +109,9 @@ impl AtomCell {
 
     #[inline]
     pub fn get_name(self) -> Atom {
-        Atom { index: (self.name() << 1) | self.is_inlined() as u64 }
+        Atom {
+            index: (self.name() << 1) | self.is_inlined() as u64,
+        }
     }
 
     #[inline]
@@ -216,21 +218,22 @@ impl Hash for Atom {
 
 pub enum AtomString<'a> {
     Static(&'a str),
-    Inlined([u8;8]),
+    Inlined([u8; 8]),
     Dynamic(AtomTableRef<str>),
 }
 
-fn inlined_to_str<'a>(bytes: &'a [u8;8]) -> &'a str {
+fn inlined_to_str<'a>(bytes: &'a [u8; 8]) -> &'a str {
     // allow the '\0\' atom to be represented as the 0-valued inlined atom
     let slice_len = if bytes[0] == 0 {
         1
     } else {
-        bytes.iter().position(|&b| b == 0u8).unwrap_or(INLINED_ATOM_MAX_LEN)
+        bytes
+            .iter()
+            .position(|&b| b == 0u8)
+            .unwrap_or(INLINED_ATOM_MAX_LEN)
     };
 
-    unsafe {
-        str::from_utf8_unchecked(&bytes[..slice_len])
-    }
+    unsafe { str::from_utf8_unchecked(&bytes[..slice_len]) }
 }
 
 impl std::fmt::Debug for AtomString<'_> {
index 4b27e4487862f1048544798d1f238a14c5fe9443..3118d6491c975480997af856a1d6b87042f7a5fb 100644 (file)
@@ -295,8 +295,10 @@ impl DebrayAllocator {
                     self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
                     temp_v!(arg)
                 } else {
-                    if let VarAlloc::Perm { allocation: PermVarAllocation::Pending, .. } =
-                        &self.var_data.records[var_num].allocation
+                    if let VarAlloc::Perm {
+                        allocation: PermVarAllocation::Pending,
+                        ..
+                    } = &self.var_data.records[var_num].allocation
                     {
                         self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
                     } else {
@@ -337,22 +339,16 @@ impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator {
 fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
     index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
     heap: &Heap,
-    arity: usize,
     heap_loc: usize,
 ) -> Option<Instruction> {
-    match fetch_index_ptr(heap, arity, heap_loc) {
-        Some(index_ptr) => {
+    if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
+        let subterm = HeapCellValue::from(*index_ptr);
+        return Some(Target::constant_subterm(subterm));
+    } else if !heap[heap_loc.saturating_sub(1)].get_mark_bit() {
+        if let Some(index_ptr) = fetch_index_ptr(heap, heap_loc) {
             let subterm = HeapCellValue::from(index_ptr);
             return Some(Target::constant_subterm(subterm));
         }
-        None => {
-            // if Level::Shallow == lvl {
-                if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
-                    let subterm = HeapCellValue::from(*index_ptr);
-                    return Some(Target::constant_subterm(subterm));
-                }
-            // }
-        }
     }
 
     None
@@ -495,23 +491,28 @@ impl CodeGenerator {
                     let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
 
                     if arity == 0 {
-                        if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, arity, heap_loc) {
+                        if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, heap_loc) {
                             let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
-                            target.push_back(Target::to_structure(lvl, name, 0, r));
                             target.push_back(instr);
+                            target.push_back(Target::to_structure(lvl, name, 0, r));
                         } else if lvl == Level::Shallow {
                             let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
                             target.push_back(Target::to_constant(lvl, atom_as_cell!(name), r));
                         }
                     } else {
                         let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
-                        target.push_back(Target::to_structure(lvl, name, arity, r));
 
                         <CodeGenerator as AddToFreeList<'a, Target>>::add_term_to_free_list(
                             self,
                             r,
                         );
 
+                        if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, heap_loc) {
+                            target.push_back(instr);
+                        }
+
+                        target.push_back(Target::to_structure(lvl, name, arity, r));
+
                         let free_list_regs: Vec<_> = (heap_loc + 1 ..= heap_loc + arity)
                             .map(|subterm_loc| {
                                 let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc);
@@ -522,10 +523,6 @@ impl CodeGenerator {
                             })
                             .collect();
 
-                        if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, arity, heap_loc) {
-                            target.push_back(instr);
-                        }
-
                         for r_opt in free_list_regs {
                             if let Some(r) = r_opt {
                                 <CodeGenerator as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
@@ -583,11 +580,11 @@ impl CodeGenerator {
                     let heap_loc = iter.focus().value() as usize;
                     let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
                     let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
-                    let (pstr_str, tail_loc) = iter.scan_slice_to_str(pstr_loc);
+                    let HeapStringScan { string, tail_idx } = iter.scan_slice_to_str(pstr_loc);
 
-                    target.push_back(Target::to_pstr(lvl, Rc::new(pstr_str.to_owned()), r));
+                    target.push_back(Target::to_pstr(lvl, Rc::new(string.to_owned()), r));
 
-                    let (tail_loc, tail) = subterm_index(iter.deref(), tail_loc);
+                    let (tail_loc, tail) = subterm_index(iter.deref(), tail_idx);
                     self.subterm_to_instr::<Target>(
                         tail, tail_loc, context, index_ptrs, &mut target,
                     );
@@ -676,12 +673,11 @@ impl CodeGenerator {
             &InlinedClauseType::CompareNumber(mut cmp) => {
                 self.marker.reset_arg(2);
 
-                let (mut lcode, at_1) =
-                    if let Some(r) = variable_marker(&mut self.marker) {
-                        (CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
-                    } else {
-                        self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
-                    };
+                let (mut lcode, at_1) = if let Some(r) = variable_marker(&mut self.marker) {
+                    (CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
+                } else {
+                    self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
+                };
 
                 let (mut rcode, at_2) =
                     self.compile_arith_expr(terms, first_arg_loc + 1, 2, context, 2)?;
@@ -720,41 +716,41 @@ impl CodeGenerator {
                 if let Some(r) = variable_marker(&mut self.marker) {
                     instr!("atomic", r)
                 } else {
-                   read_heap_cell!(first_arg,
-                       (HeapCellValueTag::Fixnum |
-                        HeapCellValueTag::F64) => {
-                           instr!("$succeed")
-                       }
-                       (HeapCellValueTag::Cons, cons_ptr) => {
-                           match cons_ptr.get_tag() {
-                               ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
-                                   instr!("$succeed")
-                               }
-                               _ => {
-                                   instr!("$fail")
-                               }
-                           }
-                       }
-                       (HeapCellValueTag::Atom, (_name, arity)) => {
-                           if arity == 0 {
-                               instr!("$succeed")
-                           } else {
-                               instr!("$fail")
-                           }
-                       }
-                       (HeapCellValueTag::Lis
-                        | HeapCellValueTag::Str
-                        | HeapCellValueTag::PStrLoc) => {
-                           instr!("$fail")
-                       }
-                       _ => {
-                           if first_arg.is_constant() {
-                               instr!("$succeed")
-                           } else {
-                               instr!("$fail")
-                           }
-                       }
-                   )
+                    read_heap_cell!(first_arg,
+                        (HeapCellValueTag::Fixnum |
+                         HeapCellValueTag::F64) => {
+                            instr!("$succeed")
+                        }
+                        (HeapCellValueTag::Cons, cons_ptr) => {
+                            match cons_ptr.get_tag() {
+                                ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
+                                    instr!("$succeed")
+                                }
+                                _ => {
+                                    instr!("$fail")
+                                }
+                            }
+                        }
+                        (HeapCellValueTag::Atom, (_name, arity)) => {
+                            if arity == 0 {
+                                instr!("$succeed")
+                            } else {
+                                instr!("$fail")
+                            }
+                        }
+                        (HeapCellValueTag::Lis
+                         | HeapCellValueTag::Str
+                         | HeapCellValueTag::PStrLoc) => {
+                            instr!("$fail")
+                        }
+                        _ => {
+                            if first_arg.is_constant() {
+                                instr!("$succeed")
+                            } else {
+                                instr!("$fail")
+                            }
+                        }
+                    )
                 }
             }
             InlinedClauseType::IsCompound(..) => {
@@ -860,7 +856,7 @@ impl CodeGenerator {
                         }
                     }
                 }
-            },
+            }
             InlinedClauseType::IsVar(..) => {
                 self.marker.reset_arg(1);
 
@@ -871,7 +867,7 @@ impl CodeGenerator {
                 } else {
                     instr!("$fail")
                 }
-            },
+            }
         };
 
         // inlined predicates are never counted, so this overrides nothing.
@@ -901,8 +897,7 @@ impl CodeGenerator {
     ) -> Result<(), CompilationError> {
         macro_rules! compile_expr {
             ($self:expr, $terms:expr, $context:expr, $code:expr) => {{
-                let (acode, at) =
-                    $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
+                let (acode, at) = $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
                 $code.extend(acode.into_iter());
                 at
             }};
@@ -1067,13 +1062,11 @@ impl CodeGenerator {
                                     code.push_back(instr!("deallocate"));
                                 }
 
-                                code.push_back(
-                                    if self.marker.in_tail_position {
-                                        instr!("$succeed").into_execute()
-                                    } else {
-                                        instr!("$succeed")
-                                    },
-                                );
+                                code.push_back(if self.marker.in_tail_position {
+                                    instr!("$succeed").into_execute()
+                                } else {
+                                    instr!("$succeed")
+                                });
                             }
                             QueryTerm::Clause(clause) => {
                                 self.compile_query_line(
@@ -1145,7 +1138,10 @@ impl CodeGenerator {
 
         self.marker.var_data = var_data;
 
-        let term = FocusedHeapRefMut { heap, focus: *term_loc };
+        let term = FocusedHeapRefMut {
+            heap,
+            focus: *term_loc,
+        };
         let mut code = VecDeque::new();
 
         let head_loc = term.nth_arg(term.focus, 1).unwrap();
@@ -1216,11 +1212,7 @@ impl CodeGenerator {
         let mut stack = Stack::uninitialized();
         let iter = query_iterator::<true>(&mut term.heap, &mut stack, clause.term_loc());
 
-        let query = self.compile_target::<QueryInstruction, _>(
-            iter,
-            &clause.code_indices,
-            context,
-        );
+        let query = self.compile_target::<QueryInstruction, _>(iter, &clause.code_indices, context);
 
         code.extend(query);
         self.add_call(code, clause.ct.to_instr(), clause.call_policy);
@@ -1342,20 +1334,14 @@ impl CodeGenerator {
                 skip_stub_try_me_else = !self.settings.is_dynamic();
             }
 
-            let arg = clause.args(heap)
-                .map(|r| heap[r.start() + optimal_index]);
+            let arg = clause.args(heap).map(|r| heap[r.start() + optimal_index]);
 
             if let Some(arg) = arg {
                 let index = code.len();
 
                 if clauses_len > 1 || self.settings.is_extensible {
                     let arg = heap_bound_store(heap, heap_bound_deref(heap, arg));
-                    code_offsets.index_term(
-                        heap,
-                        arg,
-                        index,
-                        &mut clause_index_info,
-                    );
+                    code_offsets.index_term(heap, arg, index, &mut clause_index_info);
                 }
             }
 
index d1d01aa8ae95aab876e59339c998718785276168..7c86bb881ba13bb957fa5493519f6e359a3fad96 100644 (file)
@@ -172,7 +172,9 @@ impl DebrayAllocator {
 
         for var_num in subsumed_hits {
             match &mut self.var_data.records[var_num].allocation {
-                VarAlloc::Perm { ref mut allocation, .. } => {
+                VarAlloc::Perm {
+                    ref mut allocation, ..
+                } => {
                     if let PermVarAllocation::Done {
                         shallow_safety,
                         deep_safety,
@@ -233,7 +235,7 @@ impl DebrayAllocator {
             let num_occurrences = self.var_data.records[var_num].num_occurrences;
 
             match &mut self.var_data.records[var_num].allocation {
-                VarAlloc::Perm { allocation, ..} => {
+                VarAlloc::Perm { allocation, .. } => {
                     let shallow_safety = VarSafetyStatus::needed_if(
                         shallow_safety.contains(var_num),
                         branch_designator,
@@ -514,10 +516,12 @@ impl DebrayAllocator {
                 self.perm_free_list.pop_front();
 
                 match &mut self.var_data.records[var_num].allocation {
-                    VarAlloc::Perm { reg: p, allocation: PermVarAllocation::Pending }
-                      if *p > 0 => {
-                          return Some(std::mem::replace(p, 0));
-                      }
+                    VarAlloc::Perm {
+                        reg: p,
+                        allocation: PermVarAllocation::Pending,
+                    } if *p > 0 => {
+                        return Some(std::mem::replace(p, 0));
+                    }
                     _ => {}
                 }
             } else {
@@ -543,11 +547,12 @@ impl DebrayAllocator {
 
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm {
-                allocation: PermVarAllocation::Done {
-                    deep_safety,
-                    shallow_safety,
-                    ..
-                },
+                allocation:
+                    PermVarAllocation::Done {
+                        deep_safety,
+                        shallow_safety,
+                        ..
+                    },
                 ..
             } => {
                 *deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -568,11 +573,12 @@ impl DebrayAllocator {
 
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm {
-                allocation: PermVarAllocation::Done {
-                    deep_safety,
-                    shallow_safety,
-                    ..
-                },
+                allocation:
+                    PermVarAllocation::Done {
+                        deep_safety,
+                        shallow_safety,
+                        ..
+                    },
                 ..
             } => {
                 // GetVariable in head chunk is considered safe.
@@ -612,10 +618,11 @@ impl DebrayAllocator {
 
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm {
-                allocation: PermVarAllocation::Done {
-                    ref mut shallow_safety,
-                    ..
-                },
+                allocation:
+                    PermVarAllocation::Done {
+                        ref mut shallow_safety,
+                        ..
+                    },
                 ..
             } => {
                 if !self.in_tail_position
@@ -648,10 +655,11 @@ impl DebrayAllocator {
 
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm {
-                allocation: PermVarAllocation::Done {
-                    ref mut deep_safety,
-                    ..
-                },
+                allocation:
+                    PermVarAllocation::Done {
+                        ref mut deep_safety,
+                        ..
+                    },
                 ..
             } => {
                 if self
@@ -921,10 +929,7 @@ impl Allocator for DebrayAllocator {
     }
 
     fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) {
-        let head_cell = heap_bound_store(
-            heap,
-            heap_bound_deref(heap, heap_loc_as_cell!(head_loc)),
-        );
+        let head_cell = heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(head_loc)));
 
         read_heap_cell!(head_cell,
             (HeapCellValueTag::Str, s) => {
@@ -933,7 +938,9 @@ impl Allocator for DebrayAllocator {
                 self.reset_arg(arity);
                 self.arity = arity;
 
-                for (idx, arg) in heap.splice(s+1 ..= s+arity).enumerate() {
+                for (c_idx, heap_idx) in (s+1 ..= s+arity).enumerate() {
+                    let arg = heap[heap_idx];
+
                     if arg.is_var() {
                         let var = heap_bound_store(
                             heap,
@@ -953,11 +960,11 @@ impl Allocator for DebrayAllocator {
                                 let r = self.get_var_binding(var_num);
 
                                 if !r.is_perm() && r.reg_num() == 0 {
-                                    self.in_use.insert(idx + 1);
-                                    self.shallow_temp_mappings.insert(idx + 1, var_num);
+                                    self.in_use.insert(c_idx + 1);
+                                    self.shallow_temp_mappings.insert(c_idx + 1, var_num);
                                     self.var_data.records[var_num]
                                         .allocation
-                                        .set_register(idx + 1);
+                                        .set_register(c_idx + 1);
                                 }
                             }
                             VarPtr::Anon => {}
index 4053b5a9a349664fdb32a46de0a987da4c2eff0f..6e9608df1e5cfda5110a264b0347f5c406cb24af 100644 (file)
@@ -1,7 +1,7 @@
 use crate::arena::*;
 use crate::atom_table::*;
-use crate::instructions::*;
 use crate::functor_macro::*;
+use crate::instructions::*;
 use crate::machine::disjuncts::VarData;
 use crate::machine::heap::*;
 // use crate::machine::loader::PredicateQueue;
@@ -80,8 +80,8 @@ impl GenContext {
     #[inline]
     pub fn chunk_type(&self) -> ChunkType {
         match self {
-            GenContext::Head    => ChunkType::Head,
-            GenContext::Mid(_)  => ChunkType::Mid,
+            GenContext::Head => ChunkType::Head,
+            GenContext::Mid(_) => ChunkType::Mid,
             GenContext::Last(_) => ChunkType::Last,
         }
     }
@@ -118,7 +118,10 @@ impl ChunkType {
 #[derive(Debug)]
 pub enum ChunkedTerms {
     Branch(Vec<VecDeque<ChunkedTerms>>),
-    Chunk { chunk_num: usize, terms: VecDeque<QueryTerm> },
+    Chunk {
+        chunk_num: usize,
+        terms: VecDeque<QueryTerm>,
+    },
 }
 
 #[derive(Debug)]
@@ -190,7 +193,8 @@ impl ChunkedTermVec {
     }
 
     pub fn current_gen_context(&self) -> GenContext {
-        self.current_chunk_type.to_gen_context(self.current_chunk_num)
+        self.current_chunk_type
+            .to_gen_context(self.current_chunk_num)
     }
 
     pub fn push_chunk_term(&mut self, term: QueryTerm) {
@@ -290,9 +294,7 @@ pub fn clause_predicate_key(heap: &impl SizedHeap, term_loc: usize) -> Option<Pr
     let key_opt = term_predicate_key(heap, term_loc);
 
     if Some((atom!(":-"), 2)) == key_opt {
-        term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| {
-            term_predicate_key(heap, arg_loc)
-        })
+        term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| term_predicate_key(heap, arg_loc))
     } else {
         key_opt
     }
index 081a4417358efbc1b75306aba3bd7cb5e1caa435..ee419136d51d92c04dac81d140b44429eb8e5c39 100644 (file)
@@ -1,3 +1,6 @@
+//! A macro to construct functor terms ready to be written to the WAM
+//! heap.
+
 use crate::atom_table::*;
 use crate::instructions::IndexingCodePtr;
 use crate::machine::heap::Heap;
@@ -5,7 +8,7 @@ use crate::parser::ast::Fixnum;
 use crate::types::*;
 
 #[derive(Debug, Clone, PartialEq, Eq)]
-pub enum FunctorElement {
+pub(crate) enum FunctorElement {
     AbsoluteCell(HeapCellValue),
     Cell(HeapCellValue),
     InnerFunctor(u64, Vec<FunctorElement>),
@@ -190,19 +193,19 @@ pub(crate) fn variadic_functor(
     let num_items = key_value_pairs.len();
 
     for (idx, _) in key_value_pairs.iter().enumerate() {
-        arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(2 + num_items * 2 + idx)));
+        arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(
+            2 + num_items * 2 + idx
+        )));
         arg_vec.push(FunctorElement::Cell(list_loc_as_cell!(5 + idx)));
     }
 
     arg_vec.pop();
     arg_vec.push(FunctorElement::Cell(empty_list_as_cell!()));
 
-    arg_vec.extend(key_value_pairs
-        .into_iter()
-        .map(|kv_func| {
-            let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
-            FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
-        }));
+    arg_vec.extend(key_value_pairs.into_iter().map(|kv_func| {
+        let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
+        FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
+    }));
 
     arg_vec
 }
@@ -211,13 +214,15 @@ pub(crate) fn variadic_functor(
 #[allow(unused_parens)]
 mod tests {
     use super::*;
-    use FunctorElement::*;
     use std::string::String;
+    use FunctorElement::*;
 
     #[test]
     fn basic_terms() {
-        let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
-                                                char_as_cell('c')]);
+        let functor = functor!(
+            atom!("first"),
+            [atom_as_cell((atom!("a"))), char_as_cell('c')]
+        );
 
         assert_eq!(functor.len(), 3);
 
@@ -225,10 +230,14 @@ mod tests {
         assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
         assert_eq!(functor[2], Cell(char_as_cell!('c')));
 
-        let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
-                                                 functor((atom!("b")), [fixnum(1),
-                                                                        fixnum(2)]),
-                                                 char_as_cell('c')]);
+        let functor = functor!(
+            atom!("second"),
+            [
+                atom_as_cell((atom!("a"))),
+                functor((atom!("b")), [fixnum(1), fixnum(2)]),
+                char_as_cell('c')
+            ]
+        );
 
         assert_eq!(functor.len(), 5);
 
@@ -236,13 +245,20 @@ mod tests {
         assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
         assert_eq!(functor[2], Cell(str_loc_as_cell!(4)));
         assert_eq!(functor[3], Cell(char_as_cell!('c')));
-        assert_eq!(functor[4], InnerFunctor(3, functor!(atom!("b"), [fixnum(1),
-                                                                     fixnum(2)])));
+        assert_eq!(
+            functor[4],
+            InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
+        );
 
-        let functor = functor!(atom!("third"), [atom_as_cell((atom!("a"))),
-                                                functor((atom!("b")), [fixnum(1), fixnum(2)]),
-                                                functor((atom!("c")), [fixnum(1), fixnum(2)]),
-                                   char_as_cell('c')]);
+        let functor = functor!(
+            atom!("third"),
+            [
+                atom_as_cell((atom!("a"))),
+                functor((atom!("b")), [fixnum(1), fixnum(2)]),
+                functor((atom!("c")), [fixnum(1), fixnum(2)]),
+                char_as_cell('c')
+            ]
+        );
 
         assert_eq!(functor.len(), 7);
 
@@ -251,14 +267,25 @@ mod tests {
         assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
         assert_eq!(functor[3], Cell(str_loc_as_cell!(8)));
         assert_eq!(functor[4], Cell(char_as_cell!('c')));
-        assert_eq!(functor[5], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
-        assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)])));
+        assert_eq!(
+            functor[5],
+            InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
+        );
+        assert_eq!(
+            functor[6],
+            InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)]))
+        );
 
-        let functor = functor!(atom!("fourth"), [atom_as_cell((atom!("a"))),
-                                                 functor((atom!("b")), [fixnum(1), fixnum(2)]),
-                                                 functor((atom!("c")), [fixnum(1)]),
-                                                 functor((atom!("d")), [fixnum(453), fixnum(2)]),
-                                                 char_as_cell('c')]);
+        let functor = functor!(
+            atom!("fourth"),
+            [
+                atom_as_cell((atom!("a"))),
+                functor((atom!("b")), [fixnum(1), fixnum(2)]),
+                functor((atom!("c")), [fixnum(1)]),
+                functor((atom!("d")), [fixnum(453), fixnum(2)]),
+                char_as_cell('c')
+            ]
+        );
 
         assert_eq!(functor.len(), 9);
 
@@ -268,14 +295,26 @@ mod tests {
         assert_eq!(functor[3], Cell(str_loc_as_cell!(9)));
         assert_eq!(functor[4], Cell(str_loc_as_cell!(11)));
         assert_eq!(functor[5], Cell(char_as_cell!('c')));
-        assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
-        assert_eq!(functor[7], InnerFunctor(2, functor!(atom!("c"), [fixnum(1)])));
-        assert_eq!(functor[8], InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)])));
+        assert_eq!(
+            functor[6],
+            InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
+        );
+        assert_eq!(
+            functor[7],
+            InnerFunctor(2, functor!(atom!("c"), [fixnum(1)]))
+        );
+        assert_eq!(
+            functor[8],
+            InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)]))
+        );
     }
 
     #[test]
     fn basic_terms_in_heap() {
-        let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), char_as_cell('b')]);
+        let functor = functor!(
+            atom!("first"),
+            [atom_as_cell((atom!("a"))), char_as_cell('b')]
+        );
 
         assert_eq!(functor.len(), 3);
 
@@ -291,10 +330,15 @@ mod tests {
 
         heap.truncate(2);
 
-        let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
-                                                 functor((atom!("b")), [fixnum(1), fixnum(2)]),
-                                                 functor((atom!("c")), [fixnum(1), fixnum(2)]),
-                                                 char_as_cell('b')]);
+        let functor = functor!(
+            atom!("second"),
+            [
+                atom_as_cell((atom!("a"))),
+                functor((atom!("b")), [fixnum(1), fixnum(2)]),
+                functor((atom!("c")), [fixnum(1), fixnum(2)]),
+                char_as_cell('b')
+            ]
+        );
 
         assert_eq!(functor.len(), 7);
 
@@ -318,14 +362,24 @@ mod tests {
 
     #[test]
     fn nested_functors() {
-        let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
-                                                functor((atom!("d")), [fixnum(1),
-                                                                      functor((atom!("b")),
-                                                                              [atom_as_cell((atom!("c"))),
-                                                                               char_as_cell('c')])]),
-                                                        functor((atom!("e")), [fixnum(453),
-                                                                               fixnum(2)]),
-                                                        char_as_cell('b')]);
+        let functor = functor!(
+            atom!("first"),
+            [
+                atom_as_cell((atom!("a"))),
+                functor(
+                    (atom!("d")),
+                    [
+                        fixnum(1),
+                        functor(
+                            (atom!("b")),
+                            [atom_as_cell((atom!("c"))), char_as_cell('c')]
+                        )
+                    ]
+                ),
+                functor((atom!("e")), [fixnum(453), fixnum(2)]),
+                char_as_cell('b')
+            ]
+        );
 
         assert_eq!(functor.len(), 7);
 
@@ -334,24 +388,47 @@ mod tests {
         assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
         assert_eq!(functor[3], Cell(str_loc_as_cell!(11)));
         assert_eq!(functor[4], Cell(char_as_cell!('b')));
-        assert_eq!(functor[5], InnerFunctor(6, vec![Cell(atom_as_cell!(atom!("d"), 2)),
-                                                    Cell(fixnum_as_cell!(Fixnum::build_with(1))),
-                                                    Cell(str_loc_as_cell!(3)),
-                                                    InnerFunctor(3, functor!(atom!("b"), [atom_as_cell((atom!("c"))),
-                                                                                          char_as_cell('c')]))]));
-        assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("e"), [fixnum(453),
-                                                                     fixnum(2)])));
+        assert_eq!(
+            functor[5],
+            InnerFunctor(
+                6,
+                vec![
+                    Cell(atom_as_cell!(atom!("d"), 2)),
+                    Cell(fixnum_as_cell!(Fixnum::build_with(1))),
+                    Cell(str_loc_as_cell!(3)),
+                    InnerFunctor(
+                        3,
+                        functor!(atom!("b"), [atom_as_cell((atom!("c"))), char_as_cell('c')])
+                    )
+                ]
+            )
+        );
+        assert_eq!(
+            functor[6],
+            InnerFunctor(3, functor!(atom!("e"), [fixnum(453), fixnum(2)]))
+        );
     }
 
-
     #[test]
     fn nested_functors_in_heap() {
-        let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
-                                                functor((atom!("second")), [fixnum(1),
-                                                                            functor((atom!("third")), [atom_as_cell((atom!("b"))),
-                                                                                                       char_as_cell('c')])]),
-                                                functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
-                                                char_as_cell('b')]);
+        let functor = functor!(
+            atom!("first"),
+            [
+                atom_as_cell((atom!("a"))),
+                functor(
+                    (atom!("second")),
+                    [
+                        fixnum(1),
+                        functor(
+                            (atom!("third")),
+                            [atom_as_cell((atom!("b"))), char_as_cell('c')]
+                        )
+                    ]
+                ),
+                functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
+                char_as_cell('b')
+            ]
+        );
 
         let mut heap = Heap::new();
         let mut functor_writer = Heap::functor_writer(functor);
@@ -392,33 +469,43 @@ mod tests {
 
         assert_eq!(heap[0], atom_as_cell!(atom!("first"), 1));
         assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
-        assert_eq!(heap.slice_to_str(heap_index!(2), "a string".len()), "a string");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(2), "a string".len()),
+            "a string"
+        );
         assert_eq!(heap[4], empty_list_as_cell!());
 
         heap.truncate(0);
 
-        let functor = functor!(atom!("second"), [string((String::from("a stuttered\0 string")))]);
+        let functor = functor!(
+            atom!("second"),
+            [string((String::from("a stuttered\0 string")))]
+        );
 
         let mut functor_writer = Heap::functor_writer(functor);
         functor_writer(&mut heap).unwrap();
 
-        assert_eq!(heap.cell_len(), 7);
+        assert_eq!(heap.cell_len(), 8);
 
         assert_eq!(heap[0], atom_as_cell!(atom!("second"), 1));
         assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
-        assert_eq!(heap.slice_to_str(heap_index!(2), "a stuttered".len()), "a stuttered");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(2), "a stuttered".len()),
+            "a stuttered"
+        );
         assert_eq!(heap[4], pstr_loc_as_cell!(heap_index!(5)));
-        assert_eq!(heap.slice_to_str(heap_index!(5), " string".len()), " string");
-        assert_eq!(heap[6], empty_list_as_cell!());
+        assert_eq!(
+            heap.slice_to_str(heap_index!(5), " string".len()),
+            " string"
+        );
+        assert_eq!(heap[7], empty_list_as_cell!());
     }
 
     #[test]
     fn functors_with_lists_in_heap() {
         let functor = functor!(
             atom!("first"),
-            [list([fixnum(1),
-                   atom_as_cell((atom!("a"))),
-                   fixnum(2)])]
+            [list([fixnum(1), atom_as_cell((atom!("a"))), fixnum(2)])]
         );
 
         assert_eq!(functor.len(), 3);
@@ -462,8 +549,10 @@ mod tests {
         let code_ptr = IndexingCodePtr::Internal(0);
         let functor = functor!(
             atom!("first"),
-            [string((String::from("a string"))),
-             indexing_code_ptr(code_ptr)]
+            [
+                string((String::from("a string"))),
+                indexing_code_ptr(code_ptr)
+            ]
         );
 
         let mut heap = Heap::new();
@@ -476,18 +565,30 @@ mod tests {
         assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2));
         assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
         assert_eq!(heap[2], str_loc_as_cell!(6));
-        assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(3), "a string".len()),
+            "a string"
+        );
         assert_eq!(heap[5], empty_list_as_cell!());
         assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1));
         assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0)));
 
         heap.truncate(0);
 
-        let functor = functor!(atom!("second"),
-                               [string((String::from("a string"))),
-                                functor((atom!("third")), [atom_as_cell((atom!("a"))),
-                                                           string((String::from("another string"))),
-                                                           indexing_code_ptr(code_ptr)])]);
+        let functor = functor!(
+            atom!("second"),
+            [
+                string((String::from("a string"))),
+                functor(
+                    (atom!("third")),
+                    [
+                        atom_as_cell((atom!("a"))),
+                        string((String::from("another string"))),
+                        indexing_code_ptr(code_ptr)
+                    ]
+                )
+            ]
+        );
 
         let mut functor_writer = Heap::functor_writer(functor);
         functor_writer(&mut heap).unwrap();
@@ -497,24 +598,43 @@ mod tests {
         assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2));
         assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
         assert_eq!(heap[2], str_loc_as_cell!(6));
-        assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(3), "a string".len()),
+            "a string"
+        );
         assert_eq!(heap[5], empty_list_as_cell!());
         assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3));
         assert_eq!(heap[7], atom_as_cell!(atom!("a")));
         assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10)));
         assert_eq!(heap[9], str_loc_as_cell!(13));
-        assert_eq!(heap.slice_to_str(heap_index!(10), "another string".len()), "another string");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(10), "another string".len()),
+            "another string"
+        );
         assert_eq!(heap[12], empty_list_as_cell!());
         assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1));
         assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0)));
 
-        let functor = functor!(atom!("fourth"),
-                               [string((String::from("a string"))),
-                                functor((atom!("a")),
-                                        [functor((atom!("fifth")), [fixnum(5),
-                                                                    string((String::from("another string"))),
-                                                                    indexing_code_ptr(code_ptr)]),
-                                         string((String::from("and another")))])]);
+        let functor = functor!(
+            atom!("fourth"),
+            [
+                string((String::from("a string"))),
+                functor(
+                    (atom!("a")),
+                    [
+                        functor(
+                            (atom!("fifth")),
+                            [
+                                fixnum(5),
+                                string((String::from("another string"))),
+                                indexing_code_ptr(code_ptr)
+                            ]
+                        ),
+                        string((String::from("and another")))
+                    ]
+                )
+            ]
+        );
 
         heap.truncate(0);
 
@@ -526,7 +646,10 @@ mod tests {
         assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2));
         assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
         assert_eq!(heap[2], str_loc_as_cell!(6));
-        assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(3), "a string".len()),
+            "a string"
+        );
         assert_eq!(heap[5], empty_list_as_cell!());
         assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2));
         assert_eq!(heap[7], str_loc_as_cell!(9));
@@ -535,11 +658,17 @@ mod tests {
         assert_eq!(heap[10], fixnum_as_cell!(Fixnum::build_with(5)));
         assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13)));
         assert_eq!(heap[12], str_loc_as_cell!(16));
-        assert_eq!(heap.slice_to_str(heap_index!(13), "another string".len()), "another string");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(13), "another string".len()),
+            "another string"
+        );
         assert_eq!(heap[15], empty_list_as_cell!());
         assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1));
         assert_eq!(heap[17], fixnum_as_cell!(Fixnum::build_with(0)));
-        assert_eq!(heap.slice_to_str(heap_index!(18), "and another".len()), "and another");
+        assert_eq!(
+            heap.slice_to_str(heap_index!(18), "and another".len()),
+            "and another"
+        );
         assert_eq!(heap[20], empty_list_as_cell!());
     }
 
@@ -550,17 +679,16 @@ mod tests {
 
         let stub = functor!(
             atom!("existence_error"),
-            [atom_as_cell((atom!("procedure"))), functor((culprit.clone()))]
+            [
+                atom_as_cell((atom!("procedure"))),
+                functor((culprit.clone()))
+            ]
         );
 
         println!("{:?}", stub);
 
         // now the error form
-        let lineless_error_form = functor!(
-            atom!("error"),
-            [functor(stub),
-             functor(culprit)]
-        );
+        let lineless_error_form = functor!(atom!("error"), [functor(stub), functor(culprit)]);
 
         println!("{:?}", lineless_error_form);
 
index 62e02f9f2a7f04805189c24880a0ed8dae1a214e..fd9b1b0c419c8864516e94b58180ed1063cc9a1b 100644 (file)
@@ -116,10 +116,10 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> {
                     }
                 }
                 (HeapCellValueTag::PStrLoc, h) => {
-                    let (_, tail_loc) = self.heap.scan_slice_to_str(h);
+                    let tail_idx = self.heap.scan_slice_to_str(h).tail_idx;
 
-                    self.heap[tail_loc].set_mark_bit(self.mark_phase);
-                    self.iter_stack.push(self.heap[tail_loc]);
+                    self.heap[tail_idx].set_mark_bit(self.mark_phase);
+                    self.iter_stack.push(self.heap[tail_idx]);
                 }
                 _ => {
                 }
@@ -452,12 +452,12 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
                }
                (HeapCellValueTag::PStrLoc, vh) => {
                    let cell = *cell;
-                   let (_, tail_loc) = self.heap.scan_slice_to_str(vh);
+                   let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx;
 
                    // forward the current PStrLoc cell if the zero
                    // byte at the end of the string buffer
                    // is marked
-                   let buf_bytes = self.heap[tail_loc - 1].into_bytes();
+                   let buf_bytes = self.heap[tail_idx - 1].into_bytes();
 
                    if buf_bytes[7] != 0u8 {
                        let cell = self.read_cell_mut(h);
@@ -469,9 +469,9 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
                    // is never inspected, which it isn't.
 
                    self.push_if_unmarked(
-                       IterStackLoc::iterable_loc(tail_loc - 1, HeapOrStackTag::Heap),
+                       IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap),
                    );
-                   self.stack.push(IterStackLoc::mark_loc(tail_loc, HeapOrStackTag::Heap));
+                   self.stack.push(IterStackLoc::mark_loc(tail_idx, HeapOrStackTag::Heap));
 
                    return Some(cell);
                }
@@ -502,7 +502,6 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
     }
 }
 
-
 impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
     type Item = HeapCellValue;
 
@@ -707,9 +706,8 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom)]),
-        );
+            [atom_as_cell(a_atom), atom_as_cell(b_atom)]
+        ));
 
         let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
         wam.machine_st.heap.push_cell(cell).unwrap();
@@ -733,7 +731,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -758,10 +756,7 @@ mod tests {
                 unmark_cell_bits!(iter.next().unwrap()),
                 atom_as_cell!(f_atom, 4)
             );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                str_loc_as_cell!(0)
-            );
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
                 atom_as_cell!(a_atom)
@@ -778,7 +773,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -794,7 +789,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -837,7 +832,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         // now make the list cyclic.
         wam.machine_st.heap[4] = heap_loc_as_cell!(0);
@@ -939,8 +934,6 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
-
         wam.machine_st.heap.clear();
 
         let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -955,9 +948,11 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom),
-             atom_as_cell(b_atom)]
+            [
+                atom_as_cell(a_atom),
+                atom_as_cell(b_atom),
+                atom_as_cell(b_atom)
+            ]
         ));
 
         functor_writer(&mut wam.machine_st.heap).unwrap();
@@ -1003,7 +998,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         {
             let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
@@ -1044,7 +1039,7 @@ mod tests {
             // instance.
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
         assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
@@ -1074,7 +1069,7 @@ mod tests {
             // instance.
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
         assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
@@ -1126,7 +1121,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1147,7 +1142,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[0]),
@@ -1193,7 +1188,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[0]),
@@ -1427,7 +1422,10 @@ mod tests {
         wam.machine_st.heap.clear();
 
         {
-            wam.machine_st.heap.push_cell(fixnum_as_cell!(Fixnum::build_with(0))).unwrap();
+            wam.machine_st
+                .heap
+                .push_cell(fixnum_as_cell!(Fixnum::build_with(0)))
+                .unwrap();
 
             let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
@@ -1439,7 +1437,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1473,7 +1471,7 @@ mod tests {
             assert!(iter.next().is_none());
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1504,7 +1502,7 @@ mod tests {
             assert!(iter.next().is_none());
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1564,7 +1562,7 @@ mod tests {
             assert!(iter.next().is_none());
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(wam.machine_st.heap[0], str_loc_as_cell!(1));
         assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2));
@@ -1634,13 +1632,6 @@ mod tests {
         {
             let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 9);
 
-            /*
-            while let Some(_) = iter.next() {
-                print_heap_terms(iter.heap.iter(), 0);
-                println!("");
-            }
-            */
-
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
                 list_loc_as_cell!(7)
@@ -1693,9 +1684,8 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom)]),
-        );
+            [atom_as_cell(a_atom), atom_as_cell(b_atom)]
+        ));
 
         let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
         let h = wam.machine_st.heap.cell_len();
@@ -1924,7 +1914,7 @@ mod tests {
             );
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
         assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -2021,7 +2011,11 @@ mod tests {
 
         let functor = functor!(
             f_atom,
-            [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
+            [
+                atom_as_cell(a_atom),
+                atom_as_cell(b_atom),
+                atom_as_cell(b_atom)
+            ]
         );
 
         let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2098,7 +2092,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap[4] = list_loc_as_cell!(1);
 
@@ -2163,7 +2157,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -2202,7 +2196,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -2221,18 +2215,18 @@ mod tests {
                 2,
             );
 
-            assert_eq!(
-                iter.heap.slice_to_str(0, "a string".len()),
-                "a string"
-            );
-            assert_eq!(
-                iter.next().unwrap(),
-                empty_list_as_cell!()
-            );
+            assert_eq!(iter.heap.slice_to_str(0, "a string".len()), "a string");
+            assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        assert_eq!(wam.machine_st.heap.slice_to_str(0, "a string".len()), "a string");
+        assert_eq!(wam.machine_st.heap[1], HeapCellValue::build_with(HeapCellValueTag::Cons, 0));
+
+        for idx in 2 ..= 3 {
+            assert!(!wam.machine_st.heap[idx].get_mark_bit());
+            assert!(!wam.machine_st.heap[idx].get_forwarding_bit());
+        }
 
         wam.machine_st.heap.clear();
 
@@ -2291,9 +2285,8 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom)]),
-        );
+            [atom_as_cell(a_atom), atom_as_cell(b_atom)]
+        ));
 
         let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
         let h = wam.machine_st.heap.cell_len();
@@ -2325,7 +2318,6 @@ mod tests {
 
         wam.machine_st.heap.clear();
 
-
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
             [
@@ -2361,10 +2353,7 @@ mod tests {
                 unmark_cell_bits!(iter.next().unwrap()),
                 atom_as_cell!(a_atom)
             );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                str_loc_as_cell!(0)
-            );
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
                 atom_as_cell!(f_atom, 4)
@@ -2519,7 +2508,7 @@ mod tests {
             );
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
         assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -2616,7 +2605,11 @@ mod tests {
 
         let functor = functor!(
             f_atom,
-            [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
+            [
+                atom_as_cell(a_atom),
+                atom_as_cell(b_atom),
+                atom_as_cell(b_atom)
+            ]
         );
 
         let mut writer = wam.machine_st.heap.reserve(96).unwrap();
@@ -2694,7 +2687,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap[4] = list_loc_as_cell!(1);
 
@@ -2761,7 +2754,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
         wam.machine_st.heap.clear();
     }
 
@@ -2778,9 +2771,8 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom)]),
-        );
+            [atom_as_cell(a_atom), atom_as_cell(b_atom)]
+        ));
 
         let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
         wam.machine_st.heap.push_cell(cell).unwrap();
@@ -2969,7 +2961,7 @@ mod tests {
             );
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
         assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -3039,7 +3031,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
 
@@ -3053,11 +3045,18 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
-        let functor = functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]);
+        let functor = functor!(
+            f_atom,
+            [
+                atom_as_cell(a_atom),
+                atom_as_cell(b_atom),
+                atom_as_cell(b_atom)
+            ]
+        );
 
         let mut writer = wam.machine_st.heap.reserve(96).unwrap();
 
@@ -3116,7 +3115,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap[4] = list_loc_as_cell!(1);
 
@@ -3164,6 +3163,6 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
     }
 }
index 2bc1706b727089a2992c58ee14119a5fd554f965..cdd166c87ce184d6f35e595a12d3771279838a9e 100644 (file)
@@ -486,7 +486,12 @@ pub struct HCPrinter<'a, Outputter> {
     pub double_quotes: bool,
 }
 
-fn ambiguity_check(outputter: &impl HCValueOutputter, quoted: bool, last_item_idx: usize, atom: &str) -> bool {
+fn ambiguity_check(
+    outputter: &impl HCValueOutputter,
+    quoted: bool,
+    last_item_idx: usize,
+    atom: &str,
+) -> bool {
     let tail = &outputter.as_str()[last_item_idx..];
 
     if atom == "," || !quoted || non_quoted_token(atom.chars()) {
@@ -1132,7 +1137,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             }
 
             macro_rules! emit_char {
-                ($c:expr) => ({
+                ($c:expr) => {{
                     append_str!(self, "'.'");
                     push_char!(self, '(');
 
@@ -1141,14 +1146,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
                     self.state_stack.push(TokenOrRedirect::Close);
                     char_count += 1;
-                });
+                }};
             }
 
             match iteratee {
                 PStrIteratee::Char { value, .. } => {
                     emit_char!(value);
                 }
-                PStrIteratee::PStrSlice { slice_loc, slice_len } => {
+                PStrIteratee::PStrSlice {
+                    slice_loc,
+                    slice_len,
+                } => {
                     let s = iter.heap.slice_to_str(slice_loc, slice_len);
 
                     for c in s.chars() {
@@ -1181,10 +1189,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         if max_depth == 0 {
             while let Some(iteratee) = iter.next() {
                 let iter: Box<dyn Iterator<Item = char>> = match iteratee {
-                    PStrIteratee::Char { value: c, .. } => {
-                        Box::new(std::iter::once(c))
-                    }
-                    PStrIteratee::PStrSlice { slice_loc, slice_len } => {
+                    PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
+                    PStrIteratee::PStrSlice {
+                        slice_loc,
+                        slice_len,
+                    } => {
                         let s = iter.heap.slice_to_str(slice_loc, slice_len);
                         Box::new(s.chars())
                     }
@@ -1201,10 +1210,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
             while let Some(iteratee) = iter.next() {
                 let iter: Box<dyn Iterator<Item = char>> = match iteratee {
-                    PStrIteratee::Char { value: c, .. } => {
-                        Box::new(std::iter::once(c))
-                    }
-                    PStrIteratee::PStrSlice { slice_loc, slice_len } => {
+                    PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
+                    PStrIteratee::PStrSlice {
+                        slice_loc,
+                        slice_len,
+                    } => {
                         let s = iter.heap.slice_to_str(slice_loc, slice_len);
                         Box::new(s.chars())
                     }
@@ -1583,22 +1593,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
             self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
         } else {
-            /*
-            let end_cell_h = Heap::neighboring_cell_offset(pstr_loc);
-            let end_cell = self.iter.heap[end_cell_h];
-            let end_cell = heap_bound_store(
-                self.iter.heap,
-                heap_bound_deref(self.iter.heap, end_cell),
-            );
-
-            if end_cell != empty_list_as_cell!() {
-                self.iter.push_stack(
-                    IterStackLoc::iterable_loc(end_cell_h, HeapOrStackTag::Heap),
-                );
-            }
-            */
-
-            self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
+            self.state_stack
+                .push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
             self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
         }
     }
@@ -1872,9 +1868,8 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom)]),
-        );
+            [atom_as_cell(a_atom), atom_as_cell(b_atom)]
+        ));
 
         let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
         wam.machine_st.heap.push_cell(cell).unwrap();
@@ -1893,7 +1888,7 @@ mod tests {
             assert_eq!(output.result(), "f(a,b)");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1925,7 +1920,7 @@ mod tests {
             assert_eq!(output.result(), "f(a,b,a,...)");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1968,7 +1963,7 @@ mod tests {
             assert_eq!(output.result(), "[L|L]");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -1984,9 +1979,11 @@ mod tests {
 
         let mut functor_writer = Heap::functor_writer(functor!(
             f_atom,
-            [atom_as_cell(a_atom),
-             atom_as_cell(b_atom),
-             atom_as_cell(b_atom)]
+            [
+                atom_as_cell(a_atom),
+                atom_as_cell(b_atom),
+                atom_as_cell(b_atom)
+            ]
         ));
 
         functor_writer(&mut wam.machine_st.heap).unwrap();
@@ -2005,7 +2002,7 @@ mod tests {
             assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)]");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap[4] = list_loc_as_cell!(1);
 
@@ -2023,7 +2020,7 @@ mod tests {
             assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|...]");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         {
             let mut printer = HCPrinter::new(
@@ -2043,7 +2040,7 @@ mod tests {
             assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         // issue #382
         wam.machine_st.heap.clear();
@@ -2077,7 +2074,7 @@ mod tests {
             assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -2100,7 +2097,7 @@ mod tests {
             assert_eq!(output.result(), "[a,b,c|_1]");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         let mut writer = wam.machine_st.heap.reserve(96).unwrap();
 
@@ -2131,7 +2128,7 @@ mod tests {
             assert_eq!(output.result(), "\"abcabc\"");
         }
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
 
@@ -2140,14 +2137,14 @@ mod tests {
             "=(X,[a,b,c|X])"
         );
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(
             &wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(),
             "[a,b,[a],[a,b,c]]"
         );
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(
             &wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].")
@@ -2155,11 +2152,11 @@ mod tests {
             "[[a,b,c],e,f,[g,e,h,Y,v,X,Y]]"
         );
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(&wam.parse_and_print_term("f((a,b)).").unwrap(), "f((a,b))");
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.op_dir
             .insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
@@ -2171,14 +2168,14 @@ mod tests {
             "[a|[]+b]"
         );
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         assert_eq!(
             &wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
             "[a|[b|c]*d]"
         );
 
-        all_cells_unmarked(wam.machine_st.heap.splice(..));
+        all_cells_unmarked(&wam.machine_st.heap);
 
         wam.op_dir
             .insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));
index d9a4f036cbc7119713a782017acc6e3f5d1aa308..344155d83a319a087e503c806690d562a5dc41c4 100644 (file)
@@ -1110,12 +1110,11 @@ pub(crate) fn constant_key_alternatives(
                 constants.push(
                     Fixnum::build_with_checked(value)
                         .map(|n| fixnum_as_cell!(n))
-                        .unwrap()
+                        .unwrap(),
                 );
             }
         }
-        _ => {
-        }
+        _ => {}
     }
 
     /*
@@ -1465,11 +1464,7 @@ impl<I: Indexer> CodeOffsets<I> {
         self.indices.lists().push_back(index);
     }
 
-    fn index_constant(
-        &mut self,
-        constant: HeapCellValue,
-        index: usize,
-    ) -> Vec<HeapCellValue> {
+    fn index_constant(&mut self, constant: HeapCellValue, index: usize) -> Vec<HeapCellValue> {
         let overlapping_constants = constant_key_alternatives(constant);
         let code = self.indices.constants().entry(constant).or_default();
 
index b641c756c8b29ab26d063dc40132ce9feb663cce..1de7541b1f4eddb483c5abd3a36c18ed6c6e53f0 100644 (file)
@@ -14,7 +14,9 @@ use std::iter::*;
 use std::ops::Deref;
 use std::vec::Vec;
 
-pub(crate) trait TermIterator: Deref<Target = Heap> + Iterator<Item = HeapCellValue> {
+pub(crate) trait TermIterator:
+    Deref<Target = Heap> + Iterator<Item = HeapCellValue>
+{
     fn focus(&self) -> IterStackLoc;
     fn level(&mut self) -> Level;
 }
@@ -45,9 +47,9 @@ fn record_path(
                 }
             }
             (HeapCellValueTag::Lis) => {
-                       root_terms.insert(root_loc);
-                       break;
-               }
+                root_terms.insert(root_loc);
+                break;
+            }
             _ => {
                 if cell.is_ref() {
                     root_terms.insert(cell.get_value() as usize);
@@ -228,7 +230,10 @@ pub(crate) enum ClauseItem<'a> {
     FirstBranch(usize),
     NextBranch,
     BranchEnd(usize),
-    Chunk { chunk_num: usize, terms: &'a VecDeque<QueryTerm> },
+    Chunk {
+        chunk_num: usize,
+        terms: &'a VecDeque<QueryTerm>,
+    },
 }
 
 #[derive(Debug)]
@@ -271,10 +276,9 @@ impl<'a> ClauseIterator<'a> {
 
         while let Some(state) = self.state_stack.pop() {
             match state {
-                ClauseIteratorState::RemainingBranches(terms, focus)
-                    if terms.len() == focus => {
-                        depth += 1;
-                    }
+                ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => {
+                    depth += 1;
+                }
                 _ => {
                     self.state_stack.push(state);
                     break;
@@ -292,25 +296,27 @@ impl<'a> Iterator for ClauseIterator<'a> {
     fn next(&mut self) -> Option<Self::Item> {
         while let Some(state) = self.state_stack.pop() {
             match state {
-                ClauseIteratorState::RemainingChunks(chunks, focus)
-                    if focus < chunks.len() => {
-                        if focus + 1 < chunks.len() {
+                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);
                 }
index 2b9742284df818069b7dbc0966e4647aa4d4d87a..4e8cb44e5dc1f15f73b351535d95967b9be2df9e 100644 (file)
@@ -568,6 +568,7 @@ parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
                                                 % maplist isn't
                                                 % declared as a
                                                 % meta-predicate yet
+       '$debug_hook',
        catch(lists:maplist(Selector, Options, OptionPairs0),
              error(E, _),
              builtins:throw(error(E, Stub))) ->
index a779411d9dfab2b308593a575334072a7d25b8e0..86470097d3e3440686950e8221c0c8e56e170f63 100644 (file)
@@ -1165,9 +1165,8 @@ impl MachineState {
             return Err(self.error_form(type_error, stub_gen()));
         };
 
-        let mut iter = stackful_post_order_iter::<NonListElider>(
-            &mut self.heap, &mut self.stack, root_loc,
-        );
+        let mut iter =
+            stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, root_loc);
 
         while let Some(value) = iter.next() {
             if value.get_forwarding_bit() {
index 584abc80642e39c180cb983f40e8499bf84a4c35..c288511b66d6893bf12a39521faebb4f25401fb1 100644 (file)
@@ -38,7 +38,6 @@ verify_attrs([], _, _, []).
 
 
 call_goals([ListOfGoalLists | ListsCubed]) :-
-    '$debug_hook',
     call_goals_0(ListOfGoalLists),
     call_goals(ListsCubed).
 call_goals([]).
index 6b5ae9b309ed307279ea22e1ec017752c8b0a836..368152f5b2a64311e9b01752c732a0a608985f14 100644 (file)
@@ -145,7 +145,9 @@ impl MachineState {
         };
 
         let mut iter = stackful_preorder_iter::<NonListElider>(
-            &mut self.heap, &mut self.stack, root_loc, // cell,
+            &mut self.heap,
+            &mut self.stack,
+            root_loc, // cell,
         );
 
         while let Some(value) = iter.next() {
index 71beaa47a41e388e86fa11411b15de49b00f5029..84b89c3973ca198c8cf0844b55c1bdb04cf12bd6 100644 (file)
@@ -2102,19 +2102,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
     }
 
     pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
-        let key = match self
-            .payload
-            .predicates
-            .first()
-            .map(|term| term.focus) {
-                Some(focus) => {
-                    clause_predicate_key(self.machine_heap(), focus)
-                        .ok_or(SessionError::NamelessEntry)?
-                }
-                None => {
-                    return Err(SessionError::NamelessEntry);
-                }
-            };
+        let key = match self.payload.predicates.first().map(|term| term.focus) {
+            Some(focus) => clause_predicate_key(self.machine_heap(), focus)
+                .ok_or(SessionError::NamelessEntry)?,
+            None => {
+                return Err(SessionError::NamelessEntry);
+            }
+        };
 
         let listing_src_file_name = self.listing_src_file_name();
 
@@ -2290,13 +2284,18 @@ impl Machine {
         term_reg: RegType,
         vars: Vec<HeapCellValue>,
     ) -> Result<(), SessionError> {
-        let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
+        let body_cell = self
+            .machine_st
+            .store(self.machine_st.deref(self.machine_st[term_reg]));
 
         let new_header_loc = self.machine_st.heap.cell_len();
         let arity = vars.len();
         let term_loc = self.machine_st.heap.cell_len() + 1 + arity;
 
-        let mut writer = self.machine_st.heap.reserve(4 + arity)
+        let mut writer = self
+            .machine_st
+            .heap
+            .reserve(4 + arity)
             .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
 
         writer.write_with(move |section| {
index 5bb2fe900df5bf430afc5047f5d406228d70bf9c..57e034af16c53bf9b588c3bf48a3187e5abaf5c6 100644 (file)
@@ -1,13 +1,71 @@
+use fxhash::FxBuildHasher;
+use indexmap::IndexSet;
+
 use crate::atom_table::*;
 use crate::machine::get_structure_index;
 use crate::machine::heap::*;
 use crate::machine::stack::*;
 use crate::types::*;
 
+use scryer_modular_bitfield::specifiers::*;
+use scryer_modular_bitfield::*;
+
+use std::collections::BTreeMap;
 use std::mem;
 use std::ops::{IndexMut, Range};
 
-type Trail = Vec<(Ref, HeapCellValue)>;
+#[derive(BitfieldSpecifier, Copy, Clone, Debug)]
+#[bits = 6]
+enum TrailRefTag {
+    HeapCell = 0b001011,
+    StackCell = 0b001101,
+    AttrVar = 0b010001,
+    PStrLoc = 0b001111,
+}
+
+#[bitfield]
+#[repr(u64)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+struct TrailRef {
+    val: B56,
+    #[allow(unused)]
+    m: bool,
+    #[allow(unused)]
+    f: bool,
+    tag: TrailRefTag,
+}
+
+impl TrailRef {
+    #[inline(always)]
+    fn heap_cell(h: usize) -> Self {
+        TrailRef::new()
+            .with_tag(TrailRefTag::HeapCell)
+            .with_val(h as u64)
+    }
+
+    #[inline(always)]
+    fn stack_cell(h: usize) -> Self {
+        TrailRef::new()
+            .with_tag(TrailRefTag::StackCell)
+            .with_val(h as u64)
+    }
+
+    #[inline(always)]
+    fn attr_var(h: usize) -> Self {
+        TrailRef::new()
+            .with_tag(TrailRefTag::AttrVar)
+            .with_val(h as u64)
+    }
+
+    #[inline(always)]
+    fn pstr_loc(h: usize) -> Self {
+        TrailRef::new()
+            .with_tag(TrailRefTag::PStrLoc)
+            .with_val(h as u64)
+    }
+}
+
+type Trail = Vec<(TrailRef, HeapCellValue)>;
 
 #[derive(Debug, Clone, Copy)]
 pub enum AttrVarPolicy {
@@ -18,15 +76,12 @@ pub enum AttrVarPolicy {
 pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
     fn store(&self, value: HeapCellValue) -> HeapCellValue;
     fn deref(&self, value: HeapCellValue) -> HeapCellValue;
-    // fn push_cell(&mut self, value: HeapCellValue) -> Result<(), usize>;
     fn push_attr_var_queue(&mut self, attr_var_loc: usize);
     fn stack(&mut self) -> &mut Stack;
     fn threshold(&self) -> usize;
     // returns the tail location of the pstr on success
+    fn as_slice_from<'a>(&'a self, from: usize) -> Box<dyn Iterator<Item = u8> + 'a>;
     fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize>;
-    fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize;
-    fn pstr_at(&self, loc: usize) -> bool;
-    fn next_non_pstr_cell_index(&self, loc: usize) -> usize;
     fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize>;
     fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize>;
 }
@@ -35,14 +90,25 @@ pub(crate) fn copy_term<T: CopierTarget>(
     target: T,
     addr: HeapCellValue,
     attr_var_policy: AttrVarPolicy,
-) -> Result<(), usize> {
+) -> Result<usize, usize> {
     let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
+    let old_threshold = copy_term_state.target.threshold();
 
     copy_term_state.copy_term_impl(addr)?;
     copy_term_state.copy_attr_var_lists()?;
     copy_term_state.unwind_trail();
 
-    Ok(())
+    let new_threshold = copy_term_state.target.threshold();
+    copy_term_state.copy_pstrs()?;
+
+    Ok(new_threshold - old_threshold)
+}
+
+#[derive(Debug)]
+pub struct PStrData {
+    pre_old_h_tail_loc: usize,
+    post_old_h_tail_loc: usize,
+    post_old_h_pstr_loc_locs: IndexSet<usize, FxBuildHasher>,
 }
 
 #[derive(Debug)]
@@ -53,6 +119,9 @@ struct CopyTermState<T: CopierTarget> {
     target: T,
     attr_var_policy: AttrVarPolicy,
     attr_var_list_locs: Vec<(usize, HeapCellValue)>,
+    // keys of pstr_loc_locs are byte indices rounded down to the
+    // nearest cell boundary
+    pstr_loc_locs: BTreeMap<usize, PStrData>,
 }
 
 impl<T: CopierTarget> CopyTermState<T> {
@@ -64,6 +133,7 @@ impl<T: CopierTarget> CopyTermState<T> {
             target,
             attr_var_policy,
             attr_var_list_locs: vec![],
+            pstr_loc_locs: BTreeMap::new(),
         }
     }
 
@@ -74,7 +144,7 @@ impl<T: CopierTarget> CopyTermState<T> {
 
     fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
         let trail_item = mem::replace(&mut self.target[addr], list_loc_as_cell!(threshold));
-        self.trail.push((Ref::heap_cell(addr), trail_item));
+        self.trail.push((TrailRef::heap_cell(addr), trail_item));
     }
 
     fn copy_list(&mut self, addr: usize) -> Result<(), usize> {
@@ -93,7 +163,7 @@ impl<T: CopierTarget> CopyTermState<T> {
         }
 
         let threshold = self.target.threshold();
-        self.target.copy_slice_to_end(addr .. addr + 2)?;
+        self.target.copy_slice_to_end(addr..addr + 2)?;
 
         *self.value_at_scan() = list_loc_as_cell!(threshold);
 
@@ -122,54 +192,90 @@ impl<T: CopierTarget> CopyTermState<T> {
         Ok(())
     }
 
-    /*
-     * write a null byte to the first word of a partial string to
-     * flag that it has been copied followed by the copied
-     * string's index in the next 7 bytes. write the bytes in big
-     * endian order so that the null byte is at index 0.
-     */
-    fn write_pstr_index(&mut self, head_cell_idx: usize, threshold: usize) {
-        let bytes = u64::to_be_bytes(threshold as u64);
-        debug_assert_eq!(bytes[0], 0);
-        self.target[head_cell_idx] = HeapCellValue::from_bytes(bytes);
-    }
-
     fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> {
-        let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc);
-        let head_byte_idx = heap_index!(head_cell_idx);
-        let pstr_offset = pstr_loc - head_byte_idx;
+        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<T: CopierTarget> CopyTermState<T> {
             });
 
             debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
+
             self.copy_term_impl(str_cell)?;
             list_addr = self.target[heap_loc + 1];
 
@@ -227,13 +334,13 @@ impl<T: CopierTarget> CopyTermState<T> {
                 self.target[frontier] = heap_loc_as_cell!(frontier);
                 self.target[h] = heap_loc_as_cell!(frontier);
 
-                self.trail.push((Ref::heap_cell(h), heap_loc_as_cell!(h)));
+                self.trail.push((TrailRef::heap_cell(h), heap_loc_as_cell!(h)));
             }
             (HeapCellValueTag::StackVar, s) => {
                 self.target[frontier] = heap_loc_as_cell!(frontier);
                 self.target.stack()[s] = heap_loc_as_cell!(frontier);
 
-                self.trail.push((Ref::stack_cell(s), stack_loc_as_cell!(s)));
+                self.trail.push((TrailRef::stack_cell(s), stack_loc_as_cell!(s)));
             }
             (HeapCellValueTag::AttrVar, h) => {
                 let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
@@ -245,10 +352,10 @@ impl<T: CopierTarget> CopyTermState<T> {
                 self.target[frontier] = heap_loc_as_cell!(threshold);
                 self.target[h] = heap_loc_as_cell!(threshold);
 
-                self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
+                self.trail.push((TrailRef::attr_var(h), attr_var_as_cell!(h)));
 
                 if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
-                    let mut writer = self.target.reserve(2).unwrap();
+                    let mut writer = self.target.reserve(2)?;
 
                     writer.write_with(|section| {
                         section.push_cell(attr_var_as_cell!(threshold));
@@ -256,7 +363,7 @@ impl<T: CopierTarget> CopyTermState<T> {
                     });
 
                     let old_list_link = self.target[h + 1];
-                    self.trail.push((Ref::heap_cell(h + 1), old_list_link));
+                    self.trail.push((TrailRef::heap_cell(h + 1), old_list_link));
                     self.target[h + 1] = heap_loc_as_cell!(threshold + 1);
 
                     if old_list_link.get_tag() == HeapCellValueTag::Lis {
@@ -317,7 +424,21 @@ impl<T: CopierTarget> CopyTermState<T> {
             (HeapCellValueTag::Atom, (_name, arity)) => {
                 let threshold = self.target.threshold();
 
-                *self.value_at_scan() = str_loc_as_cell!(threshold);
+                let index_cell = self.target[addr.saturating_sub(1)];
+
+                *self.value_at_scan() = if get_structure_index(index_cell).is_some() {
+                    // copy the index pointer trailing this
+                    // inlined or expanded goal.
+                    let mut writer = self.target.reserve(1).unwrap();
+
+                    writer.write_with(|section| {
+                        section.push_cell(index_cell);
+                    });
+
+                    str_loc_as_cell!(threshold + 1)
+                } else {
+                    str_loc_as_cell!(threshold)
+                };
 
                 self.target.copy_slice_to_end(addr .. addr + 1 + arity)?;
 
@@ -326,28 +447,7 @@ impl<T: CopierTarget> CopyTermState<T> {
                     str_loc_as_cell!(threshold),
                 );
 
-                self.trail.push((Ref::heap_cell(addr), trail_item));
-/*
-                self.target.push(atom_as_cell!(name, arity));
-
-                for i in 0..arity {
-                    let hcv = self.target[addr + 1 + i];
-                    self.target.push(hcv);
-                }
-*/
-                if !self.target.pstr_at(addr + 1 + arity) {
-                    let index_cell = self.target[addr + 1 + arity];
-
-                    if get_structure_index(index_cell).is_some() {
-                        // copy the index pointer trailing this
-                        // inlined or expanded goal.
-                        let mut writer = self.target.reserve(1).unwrap();
-
-                        writer.write_with(|section| {
-                            section.push_cell(index_cell);
-                        });
-                    }
-                }
+                self.trail.push((TrailRef::heap_cell(addr), trail_item));
             }
             (HeapCellValueTag::Str, h) => {
                 *self.value_at_scan() = str_loc_as_cell!(h);
@@ -370,11 +470,6 @@ impl<T: CopierTarget> CopyTermState<T> {
         });
 
         while self.scan < self.target.threshold() {
-            if self.target.pstr_at(self.scan) {
-                self.scan = self.target.next_non_pstr_cell_index(self.scan);
-                continue;
-            }
-
             let addr = *self.value_at_scan();
 
             read_heap_cell!(addr,
@@ -405,17 +500,40 @@ impl<T: CopierTarget> CopyTermState<T> {
         Ok(())
     }
 
-    fn unwind_trail(mut self) {
-        for (r, value) in self.trail {
-            let index = r.get_value() as usize;
+    fn copy_pstrs(&mut self) -> Result<(), usize> {
+        while let Some((least_pstr_loc, pstr_data)) = self.pstr_loc_locs.pop_first() {
+            let threshold = heap_index!(self.target.threshold());
+
+            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));
index 99ae40b4606dddba17a3619984347bc560b45e3c..da125518ea1e75e9b196f3d5f2acebd1d80c7745 100644 (file)
@@ -206,9 +206,9 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
                     }
                     HeapCellValueTag::PStrLoc => {
                         let h = self.next as usize;
-                        let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
+                        let tail_idx = self.heap.scan_slice_to_str(h).tail_idx;
 
-                        if self.heap[last_cell_loc].get_forwarding_bit() {
+                        if self.heap[tail_idx].get_forwarding_bit() {
                             if self.cycle_detection_active() {
                                 self.cycle_found = true;
                                 return None;
@@ -219,11 +219,11 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
                             continue;
                         }
 
-                        self.heap[last_cell_loc].set_forwarding_bit(true);
+                        self.heap[tail_idx].set_forwarding_bit(true);
 
-                        self.next = self.heap[last_cell_loc].get_value();
-                        self.heap[last_cell_loc].set_value(self.current as u64);
-                        self.current = last_cell_loc;
+                        self.next = self.heap[tail_idx].get_value();
+                        self.heap[tail_idx].set_value(self.current as u64);
+                        self.current = tail_idx;
 
                         return Some(pstr_loc_as_cell!(h));
                     }
index a7b2a128947e49a9efc63e459679da683e8b911e..ad4460d45b4b0bb389e3f46b0c80f4f0d2ad31fe 100644 (file)
@@ -2,11 +2,11 @@ use crate::atom_table::*;
 use crate::forms::*;
 use crate::instructions::*;
 use crate::iterators::fact_iterator;
-use crate::machine::Stack;
 use crate::machine::heap::*;
 use crate::machine::loader::*;
 use crate::machine::machine_errors::CompilationError;
 use crate::machine::preprocessor::*;
+use crate::machine::Stack;
 use crate::parser::ast::*;
 use crate::parser::dashu::Rational;
 use crate::types::*;
@@ -229,7 +229,8 @@ impl VarLocsToNums {
     }
 
     pub fn get(&self, idx: VarPtrIndex) -> VarPtr {
-        self.map.get(&idx)
+        self.map
+            .get(&idx)
             .cloned()
             .map(VarPtr::Numbered)
             .unwrap_or_else(|| VarPtr::Anon)
@@ -260,8 +261,10 @@ impl VarData {
 
         if let Some(global_cut_var_num) = global_cut_var_num {
             let term = QueryTerm::GetLevel(global_cut_var_num);
-            self.records[global_cut_var_num].allocation =
-                VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending };
+            self.records[global_cut_var_num].allocation = VarAlloc::Perm {
+                reg: 0,
+                allocation: PermVarAllocation::Pending,
+            };
 
             match build_stack.front_mut() {
                 Some(ChunkedTerms::Branch(_)) => {
@@ -395,11 +398,7 @@ impl VariableClassifier {
 
         let mut lvl = Level::Shallow;
         let mut stack = Stack::uninitialized();
-        let mut iter = fact_iterator::<false>(
-            term.heap,
-            &mut stack,
-            term.focus,
-        );
+        let mut iter = fact_iterator::<false>(term.heap, &mut stack, term.focus);
 
         // second arg is true to iterate the root, which may be a variable
         while let Some(subterm) = iter.next() {
@@ -425,8 +424,7 @@ impl VariableClassifier {
 
     fn probe_body_var(&mut self, context: GenContext, var_info: VarInfo) {
         let chunk_num = context.chunk_num();
-        let branch_info_v = self.branch_map.entry(var_info.var)
-            .or_default();
+        let branch_info_v = self.branch_map.entry(var_info.var).or_default();
 
         let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
             !self.root_set.contains(&last_bi.branch_num)
@@ -489,14 +487,10 @@ impl VariableClassifier {
 
             debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
 
-            for idx in str_offset + 1 ..= str_offset + arity {
+            for idx in str_offset + 1..=str_offset + arity {
                 let mut lvl = Level::Shallow;
                 let mut stack = Stack::uninitialized();
-                let mut iter = fact_iterator::<false>(
-                    heap,
-                    &mut stack,
-                    idx,
-                );
+                let mut iter = fact_iterator::<false>(heap, &mut stack, idx);
 
                 while let Some(subterm) = iter.next() {
                     if !subterm.is_var() {
@@ -661,13 +655,14 @@ impl VariableClassifier {
                     mut term_loc,
                 } => {
                     // return true iff new chunk should be added.
-                    let update_chunk_data = |build_stack: &mut ChunkedTermVec, key: PredicateKey| {
-                        if ClauseType::is_inlined(key.0, key.1) {
-                            build_stack.try_set_chunk_at_inlined_boundary()
-                        } else {
-                            build_stack.try_set_chunk_at_call_boundary()
-                        }
-                    };
+                    let update_chunk_data =
+                        |build_stack: &mut ChunkedTermVec, key: PredicateKey| {
+                            if ClauseType::is_inlined(key.0, key.1) {
+                                build_stack.try_set_chunk_at_inlined_boundary()
+                            } else {
+                                build_stack.try_set_chunk_at_call_boundary()
+                            }
+                        };
 
                     macro_rules! add_chunk {
                         ($key:expr, $tag:expr, $term_loc:expr) => {{
@@ -678,9 +673,10 @@ impl VariableClassifier {
                             let context = build_stack.current_gen_context();
 
                             for (arg_c, term_loc) in
-                                ($term_loc + 1 ..= $term_loc + $key.1).enumerate()
+                                ($term_loc + 1..=$term_loc + $key.1).enumerate()
                             {
-                                let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
+                                let mut term =
+                                    FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
 
                                 self.probe_body_term(
                                     arg_c + 1,
@@ -710,9 +706,10 @@ impl VariableClassifier {
                             let context = build_stack.current_gen_context();
 
                             for (arg_c, term_loc) in
-                                ($term_loc + 1 ..= $term_loc + $key.1).enumerate()
+                                ($term_loc + 1..=$term_loc + $key.1).enumerate()
                             {
-                                let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
+                                let mut term =
+                                    FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
 
                                 self.probe_body_term(
                                     arg_c + 1,
@@ -1043,8 +1040,8 @@ impl BranchMap {
 
         for (var, branches) in self.iter_mut() {
             let (mut var_num, var_num_incr) = match var {
-                &ClassifiedVar::InSitu { var_num} => (var_num, false),
-                _ => (var_data.records.len(), true)
+                &ClassifiedVar::InSitu { var_num } => (var_num, false),
+                _ => (var_data.records.len(), true),
             };
 
             for branch in branches.iter_mut() {
@@ -1088,7 +1085,10 @@ impl BranchMap {
                         let chunk_num = chunk.term_loc.chunk_num();
 
                         var_data.var_locs_to_nums.insert(
-                            VarPtrIndex { chunk_num, term_loc },
+                            VarPtrIndex {
+                                chunk_num,
+                                term_loc,
+                            },
                             var_num,
                         );
                     }
index ad0ebc7ddff6a1fab2e68a0d673aae46897e1906..cd6723209275f61c1f1851204551f54324e97918 100644 (file)
@@ -140,10 +140,7 @@ impl MachineState {
         let a1 = self.registers[1];
         let a2 = self.registers[2];
 
-        step_or_resource_error!(
-            self,
-            copy_term(CopyTerm::new(self), a1, attr_var_policy)
-        );
+        step_or_resource_error!(self, copy_term(CopyTerm::new(self), a1, attr_var_policy));
 
         unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
     }
@@ -162,11 +159,7 @@ impl MachineState {
 
         let heap_addr = resource_error_call_result!(
             self,
-            sized_iter_to_heap_list(
-                &mut self.heap,
-                list.len(),
-                list.into_iter(),
-            )
+            sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter(),)
         );
 
         let target_addr = self.registers[2];
@@ -5155,9 +5148,8 @@ impl Machine {
                         let r = self.machine_st.registers[2];
                         let r = self.machine_st.store(self.machine_st.deref(r));
 
-                        let mut writer = Heap::functor_writer(
-                            functor!(atom!("-"), [fixnum(n), fixnum(p)]),
-                        );
+                        let mut writer =
+                            Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
 
                         let str_cell = backtrack_on_resource_error!(
                             &mut self.machine_st,
@@ -5178,9 +5170,8 @@ impl Machine {
                         let r = self.machine_st.registers[2];
                         let r = self.machine_st.store(self.machine_st.deref(r));
 
-                        let mut writer = Heap::functor_writer(
-                            functor!(atom!("-"), [fixnum(n), fixnum(p)]),
-                        );
+                        let mut writer =
+                            Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
 
                         let str_cell = backtrack_on_resource_error!(
                             &mut self.machine_st,
index f0f480f3900cb99fb943f70797872ec732226b95..b18b5300a72b874faaf2be4bf8b4966d2a81c47e 100644 (file)
@@ -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<Self>)
     where
         Self: Sized,
-    {}
+    {
+    }
 }
 
 #[cfg(test)]
@@ -109,7 +113,63 @@ impl UnmarkPolicy for MarkerUMP {
 }
 
 #[cfg(test)]
-type PStrLocValuesMap = IndexMap<usize, usize, FxBuildHasher>;
+#[derive(Debug)]
+struct PStrLocValuesMap {
+    hit_set: BTreeMap<usize, usize>,
+    pstr_loc_locs: IndexMap<usize, usize, FxBuildHasher>,
+}
+
+#[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<usize> {
+        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, <stream ptr>]
         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]),
index 8f4d4a6c94738247d0e07273fb5763e39e7632d0..fc5177403e145160937480e0d829befaa64e4768 100644 (file)
@@ -5,22 +5,17 @@ use crate::types::*;
 
 use std::alloc;
 use std::convert::TryFrom;
-use std::mem;
 use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
 use std::ptr;
 use std::sync::Once;
 
 use super::MachineState;
 
-use bitvec::prelude::*;
-use bitvec::slice::BitSlice;
-
 const ALIGN: usize = Heap::heap_cell_alignment();
 
 #[derive(Debug)]
 pub struct Heap {
     inner: InnerHeap,
-    pstr_vec: BitVec,
     resource_err_loc: usize,
 }
 
@@ -90,40 +85,51 @@ unsafe impl Sync for Heap {}
 
 static RESOURCE_ERROR_OFFSET_INIT: Once = Once::new();
 
+#[derive(Debug)]
+pub struct HeapStringScan<'a> {
+    pub string: &'a str,
+    pub tail_idx: usize,
+}
+
 // return the string at ptr and the tail location relative to ptr.
-// pstr_vec records the location of each string cell starting at index
-// 0.
-fn scan_slice_to_str(orig_ptr: *const u8, pstr_vec: &BitSlice) -> (&str, usize) {
-    unsafe {
-        debug_assert_eq!(pstr_vec[0], true);
-
-        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<HeapCellValue>,
     ) -> Option<std::cmp::Ordering> {
         match self {
-            PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset } => {
-                let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + l1_offset);
+            PStrSegmentCmpResult::FirstMatch {
+                pstr_loc1,
+                pstr_loc2,
+                l1_offset,
+            } => {
+                let tail1 = Heap::pstr_tail_idx(pstr_loc1 + l1_offset);
                 let rest_of_l2 = pstr_loc_as_cell!(pstr_loc2 + l1_offset);
 
                 pdl.push(heap_loc_as_cell!(tail1));
                 pdl.push(rest_of_l2);
             }
-            PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset } => {
-                let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + l2_offset);
+            PStrSegmentCmpResult::SecondMatch {
+                pstr_loc1,
+                pstr_loc2,
+                l2_offset,
+            } => {
+                let tail2 = Heap::pstr_tail_idx(pstr_loc2 + l2_offset);
                 let rest_of_l1 = pstr_loc_as_cell!(pstr_loc1 + l2_offset);
 
                 pdl.push(rest_of_l1);
                 pdl.push(heap_loc_as_cell!(tail2));
             }
-            PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset } => {
+            PStrSegmentCmpResult::BothMatch {
+                pstr_loc1,
+                pstr_loc2,
+                null_offset,
+            } => {
                 // exhaustive match
-                let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + null_offset);
-                let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + null_offset);
+                let tail1 = Heap::pstr_tail_idx(pstr_loc1 + null_offset);
+                let tail2 = Heap::pstr_tail_idx(pstr_loc2 + null_offset);
 
                 pdl.push(heap_loc_as_cell!(tail1));
                 pdl.push(heap_loc_as_cell!(tail2));
@@ -163,162 +181,18 @@ impl PStrSegmentCmpResult {
     }
 }
 
-#[derive(Debug)]
-pub(crate) struct HeapView<'a> {
-    slice: *const u8,
-    cell_offset: usize,
-    slice_cell_len: usize,
-    pstr_slice: &'a BitSlice,
-}
-
-impl<'a> HeapView<'a> {
-    /*
-    pub fn get(&self, idx: usize) -> Option<HeapCellValue> {
-        if idx < self.slice_cell_len {
-            Some(*self.index(idx))
-        } else {
-            None
-        }
-    }
-    */
-
-    fn iter_follow(&mut self) -> Option<HeapCellValue> {
-        if self.slice_cell_len == 0 {
-            None
-        } else {
-            let cell;
-
-            if self.pstr_slice[0] {
-                cell = pstr_loc_as_cell!(heap_index!(self.cell_offset));
-                let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
-
-                unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
-                self.slice_cell_len -= next_cell_idx;
-                self.cell_offset += next_cell_idx;
-                self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
-            } else {
-                unsafe {
-                    cell = ptr::read(self.slice as *mut HeapCellValue);
-                    self.slice = self.slice.add(heap_index!(1));
-                }
-
-                self.cell_offset += 1;
-                self.slice_cell_len -= 1;
-                self.pstr_slice = &self.pstr_slice[1 ..];
-            }
-
-            Some(cell)
-        }
-    }
-}
-
-impl<'a> Iterator for HeapView<'a> {
-    type Item = HeapCellValue;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        self.iter_follow()
-    }
-}
-
-impl<'a> Index<usize> for HeapView<'a> {
-    type Output = HeapCellValue;
-
-    fn index(&self, idx: usize) -> &Self::Output {
-        debug_assert!(idx < self.slice_cell_len);
-        unsafe {
-            &*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
-        }
-    }
-}
-
-#[derive(Debug)]
-pub(crate) struct HeapViewMut<'a> {
-    slice: *mut u8,
-    cell_offset: usize,
-    slice_cell_len: usize,
-    pstr_slice: &'a BitSlice,
-}
-
-impl<'a> HeapViewMut<'a> {
-    fn iter_follow(&mut self) -> Option<&'a mut HeapCellValue> {
-        if self.slice_cell_len == 0 {
-            None
-        } else {
-            let cell;
-
-            loop {
-                if self.pstr_slice[0] {
-                    let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
-
-                    unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
-
-                    self.slice_cell_len -= next_cell_idx;
-                    self.cell_offset += next_cell_idx;
-                    self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
-                } else {
-                    unsafe {
-                        cell = &mut *(self.slice as *mut HeapCellValue);
-                        self.slice = self.slice.add(heap_index!(1));
-                    }
-
-                    self.cell_offset += 1;
-                    self.slice_cell_len -= 1;
-                    self.pstr_slice = &self.pstr_slice[1 ..];
-
-                    break;
-                }
-            }
-
-            Some(cell)
-        }
-    }
-}
-
-
-
-impl<'a> Index<usize> for HeapViewMut<'a> {
-    type Output = HeapCellValue;
-
-    fn index(&self, idx: usize) -> &Self::Output {
-        debug_assert!(idx < self.slice_cell_len);
-        unsafe {
-            &*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
-        }
-    }
-}
-
-impl<'a> IndexMut<usize> for HeapViewMut<'a> {
-    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
-        debug_assert!(idx < self.slice_cell_len);
-        unsafe {
-            &mut *(self.slice.add(heap_index!(idx)) as *mut HeapCellValue)
-        }
-    }
-}
-
-impl<'a> Iterator for &'a mut HeapViewMut<'a> {
-    type Item = &'a mut HeapCellValue;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        self.iter_follow()
-    }
-}
-
 #[derive(Debug)]
 pub struct PStrWriteInfo {
     pstr_loc: usize,
 }
 
 #[derive(Debug)]
-pub(crate) struct ReservedHeapSection<'a> {
+pub(crate) struct ReservedHeapSection {
     heap_ptr: *mut u8,
     heap_cell_len: usize,
-    pstr_vec: &'a mut BitVec,
 }
 
-impl<'a> ReservedHeapSection<'a> {
+impl ReservedHeapSection {
     #[inline]
     pub(crate) fn cell_len(&self) -> usize {
         self.heap_cell_len
@@ -326,16 +200,16 @@ impl<'a> ReservedHeapSection<'a> {
 
     pub(crate) fn push_cell(&mut self, cell: HeapCellValue) {
         unsafe {
-            ptr::write(self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _, cell);
+            ptr::write(
+                self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _,
+                cell,
+            );
         }
-        self.pstr_vec.push(false);
+        // self.pstr_vec.push(false);
         self.heap_cell_len += 1;
     }
 
-    fn push_pstr_segment(
-        &mut self,
-        src: &str,
-    ) -> usize {
+    fn push_pstr_segment(&mut self, src: &str) -> usize {
         if src.is_empty() {
             return 0;
         }
@@ -354,23 +228,30 @@ impl<'a> ReservedHeapSection<'a> {
 
             let align_offset = pstr_sentinel_length(zero_region_idx);
 
-            ptr::write_bytes(
-                self.heap_ptr.add(zero_region_idx),
-                0u8,
-                align_offset,
-            );
+            ptr::write_bytes(self.heap_ptr.add(zero_region_idx), 0u8, align_offset);
+
+            cells_written = if align_offset == 1 {
+                ptr::write_bytes(
+                    self.heap_ptr.add(zero_region_idx + 1),
+                    0u8,
+                    size_of::<HeapCellValue>(),
+                );
+
+                // ensure there are at least two bytes in the boundary
+                // buffer separating the string data from the tail
+                // cell
+                cell_index!(src.len() + align_offset + size_of::<HeapCellValue>())
+            } else {
+                cell_index!(src.len() + align_offset)
+            };
 
-            cells_written = cell_index!(src.len() + align_offset);
             self.heap_cell_len += cells_written;
         }
 
         cells_written
     }
 
-    pub(crate) fn push_pstr(
-        &mut self,
-        mut src: &str,
-    ) -> Option<HeapCellValue> {
+    pub(crate) fn push_pstr(&mut self, mut src: &str) -> Option<HeapCellValue> {
         let orig_h = self.cell_len();
 
         if src.is_empty() {
@@ -386,18 +267,14 @@ impl<'a> ReservedHeapSection<'a> {
 
         loop {
             let null_char_idx = src.find('\u{0}').unwrap_or_else(|| src.len());
-
-            let cell_len = self.cell_len();
             let cells_written = self.push_pstr_segment(&src[0..null_char_idx]);
             let tail_idx = self.cell_len();
 
-            self.pstr_vec.resize(cell_len + cells_written, true);
-
             if cells_written == 0 {
                 return None;
             } else if null_char_idx + 1 < src.len() {
                 self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1)));
-                src = &src[null_char_idx + 1 ..];
+                src = &src[null_char_idx + 1..];
             } else {
                 return Some(pstr_loc_as_cell!(heap_index!(orig_h)));
             }
@@ -420,7 +297,12 @@ impl<'a> ReservedHeapSection<'a> {
                 cursor: 0,
             }];
 
-            while let Some(FunctorData { functor, cell_offset, mut cursor }) = functor_stack.pop() {
+            while let Some(FunctorData {
+                functor,
+                cell_offset,
+                mut cursor,
+            }) = functor_stack.pop()
+            {
                 while cursor < functor.len() {
                     match &functor[cursor] {
                         &FunctorElement::AbsoluteCell(cell) => {
@@ -460,15 +342,13 @@ impl<'a> ReservedHeapSection<'a> {
     }
 }
 
-impl<'a> Index<usize> for ReservedHeapSection<'a> {
+impl Index<usize> for ReservedHeapSection {
     type Output = HeapCellValue;
 
     #[inline]
     fn index(&self, idx: usize) -> &Self::Output {
         debug_assert!(idx < self.heap_cell_len);
-        unsafe {
-            &*(self.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
-        }
+        unsafe { &*(self.heap_ptr as *const HeapCellValue).add(idx) }
     }
 }
 
@@ -489,7 +369,7 @@ fn pstr_sentinel_length(chunk_len: usize) -> usize {
 #[must_use]
 #[derive(Debug)]
 pub struct HeapWriter<'a> {
-    section: ReservedHeapSection<'a>,
+    section: ReservedHeapSection,
     heap_byte_len: &'a mut usize,
 }
 
@@ -504,13 +384,12 @@ impl<'a> HeapWriter<'a> {
         *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
 
         // return the number of bytes written
-        Ok(heap_index!(self.section.heap_cell_len - old_section_cell_len))
+        Ok(heap_index!(
+            self.section.heap_cell_len - old_section_cell_len
+        ))
     }
 
-    pub(crate) fn write_with(
-        &mut self,
-        writer: impl FnOnce(&mut ReservedHeapSection),
-    ) -> usize {
+    pub(crate) fn write_with(&mut self, writer: impl FnOnce(&mut ReservedHeapSection)) -> usize {
         let old_section_cell_len = self.section.heap_cell_len;
         writer(&mut self.section);
         *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
@@ -522,7 +401,7 @@ impl<'a> HeapWriter<'a> {
     #[inline]
     pub(crate) fn truncate(&mut self, cell_offset: usize) {
         self.section.heap_cell_len = cell_offset;
-        self.section.pstr_vec.truncate(cell_offset);
+        // self.section.pstr_vec.truncate(cell_offset);
         *self.heap_byte_len = heap_index!(cell_offset);
     }
 
@@ -543,9 +422,7 @@ impl<'a> Index<usize> for HeapWriter<'a> {
     #[inline]
     fn index(&self, idx: usize) -> &Self::Output {
         debug_assert!(heap_index!(idx) < *self.heap_byte_len);
-        unsafe {
-            &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
-        }
+        unsafe { &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) }
     }
 }
 
@@ -553,9 +430,7 @@ impl<'a> IndexMut<usize> for HeapWriter<'a> {
     #[inline]
     fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
         debug_assert!(heap_index!(idx) < *self.heap_byte_len);
-        unsafe {
-            &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue)
-        }
+        unsafe { &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue) }
     }
 }
 
@@ -564,17 +439,29 @@ impl<'a> SizedHeap for HeapWriter<'a> {
         self.section.cell_len()
     }
 
-    fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
-        let (s, tail_cell_offset) = scan_slice_to_str(
-            unsafe { self.section.heap_ptr.add(slice_loc) },
-            &self.section.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
-        );
+    fn scan_slice_to_str(&self, slice_loc: usize) -> HeapStringScan {
+        let HeapStringScan { string, tail_idx } = unsafe {
+            let slice = std::slice::from_raw_parts(
+                self.section.heap_ptr.byte_add(slice_loc),
+                heap_index!(self.section.heap_cell_len) - slice_loc,
+            );
+
+            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<HeapCellValue> {
         if self.inner.byte_len == 0 {
             None
         } else {
             unsafe {
-                Some(&mut *(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
-                            as *mut HeapCellValue))
+                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<HeapCellValue> {
-        if self.inner.byte_len == 0 {
-            None
-        } else {
-            unsafe {
-                Some(ptr::read(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
-                               as *const HeapCellValue))
+    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<R: RangeBounds<usize>>(
         &self,
         range: R,
@@ -876,7 +792,7 @@ impl Heap {
             slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
             cell_offset: range.start,
             slice_cell_len: range.end - range.start,
-            pstr_slice: &self.pstr_vec.as_bitslice()[range],
+            // pstr_slice: &self.pstr_vec.as_bitslice()[range],
         }
     }
 
@@ -890,9 +806,10 @@ impl Heap {
             slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
             cell_offset: range.start,
             slice_cell_len: range.end - range.start,
-            pstr_slice: &self.pstr_vec.as_bitslice()[range],
+            // pstr_slice: &self.pstr_vec.as_bitslice()[range],
         }
     }
+    */
 
     pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
         let size_in_heap = Self::compute_pstr_size(src);
@@ -911,39 +828,18 @@ impl Heap {
         })
     }
 
-    const fn heap_cell_alignment() -> usize {
+    pub const fn heap_cell_alignment() -> usize {
         // yes, size_of, not align_of. the alignment of HeapCellValue
         // is 1 byte. In the heap, though, its alignment must be its
         // size.
-        mem::size_of::<HeapCellValue>()
-    }
-
-    // takes a byte offset into the Heap ptr.
-    #[inline(always)]
-    pub(crate) const fn neighboring_cell_offset(offset: usize) -> usize {
-        cell_index!((offset & !(ALIGN - 1)) + ALIGN)
-    }
-
-    #[inline]
-    pub(crate) fn iter(&self) -> HeapView {
-        HeapView {
-            slice: self.inner.ptr,
-            cell_offset: 0,
-            slice_cell_len: cell_index!(self.inner.byte_len),
-            pstr_slice: &self.pstr_vec.as_bitslice(),
-        }
-    }
-
-    #[inline]
-    pub(crate) fn pstr_vec(&self) -> &BitSlice<usize> {
-        self.pstr_vec.as_bitslice()
+        size_of::<HeapCellValue>()
     }
 
     #[inline]
     pub(crate) fn char_at(&self, byte_idx: usize) -> char {
         let s = unsafe {
             let char_ptr = self.inner.ptr.add(byte_idx);
-            let slice = std::slice::from_raw_parts(char_ptr, mem::size_of::<char>());
+            let slice = std::slice::from_raw_parts(char_ptr, size_of::<char>());
             std::str::from_utf8_unchecked(&slice)
         };
 
@@ -961,7 +857,7 @@ impl Heap {
             let succ_len = loc + c.len_utf8();
 
             if chars_iter.next() == Some('\u{0}') {
-                (c, heap_loc_as_cell!(Self::neighboring_cell_offset(succ_len)))
+                (c, heap_loc_as_cell!(Self::pstr_tail_idx(succ_len)))
             } else {
                 (c, pstr_loc_as_cell!(succ_len))
             }
@@ -971,8 +867,8 @@ impl Heap {
     // copies only the string, not its tail. returns the cell index of
     // the tail location
     pub(crate) fn copy_pstr_within(&mut self, pstr_loc: usize) -> Result<usize, usize> {
-        let (s, tail_loc) = self.scan_slice_to_str(pstr_loc);
-        let s_len = s.len();
+        let HeapStringScan { string, tail_idx } = self.scan_slice_to_str(pstr_loc);
+        let s_len = string.len();
 
         let align_offset = pstr_sentinel_length(s_len);
         let copy_size = s_len + align_offset;
@@ -980,15 +876,10 @@ impl Heap {
         unsafe {
             loop {
                 if self.free_space() >= copy_size {
-                    let slice = std::slice::from_raw_parts_mut(
-                        self.inner.ptr,
-                        self.inner.byte_len + s_len,
-                    );
+                    let slice =
+                        std::slice::from_raw_parts_mut(self.inner.ptr, self.inner.byte_len + s_len);
 
-                    slice.copy_within(
-                        pstr_loc .. pstr_loc + s_len,
-                        self.inner.byte_len,
-                    );
+                    slice.copy_within(pstr_loc..pstr_loc + s_len, self.inner.byte_len);
 
                     ptr::write_bytes(
                         self.inner.ptr.add(self.inner.byte_len + s_len),
@@ -996,8 +887,17 @@ impl Heap {
                         align_offset,
                     );
 
-                    self.inner.byte_len += copy_size;
-                    self.pstr_vec.resize(self.cell_len(), true);
+                    if align_offset == 1 {
+                        ptr::write_bytes(
+                            self.inner.ptr.add(self.inner.byte_len + copy_size),
+                            0u8,
+                            size_of::<HeapCellValue>(),
+                        );
+
+                        self.inner.byte_len += copy_size + heap_index!(1);
+                    } else {
+                        self.inner.byte_len += copy_size;
+                    }
 
                     break;
                 } else if !self.grow() {
@@ -1006,7 +906,7 @@ impl Heap {
             }
         }
 
-        Ok(tail_loc)
+        Ok(tail_idx)
     }
 
     // src is a cell-indexed range.
@@ -1023,7 +923,7 @@ impl Heap {
                         heap_index!(len),
                     );
 
-                    self.pstr_vec.resize(self.cell_len() + len, false);
+                    // self.pstr_vec.resize(self.cell_len() + len, false);
                     self.inner.byte_len += heap_index!(len);
 
                     break;
@@ -1059,10 +959,14 @@ impl Heap {
 
             byte_size += null_idx + pstr_sentinel_length(null_idx);
 
+            // each partial string must be buffered from its tail cell
+            // by at least two null bytes so one of them may be used
+            // to mark partial strings e.g. during iteration
+
             if (null_idx + 1) % ALIGN == 0 {
-                byte_size += 2 * mem::size_of::<HeapCellValue>();
+                byte_size += 2 * size_of::<HeapCellValue>();
             } else {
-                byte_size += mem::size_of::<HeapCellValue>();
+                byte_size += size_of::<HeapCellValue>();
             }
 
             if null_idx + 1 >= src.len() {
@@ -1082,13 +986,13 @@ impl Heap {
         while idx < functor.len() {
             match &functor[idx] {
                 &FunctorElement::InnerFunctor(inner_cell_size, ref _inner_functor) => {
-                    byte_size += inner_cell_size as usize * mem::size_of::<HeapCellValue>();
+                    byte_size += inner_cell_size as usize * size_of::<HeapCellValue>();
                 }
                 FunctorElement::AbsoluteCell(_cell) | FunctorElement::Cell(_cell) => {
-                    byte_size += mem::size_of::<HeapCellValue>();
+                    byte_size += size_of::<HeapCellValue>();
                 }
                 &FunctorElement::String(cell_len, _) => {
-                    byte_size += cell_len as usize * mem::size_of::<HeapCellValue>();
+                    byte_size += cell_len as usize * size_of::<HeapCellValue>();
                 }
             }
 
@@ -1120,12 +1024,10 @@ impl Heap {
     #[inline]
     pub(crate) fn truncate(&mut self, cell_offset: usize) {
         self.inner.byte_len = heap_index!(cell_offset);
-        self.pstr_vec.truncate(cell_offset);
+        // self.pstr_vec.truncate(cell_offset);
     }
 }
 
-
-
 pub(crate) struct PStrSegmentIter<'a> {
     string_buf: &'a str,
 }
@@ -1153,7 +1055,7 @@ impl<'a> Iterator for PStrSegmentIter<'a> {
             if c == '\u{0}' {
                 None
             } else {
-                self.string_buf = &self.string_buf[c.len_utf8() ..];
+                self.string_buf = &self.string_buf[c.len_utf8()..];
                 Some(c)
             }
         })
@@ -1187,14 +1089,15 @@ pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
     fn cell_len(&self) -> usize;
 
     // return a pointer to the heap string and the cell index of its tail
-    fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize);
+    fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a>;
+
+    fn as_slice(&self) -> &[u8];
 
     // return true iff a partial string is stored at cell_offset.
-    fn pstr_at(&self, cell_offset: usize) -> bool;
+    // fn pstr_at(&self, cell_offset: usize) -> bool;
 }
 
-pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {
-}
+pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {}
 
 impl Index<usize> for Heap {
     type Output = HeapCellValue;
@@ -1215,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<Item = HeapCellValue>>(heap: I, h: usize) {
-    for (index, term) in heap.enumerate() {
-        println!("{} : {:?}", h + index, term);
+pub fn print_heap_terms(heap: &Heap, h: usize) {
+    for idx in 0..heap.cell_len() {
+        let term = heap[idx];
+        println!("{} : {:?}", h + idx, term);
     }
 }
 
index eef64f963ac547949851180aecec7106e54d9005..c139bc128237af8a3721275ea54f63a47dc0795c 100644 (file)
@@ -1,4 +1,3 @@
-use std::cmp::Ordering;
 use std::collections::BTreeMap;
 
 use crate::atom_table;
@@ -442,7 +441,7 @@ impl Iterator for QueryState<'_> {
             if let Err(resource_err_loc) = machine
                 .machine_st
                 .heap
-                .append(machine.machine_st.ball.stub.splice(..))
+                .append(&machine.machine_st.ball.stub)
             {
                 return Some(Err(Term::from_heapcell(
                     machine,
@@ -531,9 +530,9 @@ impl Machine {
     pub fn consult_module_string(&mut self, module_name: &str, program: impl Into<String>) {
         let stream = Stream::from_owned_string(program.into(), &mut self.machine_st.arena);
         self.machine_st.registers[1] = stream_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));
index 34499ced050d5ac50c2e1e60e05cebcf83420925..0d850150b1d4ac906cf202bec774d5ef6389c751 100644 (file)
@@ -27,15 +27,14 @@ impl TermWriteResult {
 
         heap[0] = value;
 
-        let inverse_var_locs = inverse_var_locs_from_iter(
-            stackful_preorder_iter::<NonListElider>(
-                heap,
-                &mut stack,
-                0,
-            ),
-        );
+        let inverse_var_locs = inverse_var_locs_from_iter(stackful_preorder_iter::<NonListElider>(
+            heap, &mut stack, 0,
+        ));
 
-        Ok(Self { focus, inverse_var_locs })
+        Ok(Self {
+            focus,
+            inverse_var_locs,
+        })
     }
 }
 
@@ -529,9 +528,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
             let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
 
             let mut term = load_state.term_stream.next(&composite_op_dir)?;
-            let predicate_focus_opt = load_state.predicates.first().map(|term_write_result| {
-                term_write_result.focus
-            });
+            let predicate_focus_opt = load_state
+                .predicates
+                .first()
+                .map(|term_write_result| term_write_result.focus);
 
             let machine_st = LS::machine_st(&mut self.payload);
             let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus);
@@ -1072,10 +1072,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
         let cell = machine_st[r];
 
         let focus = machine_st.heap.cell_len();
-        machine_st.heap.push_cell(cell)
+        machine_st
+            .heap
+            .push_cell(cell)
             .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
 
-        let export_list = FocusedHeapRefMut { heap: &mut machine_st.heap, focus };
+        let export_list = FocusedHeapRefMut {
+            heap: &mut machine_st.heap,
+            focus,
+        };
         let export_list = setup_module_export_list(export_list)?;
 
         Ok(export_list.into_iter().collect())
@@ -1129,8 +1134,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
             }
         );
 
-        Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
-           .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?)
+        Ok(
+            TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
+                .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?,
+        )
     }
 
     fn add_extensible_predicate_declaration(
@@ -1628,18 +1635,15 @@ impl Machine {
         };
 
         let value = self.machine_st.registers[2];
-        let term  = resource_error_call_result!(
+        let term = resource_error_call_result!(
             self.machine_st,
             TermWriteResult::from(&mut self.machine_st.heap, value)
         );
 
         let add_clause = || {
             let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) {
-                Some((atom!(":-"), _)) => {
-                    term_nth_arg(&self.machine_st.heap, term.focus, 1).and_then(|h| {
-                        term_nth_arg(&self.machine_st.heap, h, 1)
-                    })
-                }
+                Some((atom!(":-"), _)) => term_nth_arg(&self.machine_st.heap, term.focus, 1)
+                    .and_then(|h| term_nth_arg(&self.machine_st.heap, h, 1)),
                 Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1),
                 None => None,
             };
@@ -2240,9 +2244,11 @@ impl Machine {
         };
 
         let mut loader = self.loader_from_heap_evacuable(temp_v!(4));
-        let predicate_focus_opt = loader.payload.predicates.first().map(|term_write_result| {
-            term_write_result.focus
-        });
+        let predicate_focus_opt = loader
+            .payload
+            .predicates
+            .first()
+            .map(|term_write_result| term_write_result.focus);
 
         let is_consistent = if let Some(predicate_focus) = predicate_focus_opt {
             let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
@@ -2253,7 +2259,7 @@ impl Machine {
 
         LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
             (!loader.payload.predicates.is_empty()
-             && loader.payload.predicates.compilation_target != compilation_target)
+                && loader.payload.predicates.compilation_target != compilation_target)
                 || !is_consistent;
 
         let result = LiveLoadAndMachineState::evacuate(loader);
index 5017cb78bb72e71f66ec0950fd352f6290aa3699..1a4e84879c8df9d524d3d7342e66e1fec3c25fc3 100644 (file)
@@ -187,7 +187,11 @@ impl PermissionError for HeapCellValue {
 
         let stub = functor!(
             atom!("permission_error"),
-            [atom_as_cell((perm.as_atom())), atom_as_cell(index_atom), cell(cell)]
+            [
+                atom_as_cell((perm.as_atom())),
+                atom_as_cell(index_atom),
+                cell(cell)
+            ]
         );
 
         MachineError {
@@ -226,7 +230,10 @@ pub(super) trait DomainError {
 
 impl DomainError for HeapCellValue {
     fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
-        let stub = functor!(atom!("domain_error"), [atom_as_cell((error.as_atom())), cell(self)]);
+        let stub = functor!(
+            atom!("domain_error"),
+            [atom_as_cell((error.as_atom())), cell(self)]
+        );
 
         MachineError {
             stub,
@@ -239,7 +246,10 @@ impl DomainError for Number {
     fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
         let stub = functor!(
             atom!("domain_error"),
-            [atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))]
+            [
+                atom_as_cell((error.as_atom())),
+                number(self, (&mut machine_st.arena))
+            ]
         );
 
         MachineError {
@@ -280,7 +290,10 @@ impl MachineState {
     }
 
     pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError {
-        let stub = functor!(atom!("evaluation_error"), [atom_as_cell((eval_error.as_atom()))]);
+        let stub = functor!(
+            atom!("evaluation_error"),
+            [atom_as_cell((eval_error.as_atom()))]
+        );
 
         MachineError {
             stub,
@@ -297,7 +310,10 @@ impl MachineState {
                 )
             }
             ResourceError::OutOfFiles => {
-                functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))])
+                functor!(
+                    atom!("resource_error"),
+                    [atom_as_cell((atom!("file_descriptors")))]
+                )
             }
         };
 
@@ -480,12 +496,12 @@ impl MachineState {
             SessionError::CannotOverwriteBuiltIn(key) => self.permission_error(
                 Permission::Modify,
                 atom!("static_procedure"),
-                functor_stub(key.0, key.1)
+                functor_stub(key.0, key.1),
             ),
             SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
                 Permission::Modify,
                 atom!("static_procedure"),
-                functor_stub(key.0, key.1)
+                functor_stub(key.0, key.1),
             ),
             SessionError::CannotOverwriteBuiltInModule(module) => {
                 self.permission_error(Permission::Modify, atom!("static_module"), module)
@@ -559,14 +575,14 @@ impl MachineState {
 
         let stub = functor!(atom!("syntax_error"), [functor(stub)]);
 
-        MachineError {
-            stub,
-            location,
-        }
+        MachineError { stub, location }
     }
 
     pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
-        let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]);
+        let stub = functor!(
+            atom!("representation_error"),
+            [atom_as_cell((flag.as_atom()))]
+        );
 
         MachineError {
             stub,
@@ -593,13 +609,19 @@ impl MachineState {
     }
 
     pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
-        if let Some(ParserErrorSrc { line_num,  .. }) = err.location {
-            functor!(atom!("error"), [functor((err.stub)),
-                                      functor((atom!(":")), [functor(src),
-                                                             number(line_num, (&mut self.arena))])])
+        if let Some(ParserErrorSrc { line_num, .. }) = err.location {
+            functor!(
+                atom!("error"),
+                [
+                    functor((err.stub)),
+                    functor(
+                        (atom!(":")),
+                        [functor(src), number(line_num, (&mut self.arena))]
+                    )
+                ]
+            )
         } else {
-            functor!(atom!("error"), [functor((err.stub)),
-                                      functor(src)])
+            functor!(atom!("error"), [functor((err.stub)), functor(src)])
         }
     }
 
@@ -826,13 +848,29 @@ impl EvalError {
 // used by '$skip_max_list'.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum CycleSearchResult {
-    Cyclic { lambda: usize }, // number of steps
+    Cyclic {
+        lambda: usize,
+    }, // number of steps
     EmptyList,
-    NotList { num_steps: usize, heap_loc: HeapCellValue },
-    PartialList { num_steps: usize, heap_loc: HeapCellValue },
-    ProperList { num_steps: usize },
-    PStrLocation { num_steps: usize, pstr_loc: HeapCellValue },
-    UntouchedList { num_steps: usize, list_loc: usize },
+    NotList {
+        num_steps: usize,
+        heap_loc: HeapCellValue,
+    },
+    PartialList {
+        num_steps: usize,
+        heap_loc: HeapCellValue,
+    },
+    ProperList {
+        num_steps: usize,
+    },
+    PStrLocation {
+        num_steps: usize,
+        pstr_loc: HeapCellValue,
+    },
+    UntouchedList {
+        num_steps: usize,
+        list_loc: usize,
+    },
 }
 
 impl MachineState {
@@ -856,7 +894,9 @@ impl MachineState {
         };
 
         match BrentAlgState::detect_cycles(&self.heap, sorted) {
-            CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !sorted.is_var() => {
+            CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. }
+                if !sorted.is_var() =>
+            {
                 let err = self.type_error(ValidType::List, sorted);
                 Err(self.error_form(err, stub_gen()))
             }
@@ -868,7 +908,9 @@ impl MachineState {
         let stub_gen = || functor_stub(atom!("keysort"), 2);
 
         match BrentAlgState::detect_cycles(&self.heap, list) {
-            CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !list.is_var() => {
+            CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. }
+                if !list.is_var() =>
+            {
                 let err = self.type_error(ValidType::List, list);
                 Err(self.error_form(err, stub_gen()))
             }
index b5fdc1c06396a9c990e8ae7ae76246ce27cad138..dcf7a9201fd85640b19393ee74b8caefc681c1c5 100644 (file)
@@ -37,7 +37,7 @@ pub(super) enum MachineMode {
 pub(super) enum HeapPtr {
     HeapCell(usize),
     PStr(usize), // Char(usize),
-    // PStrLocation(usize),
+                 // PStrLocation(usize),
 }
 
 impl Default for HeapPtr {
@@ -215,7 +215,8 @@ fn push_var_eq_functors(
         let mut writer = heap.reserve(1 + 5 * size)?;
 
         writer.write_with(|section| {
-            for (var_loc, var) in iter { // (var, binding) in iter {
+            for (var_loc, var) in iter {
+                // (var, binding) in iter {
                 let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
                 let binding = heap_loc_as_cell!(var_loc);
 
@@ -224,7 +225,7 @@ fn push_var_eq_functors(
                 section.push_cell(binding);
             }
 
-            for idx in 0 .. size {
+            for idx in 0..size {
                 section.push_cell(list_loc_as_cell!(section.cell_len() + 1));
                 section.push_cell(str_loc_as_cell!(src_h + 3 * idx));
             }
@@ -252,6 +253,7 @@ pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
 #[derive(Debug)]
 pub struct Ball {
     pub(super) boundary: usize,
+    pub(super) pstr_boundary: usize,
     pub(super) stub: Heap,
 }
 
@@ -259,12 +261,14 @@ impl Ball {
     pub(super) fn new() -> Self {
         Ball {
             boundary: 0,
+            pstr_boundary: 0,
             stub: Heap::new(),
         }
     }
 
     pub(super) fn reset(&mut self) {
         self.boundary = 0;
+        self.pstr_boundary = 0;
         self.stub.clear();
     }
 
@@ -272,10 +276,23 @@ impl Ball {
         let h = dest.cell_len();
         let diff = self.boundary as i64 - h as i64;
 
-        dest.append(self.stub.splice(..))?;
+        let mut dest_writer = dest.reserve(self.stub.cell_len())?;
 
-        for cell in &mut dest.splice_mut(h ..) {
-            *cell = *cell - diff;
+        dest_writer.write_with(|section| {
+            for idx in 0..self.pstr_boundary {
+                section.push_cell(self.stub[idx] - diff);
+            }
+        });
+
+        let mut pstr_threshold = heap_index!(self.pstr_boundary);
+
+        while pstr_threshold < heap_index!(self.stub.cell_len()) {
+            let HeapStringScan { string, tail_idx } = self.stub.scan_slice_to_str(pstr_threshold);
+
+            pstr_threshold += dest_writer.write_with(|section| {
+                section.push_pstr(string).unwrap();
+                section.push_cell(self.stub[tail_idx] - diff);
+            });
         }
 
         Ok(h)
@@ -336,29 +353,13 @@ impl<'a> CopierTarget for CopyTerm<'a> {
     }
 
     #[inline(always)]
-    fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
-        self.state.heap.copy_pstr_within(pstr_loc)
-    }
-
-    #[inline(always)]
-    fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
-        self.state.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
-            .last_zero()
-            .map(|idx| idx + 1)
-            .unwrap_or(0)
+    fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
+        Box::new(self.state.heap.as_slice()[from..].iter().cloned())
     }
 
     #[inline(always)]
-    fn 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<usize, usize> {
+        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<usize, usize> {
         debug_assert!(pstr_loc < self.heap.byte_len());
 
-        let (string, tail_loc) = self.heap.scan_slice_to_str(pstr_loc);
+        let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(pstr_loc);
         self.stub.allocate_pstr(string)?;
-        Ok(tail_loc)
+        Ok(tail_idx)
     }
 
-    #[inline]
-    fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
-        self.stub.reserve(num_cells)
-    }
-
-    #[inline]
-    fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
-        if pstr_loc >= self.heap.byte_len() {
-            self.stub.pstr_vec()[0 .. cell_index!(pstr_loc - self.heap.byte_len())]
-                .last_zero()
-                .map(|idx| idx + 1)
-                .unwrap_or(0)
-        } else {
-            self.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
-                .last_zero()
-                .map(|idx| idx + 1)
-                .unwrap_or(0)
-        }
-    }
-
-    #[inline]
-    fn pstr_at(&self, loc: usize) -> bool {
-        if loc >= self.heap.cell_len() {
-            self.stub.pstr_vec()[loc - self.heap.cell_len()]
+    fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
+        if from < self.heap.byte_len() {
+            Box::new(
+                self.heap.as_slice()[from..]
+                    .iter()
+                    .cloned()
+                    .chain(self.stub.as_slice().iter().cloned()),
+            )
         } else {
-            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<HeapWriter, usize> {
+        self.stub.reserve(num_cells)
     }
 
     fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> 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<Ref, bool> = IndexMap::new();
 
-        for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus) {
+        for cell in
+            stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus)
+        {
             let cell = unmark_cell_bits!(cell);
 
             if let Some(var) = cell.as_var() {
@@ -756,9 +737,10 @@ impl MachineState {
                 singleton_var_set
                     .iter()
                     .filter(|(var, is_singleton)| {
-                        **is_singleton && term.inverse_var_locs.contains_key(
-                            &(var.get_value() as usize)
-                        )
+                        **is_singleton
+                            && term
+                                .inverse_var_locs
+                                .contains_key(&(var.get_value() as usize))
                     })
                     .count(),
                 term.inverse_var_locs
@@ -873,7 +855,8 @@ impl MachineState {
                         CompilationError::ParserError(e) if e.is_unexpected_eof() => {
                             match eof_handler(self, stream)? {
                                 OnEOF::Return => {
-                                    return self.write_read_term_options(vec![], empty_list_as_cell!());
+                                    return self
+                                        .write_read_term_options(vec![], empty_list_as_cell!());
                                 }
                                 OnEOF::Continue => continue,
                             }
@@ -1012,11 +995,9 @@ impl MachineState {
 
                 let term_loc = self.heap.cell_len();
 
-                step_or_resource_error!(
-                    self,
-                    self.heap.push_cell(term_to_be_printed),
-                    { return Ok(None); }
-                );
+                step_or_resource_error!(self, self.heap.push_cell(term_to_be_printed), {
+                    return Ok(None);
+                });
 
                 let mut printer = HCPrinter::new(
                     &mut self.heap,
index 34fbe5cac80912d13029e1642ce84992880d015f..a7dc5d9e8e767ec5bfa9909890551f9a5ae85fa9 100644 (file)
@@ -327,9 +327,9 @@ impl MachineState {
         self.ball.reset();
 
         let addr = self.registers[1];
-        let ball_boundary = self.heap.cell_len();
 
-        step_or_resource_error!(
+        self.ball.boundary = self.heap.cell_len();
+        self.ball.pstr_boundary = step_or_resource_error!(
             self,
             copy_term(
                 CopyBallTerm::new(
@@ -342,8 +342,6 @@ impl MachineState {
                 AttrVarPolicy::DeepCopy,
             )
         );
-
-        self.ball.boundary = ball_boundary;
     }
 
     #[inline(always)]
@@ -359,14 +357,14 @@ impl MachineState {
             HeapPtr::PStr(h) => {
                 let mut char_iter = self.heap.char_iter(h);
 
-                if self.s_offset == 0 { // read the car of the list
+                if self.s_offset == 0 {
+                    // read the car of the list
                     let c = char_iter.next().unwrap();
                     char_as_cell!(c)
-                } else { // read the (self.s_offset)^{th} cdr of the list
-                    let byte_offset: usize = char_iter
-                        .take(self.s_offset)
-                        .map(|c| c.len_utf8())
-                        .sum();
+                } else {
+                    // read the (self.s_offset)^{th} cdr of the list
+                    let byte_offset: usize =
+                        char_iter.take(self.s_offset).map(|c| c.len_utf8()).sum();
                     let new_h = h + byte_offset;
 
                     self.s_offset = 0;
@@ -375,7 +373,7 @@ impl MachineState {
                         self.s = HeapPtr::PStr(new_h);
                         pstr_loc_as_cell!(new_h)
                     } else {
-                        let h = Heap::neighboring_cell_offset(new_h);
+                        let h = Heap::pstr_tail_idx(new_h);
                         self.s = HeapPtr::HeapCell(h);
                         self.deref(heap_loc_as_cell!(h))
                     }
@@ -946,7 +944,7 @@ impl MachineState {
                                     if char_iter.next().is_some() {
                                         unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3);
                                     } else {
-                                        let tail_idx = Heap::neighboring_cell_offset(pstr_loc);
+                                        let tail_idx = Heap::pstr_tail_idx(pstr_loc);
                                         unify_fn!(*self, self.heap[tail_idx]);
                                     }
 
@@ -1044,7 +1042,12 @@ impl MachineState {
         }
     }
 
-    fn try_functor_fabricate_struct(&mut self, name: Atom, arity: usize, r: Ref) -> Result<(), usize> {
+    fn try_functor_fabricate_struct(
+        &mut self,
+        name: Atom,
+        arity: usize,
+        r: Ref,
+    ) -> Result<(), usize> {
         let h = self.heap.cell_len();
         let mut writer = self.heap.reserve(arity + 1)?;
 
@@ -1144,7 +1147,7 @@ impl MachineState {
                 };
 
                 read_heap_cell!(store_name,
-                    (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char | 
+                    (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char |
                      HeapCellValueTag::F64) if arity == 0 => {
                         self.bind(a1.as_var().unwrap(), deref_name);
                     }
index e0551a6006f5ee3d2b1b18937c6b7d5cd0f7231a..71f74f0c29cb64f2e71a90b478baa577726a4890 100644 (file)
@@ -51,14 +51,12 @@ impl MockWAM {
     ) -> Result<String, CompilationError> {
         let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?;
 
-        print_heap_terms(self.machine_st.heap.splice(..), term_write_result.focus);
+        print_heap_terms(&self.machine_st.heap, term_write_result.focus);
 
         let var_names = term_write_result
             .inverse_var_locs
             .iter()
-            .map(|(var_loc, var_name)| {
-                (self.machine_st.heap[*var_loc], var_name.clone())
-            })
+            .map(|(var_loc, var_name)| (self.machine_st.heap[*var_loc], var_name.clone()))
             .collect();
 
         let mut printer = HCPrinter::new(
@@ -90,6 +88,7 @@ pub struct TermCopyingMockWAM<'a> {
 impl<'a> Index<usize> for TermCopyingMockWAM<'a> {
     type Output = HeapCellValue;
 
+    #[inline]
     fn index(&self, index: usize) -> &HeapCellValue {
         &self.wam.machine_st.heap[index]
     }
@@ -107,6 +106,7 @@ impl<'a> IndexMut<usize> for TermCopyingMockWAM<'a> {
 impl<'a> Deref for TermCopyingMockWAM<'a> {
     type Target = MockWAM;
 
+    #[inline]
     fn deref(&self) -> &Self::Target {
         self.wam
     }
@@ -114,6 +114,7 @@ impl<'a> Deref for TermCopyingMockWAM<'a> {
 
 #[cfg(test)]
 impl<'a> DerefMut for TermCopyingMockWAM<'a> {
+    #[inline]
     fn deref_mut(&mut self) -> &mut Self::Target {
         self.wam
     }
@@ -170,26 +171,8 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
     }
 
     #[inline(always)]
-    fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
-        self.wam.machine_st.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
-            .last_zero()
-            .map(|idx| idx + 1)
-            .unwrap_or(0)
-    }
-
-    #[inline(always)]
-    fn pstr_at(&self, loc: usize) -> bool {
-        self.wam.machine_st.heap.pstr_vec()[loc]
-    }
-
-    #[inline(always)]
-    fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
-        // unwrap is safe here because a partial string is always
-        // followed by a tail cell, i.e. a non-pstr cell, supposing
-        // self.machine_st.heap[loc] is a pstr cell
-        self.wam.machine_st.heap.pstr_vec()[loc ..].first_zero()
-            .map(|idx| idx + loc)
-            .unwrap()
+    fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
+        Box::new(self.wam.machine_st.heap.as_slice()[from..].iter().cloned())
     }
 
     #[inline(always)]
@@ -204,20 +187,9 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
 }
 
 #[cfg(test)]
-pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
-    let mut idx = 0;
-    let cell_len = iter.cell_len();
-
-    while idx < cell_len {
-        let curr_idx = idx;
-        let cell = if iter.pstr_at(idx) {
-            let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
-            idx = last_cell_loc;
-            iter[last_cell_loc - 1]
-        } else {
-            idx += 1;
-            iter[curr_idx]
-        };
+pub fn all_cells_marked_and_unforwarded(heap: &Heap, offset: usize) {
+    for curr_idx in offset..heap.cell_len() {
+        let cell = heap[curr_idx];
 
         assert!(
             cell.get_mark_bit(),
@@ -235,43 +207,21 @@ pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
 }
 
 #[cfg(test)]
-pub fn unmark_all_cells(mut iter: impl SizedHeapMut) {
-    let mut idx = 0;
-    let cell_len = iter.cell_len();
-
-    while idx < cell_len {
-        if iter.pstr_at(idx) {
-            iter[idx].set_mark_bit(false);
-
-            let last_cell_loc = {
-                let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
-                last_cell_loc
-            };
-
-            iter[last_cell_loc].set_mark_bit(false);
-            idx = last_cell_loc;
-        } else {
-            iter[idx].set_mark_bit(false);
-            idx += 1;
-        }
+pub fn unmark_all_cells(heap: &mut Heap, offset: usize) {
+    for idx in offset..heap.cell_len() {
+        heap[idx].set_mark_bit(false);
     }
 }
 
 #[cfg(test)]
-pub fn all_cells_unmarked(iter: impl SizedHeap) {
+pub fn all_cells_unmarked(iter: &impl SizedHeap) {
     let mut idx = 0;
     let cell_len = iter.cell_len();
 
     while idx < cell_len {
         let curr_idx = idx;
-        let cell = if iter.pstr_at(idx) {
-            let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
-            idx = last_cell_loc;
-            iter[last_cell_loc - 1]
-        } else {
-            idx += 1;
-            iter[curr_idx]
-        };
+        idx += 1;
+        let cell = iter[curr_idx];
 
         assert!(
             !cell.get_mark_bit(),
@@ -354,7 +304,7 @@ mod tests {
             assert!(wam.fail);
         }
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.fail = false;
         wam.heap.clear();
@@ -375,7 +325,7 @@ mod tests {
             assert!(!wam.fail);
         }
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.fail = false;
         wam.heap.clear();
@@ -396,7 +346,7 @@ mod tests {
             assert!(!wam.fail);
         }
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.fail = false;
         wam.heap.clear();
@@ -417,7 +367,7 @@ mod tests {
             assert!(!wam.fail);
         }
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.fail = false;
         wam.heap.clear();
@@ -438,7 +388,7 @@ mod tests {
             assert!(!wam.fail);
         }
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.fail = false;
         wam.heap.clear();
@@ -450,7 +400,7 @@ mod tests {
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
 
-            all_cells_unmarked(wam.heap.splice(..));
+            all_cells_unmarked(&wam.heap);
 
             unify!(
                 wam,
@@ -461,7 +411,7 @@ mod tests {
             assert!(!wam.fail);
         }
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.heap.clear();
 
@@ -489,9 +439,15 @@ mod tests {
 
         assert!(!wam.fail);
 
+        assert_eq!(wam.heap.slice_to_str(heap_index!(0), "this is a string".len()),
+                   "this is a string");
         assert_eq!(wam.heap[3], pstr_loc_as_cell!(heap_index!(8)));
-
-        all_cells_unmarked(wam.heap.splice(..));
+        assert_eq!(wam.heap.slice_to_str(heap_index!(4), "this is a string".len()),
+                   "this is a string");
+        assert_eq!(wam.heap[7], pstr_loc_as_cell!(heap_index!(8)));
+        assert_eq!(wam.heap.slice_to_str(heap_index!(8), "this is a string".len()),
+                   "this is a string");
+        assert_eq!(wam.heap[11], pstr_loc_as_cell!(heap_index!(8)));
 
         wam.heap.clear();
 
@@ -515,7 +471,7 @@ mod tests {
 
         assert!(!wam.fail);
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.heap.clear();
 
@@ -540,7 +496,7 @@ mod tests {
         assert!(wam.fail);
 
         wam.fail = false;
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.heap.clear();
 
@@ -562,7 +518,7 @@ mod tests {
 
         unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
         assert!(!wam.fail);
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
     }
 
     #[test]
@@ -581,7 +537,7 @@ mod tests {
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
 
-            all_cells_unmarked(wam.heap.splice(..));
+            all_cells_unmarked(&wam.heap);
 
             unify_with_occurs_check!(
                 wam,
@@ -632,11 +588,7 @@ mod tests {
         let cstr_cell = wam.allocate_cstr("string").unwrap();
 
         assert_eq!(
-            compare_term_test!(
-                wam,
-                atom_as_cell!(atom!("atom")),
-                cstr_cell
-            ),
+            compare_term_test!(wam, atom_as_cell!(atom!("atom")), cstr_cell),
             Some(Ordering::Less)
         );
 
@@ -735,11 +687,7 @@ mod tests {
         let cstr_cell = wam.allocate_cstr("string").unwrap();
 
         assert_eq!(
-            compare_term_test!(
-                wam,
-                empty_list_as_cell!(),
-                cstr_cell
-            ),
+            compare_term_test!(wam, empty_list_as_cell!(), cstr_cell),
             Some(Ordering::Less)
         );
 
@@ -782,16 +730,13 @@ mod tests {
         assert!(!wam.is_cyclic_term(1));
         assert!(!wam.is_cyclic_term(2));
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
         wam.heap.clear();
 
-        let mut functor_writer = Heap::functor_writer(
-            functor!(
-                atom!("f"),
-                [atom_as_cell((atom!("a"))),
-                 atom_as_cell((atom!("b")))]
-            ),
-        );
+        let mut functor_writer = Heap::functor_writer(functor!(
+            atom!("f"),
+            [atom_as_cell((atom!("a"))), atom_as_cell((atom!("b")))]
+        ));
 
         functor_writer(&mut wam.heap).unwrap();
 
@@ -800,30 +745,30 @@ mod tests {
 
         assert!(!wam.is_cyclic_term(h));
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         assert!(!wam.is_cyclic_term(1));
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         assert!(!wam.is_cyclic_term(2));
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.heap[2] = str_loc_as_cell!(0);
 
-        print_heap_terms(wam.heap.iter(), 0);
+        print_heap_terms(&wam.heap, 0);
 
         assert!(wam.is_cyclic_term(2));
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.heap[2] = atom_as_cell!(atom!("b"));
         wam.heap[1] = str_loc_as_cell!(0);
 
         assert!(wam.is_cyclic_term(1));
 
-        all_cells_unmarked(wam.heap.splice(..));
+        all_cells_unmarked(&wam.heap);
 
         wam.heap.clear();
 
index 18cb742708772c584dd5905db5f36ac3ebe3396a..873d3ceb3361b2c1d1bdf84146fec2bcee00158c 100644 (file)
@@ -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) {
index 6176e73a027c8b92a9048fcaa9d04798d4dc3338..9484bf400d754b5b8654f1f764e136b01bbf493f 100644 (file)
@@ -19,9 +19,17 @@ pub struct HeapPStrIter<'a> {
 
 #[derive(Debug, Clone, Copy)]
 pub enum PStrCmpResult<'a> {
-    ListMatch { list_loc: usize },
-    CompletePStrMatch { chars_matched: usize, pstr_loc: usize },
-    PartialPStrMatch { string: &'a str, var_loc: usize },
+    ListMatch {
+        list_loc: usize,
+    },
+    CompletePStrMatch {
+        chars_matched: usize,
+        pstr_loc: usize,
+    },
+    PartialPStrMatch {
+        string: &'a str,
+        var_loc: usize,
+    },
 }
 
 struct PStrIterStep {
@@ -81,7 +89,7 @@ impl<'a> HeapPStrIter<'a> {
                     if s.is_empty() {
                         return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h });
                     } else {
-                        let next_hare = Heap::neighboring_cell_offset(h + bytes_matched);
+                        let next_hare = Heap::pstr_tail_idx(h + bytes_matched);
                         curr_hare = next_hare;
                     }
                 }
@@ -179,11 +187,11 @@ impl<'a> HeapPStrIter<'a> {
         loop {
             read_heap_cell!(self.heap[curr_hare],
                 (HeapCellValueTag::PStrLoc, h) => {
-                    let (s, tail_loc) = self.heap.scan_slice_to_str(h);
+                    let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(h);
 
                     return Ok(PStrIterStep {
-                        iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: s.len() },
-                        next_hare: tail_loc,
+                        iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: string.len() },
+                        next_hare: tail_idx,
                     });
                 }
                 (HeapCellValueTag::Lis, h) => {
@@ -319,7 +327,10 @@ impl<'a> Iterator for PStrCharsIter<'a> {
                     self.item = self.iter.next();
                     return Some(value);
                 }
-                PStrIteratee::PStrSlice { slice_loc, slice_len } => {
+                PStrIteratee::PStrSlice {
+                    slice_loc,
+                    slice_len,
+                } => {
                     let s = self.iter.heap.slice_to_str(slice_loc, slice_len);
 
                     match s.chars().next() {
@@ -353,7 +364,10 @@ mod test {
         let mut wam = MockWAM::new();
 
         let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
-        wam.machine_st.heap.push_cell(empty_list_as_cell!()).unwrap();
+        wam.machine_st
+            .heap
+            .push_cell(empty_list_as_cell!())
+            .unwrap();
 
         // not overwriting anything! 0 is an interstitial cell
         // reserved for use by the runtime
@@ -364,7 +378,10 @@ mod test {
 
             assert_eq!(
                 iter.next(),
-                Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }),
+                Some(PStrIteratee::PStrSlice {
+                    slice_loc: heap_index!(1),
+                    slice_len: "abc ".len()
+                }),
             );
             assert_eq!(iter.next(), None);
             assert!(!iter.is_cyclic());
@@ -384,7 +401,10 @@ mod test {
 
             assert_eq!(
                 iter.next(),
-                Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
+                Some(PStrIteratee::PStrSlice {
+                    slice_loc: heap_index!(1),
+                    slice_len: "abc ".len()
+                })
             );
             assert_eq!(
                 iter.next(),
@@ -407,7 +427,10 @@ mod test {
 
             assert_eq!(
                 iter.next(),
-                Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
+                Some(PStrIteratee::PStrSlice {
+                    slice_loc: heap_index!(1),
+                    slice_len: "abc ".len()
+                })
             );
             assert_eq!(
                 iter.next(),
@@ -552,7 +575,11 @@ mod test {
             section.push_cell(heap_loc_as_cell!(h));
         });
 
-        unify!(wam.machine_st, pstr_cell, pstr_loc_as_cell!(heap_index!(start)));
+        unify!(
+            wam.machine_st,
+            pstr_cell,
+            pstr_loc_as_cell!(heap_index!(start))
+        );
 
         assert!(!wam.machine_st.fail);
 
@@ -561,7 +588,9 @@ mod test {
             "abcdef"
         );
         assert_eq!(
-            wam.machine_st.heap.slice_to_str(heap_index!(start), "abc".len()),
+            wam.machine_st
+                .heap
+                .slice_to_str(heap_index!(start), "abc".len()),
             "abc"
         );
         assert_eq!(
@@ -587,7 +616,10 @@ mod test {
 
             assert_eq!(
                 iter.next(),
-                Some(PStrIteratee::PStrSlice { slice_loc: 'a'.len_utf8(), slice_len: "bc".len() })
+                Some(PStrIteratee::PStrSlice {
+                    slice_loc: 'a'.len_utf8(),
+                    slice_len: "bc".len()
+                })
             );
 
             for _ in iter {}
@@ -609,7 +641,11 @@ mod test {
             section.push_cell(empty_list_as_cell!());
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert!(!wam.machine_st.fail);
 
@@ -629,7 +665,11 @@ mod test {
             section.push_cell(empty_list_as_cell!());
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
         assert!(!wam.machine_st.fail);
@@ -652,7 +692,11 @@ mod test {
             section.push_cell(empty_list_as_cell!());
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
         assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b'));
@@ -676,7 +720,11 @@ mod test {
             section.push_cell(empty_list_as_cell!());
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
         assert!(!wam.machine_st.fail);
@@ -699,10 +747,17 @@ mod test {
             section.push_cell(heap_loc_as_cell!(5 + start));
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
-        assert_eq!(wam.machine_st.heap[5 + start], pstr_loc_as_cell!(heap_index!(0) + 3));
+        assert_eq!(
+            wam.machine_st.heap[5 + start],
+            pstr_loc_as_cell!(heap_index!(0) + 3)
+        );
         assert!(!wam.machine_st.fail);
 
         // #2293, test6.
@@ -723,7 +778,11 @@ mod test {
             section.push_cell(empty_list_as_cell!());
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
         assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c'));
@@ -750,7 +809,11 @@ mod test {
             section.push_cell(empty_list_as_cell!());
         });
 
-        unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+        unify!(
+            wam.machine_st,
+            list_loc_as_cell!(start),
+            pstr_loc_as_cell!(0)
+        );
 
         assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('b'));
         assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d'));
index 751b55b60d7f748054a636d919b37074ed8a1b92..51e45a4a7d0c85a9d8850abf637ec33579bf6fc2 100644 (file)
@@ -28,26 +28,26 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError
 fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
     let (focus, _cell) = subterm_index(term.heap, term.focus);
 
-    let name = match term_predicate_key(term.heap, focus+3) {
+    let name = match term_predicate_key(term.heap, focus + 3) {
         Some((name, 0)) => name,
         _ => {
             return Err(CompilationError::InvalidDirective(
-                DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]),
+                DirectiveError::InvalidOpDeclNameType(term.heap[focus + 3]),
             ));
         }
     };
 
-    let spec = match term_predicate_key(term.heap, focus+2) {
+    let spec = match term_predicate_key(term.heap, focus + 2) {
         Some((name, _)) => name,
         None => {
             return Err(CompilationError::InvalidDirective(
-                DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]),
+                DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]),
             ));
         }
     };
 
     let spec = to_op_decl_spec(spec)?;
-    let prec = term.deref_loc(focus+1);
+    let prec = term.deref_loc(focus + 1);
 
     let prec = read_heap_cell!(prec,
         (HeapCellValueTag::Fixnum, n) => {
@@ -147,34 +147,34 @@ pub(super) fn setup_module_export_list(
     let mut focus = term.focus;
 
     loop {
-          read_heap_cell!(term.heap[focus],
-              (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
-                      if h == focus {
-                          break;
-                      } else {
-                          focus = h;
-                      }
-              }
-              (HeapCellValueTag::Lis, l) => {
-                      let term = FocusedHeapRefMut {
-                          heap: term.heap,
-                          focus: l,
-                      };
-
-                      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<UseModuleExport, Co
  * contained in src/lib/ops_and_meta_predicates.pl, which is loaded before
  * src/lib/builtins.pl.
  *
- * Meta-specs have three forms:
+ * Meta-specs have four forms:
  *
  * (:)  (the argument should be expanded with (:)/2 as described above)
  * +    (mode declarations under the mode syntax, which currently have no effect)
@@ -334,7 +334,7 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
     }
 
     let heap = loader.machine_heap();
-    let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus+1]));
+    let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus + 1]));
 
     read_heap_cell!(cell,
         (HeapCellValueTag::Str, s) => {
@@ -506,28 +506,27 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
                 let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
                 let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
 
-                let (module_name, key, term_loc) =
-                    if subterm_key_opt == Some((atom!(":"), 2)) {
-                        match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) {
-                            Some(QualifiedNameInfo {
-                                module_name,
-                                name,
-                                arity,
-                                qualified_term_loc,
-                            }) => (
-                                module_name,
-                                (name, arity + supp_args),
-                                qualified_term_loc,
-                            ),
-                            None => {
-                                continue;
-                            }
+                let (module_name, key, term_loc) = if subterm_key_opt == Some((atom!(":"), 2)) {
+                    match get_qualified_name(
+                        loader.machine_heap(),
+                        subterm_loc + 1,
+                        subterm_loc + 2,
+                    ) {
+                        Some(QualifiedNameInfo {
+                            module_name,
+                            name,
+                            arity,
+                            qualified_term_loc,
+                        }) => (module_name, (name, arity + supp_args), qualified_term_loc),
+                        None => {
+                            continue;
                         }
-                    } else {
-                        (module_name, (name, arity + supp_args), subterm_loc)
-                    };
+                    }
+                } else {
+                    (module_name, (name, arity + supp_args), subterm_loc)
+                };
 
-                if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), key.1, term_loc) {
+                if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), term_loc) {
                     index_ptrs.insert(term_loc, index_ptr);
                     continue;
                 }
@@ -642,7 +641,12 @@ impl Preprocessor {
             let classifier = VariableClassifier::new(self.settings.default_call_policy());
             let var_data = classifier.classify_fact(loader, &term)?;
 
-            Ok((Fact { term_loc: term.focus }, var_data))
+            Ok((
+                Fact {
+                    term_loc: term.focus,
+                },
+                var_data,
+            ))
         } else {
             Err(CompilationError::InadmissibleFact)
         }
@@ -660,7 +664,13 @@ impl Preprocessor {
         let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
 
         if term_predicate_key(heap, head_loc).is_some() {
-            Ok((Rule { term_loc: term.focus, clauses }, var_data))
+            Ok((
+                Rule {
+                    term_loc: term.focus,
+                    clauses,
+                },
+                var_data,
+            ))
         } else {
             Err(CompilationError::InvalidRuleHead)
         }
index 2dccc87db5713de5c4fe2d39505da93d8aae386e..1dfd8f464642e62e44d58f4104866a978dea125e 100644 (file)
@@ -181,10 +181,7 @@ fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usi
         byte_offset += c.len_utf8();
     }
 
-    (
-        char_count,
-        Heap::neighboring_cell_offset(pstr_loc + byte_offset),
-    )
+    (char_count, Heap::pstr_tail_idx(pstr_loc + byte_offset))
 }
 
 fn pstr_segment_char_count_up_to(
@@ -217,10 +214,9 @@ fn pstr_segment_char_count_up_to(
             pstr_loc: pstr_loc + byte_offset,
         }
     } else {
-        let tail_loc = Heap::neighboring_cell_offset(pstr_loc + byte_offset);
         PStrSegmentCountResult::End {
             char_count,
-            tail_loc,
+            tail_loc: Heap::pstr_tail_idx(pstr_loc + byte_offset),
         }
     }
 }
@@ -567,6 +563,12 @@ struct AttrListMatch {
     prev_tail: Option<usize>,
 }
 
+#[derive(Debug)]
+pub(crate) struct FindallCopyInfo {
+    offset: usize,
+    pstr_threshold: usize,
+}
+
 impl MachineState {
     #[inline(always)]
     pub(crate) fn unattributed_var(&mut self) {
@@ -648,9 +650,8 @@ impl MachineState {
             loop {
                 read_heap_cell!(value,
                     (HeapCellValueTag::PStrLoc, h) => {
-                        let (_, tail) = heap.scan_slice_to_str(h);
-                        // let (h_offset, _) = pstr_loc_and_offset(heap, h);
-                        return tail;
+                        let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
+                        return tail_idx;
                     }
                     (HeapCellValueTag::Lis, h) => {
                         return h+1;
@@ -855,17 +856,10 @@ impl MachineState {
         &mut self,
         lh_offset: usize,
         copy_target: HeapCellValue,
-    ) -> Result<usize, usize> {
+    ) -> Result<FindallCopyInfo, usize> {
         let threshold = self.lifted_heap.cell_len() - lh_offset;
 
-        let mut copy_ball_term = CopyBallTerm::new(
-            &mut self.attr_var_init.attr_var_queue,
-            &mut self.stack,
-            &mut self.heap,
-            &mut self.lifted_heap,
-        );
-
-        let mut writer = copy_ball_term.reserve(3)?;
+        let mut writer = self.lifted_heap.reserve(3)?;
 
         writer.write_with(|section| {
             section.push_cell(list_loc_as_cell!(threshold + 1));
@@ -873,9 +867,21 @@ impl MachineState {
             section.push_cell(heap_loc_as_cell!(threshold + 2));
         });
 
-        copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?;
+        let old_lifted_cell_len = self.lifted_heap.cell_len();
+
+        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<AtomOrString> {
         read_heap_cell!(value,
-            /*
-            (HeapCellValueTag::CStr, cstr_atom) => {
-                // avoid allocating a String if possible:
-                // We must be careful to preserve the string "[]" as is,
-                // instead of turning it into the atom [], i.e., "".
-                if cstr_atom == atom!("[]") {
-                    Some(AtomOrString::String("[]".to_string()))
-                } else {
-                    Some(AtomOrString::Atom(cstr_atom))
-                }
-            }
-            */
             (HeapCellValueTag::Atom, (atom, arity)) => {
                 if arity == 0 {
                     // ... likewise.
@@ -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(
index 9a1f9fa699503bf2c2769d00cfc47a8dfcf2ec98..f8488af7ed4ec9a836f51394b341629ef4a5c542 100644 (file)
@@ -44,14 +44,19 @@ impl<'a> BootstrappingTermStream<'a> {
         listing_src: ListingSource,
     ) -> Self {
         let lexer_parser = LexerParser::new(stream, machine_st);
-        Self { lexer_parser, listing_src }
+        Self {
+            lexer_parser,
+            listing_src,
+        }
     }
 }
 
 impl<'a> TermStream for BootstrappingTermStream<'a> {
     #[inline]
     fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
-        let result = self.lexer_parser.read_term(op_dir, Tokens::Default)
+        let result = self
+            .lexer_parser
+            .read_term(op_dir, Tokens::Default)
             .map_err(CompilationError::from);
 
         result
@@ -125,7 +130,9 @@ pub struct InlineTermStream {}
 
 impl TermStream for InlineTermStream {
     fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
-        Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default())))
+        Err(CompilationError::from(ParserError::unexpected_eof(
+            ParserErrorSrc::default(),
+        )))
     }
 
     fn eof(&mut self) -> Result<bool, CompilationError> {
index 5b7c23e82a710563fb1c79491d132f4d97ccc499..899fc3ac56de47579d844be57b7c3c044f396ef6 100644 (file)
@@ -507,11 +507,9 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
     if value.is_ref() && !value.is_stack_var() {
         machine_st.heap[0] = value;
 
-        for cell in stackful_preorder_iter::<NonListElider>(
-            &mut machine_st.heap,
-            &mut machine_st.stack,
-            0,
-        ) {
+        for cell in
+            stackful_preorder_iter::<NonListElider>(&mut machine_st.heap, &mut machine_st.stack, 0)
+        {
             let cell = unmark_cell_bits!(cell);
 
             if let Some(inner_r) = cell.as_var() {
index 5463c0c82e0c8f8fe70d1ce079ab12e69f2312be..eb8a48b4ffffcf05f96e82dd3c7a07181e4b1cd4 100644 (file)
@@ -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::<HeapCellValue>()};
+    ($idx:expr) => {
+        ($idx) * std::mem::size_of::<HeapCellValue>()
+    };
 }
 
 macro_rules! cell_index {
-    ($idx:expr) => {(($idx) / std::mem::size_of::<HeapCellValue>())};
+    ($idx:expr) => {
+        (($idx) / std::mem::size_of::<HeapCellValue>())
+    };
 }
index 45335c889413a07139b6e16c9ca61a76df9fa87b..b873e61be148c17dce406e99440067f41fbba740 100644 (file)
@@ -141,7 +141,11 @@ macro_rules! fixnum {
     ($n:expr, $arena:expr) => {
         Fixnum::build_with_checked($n)
             .map(|n| fixnum_as_cell!(n))
-            .unwrap_or_else(|_| typed_arena_ptr_as_cell!(arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>))
+            .unwrap_or_else(|_| {
+                typed_arena_ptr_as_cell!(
+                    arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>
+                )
+            })
     };
     ($wrapper:ty, $n:expr, $arena:expr) => {
         Fixnum::build_with_checked($n)
@@ -614,10 +618,7 @@ impl Literal {
 
 pub type Var = Rc<String>;
 
-pub(crate) fn subterm_index(
-    heap: &impl SizedHeap,
-    subterm_loc: usize,
-) -> (usize, HeapCellValue) {
+pub(crate) fn subterm_index(heap: &impl SizedHeap, subterm_loc: usize) -> (usize, HeapCellValue) {
     let subterm = heap[subterm_loc];
 
     if subterm.is_ref() {
@@ -710,16 +711,10 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
 }
  */
 
-pub(crate) fn fetch_index_ptr(
-    heap: &impl SizedHeap,
-    arity: usize,
-    term_loc: usize,
-) -> Option<CodeIndex> {
-    if term_loc + arity + 1 >= heap.cell_len() || heap.pstr_at(term_loc + arity + 1) {
-        return None;
-    }
+pub(crate) fn fetch_index_ptr(heap: &impl SizedHeap, term_loc: usize) -> Option<CodeIndex> {
+    let index_cell_loc = term_loc.saturating_sub(1);
 
-    read_heap_cell!(heap[term_loc + arity + 1],
+    read_heap_cell!(heap[index_cell_loc],
         (HeapCellValueTag::Cons, c) => {
             match_untyped_arena_ptr!(c,
                (ArenaHeaderTag::IndexPtr, ptr) => {
@@ -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<usize> {
-    let start_term = heap_bound_store(
-        heap,
-        heap_bound_deref(heap, start_term),
-    );
+    let start_term = heap_bound_store(heap, heap_bound_deref(heap, start_term));
 
     if let HeapCellValueTag::Str = start_term.get_tag() {
         let s = start_term.get_value() as usize;
@@ -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<PredicateKey> {
+pub fn term_predicate_key(heap: &impl SizedHeap, mut term_loc: usize) -> Option<PredicateKey> {
     loop {
         read_heap_cell!(heap[term_loc],
             (HeapCellValueTag::Atom, (name, arity)) => {
@@ -874,10 +863,7 @@ pub fn inverse_var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) ->
         let var_loc = var.get_value() as usize;
 
         if count > 1 {
-            inverse_var_locs.insert(
-                var_loc,
-                Rc::new(format!("_{}", var_loc)),
-            );
+            inverse_var_locs.insert(var_loc, Rc::new(format!("_{}", var_loc)));
         }
     }
 
index 800e5f44e24c349fdc6e2d3012e7221447606cf3..b357c3e8e450672cc761cd36387179cd41dcde7f 100644 (file)
@@ -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<Integer>
-                            ))
+                            Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                n,
+                                &mut self.machine_st.arena
+                            )
+                                as TypedArenaPtr<Integer>))
                         })
                         .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<Integer>
-                            ))
+                            Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                n,
+                                &mut self.machine_st.arena
+                            )
+                                as TypedArenaPtr<Integer>))
                         })
                         .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<Integer>
-                            ))
+                            Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                n,
+                                &mut self.machine_st.arena
+                            )
+                                as TypedArenaPtr<Integer>))
                         })
                         .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::<Integer>()
                             .map(|n| {
-                                Token::Literal(typed_arena_ptr_as_cell!(
-                                    arena_alloc!(
-                                        n,
-                                        &mut self.machine_st.arena
-                                    ) as TypedArenaPtr<Integer>
-                                ))
+                                Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                    n,
+                                    &mut self.machine_st.arena
+                                )
+                                    as TypedArenaPtr<Integer>))
                             })
                             .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                     })
@@ -815,12 +806,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
                         token
                             .parse::<Integer>()
                             .map(|n| {
-                                Token::Literal(typed_arena_ptr_as_cell!(
-                                    arena_alloc!(
-                                        n,
-                                        &mut self.machine_st.arena
-                                    ) as TypedArenaPtr<Integer>
-                                ))
+                                Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                    n,
+                                    &mut self.machine_st.arena
+                                )
+                                    as TypedArenaPtr<Integer>))
                             })
                             .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::<i64>()
-                            .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::<Integer>()
                                     .map(|n| {
-                                        Token::Literal(typed_arena_ptr_as_cell!(
-                                            arena_alloc!(
-                                                n,
-                                                &mut self.machine_st.arena
-                                            ) as TypedArenaPtr<Integer>
-                                        ))
-                                    })
-                                    .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<Integer>))
                                     })
+                                    .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::<i64>()
-                            .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::<Integer>()
                                     .map(|n| {
-                                        Token::Literal(typed_arena_ptr_as_cell!(
-                                            arena_alloc!(
-                                                n,
-                                                &mut self.machine_st.arena
-                                            ) as TypedArenaPtr<Integer>
-                                        ))
-                                    })
-                                    .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<Integer>))
                                     })
+                                    .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::<i64>()
-                            .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::<Integer>()
                                     .map(|n| {
-                                        Token::Literal(typed_arena_ptr_as_cell!(
-                                            arena_alloc!(
-                                                n,
-                                                &mut self.machine_st.arena
-                                            ) as TypedArenaPtr<Integer>
-                                        ))
-                                    })
-                                    .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<Integer>))
                                     })
+                                    .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::<i64>()
-                            .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::<Integer>()
                                     .map(|n| {
-                                        Token::Literal(typed_arena_ptr_as_cell!(
-                                            arena_alloc!(
-                                                n,
-                                                &mut self.machine_st.arena
-                                            ) as TypedArenaPtr<Integer>
-                                        ))
-                                    })
-                                    .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<Integer>))
                                     })
+                                    .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                             })
                     })
             } else {
@@ -964,12 +934,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
                         token
                             .parse::<Integer>()
                             .map(|n| {
-                                Token::Literal(typed_arena_ptr_as_cell!(
-                                    arena_alloc!(
-                                        n,
-                                        &mut self.machine_st.arena
-                                    ) as TypedArenaPtr<Integer>
-                                ))
+                                Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                    n,
+                                    &mut self.machine_st.arena
+                                )
+                                    as TypedArenaPtr<Integer>))
                             })
                             .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                     })
@@ -982,12 +951,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
                     token
                         .parse::<Integer>()
                         .map(|n| {
-                            Token::Literal(typed_arena_ptr_as_cell!(
-                                arena_alloc!(
-                                    n,
-                                    &mut self.machine_st.arena
-                                ) as TypedArenaPtr<Integer>
-                            ))
+                            Token::Literal(typed_arena_ptr_as_cell!(arena_alloc!(
+                                n,
+                                &mut self.machine_st.arena
+                            )
+                                as TypedArenaPtr<Integer>))
                         })
                         .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                 })
index c726ced20a0b4c2b07e340b41c1e4dc47cc20035..00c1d101136f2cda608bc231e7ffc0b8d24335b3 100644 (file)
@@ -187,7 +187,9 @@ struct Parser<'a> {
     inverse_var_locs: InverseVarLocs,
 }
 
-pub fn read_tokens<R: CharRead>(lexer: &mut LexerParser<R>) -> Result<(Vec<Token>, usize), ParserError> {
+pub fn read_tokens<R: CharRead>(
+    lexer: &mut LexerParser<R>,
+) -> Result<(Vec<Token>, usize), ParserError> {
     let mut tokens = vec![];
     let mut term_size = 0;
 
@@ -264,9 +266,9 @@ pub(crate) fn as_partial_string(
                tail = heap[l+1];
            }
            (HeapCellValueTag::PStrLoc, l) => {
-               let (pstr, tail_loc) = heap.scan_slice_to_str(l);
+               let HeapStringScan { string: pstr, tail_idx } = heap.scan_slice_to_str(l);
                string += pstr;
-               tail = heap[tail_loc];
+               tail = heap[tail_idx];
            }
            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
                if heap[h] != tail {
@@ -306,8 +308,7 @@ impl<'a> Parser<'a> {
             TokenType::Comma => Some(atom!(",")),
             TokenType::Term { heap_loc } => {
                 if heap_loc.is_ref() {
-                    term_predicate_key(&self.terms, heap_loc.get_value() as usize)
-                        .map(|key| key.0)
+                    term_predicate_key(&self.terms, heap_loc.get_value() as usize).map(|key| key.0)
                 } else {
                     None
                 }
@@ -392,7 +393,8 @@ impl<'a> Parser<'a> {
 
     fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
         let h = self.terms.cell_len();
-        self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom)));
+        self.terms
+            .write_with(|section| section.push_cell(atom_as_cell!(atom)));
         self.stack.push(TokenDesc {
             tt: TokenType::Term {
                 heap_loc: heap_loc_as_cell!(h),
@@ -438,10 +440,12 @@ impl<'a> Parser<'a> {
                         section.push_cell(list_loc_as_cell!(h));
                     });
 
-                    TokenType::Term { heap_loc: heap_loc_as_cell!(h + 2) }
+                    TokenType::Term {
+                        heap_loc: heap_loc_as_cell!(h + 2),
+                    }
                 } else {
-                    self.terms.write_with(|section| {
-                        match section.push_pstr(&s) {
+                    self.terms
+                        .write_with(|section| match section.push_pstr(&s) {
                             Some(pstr_loc_cell) => {
                                 section.push_cell(empty_list_as_cell!());
                                 let h = section.cell_len();
@@ -451,10 +455,11 @@ impl<'a> Parser<'a> {
                             None => {
                                 section.push_cell(empty_list_as_cell!());
                             }
-                        }
-                    });
+                        });
 
-                    TokenType::Term { heap_loc: pstr_cell }
+                    TokenType::Term {
+                        heap_loc: pstr_cell,
+                    }
                 }
             }
             Token::Literal(c) => {
@@ -478,13 +483,14 @@ impl<'a> Parser<'a> {
 
                         if var.trim() != "_" {
                             self.var_locs.insert(var.clone(), heap_loc);
-                            self.inverse_var_locs.insert(heap_loc.get_value() as usize, var);
+                            self.inverse_var_locs
+                                .insert(heap_loc.get_value() as usize, var);
                         }
 
                         TokenType::Term { heap_loc }
                     }
                 }
-            },
+            }
             Token::Comma => TokenType::Comma,
             Token::Open => TokenType::Open,
             Token::Close => TokenType::Close,
@@ -619,15 +625,21 @@ impl<'a> Parser<'a> {
         let term_idx = self.terms.cell_len();
 
         let push_structure = |parser: &mut Self, name: Atom| -> TokenType {
-            parser.terms.write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
+            parser
+                .terms
+                .write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
 
             for idx in (stack_len + 2..parser.stack.len()).step_by(2) {
                 let subterm = parser.term_from_stack(idx).unwrap();
-                parser.terms.write_with(|section| section.push_cell(subterm));
+                parser
+                    .terms
+                    .write_with(|section| section.push_cell(subterm));
             }
 
             let str_loc_idx = parser.terms.cell_len();
-            parser.terms.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
+            parser
+                .terms
+                .write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
 
             TokenType::Term {
                 heap_loc: heap_loc_as_cell!(str_loc_idx),
@@ -709,23 +721,20 @@ impl<'a> Parser<'a> {
     }
 
     fn loc_to_err_src(&self) -> ParserErrorSrc {
-        ParserErrorSrc { line_num: *self.line_num, col_num: *self.col_num }
+        ParserErrorSrc {
+            line_num: *self.line_num,
+            col_num: *self.col_num,
+        }
     }
 
     fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
         if let Some(term) = self.term_from_stack(index - 1) {
             let mut op_desc = self.stack[index - 1];
-            let mut term = heap_bound_store(
-                &self.terms,
-                heap_bound_deref(
-                    &self.terms,
-                    term,
-                ),
-            );
-
-            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()));
index e0b5d7d924e3d953a3a0b4aac336b5c7012461e4..549cdef0e5ff4fdc95f4f8dd5d914da873191af5 100644 (file)
@@ -58,7 +58,7 @@ impl MachineState {
         let op_dir = CompositeOpDir::new(op_dir, None);
 
         let term_result = lexer_parser.read_term(&op_dir, Tokens::Default);
-        let lines_read  = lexer_parser.line_num();
+        let lines_read = lexer_parser.line_num();
 
         term_result.map(|term| (term, lines_read))
     }
index e9caa4a73e748e550b82cc09cd2056df80b5144b..5eee7fcc9d4546e89ff0992114090b6e1ab01f2d 100644 (file)
@@ -369,8 +369,8 @@ impl HeapCellValue {
                     name == atom!("[]") && arity == 0
                 }
                 (HeapCellValueTag::PStrLoc, h) => {
-                    let (_s, tail_loc) = heap.scan_slice_to_str(h);
-                    self = heap[tail_loc];
+                    let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
+                    self = heap[tail_idx];
                     continue;
                 }
                 (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
@@ -399,8 +399,7 @@ impl HeapCellValue {
                 | HeapCellValueTag::Var
                 | HeapCellValueTag::StackVar
                 | HeapCellValueTag::AttrVar
-                | HeapCellValueTag::PStrLoc
-                // | HeapCellValueTag::PStrOffset
+                | HeapCellValueTag::PStrLoc // | HeapCellValueTag::PStrOffset
         )
     }
 
@@ -503,9 +502,7 @@ impl HeapCellValue {
     #[inline]
     pub fn to_atom(self) -> Option<Atom> {
         match self.get_tag() {
-            HeapCellValueTag::Atom => {
-                Some(AtomCell::from_bytes(self.into_bytes()).get_name())
-            }
+            HeapCellValueTag::Atom => Some(AtomCell::from_bytes(self.into_bytes()).get_name()),
             _ => None,
         }
     }
@@ -773,7 +770,8 @@ impl Sub<i64> for HeapCellValue {
                     HeapCellValue::build_with(tag, self.get_value() + rhs.unsigned_abs())
                 }
                 tag @ HeapCellValueTag::PStrLoc => {
-                    let value = self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
+                    let value =
+                        self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
                     HeapCellValue::build_with(tag, value as u64)
                 }
                 _ => self,
index a2b9891872f85807dc9c91c1c60ba00881aabde4..a22e5be18785059606efc2b4928aea180f7ed70f 100644 (file)
@@ -1,5 +1,5 @@
-use crate::parser::ast::*;
 use crate::forms::GenContext;
+use crate::parser::ast::*;
 
 use bit_set::*;
 use fxhash::FxBuildHasher;
@@ -88,7 +88,10 @@ pub enum VarAlloc {
         safety: VarSafetyStatus,
         to_perm_var_num: Option<usize>,
     },
-    Perm { reg: usize, allocation: PermVarAllocation }, // stack offset, allocation info
+    Perm {
+        reg: usize,
+        allocation: PermVarAllocation,
+    }, // stack offset, allocation info
 }
 
 impl VarAlloc {
@@ -152,7 +155,10 @@ pub struct VariableRecord {
 impl Default for VariableRecord {
     fn default() -> Self {
         VariableRecord {
-            allocation: VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending },
+            allocation: VarAlloc::Perm {
+                reg: 0,
+                allocation: PermVarAllocation::Pending,
+            },
             num_occurrences: 0,
             running_count: 0,
         }