]> Repositorios git - scryer-prolog.git/commitdiff
remove Term
authorMark Thom <[email protected]>
Tue, 16 Jul 2024 21:38:22 +0000 (15:38 -0600)
committerMark Thom <[email protected]>
Sat, 26 Oct 2024 18:55:56 +0000 (12:55 -0600)
44 files changed:
build/instructions_template.rs
src/allocator.rs
src/arithmetic.rs
src/codegen.rs
src/debray_allocator.rs
src/forms.rs
src/heap_iter.rs
src/heap_print.rs
src/indexing.rs
src/iterators.rs
src/lib/atts.pl
src/lib/builtins.pl
src/lib/si.pl
src/loader.pl
src/machine/arithmetic_ops.rs
src/machine/attributed_variables.rs
src/machine/compile.rs
src/machine/disjuncts.rs
src/machine/dispatch.rs
src/machine/gc.rs
src/machine/lib_machine.rs
src/machine/load_state.rs
src/machine/loader.rs
src/machine/machine_errors.rs
src/machine/machine_indices.rs
src/machine/machine_state.rs
src/machine/mock_wam.rs
src/machine/preprocessor.rs
src/machine/raw_block.rs
src/machine/stack.rs
src/machine/streams.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/raw_block.rs
src/read.rs
src/targets.rs
src/tests/builtins.pl
src/variable_records.rs
tests/scryer/src_tests.rs

index 5e64f3d796af26e6be4fd5db26cbb4015fbd6e51..f38f3d2c4e9951b0add0dbd9690193f1e79f7eb2 100644 (file)
@@ -192,9 +192,9 @@ enum ReplCodePtr {
     DynamicProperty,
     #[strum_discriminants(strum(props(Arity = "3", Name = "$abolish_clause")))]
     AbolishClause,
-    #[strum_discriminants(strum(props(Arity = "3", Name = "$asserta")))]
+    #[strum_discriminants(strum(props(Arity = "2", Name = "$asserta")))]
     Asserta,
-    #[strum_discriminants(strum(props(Arity = "3", Name = "$assertz")))]
+    #[strum_discriminants(strum(props(Arity = "2", Name = "$assertz")))]
     Assertz,
     #[strum_discriminants(strum(props(Arity = "4", Name = "$retract_clause")))]
     Retract,
index e961b9757a613a3634adda3626d62b14ce416877..cd32f41fed6e47f568ab4fcb3e5f76900b85a6ff 100644 (file)
@@ -4,8 +4,6 @@ use crate::forms::*;
 use crate::instructions::*;
 use crate::targets::*;
 
-use std::cell::Cell;
-
 pub(crate) trait Allocator {
     fn new() -> Self;
 
@@ -19,22 +17,21 @@ pub(crate) trait Allocator {
     fn mark_non_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
         lvl: Level,
+        heap_loc: usize,
         context: GenContext,
-        cell: &'a Cell<RegType>,
         code: &mut CodeDeque,
-    );
+    ) -> RegType;
 
     #[allow(clippy::too_many_arguments)]
     fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
         var_num: usize,
         lvl: Level,
-        cell: &Cell<VarReg>,
-        term_loc: GenContext,
+        context: GenContext,
         code: &mut CodeDeque,
         r: RegType,
         is_new_var: bool,
-    );
+    ) -> RegType;
 
     fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType;
 
@@ -42,14 +39,13 @@ pub(crate) trait Allocator {
         &mut self,
         var_num: usize,
         lvl: Level,
-        cell: &Cell<VarReg>,
         context: GenContext,
         code: &mut CodeDeque,
-    );
+    ) -> RegType;
 
     fn reset(&mut self);
     fn reset_arg(&mut self, arg_num: usize);
-    fn reset_at_head(&mut self, args: &[Term]);
+    fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize);
     fn reset_contents(&mut self);
 
     fn advance_arg(&mut self);
index 59a4f4cdc989641ff142b35a143165beaf080d74..ced1483e45d5d60193292246a5f131bedf39c529 100644 (file)
@@ -7,6 +7,8 @@ use crate::debray_allocator::*;
 use crate::forms::*;
 use crate::instructions::*;
 use crate::iterators::*;
+use crate::machine::stack::Stack;
+use crate::parser::ast::FocusedHeap;
 use crate::targets::QueryInstruction;
 use crate::types::*;
 
@@ -20,7 +22,6 @@ use dashu::base::BitTest;
 use num_order::NumOrd;
 use ordered_float::{Float, OrderedFloat};
 
-use std::cell::Cell;
 use std::cmp::{max, min, Ordering};
 use std::convert::TryFrom;
 use std::f64;
@@ -51,13 +52,14 @@ impl Default for ArithmeticTerm {
     }
 }
 
+pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);
+
+/*
 #[derive(Debug)]
 pub(crate) struct ArithInstructionIterator<'a> {
     state_stack: Vec<TermIterState<'a>>,
 }
 
-pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);
-
 impl<'a> ArithInstructionIterator<'a> {
     fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
         self.state_stack
@@ -134,13 +136,6 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
     }
 }
 
-#[derive(Debug)]
-pub(crate) struct ArithmeticEvaluator<'a> {
-    marker: &'a mut DebrayAllocator,
-    interm: Vec<ArithmeticTerm>,
-    interm_c: usize,
-}
-
 pub(crate) trait ArithmeticTermIter<'a> {
     type Iter: Iterator<Item = Result<ArithTermRef<'a>, ArithmeticError>>;
 
@@ -154,23 +149,31 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term {
         ArithInstructionIterator::from(self)
     }
 }
+*/
+
+#[derive(Debug)]
+pub(crate) struct ArithmeticEvaluator<'a> {
+    marker: &'a mut DebrayAllocator,
+    interm: Vec<ArithmeticTerm>,
+    interm_c: usize,
+}
 
-fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: &Literal) -> Result<(), ArithmeticError> {
+fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: Literal) -> Result<(), ArithmeticError> {
     match c {
-        Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(*n))),
-        Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(*n))),
+        Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(n))),
+        Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(n))),
         Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))),
-        Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))),
-        Literal::Atom(name) if name == &atom!("e") => interm.push(ArithmeticTerm::Number(
+        Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(n))),
+        Literal::Atom(name) if name == atom!("e") => interm.push(ArithmeticTerm::Number(
             Number::Float(OrderedFloat(std::f64::consts::E)),
         )),
-        Literal::Atom(name) if name == &atom!("pi") => interm.push(ArithmeticTerm::Number(
+        Literal::Atom(name) if name == atom!("pi") => interm.push(ArithmeticTerm::Number(
             Number::Float(OrderedFloat(std::f64::consts::PI)),
         )),
-        Literal::Atom(name) if name == &atom!("epsilon") => interm.push(ArithmeticTerm::Number(
+        Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
             Number::Float(OrderedFloat(f64::EPSILON)),
         )),
-        _ => return Err(ArithmeticError::NonEvaluableFunctor(*c, 0)),
+        _ => return Err(ArithmeticError::NonEvaluableFunctor(c, 0)),
     }
 
     Ok(())
@@ -309,44 +312,57 @@ impl<'a> ArithmeticEvaluator<'a> {
 
     pub(crate) fn compile_is(
         &mut self,
-        src: &'a Term,
-        term_loc: GenContext,
+        src: &mut FocusedHeap,
+        term_loc: usize,
+        context: GenContext,
         arg: usize,
     ) -> Result<ArithCont, ArithmeticError> {
         let mut code = CodeDeque::new();
-
-        for term_ref in src.iter()? {
-            match term_ref? {
-                ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
-                ArithTermRef::Var(lvl, cell, name) => {
-                    let var_num = name.to_var_num().unwrap();
-
-                    let r = if lvl == Level::Shallow {
-                        self.marker
-                            .mark_non_callable(var_num, arg, term_loc, cell, &mut code)
-                    } else if term_loc.is_last() || cell.get().norm().reg_num() == 0 {
-                        let r = self.marker.get_binding(var_num);
+        let mut stack = Stack::uninitialized();
+        let mut iter = query_iterator::<false>(&mut src.heap, &mut stack, term_loc);
+
+        while let Some(term) = iter.next() {
+            read_heap_cell!(term,
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let lvl = iter.level();
+                    let var_ptr = src.var_locs.read_next_var_ptr_at_key(h).unwrap();
+                    let var_num = var_ptr.to_var_num().unwrap();
+                    let old_r = self.marker.get_var_binding(var_num);
+
+                    let r = if lvl == Level::Root {
+                        self.marker.mark_non_callable(var_num, arg, context, &mut code)
+                    } else if context.is_last() || old_r.reg_num() == 0 {
+                        let r = old_r;
 
                         if r.reg_num() == 0 {
                             self.marker.mark_var::<QueryInstruction>(
-                                var_num, lvl, cell, term_loc, &mut code,
-                            );
-                            cell.get().norm()
+                                var_num, lvl, context, &mut code,
+                            )
                         } else {
                             self.marker.increment_running_count(var_num);
                             r
                         }
                     } else {
                         self.marker.increment_running_count(var_num);
-                        cell.get().norm()
+                        old_r
                     };
 
                     self.interm.push(ArithmeticTerm::Reg(r));
                 }
-                ArithTermRef::Op(name, arity) => {
-                    code.push_back(self.instr_from_clause(name, arity)?);
+                (HeapCellValueTag::Atom, (name, arity)) => {
+                    if arity == 0 {
+                        push_literal(&mut self.interm, Literal::Atom(name))?;
+                    } else {
+                        code.push_back(self.instr_from_clause(name, arity)?);
+                    }
                 }
-            }
+                _ => {
+                    match Literal::try_from(term) {
+                        Ok(lit) => push_literal(&mut self.interm, lit)?,
+                        _ => unreachable!()
+                    }
+                }
+            );
         }
 
         Ok((code, self.interm.pop()))
index 5de8558432b6e6c6a56b5665926e92ddfac3f845..24f90c8b771e45f5cb1d74357823dff89f248e90 100644 (file)
@@ -1,4 +1,5 @@
 use crate::allocator::*;
+use crate::arena::ArenaHeaderTag;
 use crate::arithmetic::*;
 use crate::atom_table::*;
 use crate::debray_allocator::*;
@@ -6,6 +7,7 @@ use crate::forms::*;
 use crate::indexing::*;
 use crate::instructions::*;
 use crate::iterators::*;
+use crate::machine::heap::{heap_bound_deref, heap_bound_store};
 use crate::parser::ast::*;
 use crate::targets::*;
 use crate::types::*;
@@ -13,11 +15,14 @@ use crate::variable_records::*;
 
 use crate::machine::disjuncts::*;
 use crate::machine::machine_errors::*;
+use crate::machine::machine_indices::CodeIndex;
+use crate::machine::machine_state::pstr_loc_and_offset;
+use crate::machine::stack::Stack;
 
 use fxhash::FxBuildHasher;
+use indexmap::IndexMap;
 use indexmap::IndexSet;
 
-use std::cell::Cell;
 use std::collections::VecDeque;
 
 #[derive(Debug)]
@@ -276,37 +281,45 @@ pub(crate) struct CodeGenerator<'a> {
     pub(crate) skeleton: PredicateSkeleton,
 }
 
-impl DebrayAllocator {
-    fn mark_var_in_non_callable(
-        &mut self,
-        var_num: usize,
-        term_loc: GenContext,
-        vr: &Cell<VarReg>,
-        code: &mut CodeDeque,
-    ) -> RegType {
-        self.mark_var::<QueryInstruction>(var_num, Level::Shallow, vr, term_loc, code);
-        vr.get().norm()
+fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) {
+    let subterm = heap[subterm_loc];
+
+    if subterm.is_ref() {
+        let subterm = heap_bound_deref(heap, subterm);
+        let subterm_loc = subterm.get_value() as usize;
+        let subterm = heap_bound_store(heap, subterm);
+
+        let subterm_loc = if subterm.is_ref() {
+            subterm.get_value() as usize
+        } else {
+            subterm_loc
+        };
+
+        (subterm_loc, subterm)
+    } else {
+        (subterm_loc, subterm)
     }
+}
 
+impl DebrayAllocator {
     pub(crate) fn mark_non_callable(
         &mut self,
         var_num: usize,
         arg: usize,
-        term_loc: GenContext,
-        vr: &Cell<VarReg>,
+        context: GenContext,
         code: &mut CodeDeque,
     ) -> RegType {
-        match self.get_binding(var_num) {
+        match self.get_var_binding(var_num) {
             RegType::Temp(t) if t != 0 => RegType::Temp(t),
             RegType::Perm(p) if p != 0 => {
-                if let GenContext::Last(_) = term_loc {
-                    self.mark_var_in_non_callable(var_num, term_loc, vr, code);
+                if let GenContext::Last(_) = context {
+                    self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
                     temp_v!(arg)
                 } else {
-                    if let VarAlloc::Perm(_, PermVarAllocation::Pending) =
+                    if let VarAlloc::Perm { allocation: PermVarAllocation::Pending, .. } =
                         &self.var_data.records[var_num].allocation
                     {
-                        self.mark_var_in_non_callable(var_num, term_loc, vr, code);
+                        self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
                     } else {
                         self.increment_running_count(var_num);
                     }
@@ -314,35 +327,14 @@ impl DebrayAllocator {
                     RegType::Perm(p)
                 }
             }
-            _ => self.mark_var_in_non_callable(var_num, term_loc, vr, code),
-        }
-    }
-}
-
-// if the final argument of the structure is a Literal::Index,
-// decrement the arity of the PutStructure instruction by 1.
-fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term) {
-    match instr {
-        Instruction::PutStructure(_, ref mut arity, _)
-        | Instruction::GetStructure(.., ref mut arity, _) => {
-            if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
-                // it is acceptable if arity == 0 is the result of
-                // this decrement. call/N will have to read the index
-                // constant for '$call_inline' to succeed. to find it,
-                // it must know the heap location of the index.
-                // self.store must stop before reading the atom into a
-                // register.
-
-                *arity -= 1;
-            }
+            _ => self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code),
         }
-        _ => {}
     }
 }
 
 trait AddToFreeList<'a, Target: CompilationTarget<'a>> {
     fn add_term_to_free_list(&mut self, r: RegType);
-    fn add_subterm_to_free_list(&mut self, term: &Term);
+    fn add_subterm_to_free_list(&mut self, r: RegType);
 }
 
 impl<'a, 'b> AddToFreeList<'a, FactInstruction> for CodeGenerator<'b> {
@@ -350,7 +342,7 @@ impl<'a, 'b> AddToFreeList<'a, FactInstruction> for CodeGenerator<'b> {
         self.marker.add_reg_to_free_list(r);
     }
 
-    fn add_subterm_to_free_list(&mut self, _term: &Term) {}
+    fn add_subterm_to_free_list(&mut self, _r: RegType) {}
 }
 
 impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> {
@@ -358,21 +350,33 @@ impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> {
     fn add_term_to_free_list(&mut self, _r: RegType) {}
 
     #[inline(always)]
-    fn add_subterm_to_free_list(&mut self, term: &Term) {
-        if let Some(cell) = structure_cell(term) {
-            self.marker.add_reg_to_free_list(cell.get());
-        }
+    fn add_subterm_to_free_list(&mut self, r: RegType) {
+        self.marker.add_reg_to_free_list(r);
     }
 }
 
-fn structure_cell(term: &Term) -> Option<&Cell<RegType>> {
-    match term {
-        &Term::Cons(ref cell, ..)
-        | &Term::Clause(ref cell, ..)
-        | Term::PartialString(ref cell, ..)
-        | Term::CompleteString(ref cell, ..) => Some(cell),
-        _ => None,
+fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
+    index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
+    heap: &[HeapCellValue],
+    arity: usize,
+    heap_loc: usize,
+) -> Option<Instruction> {
+    match fetch_index_ptr(heap, arity, heap_loc) {
+        Some(index_ptr) => {
+            let subterm = Literal::CodeIndex(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 = Literal::CodeIndex(*index_ptr);
+                    return Some(Target::constant_subterm(subterm));
+                }
+            // }
+        }
     }
+
+    None
 }
 
 impl<'b> CodeGenerator<'b> {
@@ -401,14 +405,13 @@ impl<'b> CodeGenerator<'b> {
 
     fn deep_var_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
         &mut self,
-        cell: &'a Cell<VarReg>,
         var_num: usize,
-        term_loc: GenContext,
+        context: GenContext,
         target: &mut CodeDeque,
     ) {
         if self.marker.var_data.records[var_num].num_occurrences > 1 {
             self.marker
-                .mark_var::<Target>(var_num, Level::Deep, cell, term_loc, target);
+                .mark_var::<Target>(var_num, Level::Deep, context, target);
         } else {
             Self::add_or_increment_void_instr::<Target>(target);
         }
@@ -416,134 +419,244 @@ impl<'b> CodeGenerator<'b> {
 
     fn subterm_to_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
         &mut self,
-        subterm: &'a Term,
-        term_loc: GenContext,
+        subterm: HeapCellValue,
+        var_locs: &mut VarLocs,
+        heap_loc: usize,
+        context: GenContext,
+        index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
         target: &mut CodeDeque,
-    ) {
-        match subterm {
-            &Term::AnonVar => {
-                Self::add_or_increment_void_instr::<Target>(target);
+    ) -> Option<RegType> {
+        let subterm = unmark_cell_bits!(subterm);
+
+        read_heap_cell!(subterm,
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                let var_ptr = var_locs.read_next_var_ptr_at_key(h).unwrap();
+
+                if var_ptr.is_anon() {
+                    Self::add_or_increment_void_instr::<Target>(target);
+                } else {
+                    let var_num = var_ptr.to_var_num().unwrap();
+
+                    self.deep_var_instr::<Target>(
+                        var_num,
+                        context,
+                        target,
+                    );
+                }
+
+                None
             }
-            &Term::Cons(ref cell, ..)
-            | &Term::Clause(ref cell, ..)
-            | Term::PartialString(ref cell, ..)
-            | Term::CompleteString(ref cell, ..) => {
-                self.marker
-                    .mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
-                target.push_back(Target::clause_arg_to_instr(cell.get()));
+            (HeapCellValueTag::Atom, (name, arity)) => {
+                debug_assert_eq!(arity, 0);
+
+                if index_ptrs.contains_key(&heap_loc) {
+                    let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target);
+                    target.push_back(Target::clause_arg_to_instr(r));
+                    return Some(r);
+                } else {
+                    target.push_back(Target::constant_subterm(Literal::Atom(name)));
+                }
+
+                None
             }
-            Term::Literal(_, ref constant) => {
-                target.push_back(Target::constant_subterm(*constant));
+            (HeapCellValueTag::Str
+             | HeapCellValueTag::Lis
+             | HeapCellValueTag::PStrLoc
+             | HeapCellValueTag::CStr) => {
+                let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target);
+                target.push_back(Target::clause_arg_to_instr(r));
+                return Some(r);
             }
-            Term::Var(ref cell, ref var_ptr) => {
-                self.deep_var_instr::<Target>(
-                    cell,
-                    var_ptr.to_var_num().unwrap(),
-                    term_loc,
-                    target,
-                );
+            _ => {
+                match Literal::try_from(subterm) {
+                    Ok(lit) => target.push_back(Target::constant_subterm(lit)),
+                    Err(_)  => unreachable!(),
+                }
+
+                None
             }
-        };
+        )
     }
 
-    fn compile_target<'a, Target, Iter>(&mut self, iter: Iter, term_loc: GenContext) -> CodeDeque
+    fn compile_target<'a, Target, Iter>(
+        &mut self,
+        mut iter: Iter,
+        index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
+        var_locs: &mut VarLocs,
+        context: GenContext,
+    ) -> CodeDeque
     where
         Target: crate::targets::CompilationTarget<'a>,
-        Iter: Iterator<Item = TermRef<'a>>,
+        Iter: TermIterator,
         CodeGenerator<'b>: AddToFreeList<'a, Target>,
     {
         let mut target = CodeDeque::new();
 
-        for term in iter {
-            match term {
-                TermRef::AnonVar(lvl @ Level::Shallow) => {
-                    if let GenContext::Head = term_loc {
-                        self.marker.advance_arg();
+        while let Some(term) = iter.next() {
+            let lvl = iter.level();
+            let term = unmark_cell_bits!(term);
+
+            read_heap_cell!(term,
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    if lvl == Level::Shallow {
+                        let var_ptr = var_locs.read_next_var_ptr_at_key(h).unwrap();
+
+                        if var_ptr.is_anon() {
+                            if let GenContext::Head = context {
+                                self.marker.advance_arg();
+                            } else {
+                                self.marker.mark_anon_var::<Target>(lvl, context, &mut target);
+                            }
+                        } else {
+                            self.marker.mark_var::<Target>(
+                                var_ptr.to_var_num().unwrap(),
+                                lvl,
+                                context,
+                                &mut target,
+                            );
+                        }
+                    }
+                }
+                (HeapCellValueTag::Atom, (name, arity)) => {
+                    let heap_loc = iter.focus().value() as usize;
+                    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) {
+                            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);
+                        } 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, Literal::Atom(name), r));
+                        }
                     } else {
-                        self.marker
-                            .mark_anon_var::<Target>(lvl, term_loc, &mut target);
+                        let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
+                        target.push_back(Target::to_structure(lvl, name, arity, r));
+
+                        <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
+                            self,
+                            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);
+
+                                self.subterm_to_instr::<Target>(
+                                    subterm, var_locs, subterm_loc, context, index_ptrs, &mut target,
+                                )
+                            })
+                            .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<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
+                                    self, r,
+                                );
+                            }
+                        }
                     }
                 }
-                TermRef::Clause(lvl, cell, name, terms) => {
-                    self.marker
-                        .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push_back(Target::to_structure(lvl, name, terms.len(), cell.get()));
+                (HeapCellValueTag::Lis, l) => {
+                    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);
+
+                    target.push_back(Target::to_list(lvl, r));
 
                     <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
                         self,
-                        cell.get(),
+                        r,
                     );
 
-                    if let Some(instr) = target.back_mut() {
-                        if let Some(term) = terms.last() {
-                            trim_structure_by_last_arg(instr, term);
-                        }
-                    }
+                    let (head_loc, head) = subterm_index(iter.deref(), l);
+                    let (tail_loc, tail) = subterm_index(iter.deref(), l+1);
+
+                    let head_r_opt = self.subterm_to_instr::<Target>(
+                        head,
+                        var_locs,
+                        head_loc,
+                        context,
+                        index_ptrs,
+                        &mut target,
+                    );
 
-                    for subterm in terms {
-                        self.subterm_to_instr::<Target>(subterm, term_loc, &mut target);
+                    let tail_r_opt = self.subterm_to_instr::<Target>(
+                        tail,
+                        var_locs,
+                        tail_loc,
+                        context,
+                        index_ptrs,
+                        &mut target,
+                    );
+
+                    if let Some(r) = head_r_opt {
+                        <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
+                            self, r,
+                        );
                     }
 
-                    for subterm in terms {
+                    if let Some(r) = tail_r_opt {
                         <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
-                            self, subterm,
+                            self, r,
                         );
                     }
                 }
-                TermRef::Cons(lvl, cell, head, tail) => {
-                    self.marker
-                        .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push_back(Target::to_list(lvl, cell.get()));
+                (HeapCellValueTag::CStr, cstr_atom) => {
+                    let heap_loc = iter.focus().value() as usize;
+                    let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
 
-                    <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
-                        self,
-                        cell.get(),
-                    );
+                    target.push_back(Target::to_pstr(lvl, cstr_atom, r, false));
+                }
+                (HeapCellValueTag::PStr, pstr_atom) => {
+                    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);
 
-                    self.subterm_to_instr::<Target>(head, term_loc, &mut target);
-                    self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
+                    target.push_back(Target::to_pstr(lvl, pstr_atom, r, true));
 
-                    <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
-                        self, head,
-                    );
-                    <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
-                        self, tail,
+                    let (tail_loc, tail) = subterm_index(iter.deref(), heap_loc + 1);
+                    self.subterm_to_instr::<Target>(
+                        tail, var_locs, tail_loc, context, index_ptrs, &mut target,
                     );
                 }
-                TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
-                    self.marker
-                        .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push_back(Target::to_pstr(lvl, *string, cell.get(), false));
-                }
-                TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
-                    self.marker
-                        .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push_back(Target::to_constant(lvl, *constant, cell.get()));
-                }
-                TermRef::PartialString(lvl, cell, string, tail) => {
-                    self.marker
-                        .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    let atom = AtomTable::build_with(self.atom_tbl, string);
+                (HeapCellValueTag::PStrOffset, l) => {
+                    let heap_loc = iter.focus().value() as usize;
+                    let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
 
-                    target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
-                    self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
-                }
-                TermRef::CompleteString(lvl, cell, atom) => {
-                    self.marker
-                        .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push_back(Target::to_pstr(lvl, atom, cell.get(), false));
-                }
-                TermRef::Var(lvl @ Level::Shallow, cell, var) => {
-                    self.marker.mark_var::<Target>(
-                        var.to_var_num().unwrap(),
-                        lvl,
-                        cell,
-                        term_loc,
-                        &mut target,
+                    let (index, n) = pstr_loc_and_offset(&iter, l);
+                    let n = n.get_num() as usize;
+
+                    let pstr_atom = cell_as_atom!(iter[index]);
+                    let pstr_offset_atom = if n == 0 {
+                        pstr_atom
+                    } else {
+                        AtomTable::build_with(self.atom_tbl, &pstr_atom.as_str()[n ..])
+                    };
+
+                    let (tail_loc, tail) = subterm_index(iter.deref(), l+1);
+                    target.push_back(Target::to_pstr(lvl, pstr_offset_atom, r, true));
+
+                    self.subterm_to_instr::<Target>(
+                        tail, var_locs, tail_loc, context, index_ptrs, &mut target,
                     );
                 }
+                _ if lvl == Level::Shallow => {
+                    if let Ok(lit) = Literal::try_from(term) {
+                        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);
+                        target.push_back(Target::to_constant(lvl, lit, r));
+                    }
+                }
                 _ => {}
-            };
+            );
         }
 
         target
@@ -575,21 +688,26 @@ impl<'b> CodeGenerator<'b> {
     fn compile_inlined(
         &mut self,
         ct: &InlinedClauseType,
-        terms: &'_ [Term],
-        term_loc: GenContext,
+        terms: &mut FocusedHeap,
+        term_loc: usize,
+        context: GenContext,
         code: &mut CodeDeque,
     ) -> Result<(), CompilationError> {
+        let term = terms.heap[terms.nth_arg(term_loc, 1).unwrap()];
+
         let call_instr = match ct {
             &InlinedClauseType::CompareNumber(mut cmp) => {
                 self.marker.reset_arg(2);
 
-                let (mut lcode, at_1) = self.compile_arith_expr(&terms[0], 1, term_loc, 1)?;
+                let (mut lcode, at_1) =
+                    self.compile_arith_expr(terms, term_loc + 1, 1, context, 1)?;
 
-                if !matches!(terms[0], Term::Var(..)) {
+                if !terms.deref_loc(term_loc + 1).is_var() {
                     self.marker.advance_arg();
                 }
 
-                let (mut rcode, at_2) = self.compile_arith_expr(&terms[1], 2, term_loc, 2)?;
+                let (mut rcode, at_2) =
+                    self.compile_arith_expr(terms, term_loc + 2, 2, context, 2)?;
 
                 code.append(&mut lcode);
                 code.append(&mut rcode);
@@ -599,213 +717,294 @@ impl<'b> CodeGenerator<'b> {
 
                 compare_number_instr!(cmp, at_1, at_2)
             }
-            InlinedClauseType::IsAtom(..) => match &terms[0] {
-                Term::Literal(_, Literal::Char(_))
-                | Term::Literal(_, Literal::Atom(atom!("[]")))
-                | Term::Literal(_, Literal::Atom(..)) => {
+            InlinedClauseType::IsAtom(..) => read_heap_cell!(term,
+                (HeapCellValueTag::Atom, (_name, arity)) => {
+                    if arity == 0 {
+                        instr!("$succeed")
+                    } else {
+                        instr!("$fail")
+                    }
+                }
+                (HeapCellValueTag::Char) => {
                     instr!("$succeed")
                 }
-                Term::Var(ref vr, ref name) => {
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
                     self.marker.reset_arg(1);
 
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
+                    if var_ptr.is_anon() {
+                        instr!("$fail")
+                    } else {
+                        let r = self.marker.mark_non_callable(
+                            var_ptr.to_var_num().unwrap(),
+                            1,
+                            context,
+                            code,
+                        );
 
-                    instr!("atom", r)
+                        instr!("atom", r)
+                    }
                 }
                 _ => {
                     instr!("$fail")
                 }
-            },
-            InlinedClauseType::IsAtomic(..) => match &terms[0] {
-                Term::AnonVar
-                | Term::Clause(..)
-                | Term::Cons(..)
-                | Term::PartialString(..)
-                | Term::CompleteString(..) => {
-                    instr!("$fail")
-                }
-                Term::Literal(_, Literal::String(_)) => {
-                    instr!("$fail")
-                }
-                Term::Literal(..) => {
-                    instr!("$succeed")
-                }
-                Term::Var(ref vr, ref name) => {
-                    self.marker.reset_arg(1);
+            ),
+            InlinedClauseType::IsAtomic(..) => read_heap_cell!(term,
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
 
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
+                    if var_ptr.is_anon() {
+                        instr!("$fail")
+                    } else {
+                        self.marker.reset_arg(1);
+
+                        let r = self.marker.mark_non_callable(
+                            var_ptr.to_var_num().unwrap(),
+                            1,
+                            context,
+                            code,
+                        );
 
-                    instr!("atomic", r)
+                        instr!("atomic", r)
+                    }
                 }
-            },
-            InlinedClauseType::IsCompound(..) => match &terms[0] {
-                Term::Clause(..)
-                | Term::Cons(..)
-                | Term::PartialString(..)
-                | Term::CompleteString(..)
-                | Term::Literal(_, Literal::String(..)) => {
+                (HeapCellValueTag::Fixnum |
+                 HeapCellValueTag::Char |
+                 HeapCellValueTag::F64) => {
                     instr!("$succeed")
                 }
-                Term::Var(ref vr, ref name) => {
-                    self.marker.reset_arg(1);
-
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
-
-                    instr!("compound", r)
-                }
-                _ => {
-                    instr!("$fail")
+                (HeapCellValueTag::Cons, cons_ptr) => {
+                    match cons_ptr.get_tag() {
+                        ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
+                            instr!("$succeed")
+                        }
+                        _ => {
+                            instr!("$fail")
+                        }
+                    }
                 }
-            },
-            InlinedClauseType::IsRational(..) => match terms[0] {
-                Term::Literal(_, Literal::Rational(_)) => {
-                    instr!("$succeed")
+                (HeapCellValueTag::Atom, (_name, arity)) => {
+                    if arity == 0 {
+                        instr!("$succeed")
+                    } else {
+                        instr!("$fail")
+                    }
                 }
-                Term::Var(ref vr, ref name) => {
-                    self.marker.reset_arg(1);
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
-                    instr!("rational", r)
+                (HeapCellValueTag::Lis
+                 | HeapCellValueTag::Str
+                 | HeapCellValueTag::PStrLoc
+                 | HeapCellValueTag::CStr) => {
+                    instr!("$fail")
                 }
                 _ => {
-                    instr!("$fail")
+                    if Literal::try_from(term).is_ok() {
+                        instr!("$succeed")
+                    } else {
+                        instr!("$fail")
+                    }
                 }
-            },
-            InlinedClauseType::IsFloat(..) => match terms[0] {
-                Term::Literal(_, Literal::Float(_)) => {
+            ),
+            InlinedClauseType::IsCompound(..) => {
+                read_heap_cell!(term,
+                    (HeapCellValueTag::Atom, (_, arity)) => {
+                        if arity > 0 {
+                            instr!("$succeed")
+                        } else {
+                            instr!("$fail")
+                        }
+                    }
+                    (HeapCellValueTag::Lis
+                     | HeapCellValueTag::Str
+                     | HeapCellValueTag::PStrLoc
+                     | HeapCellValueTag::CStr) => {
+                        instr!("$succeed")
+                    }
+                    (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                        let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
+
+                        if var_ptr.is_anon() {
+                            instr!("$fail")
+                        } else {
+                            self.marker.reset_arg(1);
+
+                            let r = self.marker.mark_non_callable(
+                                var_ptr.to_var_num().unwrap(),
+                                1,
+                                context,
+                                code,
+                            );
+
+                            instr!("compound", r)
+                        }
+                    }
+                    _ => {
+                        instr!("$fail")
+                    }
+                )
+            }
+            InlinedClauseType::IsRational(..) => {
+                read_heap_cell!(term,
+                    (HeapCellValueTag::Cons, cons_ptr) => {
+                        match cons_ptr.get_tag() {
+                            ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
+                                instr!("$succeed")
+                            }
+                            _ => {
+                                instr!("$fail")
+                            }
+                        }
+                    }
+                    (HeapCellValueTag::Fixnum) => {
+                        instr!("$succeed")
+                    }
+                    (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                        let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
+                        self.marker.reset_arg(1);
+
+                        if var_ptr.is_anon() {
+                            instr!("$fail")
+                        } else {
+                            let r = self.marker.mark_non_callable(
+                                var_ptr.to_var_num().unwrap(),
+                                1,
+                                context,
+                                code,
+                            );
+
+                            instr!("rational", r)
+                        }
+                    }
+                    _ => {
+                        instr!("$fail")
+                    }
+                )
+            }
+            InlinedClauseType::IsFloat(..) => read_heap_cell!(term,
+                (HeapCellValueTag::F64) => {
                     instr!("$succeed")
                 }
-                Term::Var(ref vr, ref name) => {
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
                     self.marker.reset_arg(1);
 
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
+                    if var_ptr.is_anon() {
+                        instr!("$fail")
+                    } else {
+                        let r = self.marker.mark_non_callable(
+                            var_ptr.to_var_num().unwrap(),
+                            1,
+                            context,
+                            code,
+                        );
 
-                    instr!("float", r)
+                        instr!("float", r)
+                    }
                 }
                 _ => {
                     instr!("$fail")
                 }
-            },
-            InlinedClauseType::IsNumber(..) => match terms[0] {
-                Term::Literal(_, Literal::Float(_))
-                | Term::Literal(_, Literal::Rational(_))
-                | Term::Literal(_, Literal::Integer(_))
-                | Term::Literal(_, Literal::Fixnum(_)) => {
-                    instr!("$succeed")
-                }
-                Term::Var(ref vr, ref name) => {
+            ),
+            InlinedClauseType::IsNumber(..) => read_heap_cell!(term,
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
                     self.marker.reset_arg(1);
 
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
+                    if var_ptr.is_anon() {
+                        instr!("$fail")
+                    } else {
+                        let r = self.marker.mark_non_callable(
+                            var_ptr.to_var_num().unwrap(),
+                            1,
+                            context,
+                            code,
+                        );
 
-                    instr!("number", r)
+                        instr!("number", r)
+                    }
                 }
                 _ => {
-                    instr!("$fail")
-                }
-            },
-            InlinedClauseType::IsNonVar(..) => match terms[0] {
-                Term::AnonVar => {
-                    instr!("$fail")
+                    if Number::try_from(term).is_ok() {
+                        instr!("$succeed")
+                    } else {
+                        instr!("$fail")
+                    }
                 }
-                Term::Var(ref vr, ref name) => {
+            ),
+            InlinedClauseType::IsNonVar(..) => read_heap_cell!(term,
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
                     self.marker.reset_arg(1);
 
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
+                    if var_ptr.is_anon() {
+                        instr!("$fail")
+                    } else {
+                        let r = self.marker.mark_non_callable(
+                            var_ptr.to_var_num().unwrap(),
+                            1,
+                            context,
+                            code,
+                        );
 
-                    instr!("nonvar", r)
+                        instr!("nonvar", r)
+                    }
                 }
                 _ => {
                     instr!("$succeed")
                 }
-            },
-            InlinedClauseType::IsInteger(..) => match &terms[0] {
-                Term::Literal(_, Literal::Integer(_)) | Term::Literal(_, Literal::Fixnum(_)) => {
-                    instr!("$succeed")
-                }
-                Term::Var(ref vr, name) => {
+            ),
+            InlinedClauseType::IsInteger(..) => {
+                read_heap_cell!(term,
+                    (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                        let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
+                        self.marker.reset_arg(1);
+
+                        if var_ptr.is_anon() {
+                            instr!("$fail")
+                        } else {
+                            let r = self.marker.mark_non_callable(
+                                var_ptr.to_var_num().unwrap(),
+                                1,
+                                context,
+                                code,
+                            );
+
+                            instr!("integer", r)
+                        }
+                    }
+                    _ => {
+                        match Number::try_from(term) {
+                            Ok(Number::Integer(_) | Number::Fixnum(_)) => {
+                                instr!("$succeed")
+                            }
+                            _ => {
+                                instr!("$fail")
+                            }
+                        }
+                    }
+                )
+            }
+            InlinedClauseType::IsVar(..) => read_heap_cell!(term,
+                (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                    let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
                     self.marker.reset_arg(1);
 
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
+                    if var_ptr.is_anon() {
+                        instr!("$succeed")
+                    } else {
+                        let r = self.marker.mark_non_callable(
+                            var_ptr.to_var_num().unwrap(),
+                            1,
+                            context,
+                            code,
+                        );
 
-                    instr!("integer", r)
+                        instr!("var", r)
+                    }
                 }
                 _ => {
                     instr!("$fail")
                 }
-            },
-            InlinedClauseType::IsVar(..) => match terms[0] {
-                Term::Literal(..)
-                | Term::Clause(..)
-                | Term::Cons(..)
-                | Term::PartialString(..)
-                | Term::CompleteString(..) => {
-                    instr!("$fail")
-                }
-                Term::AnonVar => {
-                    instr!("$succeed")
-                }
-                Term::Var(ref vr, ref name) => {
-                    self.marker.reset_arg(1);
-
-                    let r = self.marker.mark_non_callable(
-                        name.to_var_num().unwrap(),
-                        1,
-                        term_loc,
-                        vr,
-                        code,
-                    );
-
-                    instr!("var", r)
-                }
-            },
+            ),
         };
 
         // inlined predicates are never counted, so this overrides nothing.
@@ -816,25 +1015,28 @@ impl<'b> CodeGenerator<'b> {
 
     fn compile_arith_expr(
         &mut self,
-        term: &Term,
+        terms: &mut FocusedHeap,
+        term_loc: usize,
         target_int: usize,
-        term_loc: GenContext,
+        context: GenContext,
         arg: usize,
     ) -> Result<ArithCont, ArithmeticError> {
         let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int);
-        evaluator.compile_is(term, term_loc, arg)
+        evaluator.compile_is(terms, term_loc, context, arg)
     }
 
     fn compile_is_call(
         &mut self,
-        terms: &[Term],
+        terms: &mut FocusedHeap,
+        term_loc: usize,
         code: &mut CodeDeque,
-        term_loc: GenContext,
+        context: GenContext,
         call_policy: CallPolicy,
     ) -> Result<(), CompilationError> {
         macro_rules! compile_expr {
-            ($self:expr, $terms:expr, $term_loc:expr, $code:expr) => {{
-                let (acode, at) = $self.compile_arith_expr($terms, 1, $term_loc, 2)?;
+            ($self:expr, $terms:expr, $context:expr, $code:expr) => {{
+                let (acode, at) =
+                    $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
                 $code.extend(acode.into_iter());
                 at
             }};
@@ -842,70 +1044,74 @@ impl<'b> CodeGenerator<'b> {
 
         self.marker.reset_arg(2);
 
-        let at = match terms[0] {
-            Term::Var(ref vr, ref name) => {
-                let var_num = name.to_var_num().unwrap();
+        let var = {
+            let var_cell = terms.heap[term_loc + 1];
+            let terms = FocusedHeapRefMut::from_cell(&mut terms.heap, var_cell);
+
+            terms.deref_loc(term_loc + 1)
+        };
+
+        let at = read_heap_cell!(var,
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
+                let var_num = var_ptr.to_var_num().unwrap();
 
                 if self.marker.var_data.records[var_num].num_occurrences > 1 {
                     self.marker.mark_var::<QueryInstruction>(
                         var_num,
                         Level::Shallow,
-                        vr,
-                        term_loc,
+                        context,
                         code,
                     );
 
                     self.marker.mark_safe_var_unconditionally(var_num);
-                    compile_expr!(self, &terms[1], term_loc, code)
+                    compile_expr!(self, terms, context, code)
                 } else {
-                    self.marker
-                        .mark_anon_var::<QueryInstruction>(Level::Shallow, term_loc, code);
+                    /*
+                    if var.is_var() {
+                        let h = var.get_value() as usize;
 
-                    if let Term::Var(ref vr, ref var) = &terms[1] {
-                        let var_num = var.to_var_num().unwrap();
+                        let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
+                        let var_num = var_ptr.to_var_num().unwrap();
 
                         // if var is an anonymous variable, insert
                         // is/2 call so that an instantiation error is
                         // thrown when the predicate is run.
+
                         if self.marker.var_data.records[var_num].num_occurrences > 1 {
-                            self.marker.mark_var::<QueryInstruction>(
+                            let r = self.marker.mark_var::<QueryInstruction>(
                                 var_num,
                                 Level::Shallow,
-                                vr,
-                                term_loc,
+                                context,
                                 code,
                             );
 
                             self.marker.mark_safe_var_unconditionally(var_num);
 
-                            let at = ArithmeticTerm::Reg(vr.get().norm());
+                            let at = ArithmeticTerm::Reg(r);
                             self.add_call(code, instr!("$get_number", at), call_policy);
 
                             return Ok(());
                         }
                     }
+                    */
 
-                    compile_expr!(self, &terms[1], term_loc, code)
+                    compile_expr!(self, terms, context, code)
                 }
             }
-            Term::Literal(
-                _,
-                c @ Literal::Integer(_)
-                | c @ Literal::Float(_)
-                | c @ Literal::Rational(_)
-                | c @ Literal::Fixnum(_),
-            ) => {
-                let v = HeapCellValue::from(c);
-                code.push_back(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
-
-                self.marker.advance_arg();
-                compile_expr!(self, &terms[1], term_loc, code)
-            }
             _ => {
-                code.push_back(instr!("$fail"));
-                return Ok(());
+                if Number::try_from(var).is_ok() {
+                    let v = HeapCellValue::from(var);
+                    code.push_back(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
+
+                    self.marker.advance_arg();
+                    compile_expr!(self, terms, context, code)
+                } else {
+                    code.push_back(instr!("$fail"));
+                    return Ok(());
+                }
             }
-        };
+        );
 
         let at = at.unwrap_or(interm!(1));
         self.add_call(code, instr!("is", temp_v!(1), at), call_policy);
@@ -915,6 +1121,7 @@ impl<'b> CodeGenerator<'b> {
 
     fn compile_seq(
         &mut self,
+        terms: &mut FocusedHeap,
         clauses: &ChunkedTermVec,
         code: &mut CodeDeque,
     ) -> Result<(), CompilationError> {
@@ -926,7 +1133,7 @@ impl<'b> CodeGenerator<'b> {
             match clause_item {
                 ClauseItem::Chunk(chunk) => {
                     for (idx, term) in chunk.iter().enumerate() {
-                        let term_loc = if idx + 1 < chunk.len() {
+                        let context = if idx + 1 < chunk.len() {
                             GenContext::Mid(chunk_num)
                         } else {
                             self.marker.in_tail_position = clause_iter.in_tail_position();
@@ -955,7 +1162,7 @@ impl<'b> CodeGenerator<'b> {
                                 if chunk_num == 0 {
                                     code.push_back(instr!("neck_cut"));
                                 } else {
-                                    let r = self.marker.get_binding(var_num);
+                                    let r = self.marker.get_var_binding(var_num);
                                     code.push_back(instr!("cut", r));
                                 }
 
@@ -969,7 +1176,7 @@ impl<'b> CodeGenerator<'b> {
                             }
                             &QueryTerm::LocalCut { var_num, cut_prev } => {
                                 let code = branch_code_stack.code(code);
-                                let r = self.marker.get_binding(var_num);
+                                let r = self.marker.get_var_binding(var_num);
 
                                 code.push_back(if cut_prev {
                                     instr!("cut_prev", r)
@@ -988,31 +1195,55 @@ impl<'b> CodeGenerator<'b> {
                                 }
                             }
                             &QueryTerm::Clause(
-                                _,
-                                ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
-                                ref terms,
-                                call_policy,
+                                ref clause @ QueryClause {
+                                    ct: ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
+                                    call_policy,
+                                    ..
+                                },
                             ) => self.compile_is_call(
                                 terms,
+                                clause.term_loc(),
                                 branch_code_stack.code(code),
-                                term_loc,
+                                context,
                                 call_policy,
                             )?,
-                            &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
-                                self.compile_inlined(
-                                    ct,
-                                    terms,
-                                    term_loc,
-                                    branch_code_stack.code(code),
-                                )?
-                            }
+                            &QueryTerm::Clause(
+                                ref clause @ QueryClause {
+                                    ct: ClauseType::Inlined(ref ct),
+                                    ..
+                                },
+                            ) => self.compile_inlined(
+                                ct,
+                                terms,
+                                clause.term_loc(),
+                                context,
+                                branch_code_stack.code(code),
+                            )?,
                             &QueryTerm::Fail => {
                                 branch_code_stack.code(code).push_back(instr!("$fail"));
                             }
-                            term @ &QueryTerm::Clause(..) => {
+                            &QueryTerm::Succeed => {
+                                let code = branch_code_stack.code(code);
+
+                                if self.marker.in_tail_position {
+                                    if self.marker.var_data.allocates {
+                                        code.push_back(instr!("deallocate"));
+                                    }
+                                }
+
+                                code.push_back(
+                                    if self.marker.in_tail_position {
+                                        instr!("$succeed").to_execute()
+                                    } else {
+                                        instr!("$succeed")
+                                    },
+                                );
+                            }
+                            QueryTerm::Clause(clause) => {
                                 self.compile_query_line(
-                                    term,
-                                    term_loc,
+                                    terms,
+                                    clause,
+                                    context,
                                     branch_code_stack.code(code),
                                 );
 
@@ -1071,20 +1302,31 @@ impl<'b> CodeGenerator<'b> {
 
     pub(crate) fn compile_rule(
         &mut self,
-        rule: &Rule,
+        rule: &mut Rule,
         var_data: VarData,
     ) -> Result<Code, CompilationError> {
         let Rule {
-            head: (_, args),
+            ref mut term,
             clauses,
         } = rule;
         self.marker.var_data = var_data;
+
         let mut code = VecDeque::new();
+        let head_loc = term.nth_arg(term.focus, 1).unwrap();
 
-        self.marker.reset_at_head(args);
+        self.marker.reset_at_head(term, head_loc);
 
-        let iter = FactIterator::from_rule_head_clause(args);
-        let fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);
+        let mut stack = Stack::uninitialized();
+        let iter = fact_iterator::<true>(
+            &mut term.heap, &mut stack, head_loc,
+        );
+
+        let fact = self.compile_target::<FactInstruction, _>(
+            iter,
+            &IndexMap::with_hasher(FxBuildHasher::default()),
+            &mut term.var_locs,
+            GenContext::Head,
+        );
 
         if self.marker.max_reg_allocated() > MAX_ARITY {
             return Err(CompilationError::ExceededMaxArity);
@@ -1093,50 +1335,66 @@ impl<'b> CodeGenerator<'b> {
         self.marker.reset_free_list();
         code.extend(fact);
 
-        self.compile_seq(clauses, &mut code)?;
+        self.compile_seq(term, &clauses, &mut code)?;
 
         Ok(Vec::from(code))
     }
 
     pub(crate) fn compile_fact(
         &mut self,
-        fact: &Fact,
+        fact: &mut Fact,
         var_data: VarData,
     ) -> Result<Code, CompilationError> {
         let mut code = Vec::new();
-        self.marker.var_data = var_data;
 
-        if let Term::Clause(_, _, args) = &fact.head {
-            self.marker.reset_at_head(args);
+        let fact_focus = fact.term.focus;
+        let mut stack = Stack::uninitialized();
 
-            let iter = FactInstruction::iter(&fact.head);
-            let compiled_fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);
+        self.marker.var_data = var_data;
+        self.marker.reset_at_head(&mut fact.term, fact_focus);
 
-            if self.marker.max_reg_allocated() > MAX_ARITY {
-                return Err(CompilationError::ExceededMaxArity);
-            }
+        let iter = fact_iterator::<true>(
+            &mut fact.term.heap, &mut stack, fact_focus,
+        );
 
-            code.extend(compiled_fact);
+        let compiled_fact = self.compile_target::<FactInstruction, _>(
+            iter,
+            &IndexMap::with_hasher(FxBuildHasher::default()),
+            &mut fact.term.var_locs,
+            GenContext::Head,
+        );
+
+        if self.marker.max_reg_allocated() > MAX_ARITY {
+            return Err(CompilationError::ExceededMaxArity);
         }
 
+        code.extend(compiled_fact);
         code.push(instr!("proceed"));
+
         Ok(code)
     }
 
-    fn compile_query_line(&mut self, term: &QueryTerm, term_loc: GenContext, code: &mut CodeDeque) {
-        self.marker.reset_arg(term.arity());
+    fn compile_query_line(
+        &mut self,
+        term: &mut FocusedHeap,
+        clause: &QueryClause,
+        context: GenContext,
+        code: &mut CodeDeque,
+    ) {
+        self.marker.reset_arg(term.arity(clause.term_loc()));
 
-        let iter = QueryIterator::new(term);
-        let query = self.compile_target::<QueryInstruction, _>(iter, term_loc);
+        let mut stack = Stack::uninitialized();
+        let iter = query_iterator::<true>(&mut term.heap, &mut stack, clause.term_loc());
 
-        code.extend(query);
+        let query = self.compile_target::<QueryInstruction, _>(
+            iter,
+            &clause.code_indices,
+            &mut term.var_locs,
+            context,
+        );
 
-        match term {
-            &QueryTerm::Clause(_, ref ct, _, call_policy) => {
-                self.add_call(code, ct.to_instr(), call_policy);
-            }
-            _ => unreachable!(),
-        };
+        code.extend(query);
+        self.add_call(code, clause.ct.to_instr(), clause.call_policy);
     }
 
     fn split_predicate(clauses: &[PredicateClause]) -> Vec<ClauseSpan> {
@@ -1146,28 +1404,27 @@ impl<'b> CodeGenerator<'b> {
 
         'outer: for (right, clause) in clauses.iter().enumerate() {
             if let Some(args) = clause.args() {
-                for (instantiated_arg_index, arg) in args.iter().enumerate() {
-                    match arg {
-                        Term::Var(..) | Term::AnonVar => {}
-                        _ => {
-                            if optimal_index != instantiated_arg_index {
-                                if left >= right {
-                                    optimal_index = instantiated_arg_index;
-                                    continue 'outer;
-                                }
-
-                                subseqs.push(ClauseSpan {
-                                    left,
-                                    right,
-                                    instantiated_arg_index: optimal_index,
-                                });
+                for (instantiated_arg_index, arg) in args.iter().cloned().enumerate() {
+                    let arg = heap_bound_store(clause.heap(), heap_bound_deref(clause.heap(), arg));
 
+                    if !arg.is_var() {
+                        if optimal_index != instantiated_arg_index {
+                            if left >= right {
                                 optimal_index = instantiated_arg_index;
-                                left = right;
+                                continue 'outer;
                             }
 
-                            continue 'outer;
+                            subseqs.push(ClauseSpan {
+                                left,
+                                right,
+                                instantiated_arg_index: optimal_index,
+                            });
+
+                            optimal_index = instantiated_arg_index;
+                            left = right;
                         }
+
+                        continue 'outer;
                     }
                 }
             }
@@ -1256,11 +1513,18 @@ impl<'b> CodeGenerator<'b> {
 
             let arg = clause.args().and_then(|args| args.get(optimal_index));
 
-            if let Some(arg) = arg {
+            if let Some(arg) = arg.cloned() {
                 let index = code.len();
 
                 if clauses_len > 1 || self.settings.is_extensible {
-                    code_offsets.index_term(arg, index, &mut clause_index_info, self.atom_tbl);
+                    let arg = heap_bound_store(clause.heap(), heap_bound_deref(clause.heap(), arg));
+                    code_offsets.index_term(
+                        clause.heap(),
+                        arg,
+                        index,
+                        &mut clause_index_info,
+                        self.atom_tbl,
+                    );
                 }
             }
 
index d44c36cb69819342891f6e40730f3351499d275a..b473d9d134522ee0dd9621e342e3761230cb8d0c 100644 (file)
@@ -1,10 +1,13 @@
 use crate::allocator::*;
+use crate::atom_table::*;
 use crate::codegen::SubsumedBranchHits;
 use crate::forms::Level;
 use crate::instructions::*;
 use crate::machine::disjuncts::VarData;
+use crate::machine::heap::{heap_bound_deref, heap_bound_store};
 use crate::parser::ast::*;
 use crate::targets::*;
+use crate::types::*;
 use crate::variable_records::*;
 
 use bit_set::*;
@@ -12,7 +15,6 @@ use bitvec::prelude::*;
 use fxhash::FxBuildHasher;
 use indexmap::IndexMap;
 
-use std::cell::Cell;
 use std::collections::VecDeque;
 use std::ops::{Deref, DerefMut};
 
@@ -152,6 +154,8 @@ pub(crate) struct DebrayAllocator {
     in_use: BitSet<usize>, // deep and non-var allocations
     temp_free_list: Vec<usize>,
     perm_free_list: VecDeque<(usize, usize)>, // chunk_num, var_num
+    non_var_registers: IndexMap<usize, usize, FxBuildHasher>,
+    non_var_register_heap_locs: IndexMap<usize, usize, FxBuildHasher>,
 }
 
 impl DebrayAllocator {
@@ -168,7 +172,7 @@ 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,
@@ -229,7 +233,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,
@@ -366,7 +370,7 @@ impl DebrayAllocator {
         &mut self,
         chunk_num: usize,
         code: &mut CodeDeque,
-    ) {
+    ) -> Option<RegType> {
         if let Some((var_num, r)) = self.alloc_in_last_goal_hint(chunk_num) {
             let k = self.arg_c;
 
@@ -382,8 +386,12 @@ impl DebrayAllocator {
                     .allocation
                     .set_register(r.reg_num());
                 self.in_use.insert(r.reg_num());
+
+                return Some(r);
             }
         };
+
+        None
     }
 
     fn alloc_reg_to_var<'a, Target: CompilationTarget<'a>>(
@@ -433,6 +441,7 @@ impl DebrayAllocator {
         }
 
         self.temp_lb = final_index + 1;
+
         final_index
     }
 
@@ -456,7 +465,11 @@ impl DebrayAllocator {
             p
         };
 
-        self.var_data.records[var_num].allocation = VarAlloc::Perm(p, PermVarAllocation::done());
+        self.var_data.records[var_num].allocation = VarAlloc::Perm {
+            reg: p,
+            allocation: PermVarAllocation::done(),
+        };
+
         p
     }
 
@@ -472,10 +485,15 @@ impl DebrayAllocator {
     }
 
     #[inline(always)]
-    pub fn get_binding(&self, var_num: usize) -> RegType {
+    pub fn get_var_binding(&self, var_num: usize) -> RegType {
         self.var_data.records[var_num].allocation.as_reg_type()
     }
 
+    #[inline(always)]
+    pub fn get_non_var_binding(&self, heap_loc: usize) -> RegType {
+        RegType::Temp(self.non_var_registers.get(&heap_loc).cloned().unwrap_or(0))
+    }
+
     pub fn num_perm_vars(&self) -> usize {
         self.perm_lb - 1
     }
@@ -485,7 +503,7 @@ impl DebrayAllocator {
     }
 
     fn add_perm_to_free_list(&mut self, chunk_num: usize, var_num: usize) {
-        if let VarAlloc::Perm(..) = &self.var_data.records[var_num].allocation {
+        if let VarAlloc::Perm { .. } = &self.var_data.records[var_num].allocation {
             self.perm_free_list.push_back((chunk_num, var_num));
         }
     }
@@ -496,9 +514,10 @@ impl DebrayAllocator {
                 self.perm_free_list.pop_front();
 
                 match &mut self.var_data.records[var_num].allocation {
-                    VarAlloc::Perm(p, 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 {
@@ -510,9 +529,12 @@ impl DebrayAllocator {
     }
 
     pub(crate) fn free_var(&mut self, chunk_num: usize, var_num: usize) {
-        if let VarAlloc::Perm(_, allocation) = &mut self.var_data.records[var_num].allocation {
-            *allocation = PermVarAllocation::Pending;
-            self.add_perm_to_free_list(chunk_num, var_num);
+        match &mut self.var_data.records[var_num].allocation {
+            VarAlloc::Perm { allocation, .. } => {
+                *allocation = PermVarAllocation::Pending;
+                self.add_perm_to_free_list(chunk_num, var_num);
+            }
+            _ => {}
         }
     }
 
@@ -520,14 +542,14 @@ impl DebrayAllocator {
         let branch_designator = self.branch_stack.current_branch_designator();
 
         match &mut self.var_data.records[var_num].allocation {
-            VarAlloc::Perm(
-                _,
-                PermVarAllocation::Done {
+            VarAlloc::Perm {
+                allocation: PermVarAllocation::Done {
                     deep_safety,
                     shallow_safety,
                     ..
                 },
-            ) => {
+                ..
+            } => {
                 *deep_safety = VarSafetyStatus::unneeded(branch_designator);
                 *shallow_safety = VarSafetyStatus::unneeded(branch_designator);
             }
@@ -542,14 +564,14 @@ impl DebrayAllocator {
         let branch_designator = self.branch_stack.current_branch_designator();
 
         match &mut self.var_data.records[var_num].allocation {
-            VarAlloc::Perm(
-                _,
-                PermVarAllocation::Done {
+            VarAlloc::Perm {
+                allocation: PermVarAllocation::Done {
                     deep_safety,
                     shallow_safety,
                     ..
                 },
-            ) => {
+                ..
+            } => {
                 // GetVariable in head chunk is considered safe.
                 if lvl == Level::Deep {
                     *deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -586,13 +608,13 @@ impl DebrayAllocator {
         let branch_designator = self.branch_stack.current_branch_designator();
 
         match &mut self.var_data.records[var_num].allocation {
-            VarAlloc::Perm(
-                _,
-                PermVarAllocation::Done {
+            VarAlloc::Perm {
+                allocation: PermVarAllocation::Done {
                     ref mut shallow_safety,
                     ..
                 },
-            ) => {
+                ..
+            } => {
                 if !self.in_tail_position
                     || self
                         .branch_stack
@@ -622,13 +644,13 @@ impl DebrayAllocator {
         let branch_designator = self.branch_stack.current_branch_designator();
 
         match &mut self.var_data.records[var_num].allocation {
-            VarAlloc::Perm(
-                _,
-                PermVarAllocation::Done {
+            VarAlloc::Perm {
+                allocation: PermVarAllocation::Done {
                     ref mut deep_safety,
                     ..
                 },
-            ) => {
+                ..
+            } => {
                 if self
                     .branch_stack
                     .safety_unneeded_in_branch(deep_safety, &branch_designator)
@@ -671,13 +693,15 @@ impl Allocator for DebrayAllocator {
             temp_free_list: vec![],
             perm_free_list: VecDeque::new(),
             branch_stack: BranchStack { stack: vec![] },
+            non_var_registers: IndexMap::with_hasher(FxBuildHasher::default()),
+            non_var_register_heap_locs: IndexMap::with_hasher(FxBuildHasher::default()),
         }
     }
 
     fn mark_anon_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
         lvl: Level,
-        term_loc: GenContext,
+        context: GenContext,
         code: &mut CodeDeque,
     ) {
         let r = RegType::Temp(self.alloc_reg_to_non_var());
@@ -687,7 +711,7 @@ impl Allocator for DebrayAllocator {
             Level::Root | Level::Shallow => {
                 let k = self.arg_c;
 
-                if let GenContext::Last(chunk_num) = term_loc {
+                if let GenContext::Last(chunk_num) = context {
                     self.evacuate_arg::<Target>(chunk_num, code);
                 }
 
@@ -701,55 +725,69 @@ impl Allocator for DebrayAllocator {
     fn mark_non_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
         lvl: Level,
-        term_loc: GenContext,
-        cell: &'a Cell<RegType>,
+        heap_loc: usize,
+        context: GenContext,
         code: &mut CodeDeque,
-    ) {
-        let r = cell.get();
+    ) -> RegType {
+        let r = self.get_non_var_binding(heap_loc);
 
         let r = match lvl {
             Level::Shallow => {
                 let k = self.arg_c;
 
-                if let GenContext::Last(chunk_num) = term_loc {
-                    self.evacuate_arg::<Target>(chunk_num, code);
+                if let GenContext::Last(chunk_num) = context {
+                    if let Some(new_r) = self.evacuate_arg::<Target>(chunk_num, code) {
+                        self.non_var_register_heap_locs
+                            .swap_remove(&k)
+                            .map(|old_heap_loc| {
+                                self.non_var_registers.insert(old_heap_loc, new_r.reg_num());
+                                self.non_var_register_heap_locs
+                                    .insert(new_r.reg_num(), old_heap_loc);
+                            });
+
+                        self.non_var_registers.insert(heap_loc, k);
+                        self.non_var_register_heap_locs.insert(k, heap_loc);
+                    }
                 }
 
                 self.arg_c += 1;
                 RegType::Temp(k)
             }
-            _ if r.reg_num() == 0 => RegType::Temp(self.alloc_reg_to_non_var()),
+            _ if r.reg_num() == 0 => {
+                let r = RegType::Temp(self.alloc_reg_to_non_var());
+                self.non_var_registers.insert(heap_loc, r.reg_num());
+                self.non_var_register_heap_locs
+                    .insert(r.reg_num(), heap_loc);
+                r
+            }
             _ => {
                 self.in_use.insert(r.reg_num());
                 r
             }
         };
 
-        cell.set(r);
+        r
     }
 
     fn mark_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
         var_num: usize,
         lvl: Level,
-        cell: &Cell<VarReg>,
-        term_loc: GenContext,
+        context: GenContext,
         code: &mut CodeDeque,
-    ) {
-        let (r, is_new_var) = match self.get_binding(var_num) {
+    ) -> RegType {
+        let (r, is_new_var) = match self.get_var_binding(var_num) {
             RegType::Temp(0) => {
-                let o = self.alloc_reg_to_var::<Target>(var_num, lvl, term_loc, code);
-                cell.set(VarReg::Norm(RegType::Temp(o)));
+                let o = self.alloc_reg_to_var::<Target>(var_num, lvl, context, code);
                 (RegType::Temp(o), true)
             }
             RegType::Perm(0) => {
-                let p = self.alloc_perm_var(var_num, term_loc.chunk_num());
-                cell.set(VarReg::Norm(RegType::Perm(p)));
+                let p = self.alloc_perm_var(var_num, context.chunk_num());
                 (RegType::Perm(p), true)
             }
             r @ RegType::Perm(_) => {
                 let is_new_var = match &mut self.var_data.records[var_num].allocation {
-                    VarAlloc::Perm(_, allocation) => {
+                    VarAlloc::Perm { allocation, .. } => {
                         if allocation.pending() {
                             *allocation = PermVarAllocation::done();
                             true
@@ -765,32 +803,29 @@ impl Allocator for DebrayAllocator {
             r => (r, false),
         };
 
-        self.mark_reserved_var::<Target>(var_num, lvl, cell, term_loc, code, r, is_new_var);
+        self.mark_reserved_var::<Target>(var_num, lvl, context, code, r, is_new_var)
     }
 
     fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
         var_num: usize,
         lvl: Level,
-        cell: &Cell<VarReg>,
-        term_loc: GenContext,
+        context: GenContext,
         code: &mut CodeDeque,
         r: RegType,
         is_new_var: bool,
-    ) {
+    ) -> RegType {
         match lvl {
             Level::Root | Level::Shallow => {
                 let k = self.arg_c;
 
                 if self.is_curr_arg_distinct_from(var_num) {
-                    self.evacuate_arg::<Target>(term_loc.chunk_num(), code);
+                    self.evacuate_arg::<Target>(context.chunk_num(), code);
                 }
 
-                cell.set(VarReg::ArgAndNorm(r, k));
-
-                if !self.in_place(var_num, term_loc, r, k) {
+                if !self.in_place(var_num, context, r, k) {
                     if is_new_var {
-                        self.mark_safe_var(var_num, lvl, term_loc);
+                        self.mark_safe_var(var_num, lvl, context);
                         code.push_back(Target::argument_to_variable(r, k));
                     } else {
                         code.push_back(self.argument_to_value::<Target>(var_num, r, k));
@@ -800,15 +835,15 @@ impl Allocator for DebrayAllocator {
                 self.arg_c += 1;
             }
             Level::Deep if is_new_var => {
-                if let GenContext::Head = term_loc {
+                if let GenContext::Head = context {
                     if self.occurs_shallowly_in_head(var_num, r.reg_num()) {
                         code.push_back(self.subterm_to_value::<Target>(var_num, r));
                     } else {
-                        self.mark_safe_var(var_num, lvl, term_loc);
+                        self.mark_safe_var(var_num, lvl, context);
                         code.push_back(Target::subterm_to_variable(r));
                     }
                 } else {
-                    self.mark_safe_var(var_num, lvl, term_loc);
+                    self.mark_safe_var(var_num, lvl, context);
                     code.push_back(Target::subterm_to_variable(r));
                 }
             }
@@ -830,14 +865,15 @@ impl Allocator for DebrayAllocator {
         if record.running_count < record.num_occurrences {
             record.running_count += 1;
         } else {
-            self.free_var(term_loc.chunk_num(), var_num);
+            self.free_var(context.chunk_num(), var_num);
         }
 
         self.in_use.insert(o);
+        r
     }
 
     fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType {
-        match self.get_binding(var_num) {
+        match self.get_var_binding(var_num) {
             RegType::Perm(0) => RegType::Perm(self.alloc_perm_var(var_num, chunk_num)),
             RegType::Temp(0) => {
                 let t = self.alloc_reg_to_non_var();
@@ -861,6 +897,8 @@ impl Allocator for DebrayAllocator {
     fn reset(&mut self) {
         self.perm_lb = 1;
         self.shallow_temp_mappings.clear();
+        self.non_var_registers.clear();
+        self.non_var_register_heap_locs.clear();
         self.in_use.clear();
         self.temp_free_list.clear();
     }
@@ -868,6 +906,8 @@ impl Allocator for DebrayAllocator {
     fn reset_contents(&mut self) {
         self.in_use.clear();
         self.shallow_temp_mappings.clear();
+        self.non_var_registers.clear();
+        self.non_var_register_heap_locs.clear();
         self.temp_free_list.clear();
     }
 
@@ -875,24 +915,44 @@ impl Allocator for DebrayAllocator {
         self.arg_c += 1;
     }
 
-    fn reset_at_head(&mut self, args: &[Term]) {
-        self.reset_arg(args.len());
-        self.arity = args.len();
+    fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize) {
+        read_heap_cell!(term.deref_loc(head_loc),
+            (HeapCellValueTag::Str, s) => {
+                let arity = cell_as_atom_cell!(term.heap[s]).get_arity();
 
-        for (idx, arg) in args.iter().enumerate() {
-            if let Term::Var(_, ref var) = arg {
-                let var_num = var.to_var_num().unwrap();
-                let r = self.get_binding(var_num);
+                self.reset_arg(arity);
+                self.arity = arity;
 
-                if !r.is_perm() && r.reg_num() == 0 {
-                    self.in_use.insert(idx + 1);
-                    self.shallow_temp_mappings.insert(idx + 1, var_num);
-                    self.var_data.records[var_num]
-                        .allocation
-                        .set_register(idx + 1);
+                for (idx, arg) in term.heap[s+1 .. s+arity+1].iter().cloned().enumerate() {
+                    if arg.is_var() {
+                        let var = heap_bound_store(
+                            &term.heap,
+                            heap_bound_deref(&term.heap, arg),
+                        );
+
+                        if !var.is_var() {
+                            continue;
+                        }
+
+                        let h = var.get_value() as usize;
+                        let var_ptr = term.var_locs.peek_next_var_ptr_at_key(h).unwrap();
+                        let var_num = var_ptr.to_var_num().unwrap();
+                        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.var_data.records[var_num]
+                                .allocation
+                                .set_register(idx + 1);
+                        }
+                    }
                 }
             }
-        }
+            _ => {
+                self.reset_arg(0);
+            }
+        );
     }
 
     fn reset_arg(&mut self, arity: usize) {
index 148d567f98a6d271bc32797cbbf3f69f72fb6a9d..4dee7439dec45dd0e65327ce9d558ceca05fce29 100644 (file)
@@ -17,7 +17,6 @@ use fxhash::FxBuildHasher;
 use indexmap::{IndexMap, IndexSet};
 use ordered_float::OrderedFloat;
 
-use std::cell::Cell;
 use std::collections::VecDeque;
 use std::convert::TryFrom;
 use std::fmt;
@@ -67,15 +66,6 @@ pub enum Level {
     Shallow,
 }
 
-impl Level {
-    pub(crate) fn child_level(self) -> Level {
-        match self {
-            Level::Root => Level::Shallow,
-            _ => Level::Deep,
-        }
-    }
-}
-
 #[derive(Debug, Clone, Copy)]
 pub enum CallPolicy {
     Default,
@@ -89,19 +79,6 @@ pub enum ChunkType {
     Last,
 }
 
-#[derive(Debug)]
-pub enum RootIterationPolicy {
-    Iterated,
-    NotIterated,
-}
-
-impl RootIterationPolicy {
-    #[inline(always)]
-    pub fn iterable(&self) -> bool {
-        matches!(self, RootIterationPolicy::Iterated)
-    }
-}
-
 impl ChunkType {
     #[inline(always)]
     pub fn to_gen_context(self, chunk_num: usize) -> GenContext {
@@ -182,35 +159,40 @@ impl ChunkedTermVec {
     }
 }
 
+#[derive(Debug)]
+pub struct QueryClause {
+    pub ct: ClauseType,
+    pub arity: usize,
+    pub term: HeapCellValue,
+    pub code_indices: IndexMap<usize, CodeIndex, FxBuildHasher>,
+    pub call_policy: CallPolicy,
+}
+
+impl QueryClause {
+    pub fn term_loc(&self) -> usize {
+        self.term.get_value() as usize
+    }
+}
+
 #[derive(Debug)]
 pub enum QueryTerm {
-    // register, clause type, subterms, clause call policy.
-    Clause(Cell<RegType>, ClauseType, Vec<Term>, CallPolicy),
+    Clause(QueryClause),
     Fail,
-    LocalCut { var_num: usize, cut_prev: bool }, // var_num
-    GlobalCut(usize),                            // var_num
+    Succeed,
+    LocalCut { var_num: usize, cut_prev: bool },
+    GlobalCut(usize), // var_num
     GetCutPoint { var_num: usize, prev_b: bool },
     GetLevel(usize), // var_num
 }
 
-impl QueryTerm {
-    pub(crate) fn arity(&self) -> usize {
-        match self {
-            QueryTerm::Clause(_, _, subterms, ..) => subterms.len(),
-            &QueryTerm::GetLevel(_) | &QueryTerm::GetCutPoint { .. } => 1,
-            _ => 0,
-        }
-    }
-}
-
 #[derive(Debug)]
 pub struct Fact {
-    pub(crate) head: Term,
+    pub(crate) term: FocusedHeap,
 }
 
 #[derive(Debug)]
 pub struct Rule {
-    pub(crate) head: (Atom, Vec<Term>),
+    pub(crate) term: FocusedHeap,
     pub(crate) clauses: ChunkedTermVec,
 }
 
@@ -253,6 +235,53 @@ impl ClauseInfo for PredicateKey {
     }
 }
 
+fn clause_name(heap: &[HeapCellValue], term_loc: usize) -> Option<Atom> {
+    let name = term_name(heap, term_loc);
+
+    if Some(atom!(":-")) == name && 2 == term_arity(heap, term_loc) {
+        term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| term_name(heap, arg_loc))
+    } else {
+        name
+    }
+}
+
+fn clause_arity(heap: &[HeapCellValue], term_loc: usize) -> usize {
+    let name = term_name(heap, term_loc);
+
+    if Some(atom!(":-")) == name && 2 == term_arity(heap, term_loc) {
+        term_nth_arg(heap, term_loc, 1)
+            .map(|arg_loc| term_arity(heap, arg_loc))
+            .unwrap_or(0)
+    } else {
+        term_arity(heap, term_loc)
+    }
+}
+
+impl ClauseInfo for FocusedHeap {
+    #[inline]
+    fn name(&self) -> Option<Atom> {
+        clause_name(&self.heap, self.focus)
+    }
+
+    #[inline]
+    fn arity(&self) -> usize {
+        clause_arity(&self.heap, self.focus)
+    }
+}
+
+impl<'a> ClauseInfo for FocusedHeapRefMut<'a> {
+    #[inline]
+    fn name(&self) -> Option<Atom> {
+        clause_name(self.heap, self.focus)
+    }
+
+    #[inline]
+    fn arity(&self) -> usize {
+        clause_arity(self.heap, self.focus)
+    }
+}
+
+/*
 impl ClauseInfo for Term {
     fn name(&self) -> Option<Atom> {
         match self {
@@ -287,29 +316,30 @@ impl ClauseInfo for Term {
         }
     }
 }
+*/
 
 impl ClauseInfo for Rule {
     fn name(&self) -> Option<Atom> {
-        Some(self.head.0)
+        self.term.name(self.term.focus)
     }
 
     fn arity(&self) -> usize {
-        self.head.1.len()
+        self.term.arity(self.term.focus)
     }
 }
 
 impl ClauseInfo for PredicateClause {
     fn name(&self) -> Option<Atom> {
         match self {
-            PredicateClause::Fact(ref term, ..) => term.head.name(),
-            PredicateClause::Rule(ref rule, ..) => rule.name(),
+            PredicateClause::Fact(ref fact, ..) => fact.term.name(fact.term.focus),
+            PredicateClause::Rule(ref rule, ..) => rule.term.name(rule.term.focus),
         }
     }
 
     fn arity(&self) -> usize {
         match self {
-            PredicateClause::Fact(ref term, ..) => term.head.arity(),
-            PredicateClause::Rule(ref rule, ..) => rule.arity(),
+            PredicateClause::Fact(ref fact, ..) => fact.term.arity(fact.term.focus),
+            PredicateClause::Rule(ref rule, ..) => rule.term.arity(rule.term.focus),
         }
     }
 }
@@ -321,19 +351,31 @@ pub enum PredicateClause {
 }
 
 impl PredicateClause {
-    pub(crate) fn args(&self) -> Option<&[Term]> {
-        match self {
-            PredicateClause::Fact(term, ..) => match &term.head {
-                Term::Clause(_, _, args) => Some(args),
-                _ => None,
-            },
-            PredicateClause::Rule(rule, ..) => {
-                if rule.head.1.is_empty() {
-                    None
-                } else {
-                    Some(&rule.head.1)
-                }
+    pub(crate) fn args(&self) -> Option<&[HeapCellValue]> {
+        let (term, focus) = match self {
+            PredicateClause::Fact(Fact { term }, _) => (term, term.focus),
+            PredicateClause::Rule(Rule { term, .. }, _) => {
+                let focus = term.nth_arg(term.focus, 1).unwrap();
+                (term, focus)
+            }
+        };
+
+        let arity = term.arity(focus);
+
+        read_heap_cell!(term.deref_loc(focus),
+            (HeapCellValueTag::Str, s) => {
+                Some(&term.heap[s+1 .. s+arity+1])
+            }
+            _ => {
+                None
             }
+        )
+    }
+
+    pub(crate) fn heap(&self) -> &[HeapCellValue] {
+        match self {
+            PredicateClause::Fact(ref fact, ..) => &fact.term.heap,
+            PredicateClause::Rule(ref rule, ..) => &rule.term.heap,
         }
     }
 }
index 61fde0ebb4f36965d7c7437277ed9ecab4fcd4fd..5b62183665423eb9d48336e9c9c4cce7ba4c218e 100644 (file)
@@ -34,7 +34,7 @@ pub struct EagerStackfulPreOrderHeapIter<'a> {
     start_value: HeapCellValue,
     iter_stack: Vec<HeapCellValue>,
     mark_phase: bool,
-    heap: &'a mut Heap,
+    pub heap: &'a mut Heap,
 }
 
 impl<'a> Drop for EagerStackfulPreOrderHeapIter<'a> {
@@ -249,7 +249,7 @@ impl ListElisionPolicy for NonListElider {
 
 #[derive(Debug)]
 pub struct StackfulPreOrderHeapIter<'a, ElideLists> {
-    pub heap: &'a mut Vec<HeapCellValue>,
+    pub heap: &'a mut [HeapCellValue],
     pub machine_stack: &'a mut Stack,
     stack: Vec<IterStackLoc>,
     h: IterStackLoc,
@@ -265,11 +265,13 @@ impl<'a, ElideLists> Drop for StackfulPreOrderHeapIter<'a, ElideLists> {
             cell.set_mark_bit(false);
         }
 
-        self.heap.pop();
+        // self.heap.pop();
     }
 }
 
-pub trait FocusedHeapIter: Iterator<Item = HeapCellValue> {
+pub trait FocusedHeapIter:
+    Deref<Target = [HeapCellValue]> + Iterator<Item = HeapCellValue>
+{
     fn focus(&self) -> IterStackLoc;
 }
 
@@ -282,6 +284,14 @@ impl<'a, ElideLists: ListElisionPolicy> FocusedHeapIter
     }
 }
 
+impl<'a, ElideLists> Deref for StackfulPreOrderHeapIter<'a, ElideLists> {
+    type Target = [HeapCellValue];
+
+    fn deref(&self) -> &Self::Target {
+        &self.heap
+    }
+}
+
 impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
     #[inline]
     pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue {
@@ -358,9 +368,9 @@ impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
 
 impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> {
     #[inline]
-    fn new(heap: &'a mut Vec<HeapCellValue>, stack: &'a mut Stack, cell: HeapCellValue) -> Self {
-        let h = IterStackLoc::iterable_loc(heap.len(), HeapOrStackTag::Heap);
-        heap.push(cell);
+    fn new(heap: &'a mut [HeapCellValue], stack: &'a mut Stack, root_loc: usize) -> Self {
+        let h = IterStackLoc::iterable_loc(root_loc, HeapOrStackTag::Heap);
+        // heap.push(cell);
 
         Self {
             heap,
@@ -501,6 +511,7 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
     }
 }
 
+
 impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
     type Item = HeapCellValue;
 
@@ -524,9 +535,9 @@ pub(crate) fn cycle_detecting_stackless_preorder_iter(
 pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>(
     heap: &'a mut Vec<HeapCellValue>,
     stack: &'a mut Stack,
-    cell: HeapCellValue,
+    root_loc: usize,
 ) -> StackfulPreOrderHeapIter<'a, ElideLists> {
-    StackfulPreOrderHeapIter::new(heap, stack, cell)
+    StackfulPreOrderHeapIter::new(heap, stack, root_loc)
 }
 
 #[derive(Debug)]
@@ -538,7 +549,7 @@ pub(crate) struct PostOrderIterator<Iter: FocusedHeapIter> {
 }
 
 impl<Iter: FocusedHeapIter> Deref for PostOrderIterator<Iter> {
-    type Target = Iter;
+    type Target = [HeapCellValue];
 
     fn deref(&self) -> &Self::Target {
         &self.base_iter
@@ -610,6 +621,7 @@ impl<Iter: FocusedHeapIter> FocusedHeapIter for PostOrderIterator<Iter> {
     }
 }
 
+/*
 impl<Iter: FocusedHeapIter> PostOrderIterator<Iter> {
     /* return true if the term at heap offset idx_loc is a
      * direct/inlined subterm of a structure at the focus of
@@ -631,6 +643,7 @@ impl<Iter: FocusedHeapIter> PostOrderIterator<Iter> {
         false
     }
 }
+*/
 
 pub(crate) type LeftistPostOrderHeapIter<'a, ElideLists> =
     PostOrderIterator<StackfulPreOrderHeapIter<'a, ElideLists>>;
@@ -657,9 +670,9 @@ impl<'a, ElideLists: ListElisionPolicy> LeftistPostOrderHeapIter<'a, ElideLists>
 pub(crate) fn stackful_post_order_iter<'a, ElideLists: ListElisionPolicy>(
     heap: &'a mut Heap,
     stack: &'a mut Stack,
-    cell: HeapCellValue,
+    root_loc: usize,
 ) -> LeftistPostOrderHeapIter<'a, ElideLists> {
-    PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, cell))
+    PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, root_loc))
 }
 
 #[cfg(test)]
@@ -1771,11 +1784,13 @@ mod tests {
             .heap
             .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
 
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                str_loc_as_cell!(0),
+                3,
             );
 
             assert_eq!(
@@ -1810,7 +1825,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                str_loc_as_cell!(0),
+                4,
             );
 
             assert_eq!(
@@ -1842,7 +1857,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let mut var = heap_loc_as_cell!(0);
@@ -1869,7 +1884,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                1,
             );
 
             assert_eq!(
@@ -1893,7 +1908,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(
@@ -1929,7 +1944,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             // the cycle will be iterated twice before being detected.
@@ -1951,7 +1966,15 @@ mod tests {
             );
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                heap_loc_as_cell!(0)
+                list_loc_as_cell!(1)
+            );
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                atom_as_cell!(a_atom)
+            );
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                list_loc_as_cell!(3)
             );
 
             assert_eq!(iter.next(), None);
@@ -1961,7 +1984,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             // cut the iteration short to check that all cells are
@@ -2000,7 +2023,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2025,7 +2048,7 @@ mod tests {
             let mut iter = stackful_preorder_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2048,11 +2071,14 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(0i64)));
 
+        let h = wam.machine_st.heap.len();
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
+
         {
             let mut iter = stackful_preorder_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             let pstr_offset_cell = pstr_offset_as_cell!(0);
@@ -2078,16 +2104,20 @@ mod tests {
         }
         */
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
         wam.machine_st
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(1i64)));
 
+        let h = wam.machine_st.heap.len();
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
+
         {
             let mut iter = stackful_preorder_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             let pstr_offset_cell = pstr_offset_as_cell!(0);
@@ -2127,11 +2157,14 @@ mod tests {
 
         wam.machine_st.heap.extend(functor);
 
+        let h = wam.machine_st.heap.len();
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
+
         {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2194,7 +2227,7 @@ mod tests {
             let mut iter = stackful_preorder_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2263,7 +2296,7 @@ mod tests {
             let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let mut cyclic_link = list_loc_as_cell!(1);
@@ -2292,12 +2325,13 @@ mod tests {
 
         wam.machine_st.heap.push(pstr_as_cell!(atom!("a string")));
         wam.machine_st.heap.push(empty_list_as_cell!());
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
 
         {
             let mut iter = stackful_preorder_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                2,
             );
 
             assert_eq!(
@@ -2325,11 +2359,14 @@ mod tests {
         wam.machine_st.heap.push(str_loc_as_cell!(4));
         wam.machine_st.heap.push(empty_list_as_cell!());
 
+        let h = wam.machine_st.heap.len();
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
+
         {
             let mut iter = stackful_preorder_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2359,6 +2396,8 @@ mod tests {
         let a_atom = atom!("a");
         let b_atom = atom!("b");
 
+        wam.machine_st.heap.push(str_loc_as_cell!(1));
+
         wam.machine_st
             .heap
             .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
@@ -2367,7 +2406,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                str_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(
@@ -2388,13 +2427,14 @@ mod tests {
 
         wam.machine_st.heap.clear();
 
+        wam.machine_st.heap.push(str_loc_as_cell!(1));
         wam.machine_st.heap.extend(functor!(
             f_atom,
             [
                 atom(a_atom),
                 atom(b_atom),
                 atom(a_atom),
-                cell(str_loc_as_cell!(0))
+                cell(str_loc_as_cell!(1))
             ]
         ));
 
@@ -2403,7 +2443,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                str_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(
@@ -2419,7 +2459,7 @@ mod tests {
                 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!(1));
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -2437,7 +2477,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let mut var = heap_loc_as_cell!(0);
@@ -2464,7 +2504,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                1,
             );
 
             assert_eq!(
@@ -2484,11 +2524,14 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(b_atom));
         wam.machine_st.heap.push(empty_list_as_cell!());
 
+        let h = wam.machine_st.heap.len();
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
+
         {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2515,16 +2558,18 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
 
         // now make the list cyclic.
+        let h = wam.machine_st.heap.len();
         wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
         {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                h,
             );
 
             // the cycle will be iterated twice before being detected.
@@ -2556,7 +2601,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             // cut the iteration short to check that all cells are
@@ -2591,11 +2636,15 @@ mod tests {
             put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
         let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
+        let h = wam.machine_st.heap.len() - 1;
+
         {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2608,6 +2657,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
         wam.machine_st.heap.push(pstr_loc_as_cell!(2));
 
@@ -2615,11 +2665,15 @@ mod tests {
             put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
         let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
+        let h = wam.machine_st.heap.len() - 1;
+
         {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2632,6 +2686,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
         wam.machine_st
             .heap
@@ -2642,11 +2697,15 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(0i64)));
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
+        let h = wam.machine_st.heap.len() - 1;
+
         {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2664,16 +2723,21 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
         wam.machine_st
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(1i64)));
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
+        let h = wam.machine_st.heap.len() - 1;
+
         {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             assert_eq!(
@@ -2707,7 +2771,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(
@@ -2771,7 +2835,7 @@ mod tests {
             let mut iter = stackful_post_order_iter::<NonListElider>(
                 &mut wam.machine_st.heap,
                 &mut wam.machine_st.stack,
-                heap_loc_as_cell!(0),
+                0,
             );
 
             assert_eq!(
index 3c22f0aec8bcd25984465cbc9a057ca51419b7e1..c4e50175ccb93e6dedfb3845f85d3e20d6ddf01b 100644 (file)
@@ -532,11 +532,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         stack: &'a mut Stack,
         op_dir: &'a OpDir,
         output: Outputter,
-        cell: HeapCellValue,
+        root_loc: usize,
     ) -> Self {
         HCPrinter {
             outputter: output,
-            iter: stackful_preorder_iter(heap, stack, cell),
+            iter: stackful_preorder_iter(heap, stack, root_loc),
             atom_tbl,
             op_dir,
             state_stack: vec![],
@@ -1835,6 +1835,8 @@ mod tests {
             .heap
             .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
 
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         {
             let printer = HCPrinter::new(
                 &mut wam.machine_st.heap,
@@ -1842,7 +1844,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let output = printer.print();
@@ -1864,6 +1866,9 @@ mod tests {
             ]
         ));
 
+        let h = wam.machine_st.heap.len();
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         {
             let printer = HCPrinter::new(
                 &mut wam.machine_st.heap,
@@ -1871,7 +1876,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                h,
             );
 
             let output = printer.print();
@@ -1895,7 +1900,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let output = printer.print();
@@ -1908,7 +1913,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             printer
@@ -1941,7 +1946,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let output = printer.print();
@@ -1960,7 +1965,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             let output = printer.print();
@@ -1977,7 +1982,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             printer
@@ -2009,7 +2014,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             printer.max_depth = 5;
@@ -2025,6 +2030,10 @@ mod tests {
 
         put_partial_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
+        let h = wam.machine_st.heap.len() - 1;
+
         {
             let printer = HCPrinter::new(
                 &mut wam.machine_st.heap,
@@ -2032,7 +2041,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                pstr_loc_as_cell!(0),
+                h,
             );
 
             let output = printer.print();
@@ -2042,6 +2051,7 @@ mod tests {
 
         all_cells_unmarked(&wam.machine_st.heap);
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
 
         wam.machine_st.heap.push(list_loc_as_cell!(2));
@@ -2060,7 +2070,7 @@ mod tests {
                 &mut wam.machine_st.stack,
                 &wam.op_dir,
                 PrinterOutputter::new(),
-                heap_loc_as_cell!(0),
+                0,
             );
 
             printer.double_quotes = true;
index f4cb22aef4cdb3153faf7a2650c9f07b07933e2f..a199e625b43b6b6e2fb7e4a47c88e90afad3e90b 100644 (file)
@@ -1,8 +1,8 @@
 use crate::atom_table::*;
-use crate::parser::ast::*;
-
 use crate::forms::*;
 use crate::instructions::*;
+use crate::parser::ast::*;
+use crate::types::*;
 
 use fxhash::FxBuildHasher;
 use indexmap::IndexMap;
@@ -1491,34 +1491,60 @@ impl<I: Indexer> CodeOffsets<I> {
 
     pub(crate) fn index_term(
         &mut self,
-        optimal_arg: &Term,
+        heap: &[HeapCellValue],
+        optimal_arg: HeapCellValue,
         index: usize,
         clause_index_info: &mut ClauseIndexInfo,
         atom_tbl: &AtomTable,
     ) {
-        match optimal_arg {
-            &Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {
-                clause_index_info.opt_arg_index_key = OptArgIndexKey::List(self.optimal_index, 0);
-                self.index_list(index);
+        read_heap_cell!(optimal_arg,
+            (HeapCellValueTag::Str, s) => {
+                let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
+
+                if (name, arity) == (atom!("."), 2) {
+                    clause_index_info.opt_arg_index_key = OptArgIndexKey::List(self.optimal_index, 0);
+                    self.index_list(index);
+                } else {
+                    clause_index_info.opt_arg_index_key =
+                        OptArgIndexKey::Structure(self.optimal_index, 0, name, arity);
+
+                    self.index_structure(name, arity, index);
+                }
+            }
+            (HeapCellValueTag::Atom, (name, arity)) => {
+                debug_assert_eq!(arity, 0);
+
+                let overlapping_constants = self.index_constant(atom_tbl, Literal::Atom(name), index);
+
+                clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal(
+                    self.optimal_index,
+                    0,
+                    Literal::Atom(name),
+                    overlapping_constants,
+                );
             }
-            &Term::Cons(..) | &Term::Literal(_, Literal::String(_)) | &Term::PartialString(..) => {
+            (HeapCellValueTag::Lis
+             | HeapCellValueTag::CStr
+             | HeapCellValueTag::PStrLoc) => {
                 clause_index_info.opt_arg_index_key = OptArgIndexKey::List(self.optimal_index, 0);
                 self.index_list(index);
             }
-            &Term::Clause(_, name, ref terms) => {
-                clause_index_info.opt_arg_index_key =
-                    OptArgIndexKey::Structure(self.optimal_index, 0, name, terms.len());
-
-                self.index_structure(name, terms.len(), index);
-            }
-            &Term::Literal(_, constant) => {
-                let overlapping_constants = self.index_constant(atom_tbl, constant, index);
-
-                clause_index_info.opt_arg_index_key =
-                    OptArgIndexKey::Literal(self.optimal_index, 0, constant, overlapping_constants);
+            _ => {
+                match Literal::try_from(optimal_arg) {
+                    Ok(lit) => {
+                        let overlapping_constants = self.index_constant(atom_tbl, lit, index);
+
+                        clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal(
+                            self.optimal_index,
+                            0,
+                            lit,
+                            overlapping_constants,
+                        );
+                    }
+                    _ => {}
+                }
             }
-            _ => {}
-        }
+        );
     }
 
     pub(crate) fn no_indices(&mut self) -> bool {
index b3140ee93d6cf1bcc4edf0d6a661a6fda1b56139..030daf8150577b70518d94e36d756f9d95527ba5 100644 (file)
-use crate::atom_table::*;
+use crate::atom_table::AtomCell;
 use crate::forms::*;
-use crate::instructions::*;
-use crate::parser::ast::*;
+use crate::heap_iter::*;
+use crate::machine::heap::*;
+use crate::machine::stack::*;
+use crate::types::*;
+
+use bit_set::*;
+use fxhash::FxBuildHasher;
+use indexmap::IndexMap;
 
-use std::cell::Cell;
 use std::collections::VecDeque;
 use std::iter::*;
+use std::ops::Deref;
 use std::vec::Vec;
 
-#[allow(clippy::borrowed_box)]
-#[derive(Debug, Clone)]
-pub(crate) enum TermRef<'a> {
-    AnonVar(Level),
-    Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    Literal(Level, &'a Cell<RegType>, &'a Literal),
-    Clause(Level, &'a Cell<RegType>, Atom, &'a Vec<Term>),
-    PartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
-    CompleteString(Level, &'a Cell<RegType>, Atom),
-    Var(Level, &'a Cell<VarReg>, VarPtr),
-}
-
-/*
-impl<'a> TermRef<'a> {
-    pub(crate) fn level(&self) -> Level {
-        match self {
-            TermRef::AnonVar(lvl) |
-            TermRef::Cons(lvl, ..) |
-            TermRef::Literal(lvl, ..) |
-            TermRef::Var(lvl, ..) |
-            TermRef::Clause(lvl, ..) |
-            TermRef::CompleteString(lvl, ..) |
-            TermRef::PartialString(lvl, ..) => *lvl,
-        }
-    }
+pub(crate) trait TermIterator:
+    Deref<Target = [HeapCellValue]> + Iterator<Item = HeapCellValue>
+{
+    fn focus(&self) -> IterStackLoc;
+    fn level(&mut self) -> Level;
 }
-*/
 
-#[allow(clippy::borrowed_box)]
 #[derive(Debug)]
-pub(crate) enum TermIterState<'a> {
-    AnonVar(Level),
-    Clause(Level, usize, &'a Cell<RegType>, Atom, &'a Vec<Term>),
-    Literal(Level, &'a Cell<RegType>, &'a Literal),
-    InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
-    FinalPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
-    CompleteString(Level, &'a Cell<RegType>, Atom),
-    Var(Level, &'a Cell<VarReg>, VarPtr),
+pub(crate) struct TargetIterator<I: FocusedHeapIter, const SKIP_ROOT: bool> {
+    shallow_terms: IndexMap<usize, BitSet<usize>, FxBuildHasher>,
+    root_terms: BitSet<usize>,
+    iter: I,
+    arg_c: usize,
 }
 
-impl<'a> TermIterState<'a> {
-    pub(crate) fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
-        match term {
-            Term::AnonVar => TermIterState::AnonVar(lvl),
-            Term::Clause(cell, name, subterms) => {
-                TermIterState::Clause(lvl, 0, cell, *name, subterms)
-            }
-            Term::Cons(cell, head, tail) => {
-                TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
+fn record_path(
+    heap: &[HeapCellValue],
+    root_terms: &mut BitSet<usize>,
+    mut root_loc: usize,
+) -> usize {
+    loop {
+        let cell = heap[root_loc];
+        root_terms.insert(root_loc);
+
+        read_heap_cell!(cell,
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                if h == root_loc {
+                    break;
+                } else {
+                    root_loc = h;
+                }
             }
-            Term::Literal(cell, constant) => TermIterState::Literal(lvl, cell, constant),
-            Term::PartialString(cell, string_buf, tail) => {
-                TermIterState::InitialPartialString(lvl, cell, string_buf, tail)
+            (HeapCellValueTag::Lis) => {
+               root_terms.insert(root_loc);
+               break;
+           }
+            _ => {
+                if cell.is_ref() {
+                    root_terms.insert(cell.get_value() as usize);
+                }
+
+                break;
             }
-            Term::CompleteString(cell, atom) => TermIterState::CompleteString(lvl, cell, *atom),
-            Term::Var(cell, var_ptr) => TermIterState::Var(lvl, cell, var_ptr.clone()),
-        }
+        );
     }
+
+    root_loc
 }
 
-#[derive(Debug)]
-pub(crate) struct QueryIterator<'a> {
-    state_stack: Vec<TermIterState<'a>>,
+fn find_root_terms(heap: &[HeapCellValue], root_loc: usize) -> (usize, BitSet<usize>) {
+    let mut root_terms = BitSet::<usize>::default();
+    let root_loc = record_path(heap, &mut root_terms, root_loc);
+    (root_loc, root_terms)
 }
 
-impl<'a> QueryIterator<'a> {
-    fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
-        self.state_stack
-            .push(TermIterState::subterm_to_state(lvl, term));
-    }
+fn find_shallow_terms(
+    heap: &[HeapCellValue],
+    root_loc: usize,
+) -> IndexMap<usize, BitSet<usize>, FxBuildHasher> {
+    let mut shallow_terms_map = IndexMap::with_hasher(FxBuildHasher::default());
 
-    /*
-    fn from_rule_head_clause(terms: &'a Vec<Term>) -> Self {
-        let state_stack = terms
-            .iter()
-            .rev()
-            .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt))
-            .collect();
+    let (h, arity) = read_heap_cell!(heap[root_loc],
+        (HeapCellValueTag::Str, s) => {
+            (s+1, cell_as_atom_cell!(heap[s]).get_arity())
+        }
+        (HeapCellValueTag::Lis, l) => {
+            (l, 2)
+        }
+        (HeapCellValueTag::Atom, (_name, arity)) => {
+            (root_loc + 1, arity)
+        }
+        _ => {
+            (root_loc, 0)
+        }
+    );
 
-        QueryIterator { state_stack }
+    for idx in 0..arity {
+        let mut shallow_terms = BitSet::default();
+        record_path(heap, &mut shallow_terms, h + idx);
+        shallow_terms_map.insert(idx + 1, shallow_terms);
     }
-    */
-
-    fn from_term(term: &'a Term) -> Self {
-        let state = match term {
-            Term::AnonVar
-            | Term::Cons(..)
-            | Term::Literal(..)
-            | Term::PartialString(..)
-            | Term::CompleteString(..) => {
-                return QueryIterator {
-                    state_stack: vec![],
-                }
-            }
-            Term::Clause(r, name, terms) => TermIterState::Clause(Level::Root, 0, r, *name, terms),
-            Term::Var(cell, var_ptr) => TermIterState::Var(Level::Root, cell, var_ptr.clone()),
-        };
 
-        QueryIterator {
-            state_stack: vec![state],
+    shallow_terms_map
+}
+
+impl<I: FocusedHeapIter, const SKIP_ROOT: bool> TargetIterator<I, SKIP_ROOT> {
+    fn new(iter: I, root_loc: usize, arg_c: usize) -> Self {
+        let (derefed_root_loc, root_terms) = find_root_terms(&iter, root_loc);
+        let shallow_terms = find_shallow_terms(&iter, derefed_root_loc);
+
+        Self {
+            shallow_terms,
+            root_terms,
+            iter,
+            arg_c,
         }
     }
 
-    fn extend_state(&mut self, lvl: Level, term: &'a QueryTerm) {
-        match term {
-            QueryTerm::Clause(ref cell, ClauseType::CallN(_), ref terms, _) => {
-                self.state_stack
-                    .push(TermIterState::Clause(lvl, 1, cell, atom!("$call"), terms));
-            }
-            QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
-                self.state_stack
-                    .push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms));
+    fn current_level(&self, arg_c_inc: usize) -> Level {
+        let current_focus = self.iter.focus().value() as usize;
+
+        if self.root_terms.contains(current_focus) {
+            return Level::Root;
+        }
+
+        if let Some(shallow_terms) = self.shallow_terms.get(&(self.arg_c + arg_c_inc)) {
+            if shallow_terms.contains(current_focus) {
+                return Level::Shallow;
             }
-            _ => {}
         }
-    }
 
-    pub fn new(term: &'a QueryTerm) -> Self {
-        let mut iter = QueryIterator {
-            state_stack: vec![],
-        };
-        iter.extend_state(Level::Root, term);
-        iter
+        Level::Deep
     }
 }
 
-impl<'a> Iterator for QueryIterator<'a> {
-    type Item = TermRef<'a>;
+impl<'a, const SKIP_ROOT: bool> TermIterator for FactIterator<'a, SKIP_ROOT> {
+    fn focus(&self) -> IterStackLoc {
+        self.iter.focus()
+    }
 
-    fn next(&mut self) -> Option<Self::Item> {
-        while let Some(iter_state) = self.state_stack.pop() {
-            match iter_state {
-                TermIterState::AnonVar(lvl) => {
-                    return Some(TermRef::AnonVar(lvl));
-                }
-                TermIterState::Clause(lvl, child_num, cell, name, child_terms) => {
-                    if child_num == child_terms.len() {
-                        match name {
-                            atom!("$call") if lvl == Level::Root => {
-                                self.push_subterm(Level::Shallow, &child_terms[0]);
-                            }
-                            _ => {
-                                return match lvl {
-                                    Level::Root => None,
-                                    lvl => Some(TermRef::Clause(lvl, cell, name, child_terms)),
-                                }
-                            }
-                        };
-                    } else {
-                        self.state_stack.push(TermIterState::Clause(
-                            lvl,
-                            child_num + 1,
-                            cell,
-                            name,
-                            child_terms,
-                        ));
-
-                        self.push_subterm(lvl.child_level(), &child_terms[child_num]);
-                    }
-                }
-                TermIterState::InitialCons(lvl, cell, head, tail) => {
-                    self.state_stack
-                        .push(TermIterState::FinalCons(lvl, cell, head, tail));
+    fn level(&mut self) -> Level {
+        let lvl = self.current_level(1);
 
-                    self.push_subterm(lvl.child_level(), tail);
-                    self.push_subterm(lvl.child_level(), head);
-                }
-                TermIterState::InitialPartialString(lvl, cell, string, tail) => {
-                    self.state_stack
-                        .push(TermIterState::FinalPartialString(lvl, cell, string, tail));
-                    self.push_subterm(lvl.child_level(), tail);
-                }
-                TermIterState::FinalPartialString(lvl, cell, atom, tail) => {
-                    return Some(TermRef::PartialString(lvl, cell, atom, tail));
-                }
-                TermIterState::CompleteString(lvl, cell, atom) => {
-                    return Some(TermRef::CompleteString(lvl, cell, atom));
-                }
-                TermIterState::FinalCons(lvl, cell, head, tail) => {
-                    return Some(TermRef::Cons(lvl, cell, head, tail));
-                }
-                TermIterState::Literal(lvl, cell, constant) => {
-                    return Some(TermRef::Literal(lvl, cell, constant));
-                }
-                TermIterState::Var(lvl, cell, var_ptr) => {
-                    return Some(TermRef::Var(lvl, cell, var_ptr));
-                }
-            };
+        if let Level::Shallow = lvl {
+            self.arg_c += 1;
         }
 
-        None
+        lvl
     }
 }
 
-#[derive(Debug)]
-pub(crate) struct FactIterator<'a> {
-    state_queue: VecDeque<TermIterState<'a>>,
-    iterable_root: RootIterationPolicy,
-}
-
-impl<'a> FactIterator<'a> {
-    fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
-        self.state_queue
-            .push_back(TermIterState::subterm_to_state(lvl, term));
+impl<'a, const SKIP_ROOT: bool> TermIterator for QueryIterator<'a, SKIP_ROOT> {
+    fn focus(&self) -> IterStackLoc {
+        self.iter.focus()
     }
 
-    pub(crate) fn from_rule_head_clause(terms: &'a [Term]) -> Self {
-        let state_queue = terms
-            .iter()
-            .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt))
-            .collect();
+    fn level(&mut self) -> Level {
+        let lvl = self.current_level(0);
 
-        FactIterator {
-            state_queue,
-            iterable_root: RootIterationPolicy::NotIterated,
+        if let Level::Shallow = lvl {
+            self.arg_c += 1;
         }
-    }
 
-    fn new(term: &'a Term, iterable_root: RootIterationPolicy) -> Self {
-        let states = match term {
-            Term::AnonVar => {
-                vec![TermIterState::AnonVar(Level::Root)]
-            }
-            Term::Clause(cell, name, terms) => {
-                vec![TermIterState::Clause(Level::Root, 0, cell, *name, terms)]
-            }
-            Term::Cons(cell, head, tail) => vec![TermIterState::InitialCons(
-                Level::Root,
-                cell,
-                head.as_ref(),
-                tail.as_ref(),
-            )],
-            Term::PartialString(cell, string_buf, tail) => {
-                vec![TermIterState::InitialPartialString(
-                    Level::Root,
-                    cell,
-                    string_buf,
-                    tail,
-                )]
-            }
-            Term::CompleteString(cell, atom) => {
-                vec![TermIterState::CompleteString(Level::Root, cell, *atom)]
-            }
-            Term::Literal(cell, constant) => {
-                vec![TermIterState::Literal(Level::Root, cell, constant)]
-            }
-            Term::Var(cell, var_ptr) => {
-                vec![TermIterState::Var(Level::Root, cell, var_ptr.clone())]
-            }
-        };
-
-        FactIterator {
-            state_queue: VecDeque::from(states),
-            iterable_root,
-        }
+        lvl
     }
 }
 
-impl<'a> Iterator for FactIterator<'a> {
-    type Item = TermRef<'a>;
+impl<I: FocusedHeapIter, const SKIP_ROOT: bool> Iterator for TargetIterator<I, SKIP_ROOT> {
+    type Item = HeapCellValue;
 
     fn next(&mut self) -> Option<Self::Item> {
-        while let Some(state) = self.state_queue.pop_front() {
-            match state {
-                TermIterState::AnonVar(lvl) => {
-                    return Some(TermRef::AnonVar(lvl));
-                }
-                TermIterState::Clause(lvl, _, cell, name, child_terms) => {
-                    for child_term in child_terms {
-                        self.push_subterm(lvl.child_level(), child_term);
-                    }
+        loop {
+            let next_term = self.iter.next();
 
-                    match lvl {
-                        Level::Root if !self.iterable_root.iterable() => continue,
-                        _ => return Some(TermRef::Clause(lvl, cell, name, child_terms)),
-                    };
-                }
-                TermIterState::InitialCons(lvl, cell, head, tail) => {
-                    self.push_subterm(Level::Deep, head);
-                    self.push_subterm(Level::Deep, tail);
+            if next_term.is_none() {
+                return None;
+            }
 
-                    return Some(TermRef::Cons(lvl, cell, head, tail));
-                }
-                TermIterState::InitialPartialString(lvl, cell, string_buf, tail) => {
-                    self.push_subterm(Level::Deep, tail);
-                    return Some(TermRef::PartialString(lvl, cell, string_buf, tail));
-                }
-                TermIterState::CompleteString(lvl, cell, atom) => {
-                    return Some(TermRef::CompleteString(lvl, cell, atom));
-                }
-                TermIterState::Literal(lvl, cell, constant) => {
-                    return Some(TermRef::Literal(lvl, cell, constant))
-                }
-                TermIterState::Var(lvl, cell, var_ptr) => {
-                    return Some(TermRef::Var(lvl, cell, var_ptr));
-                }
-                _ => {}
+            let focus = self.iter.focus().value() as usize;
+
+            if SKIP_ROOT && self.root_terms.contains(focus) {
+                continue;
+            } else {
+                return next_term;
             }
         }
+    }
+}
 
-        None
+impl<I: FocusedHeapIter, const SKIP_ROOT: bool> Deref for TargetIterator<I, SKIP_ROOT> {
+    type Target = [HeapCellValue];
+
+    fn deref(&self) -> &Self::Target {
+        self.iter.deref()
     }
 }
 
-pub(crate) fn post_order_iter(term: &'_ Term) -> QueryIterator {
-    QueryIterator::from_term(term)
+impl<I: FocusedHeapIter, const SKIP_ROOT: bool> FocusedHeapIter for TargetIterator<I, SKIP_ROOT> {
+    fn focus(&self) -> IterStackLoc {
+        self.iter.focus()
+    }
 }
 
-pub(crate) fn breadth_first_iter(
-    term: &'_ Term,
-    iterable_root: RootIterationPolicy,
-) -> FactIterator {
-    FactIterator::new(term, iterable_root)
+pub(crate) type FactIterator<'a, const SKIP_ROOT: bool> =
+    TargetIterator<StackfulPreOrderHeapIter<'a, NonListElider>, SKIP_ROOT>;
+
+pub(crate) fn fact_iterator<'a, const SKIP_ROOT: bool>(
+    heap: &'a mut Heap,
+    stack: &'a mut Stack,
+    root_loc: usize,
+) -> FactIterator<'a, SKIP_ROOT> {
+    // let cell = heap[root_loc];
+    TargetIterator::new(stackful_preorder_iter(heap, stack, root_loc), root_loc, 0)
+}
+
+pub(crate) type QueryIterator<'a, const SKIP_ROOT: bool> =
+    TargetIterator<PostOrderIterator<StackfulPreOrderHeapIter<'a, NonListElider>>, SKIP_ROOT>;
+
+pub(crate) fn query_iterator<'a, const SKIP_ROOT: bool>(
+    heap: &'a mut Heap,
+    stack: &'a mut Stack,
+    root_loc: usize,
+) -> QueryIterator<'a, SKIP_ROOT> {
+    // let cell = heap[root_loc];
+    TargetIterator::new(stackful_post_order_iter(heap, stack, root_loc), root_loc, 1)
 }
 
 #[derive(Debug, Copy, Clone)]
index f251b57d9d4228c3e8169c7fd712eefe0ec67069..6d18b447cf0261dc9ee0a8625b332bb479cddc1c 100644 (file)
@@ -59,7 +59,7 @@ get_attrs_var_check(Module) -->
                              !,
                              '$get_attr_list'(Var, Ls),
                              nonvar(Ls),
-                                        atts:'$copy_attr_list'(Ls, Module, Attr))].
+                            atts:'$copy_attr_list'(Ls, Module, Attr))].
 
 put_attrs(Name/Arity, Module) -->
     put_attr(Name, Arity, Module),
index b24244d6bd7c077cb68a69a35678ef04f055441d..e3e25a6ab19925b2525ef07258158492db38ddec 100644 (file)
@@ -1173,13 +1173,7 @@ clause(H, B) :-
 % The clause will be inserted at the beginning of the module.
 asserta(Clause0) :-
     loader:strip_subst_module(Clause0, user, Module, Clause),
-    asserta_(Module, Clause).
-
-asserta_(Module, (Head :- Body)) :-
-    !,
-    '$asserta'(Module, Head, Body).
-asserta_(Module, Fact) :-
-    '$asserta'(Module, Fact, true).
+    '$asserta'(Module, Clause).
 
 :- meta_predicate assertz(:).
 
@@ -1189,13 +1183,7 @@ asserta_(Module, Fact) :-
 % The clase will be inserted at the end of the module.
 assertz(Clause0) :-
     loader:strip_subst_module(Clause0, user, Module, Clause),
-    assertz_(Module, Clause).
-
-assertz_(Module, (Head :- Body)) :-
-    !,
-    '$assertz'(Module, Head, Body).
-assertz_(Module, Fact) :-
-    '$assertz'(Module, Fact, true).
+    '$assertz'(Module, Clause).
 
 
 :- meta_predicate retract(:).
index 0e29c190d0879b108406733ba45015175a2daf64..90cc4d3ff902f86ef4142fb8bb96d2195c1a9963 100644 (file)
@@ -126,4 +126,3 @@ when_condition_si((A, B)) :-
 when_condition_si((A ; B)) :-
     when_condition_si(A),
     when_condition_si(B).
-
index 44926aba957024df70bc498377eba252346b85fe..69696794630e75b645cca9b5834da942982c5f2f 100644 (file)
@@ -205,6 +205,7 @@ load_loop(Stream, Evacuable) :-
        read_term(Stream, Term, [singletons(Singletons)])
     ;  Term = end_of_file
     ),
+    % write('Term: '), writeq(Term), nl,
     (  Term == end_of_file ->
        close(Stream),
        '$conclude_load'(Evacuable)
@@ -218,6 +219,7 @@ load_loop(Stream, Evacuable) :-
 
 compile_term(Term, Evacuable) :-
     expand_terms_and_goals(Term, Terms),
+    % write('Terms: '), writeq(Terms),nl,
     !,
     (  var(Terms) ->
        instantiation_error(load/1)
index 64e66f4de35e49ec5525c143b707171dde3a8120..b9721af99cd772d6a542497d0c6d85b194a50343 100644 (file)
@@ -1132,8 +1132,17 @@ impl MachineState {
         value: HeapCellValue,
     ) -> Result<Number, MachineStub> {
         let stub_gen = || functor_stub(atom!("is"), 2);
-        let mut iter =
-            stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
+
+        let root_loc = if value.is_ref() {
+            value.get_value() as usize
+        } else {
+            let type_error = self.type_error(ValidType::Evaluable, value);
+            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,
+        );
 
         while let Some(value) = iter.next() {
             if value.get_forwarding_bit() {
index d84822fe86f792a78dc4d1a8ef0c646d5f8f0e51..794c0e76e89c7179b8c9b455e621cecf886ed141 100644 (file)
@@ -11,8 +11,8 @@ use std::vec::IntoIter;
 pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
 
 #[derive(Debug)]
-pub(super) struct AttrVarInitializer {
-    pub(super) attr_var_queue: Vec<usize>,
+pub(crate) struct AttrVarInitializer {
+    pub(crate) attr_var_queue: Vec<usize>,
     pub(super) bindings: Bindings,
     pub(super) p: usize,
     pub(super) cp: usize,
@@ -131,9 +131,15 @@ impl MachineState {
     pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> {
         let mut seen_set = IndexSet::new();
         let mut seen_vars = vec![];
+        let root_loc = if cell.is_ref() {
+            cell.get_value() as usize
+        } else {
+            return vec![];
+        };
 
-        let mut iter =
-            stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, cell);
+        let mut iter = stackful_preorder_iter::<NonListElider>(
+            &mut self.heap, &mut self.stack, root_loc, // cell,
+        );
 
         while let Some(value) = iter.next() {
             read_heap_cell!(value,
index e58f3553aff0f61259bc9f65e4402734094dafc9..4ddf1f33fe0d9dc106abb010dbc65530b758d0c9 100644 (file)
@@ -11,7 +11,6 @@ use crate::machine::term_stream::*;
 use crate::machine::*;
 use crate::parser::ast::*;
 
-use std::cell::Cell;
 use std::collections::VecDeque;
 use std::mem;
 use std::ops::Range;
@@ -1233,14 +1232,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
 
     fn compile_standalone_clause(
         &mut self,
-        term: Term,
+        term: FocusedHeap,
         settings: CodeGenSettings,
     ) -> Result<StandaloneCompileResult, SessionError> {
         let mut preprocessor = Preprocessor::new(settings);
 
         let clause = self.try_term_to_tl(term, &mut preprocessor)?;
-        // let queue = preprocessor.parse_queue(self)?;
-
         let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
 
         let clause_code = cg.compile_predicate(vec![clause])?;
@@ -1272,7 +1269,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
         }
 
         let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
-
         let mut code = cg.compile_predicate(clauses)?;
 
         if settings.is_extensible {
@@ -1470,7 +1466,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
     pub(super) fn incremental_compile_clause(
         &mut self,
         key: PredicateKey,
-        clause: Term,
+        clause: FocusedHeap,
         compilation_target: CompilationTarget,
         non_counted_bt: bool,
         append_or_prepend: AppendOrPrepend,
@@ -2005,16 +2001,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
 }
 
 impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
-    pub(super) fn compile_clause_clauses<ClauseIter: Iterator<Item = (Term, Term)>>(
+    pub(super) fn compile_clause_clauses(
         &mut self,
         key: PredicateKey,
         compilation_target: CompilationTarget,
-        clause_clauses: ClauseIter,
+        clause_clauses: Vec<FocusedHeap>,
         append_or_prepend: AppendOrPrepend,
     ) -> Result<(), SessionError> {
-        let clause_predicates = clause_clauses
-            .map(|(head, body)| Term::Clause(Cell::default(), atom!("$clause"), vec![head, body]));
-
         let clause_clause_compilation_target = match compilation_target {
             CompilationTarget::User => CompilationTarget::Module(atom!("builtins")),
             _ => compilation_target,
@@ -2022,7 +2015,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
 
         let mut num_clause_predicates = 0;
 
-        for clause_term in clause_predicates {
+        for clause_term in clause_clauses {
             self.incremental_compile_clause(
                 (atom!("$clause"), 2),
                 clause_term,
@@ -2253,13 +2246,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
                 .clause_clauses
                 .drain(0..std::cmp::min(predicates_len, clause_clauses_len))
                 .collect();
-
             let compilation_target = self.payload.predicates.compilation_target;
 
             self.compile_clause_clauses(
                 key,
                 compilation_target,
-                clauses_vec.into_iter(),
+                clauses_vec,
                 AppendOrPrepend::Append,
             )?;
         }
@@ -2288,15 +2280,43 @@ impl Machine {
 
     pub(crate) fn compile_standalone_clause(
         &mut self,
-        term_loc: RegType,
-        vars: &[Term],
+        term_reg: RegType,
+        vars: Vec<HeapCellValue>,
     ) -> Result<(), SessionError> {
-        let mut compile = || {
+        let cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
+
+        // append the variables of vars.
+        let focus      = cell.get_value() as usize;
+        let header_loc = term_nth_arg(&self.machine_st.heap, focus, 0).unwrap();
+        let name       = term_name(&self.machine_st.heap, header_loc).unwrap();
+        let old_arity  = term_arity(&self.machine_st.heap, header_loc);
+
+        let new_header_loc = self.machine_st.heap.len();
+        let new_arity = old_arity + vars.len();
+
+        self.machine_st.heap.push(atom_as_cell!(name, new_arity));
+
+        for idx in header_loc + 1 .. header_loc + 1 + old_arity {
+            self.machine_st.heap.push(self.machine_st.heap[idx]);
+        }
+
+        for var in vars {
+            self.machine_st.heap.push(var);
+        }
+
+        let value = if new_arity > 0 {
+            str_loc_as_cell!(new_header_loc)
+        } else {
+            heap_loc_as_cell!(new_header_loc)
+        };
+
+        let mut compile = |cell| {
+            use crate::heap_iter::eager_stackful_preorder_iter;
+
             let mut loader: Loader<'_, InlineLoadState<'_>> =
                 Loader::new(self, InlineTermStream {});
 
-            let term = loader.read_term_from_heap(term_loc);
-            let clause = build_rule_body(vars, term);
+            let mut term = loader.copy_term_from_heap(cell);
 
             let settings = CodeGenSettings {
                 global_clock_tick: None,
@@ -2304,10 +2324,16 @@ impl Machine {
                 non_counted_bt: true,
             };
 
-            loader.compile_standalone_clause(clause, settings)
+            let value = term.heap[term.focus];
+
+            term.var_locs = var_locs_from_iter(
+                eager_stackful_preorder_iter(&mut term.heap, value),
+            );
+
+            loader.compile_standalone_clause(term, settings)
         };
 
-        let StandaloneCompileResult { clause_code, .. } = compile()?;
+        let StandaloneCompileResult { clause_code, .. } = compile(value)?;
         self.code.extend(clause_code);
 
         Ok(())
index 651b3db77bd79173aebca4d13308b5e281a9fc3c..801ce078ed4068c650da7b4e653e5143d3c9c7ed 100644 (file)
@@ -1,18 +1,19 @@
 use crate::atom_table::*;
 use crate::forms::*;
 use crate::instructions::*;
-use crate::iterators::*;
+use crate::iterators::fact_iterator;
+use crate::machine::Stack;
 use crate::machine::loader::*;
 use crate::machine::machine_errors::CompilationError;
 use crate::machine::preprocessor::*;
 use crate::parser::ast::*;
 use crate::parser::dashu::Rational;
+use crate::types::*;
 use crate::variable_records::*;
 
 use dashu::Integer;
 use indexmap::{IndexMap, IndexSet};
 
-use std::cell::Cell;
 use std::cmp::Ordering;
 use std::collections::VecDeque;
 use std::hash::{Hash, Hasher};
@@ -147,11 +148,21 @@ enum TraversalState {
     // where it leaves off.
     BuildFinalDisjunct(usize),
     Fail,
-    GetCutPoint { var_num: usize, prev_b: bool },
-    Cut { var_num: usize, is_global: bool },
+    Succeed,
+    GetCutPoint {
+        var_num: usize,
+        prev_b: bool,
+    },
+    Cut {
+        var_num: usize,
+        is_global: bool,
+    },
     CutPrev(usize),
     ResetCallPolicy(CallPolicy),
-    Term(Term),
+    Term {
+        subterm: HeapCellValue,
+        term_loc: usize,
+    },
     OverrideGlobalCutVar(usize),
     ResetGlobalCutVarOverride(Option<usize>),
     RemoveBranchNum,            // pop the current_branch_num and from the root set.
@@ -183,7 +194,7 @@ impl VarData {
     fn emit_initial_get_level(&mut self, build_stack: &mut ChunkedTermVec) {
         let global_cut_var_num = if let &Some(global_cut_var_num) = &self.global_cut_var_num {
             match &self.records[global_cut_var_num].allocation {
-                VarAlloc::Perm(..) => Some(global_cut_var_num),
+                VarAlloc::Perm { .. } => Some(global_cut_var_num),
                 VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => {
                     Some(global_cut_var_num)
                 }
@@ -196,7 +207,7 @@ 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(0, PermVarAllocation::Pending);
+                VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending };
 
             match build_stack.front_mut() {
                 Some(ChunkedTerms::Branch(_)) => {
@@ -213,8 +224,8 @@ impl VarData {
     }
 }
 
-pub type ClassifyFactResult = (Term, VarData);
-pub type ClassifyRuleResult = (Term, ChunkedTermVec, VarData);
+pub type ClassifyFactResult = VarData;
+pub type ClassifyRuleResult = (ChunkedTermVec, VarData);
 
 fn merge_branch_seq(branches: impl Iterator<Item = BranchInfo>) -> BranchInfo {
     let mut branch_info = BranchInfo::new(BranchNumber::default());
@@ -255,28 +266,32 @@ impl VariableClassifier {
         }
     }
 
-    pub fn classify_fact(mut self, term: Term) -> Result<ClassifyFactResult, CompilationError> {
-        self.classify_head_variables(&term)?;
-        Ok((
-            term,
-            self.branch_map.separate_and_classify_variables(
-                self.var_num,
-                self.global_cut_var_num,
-                self.current_chunk_num,
-            ),
+    pub fn classify_fact(
+        mut self,
+        term: &mut FocusedHeap,
+    ) -> Result<ClassifyFactResult, CompilationError> {
+        let focus = term.focus;
+        self.classify_head_variables(term, focus)?;
+
+        Ok(self.branch_map.separate_and_classify_variables(
+            self.var_num,
+            self.global_cut_var_num,
+            self.current_chunk_num,
         ))
     }
 
     pub fn classify_rule<'a, LS: LoadState<'a>>(
         mut self,
         loader: &mut Loader<'a, LS>,
-        head: Term,
-        body: Term,
+        term: &mut FocusedHeap,
     ) -> Result<ClassifyRuleResult, CompilationError> {
-        self.classify_head_variables(&head)?;
+        let head_loc = term.nth_arg(term.focus, 1).unwrap();
+        let body_loc = term.nth_arg(term.focus, 2).unwrap();
+
+        self.classify_head_variables(term, head_loc)?;
         self.root_set.insert(self.current_branch_num.clone());
 
-        let mut query_terms = self.classify_body_variables(loader, body)?;
+        let mut query_terms = self.classify_body_variables(loader, term, body_loc)?;
 
         self.merge_branches();
 
@@ -288,7 +303,7 @@ impl VariableClassifier {
 
         var_data.emit_initial_get_level(&mut query_terms);
 
-        Ok((head, query_terms, var_data))
+        Ok((query_terms, var_data))
     }
 
     fn merge_branches(&mut self) {
@@ -332,22 +347,39 @@ impl VariableClassifier {
         }
     }
 
-    fn probe_body_term(&mut self, arg_c: usize, arity: usize, term: &Term) {
+    fn probe_body_term(
+        &mut self,
+        arg_c: usize,
+        arity: usize,
+        term: &mut FocusedHeap,
+        term_loc: usize,
+    ) {
         let classify_info = ClassifyInfo { arg_c, arity };
 
+        let mut lvl = Level::Shallow;
+        let mut stack = Stack::uninitialized();
+        let mut iter = fact_iterator::<false>(
+            &mut term.heap,
+            &mut stack,
+            term_loc,
+        );
+
         // second arg is true to iterate the root, which may be a variable
-        for term_ref in breadth_first_iter(term, RootIterationPolicy::Iterated) {
-            if let TermRef::Var(lvl, _, var_ptr) = term_ref {
-                // root terms are shallow here (since we're iterating a
-                // body term) so take the child level.
-                let lvl = lvl.child_level();
-                self.probe_body_var(VarInfo {
-                    var_ptr,
-                    lvl,
-                    classify_info,
-                    chunk_type: self.current_chunk_type,
-                });
+        while let Some(subterm) = iter.next() {
+            if !subterm.is_var() {
+                lvl = Level::Deep;
+                continue;
             }
+
+            let var_loc = subterm.get_value() as usize;
+            let var_ptr = term.var_locs.read_next_var_ptr_at_key(var_loc).unwrap();
+
+            self.probe_body_var(VarInfo {
+                var_ptr: var_ptr.clone(),
+                lvl,
+                classify_info,
+                chunk_type: self.current_chunk_type,
+            });
         }
     }
 
@@ -401,56 +433,79 @@ impl VariableClassifier {
         self.probe_body_var(var_info);
     }
 
-    fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> {
-        match term {
-            Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => {}
-            _ => return Err(CompilationError::InvalidRuleHead),
-        }
+    fn classify_head_variables(
+        &mut self,
+        term: &mut FocusedHeap,
+        head_loc: usize,
+    ) -> Result<(), CompilationError> {
+        let arity = read_heap_cell!(term.deref_loc(head_loc),
+            (HeapCellValueTag::Str, s) => {
+                cell_as_atom_cell!(term.heap[s]).get_arity()
+            }
+            (HeapCellValueTag::Atom) => {
+                return Ok(());
+            }
+            _ => {
+                return Err(CompilationError::InvalidRuleHead);
+            }
+        );
 
-        let mut classify_info = ClassifyInfo {
-            arg_c: 1,
-            arity: term.arity(),
-        };
+        let mut classify_info = ClassifyInfo { arg_c: 1, arity };
 
-        if let Term::Clause(_, _, terms) = term {
-            for term in terms.iter() {
-                for term_ref in breadth_first_iter(term, RootIterationPolicy::Iterated) {
-                    if let TermRef::Var(lvl, _, var_ptr) = term_ref {
-                        // a body term, so we need the child level here.
-                        let lvl = lvl.child_level();
+        if arity > 0 {
+            let (_term_loc, value) = subterm_index(&term.heap, head_loc);
+            let str_offset = value.get_value() as usize;
 
-                        // the body of the if let here is an inlined
-                        // "probe_head_var". note the difference between it
-                        // and "probe_body_var".
-                        let branch_info_v = self.branch_map.entry(var_ptr.clone()).or_default();
+            debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
 
-                        let needs_new_branch = branch_info_v.is_empty();
+            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>(
+                    &mut term.heap,
+                    &mut stack,
+                    idx,
+                );
 
-                        if needs_new_branch {
-                            branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
-                        }
+                while let Some(subterm) = iter.next() {
+                    if !subterm.is_var() {
+                        lvl = Level::Deep;
+                        continue;
+                    }
 
-                        let branch_info = branch_info_v.last_mut().unwrap();
-                        let needs_new_chunk = branch_info.chunks.is_empty();
+                    let h = subterm.get_value() as usize;
+                    let var_ptr = term.var_locs.read_next_var_ptr_at_key(h).unwrap().clone();
 
-                        if needs_new_chunk {
-                            branch_info.chunks.push(ChunkInfo {
-                                chunk_num: self.current_chunk_num,
-                                term_loc: GenContext::Head,
-                                vars: vec![],
-                            });
-                        }
+                    // the body of the if let here is an inlined
+                    // "probe_head_var". note the difference between it
+                    // and "probe_body_var".
+                    let branch_info_v = self.branch_map.entry(var_ptr.clone()).or_default();
+                    let needs_new_branch = branch_info_v.is_empty();
 
-                        let chunk_info = branch_info.chunks.last_mut().unwrap();
-                        let var_info = VarInfo {
-                            var_ptr,
-                            classify_info,
-                            chunk_type: self.current_chunk_type,
-                            lvl,
-                        };
+                    if needs_new_branch {
+                        branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
+                    }
+
+                    let branch_info = branch_info_v.last_mut().unwrap();
+                    let needs_new_chunk = branch_info.chunks.is_empty();
 
-                        chunk_info.vars.push(var_info);
+                    if needs_new_chunk {
+                        branch_info.chunks.push(ChunkInfo {
+                            chunk_num: self.current_chunk_num,
+                            term_loc: GenContext::Head,
+                            vars: vec![],
+                        });
                     }
+
+                    let chunk_info = branch_info.chunks.last_mut().unwrap();
+                    let var_info = VarInfo {
+                        var_ptr,
+                        classify_info,
+                        chunk_type: self.current_chunk_type,
+                        lvl,
+                    };
+
+                    chunk_info.vars.push(var_info);
                 }
 
                 classify_info.arg_c += 1;
@@ -460,17 +515,40 @@ impl VariableClassifier {
         Ok(())
     }
 
+    fn new_cut_state(&mut self) -> TraversalState {
+        let (var_num, is_global) = if let Some(var_num) = self.global_cut_var_num_override {
+            (var_num, false)
+        } else if let Some(var_num) = self.global_cut_var_num {
+            (var_num, true)
+        } else {
+            let var_num = self.var_num;
+
+            self.global_cut_var_num = Some(var_num);
+            self.var_num += 1;
+
+            (var_num, true)
+        };
+
+        self.probe_in_situ_var(var_num);
+
+        TraversalState::Cut { var_num, is_global }
+    }
+
     fn classify_body_variables<'a, LS: LoadState<'a>>(
         &mut self,
         loader: &mut Loader<'a, LS>,
-        term: Term,
+        terms: &mut FocusedHeap,
+        term_loc: usize,
     ) -> Result<ChunkedTermVec, CompilationError> {
-        let mut state_stack = vec![TraversalState::Term(term)];
+        let mut state_stack = vec![TraversalState::Term {
+            subterm: terms.heap[term_loc],
+            term_loc,
+        }];
         let mut build_stack = ChunkedTermVec::new();
 
         self.current_chunk_type = ChunkType::Mid;
 
-        while let Some(traversal_st) = state_stack.pop() {
+        'outer: while let Some(traversal_st) = state_stack.pop() {
             match traversal_st {
                 TraversalState::AddBranchNum(branch_num) => {
                     self.root_set.insert(branch_num.clone());
@@ -544,297 +622,339 @@ impl VariableClassifier {
                 TraversalState::Fail => {
                     build_stack.push_chunk_term(QueryTerm::Fail);
                 }
-                TraversalState::Term(term) => {
+                TraversalState::Succeed => {
+                    build_stack.push_chunk_term(QueryTerm::Succeed);
+                }
+                TraversalState::Term {
+                    mut subterm,
+                    mut term_loc,
+                } => {
                     // return true iff new chunk should be added.
-                    let update_chunk_data = |classifier: &mut Self, predicate_name, arity| {
-                        if ClauseType::is_inlined(predicate_name, arity) {
+                    let update_chunk_data = |classifier: &mut Self, key: PredicateKey| {
+                        if ClauseType::is_inlined(key.0, key.1) {
                             classifier.try_set_chunk_at_inlined_boundary()
                         } else {
                             classifier.try_set_chunk_at_call_boundary()
                         }
                     };
 
-                    let mut add_chunk = |classifier: &mut Self, name: Atom, terms: Vec<Term>| {
-                        if update_chunk_data(classifier, name, terms.len()) {
-                            build_stack.add_chunk();
-                        }
-
-                        for (arg_c, term) in terms.iter().enumerate() {
-                            classifier.probe_body_term(arg_c + 1, terms.len(), term);
-                        }
-
-                        build_stack.push_chunk_term(clause_to_query_term(
-                            loader,
-                            name,
-                            terms,
-                            classifier.call_policy,
-                        ));
-                    };
-
-                    match term {
-                        Term::Clause(
-                            _,
-                            name @ (atom!("->") | atom!(";") | atom!(",")),
-                            mut terms,
-                        ) if terms.len() == 3 => {
-                            if let Some(last_arg) = terms.last() {
-                                if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
-                                    terms.pop();
-                                    state_stack.push(TraversalState::Term(Term::Clause(
-                                        Cell::default(),
-                                        name,
-                                        terms,
-                                    )));
-                                } else {
-                                    add_chunk(self, name, terms);
-                                }
+                    macro_rules! add_chunk {
+                        ($classifier:ident, $key:expr, $tag:expr, $term_loc:expr) => {{
+                            if update_chunk_data($classifier, $key) {
+                                build_stack.add_chunk();
                             }
-                        }
-                        Term::Clause(_, atom!(","), mut terms) if terms.len() == 2 => {
-                            let tail = terms.pop().unwrap();
-                            let head = terms.pop().unwrap();
-
-                            let iter = unfold_by_str(tail, atom!(","))
-                                .into_iter()
-                                .rev()
-                                .chain(std::iter::once(head))
-                                .map(TraversalState::Term);
-
-                            state_stack.extend(iter);
-                        }
-                        Term::Clause(_, atom!(";"), mut terms) if terms.len() == 2 => {
-                            let tail = terms.pop().unwrap();
-                            let head = terms.pop().unwrap();
-
-                            let first_branch_num = self.current_branch_num.split();
-                            let branches: Vec<_> = std::iter::once(head)
-                                .chain(unfold_by_str(tail, atom!(";")).into_iter())
-                                .collect();
-
-                            let mut branch_numbers = vec![first_branch_num];
-
-                            for idx in 1..branches.len() {
-                                let succ_branch_number = branch_numbers[idx - 1].incr_by_delta();
 
-                                branch_numbers.push(if idx + 1 < branches.len() {
-                                    succ_branch_number.split()
-                                } else {
-                                    succ_branch_number
-                                });
+                            for (arg_c, term_loc) in
+                                ($term_loc + 1 ..= $term_loc + $key.1).enumerate()
+                            {
+                                $classifier.probe_body_term(arg_c + 1, $key.1, terms, term_loc);
                             }
 
-                            let build_stack_len = build_stack.len();
-                            build_stack.reserve_branch(branches.len());
-
-                            state_stack.push(TraversalState::RepBranchNum(
-                                self.current_branch_num.halve_delta(),
-                            ));
-
-                            let iter = branches.into_iter().zip(branch_numbers.into_iter());
-                            let final_disjunct_loc = state_stack.len();
+                            build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
+                                loader,
+                                $key,
+                                terms.as_ref_mut($term_loc),
+                                HeapCellValue::build_with($tag, $term_loc as u64),
+                                $classifier.call_policy,
+                            )));
+                        }};
+                    }
 
-                            for (term, branch_num) in iter.rev() {
-                                state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
-                                state_stack.push(TraversalState::RemoveBranchNum);
-                                state_stack.push(TraversalState::Term(term));
-                                state_stack.push(TraversalState::AddBranchNum(branch_num));
+                    macro_rules! add_qualified_chunk {
+                        ($classifier:ident, $module_name:expr, $key:expr, $tag:expr, $term_loc:expr) => {{
+                            if update_chunk_data($classifier, $key) {
+                                build_stack.add_chunk();
                             }
 
-                            if let TraversalState::BuildDisjunct(build_stack_len) =
-                                state_stack[final_disjunct_loc]
+                            for (arg_c, term_loc) in
+                                ($term_loc + 1..$term_loc + $key.1 + 1).enumerate()
                             {
-                                state_stack[final_disjunct_loc] =
-                                    TraversalState::BuildFinalDisjunct(build_stack_len);
+                                $classifier.probe_body_term(arg_c + 1, $key.1, terms, term_loc);
                             }
 
-                            self.current_chunk_type = ChunkType::Mid;
-                            self.current_chunk_num += 1;
-                        }
-                        Term::Clause(_, atom!("->"), mut terms) if terms.len() == 2 => {
-                            let then_term = terms.pop().unwrap();
-                            let if_term = terms.pop().unwrap();
-
-                            let prev_b = if matches!(
-                                state_stack.last(),
-                                Some(TraversalState::RemoveBranchNum)
-                            ) {
-                                // check if the second-to-last element
-                                // is a regular BuildDisjunct, as we
-                                // don't want to add GetPrevLevel in
-                                // case of a TrustMe.
-                                match state_stack.iter().rev().nth(1) {
-                                    Some(&TraversalState::BuildDisjunct(preceding_len)) => {
-                                        preceding_len + 1 == build_stack.len()
-                                    }
-                                    _ => false,
-                                }
-                            } else {
-                                false
-                            };
-
-                            state_stack.push(TraversalState::Term(then_term));
-                            state_stack.push(TraversalState::Cut {
-                                var_num: self.var_num,
-                                is_global: false,
-                            });
-                            state_stack.push(TraversalState::Term(if_term));
-                            state_stack.push(TraversalState::GetCutPoint {
-                                var_num: self.var_num,
-                                prev_b,
-                            });
-
-                            self.var_num += 1;
-                        }
-                        Term::Clause(_, atom!("\\+"), mut terms) if terms.len() == 1 => {
-                            let not_term = terms.pop().unwrap();
-                            let build_stack_len = build_stack.len();
-
-                            build_stack.reserve_branch(2);
-
-                            state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len));
-                            state_stack.push(TraversalState::Term(Term::Clause(
-                                Cell::default(),
-                                atom!("$succeed"),
-                                vec![],
-                            )));
-                            state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
-                            state_stack.push(TraversalState::Fail);
-                            state_stack.push(TraversalState::CutPrev(self.var_num));
-                            state_stack.push(TraversalState::ResetGlobalCutVarOverride(
-                                self.global_cut_var_num_override,
+                            build_stack.push_chunk_term(QueryTerm::Clause(
+                                qualified_clause_to_query_term(
+                                    loader,
+                                    $key,
+                                    $module_name,
+                                    terms.as_ref_mut($term_loc),
+                                    HeapCellValue::build_with($tag, $term_loc as u64),
+                                    $classifier.call_policy,
+                                ),
                             ));
-                            state_stack.push(TraversalState::Term(not_term));
-                            state_stack.push(TraversalState::OverrideGlobalCutVar(self.var_num));
-                            state_stack.push(TraversalState::GetCutPoint {
-                                var_num: self.var_num,
-                                prev_b: false,
-                            });
+                        }};
+                    }
 
-                            self.current_chunk_type = ChunkType::Mid;
-                            self.current_chunk_num += 1;
+                    loop {
+                        read_heap_cell!(subterm,
+                            (HeapCellValueTag::Str, subterm_loc) => {
+                                let (name, arity) = cell_as_atom_cell!(terms.heap[subterm_loc])
+                                    .get_name_and_arity();
 
-                            self.var_num += 1;
-                        }
-                        Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => {
-                            let predicate_name = terms.pop().unwrap();
-                            let module_name = terms.pop().unwrap();
-
-                            match (module_name, predicate_name) {
-                                (
-                                    Term::Literal(_, Literal::Atom(module_name)),
-                                    Term::Literal(_, Literal::Atom(predicate_name)),
-                                ) => {
-                                    if update_chunk_data(self, predicate_name, 0) {
-                                        build_stack.add_chunk();
-                                    }
+                                match (name, arity) {
+                                    (atom!("->") | atom!(";") | atom!(","), 3) => {
+                                        if blunt_index_ptr(&mut terms.heap, (name, 2), subterm_loc) {
+                                            subterm = terms.heap[subterm_loc];
+                                            continue;
+                                        }
 
-                                    build_stack.push_chunk_term(qualified_clause_to_query_term(
-                                        loader,
-                                        module_name,
-                                        predicate_name,
-                                        vec![],
-                                        self.call_policy,
-                                    ));
-                                }
-                                (
-                                    Term::Literal(_, Literal::Atom(module_name)),
-                                    Term::Clause(_, name, terms),
-                                ) => {
-                                    if update_chunk_data(self, name, terms.len()) {
-                                        build_stack.add_chunk();
+                                        add_chunk!(self, (name, 2), HeapCellValueTag::Str, subterm_loc);
                                     }
-
-                                    for (arg_c, term) in terms.iter().enumerate() {
-                                        self.probe_body_term(arg_c + 1, terms.len(), term);
+                                    (atom!(","), 2) => {
+                                        let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
+                                        let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+                                        let head = terms.heap[head_loc];
+
+                                        let iter = unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(","))
+                                            .into_iter()
+                                            .rev()
+                                            .chain(std::iter::once((head, head_loc)))
+                                            .map(|(subterm, term_loc)| {
+                                                TraversalState::Term { subterm, term_loc }
+                                            });
+                                        state_stack.extend(iter);
                                     }
-
-                                    build_stack.push_chunk_term(qualified_clause_to_query_term(
-                                        loader,
-                                        module_name,
-                                        name,
-                                        terms,
-                                        self.call_policy,
-                                    ));
-                                }
-                                (module_name, predicate_name) => {
-                                    if update_chunk_data(self, atom!("call"), 2) {
-                                        build_stack.add_chunk();
+                                    (atom!(";"), 2) => {
+                                        let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
+                                        let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+
+                                        let head = terms.heap[head_loc];
+
+                                        let first_branch_num = self.current_branch_num.split();
+                                        let branches: Vec<_> = std::iter::once((head, head_loc))
+                                            .chain(
+                                                unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(";"))
+                                                    .into_iter(),
+                                            )
+                                            .collect();
+
+                                        let mut branch_numbers = vec![first_branch_num];
+
+                                        for idx in 1..branches.len() {
+                                            let succ_branch_number = branch_numbers[idx - 1].incr_by_delta();
+
+                                            branch_numbers.push(if idx + 1 < branches.len() {
+                                                succ_branch_number.split()
+                                            } else {
+                                                succ_branch_number
+                                            });
+                                        }
+
+                                        let build_stack_len = build_stack.len();
+                                        build_stack.reserve_branch(branches.len());
+
+                                        state_stack.push(TraversalState::RepBranchNum(
+                                            self.current_branch_num.halve_delta(),
+                                        ));
+
+                                        let iter = branches.into_iter().zip(branch_numbers.into_iter());
+                                        let final_disjunct_loc = state_stack.len();
+
+                                        for ((subterm, term_loc), branch_num) in iter.rev() {
+                                            state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
+                                            state_stack.push(TraversalState::RemoveBranchNum);
+                                            state_stack.push(TraversalState::Term { subterm, term_loc });
+                                            state_stack.push(TraversalState::AddBranchNum(branch_num));
+                                        }
+
+                                        if let TraversalState::BuildDisjunct(build_stack_len) =
+                                            state_stack[final_disjunct_loc]
+                                        {
+                                            state_stack[final_disjunct_loc] =
+                                                TraversalState::BuildFinalDisjunct(build_stack_len);
+                                        }
+
+                                        self.current_chunk_type = ChunkType::Mid;
+                                        self.current_chunk_num += 1;
                                     }
+                                    (atom!("->"), 2) => {
+                                        let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
+                                        let then_term_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+
+                                        let if_term = terms.heap[if_term_loc];
+                                        let then_term = terms.heap[then_term_loc];
+
+                                        let prev_b = if matches!(
+                                            state_stack.last(),
+                                            Some(TraversalState::RemoveBranchNum)
+                                        ) {
+                                            // check if the second-to-last element
+                                            // is a regular BuildDisjunct, as we
+                                            // don't want to add GetPrevLevel in
+                                            // case of a TrustMe.
+                                            match state_stack.iter().rev().nth(1) {
+                                                Some(&TraversalState::BuildDisjunct(preceding_len)) => {
+                                                    preceding_len + 1 == build_stack.len()
+                                                }
+                                                _ => false,
+                                            }
+                                        } else {
+                                            false
+                                        };
+
+                                        state_stack.push(TraversalState::Term {
+                                            subterm: then_term,
+                                            term_loc: then_term_loc,
+                                        });
+                                        state_stack.push(TraversalState::Cut {
+                                            var_num: self.var_num,
+                                            is_global: false,
+                                        });
+                                        state_stack.push(TraversalState::Term {
+                                            subterm: if_term,
+                                            term_loc: if_term_loc,
+                                        });
+                                        state_stack.push(TraversalState::GetCutPoint {
+                                            var_num: self.var_num,
+                                            prev_b,
+                                        });
+
+                                        self.var_num += 1;
+                                    }
+                                    (atom!("\\+"), 1) => {
+                                        let not_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
+                                        let not_term = terms.heap[not_term_loc];
+                                        let build_stack_len = build_stack.len();
+
+                                        build_stack.reserve_branch(2);
+
+                                        let branch_num = self.current_branch_num.split();
+                                        let succ_branch_num = branch_num.incr_by_delta();
+
+                                        state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len));
+                                        state_stack.push(TraversalState::Succeed);
+                                        state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
+                                        state_stack.push(TraversalState::RepBranchNum(succ_branch_num));
+                                        state_stack.push(TraversalState::Fail);
+                                        state_stack.push(TraversalState::CutPrev(self.var_num));
+                                        state_stack.push(TraversalState::ResetGlobalCutVarOverride(
+                                            self.global_cut_var_num_override,
+                                        ));
+                                        state_stack.push(TraversalState::Term {
+                                            subterm: not_term,
+                                            term_loc: not_term_loc,
+                                        });
+                                        state_stack.push(TraversalState::OverrideGlobalCutVar(self.var_num));
+                                        state_stack.push(TraversalState::GetCutPoint {
+                                            var_num: self.var_num,
+                                            prev_b: false,
+                                        });
+                                        state_stack.push(TraversalState::AddBranchNum(branch_num));
+
+                                        self.current_chunk_type = ChunkType::Mid;
+                                        self.current_chunk_num += 1;
+
+                                        self.var_num += 1;
+                                    }
+                                    (atom!(":"), 2) => {
+                                        let module_name_loc = terms.nth_arg(subterm_loc, 1).unwrap();
+                                        let predicate_term_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+
+                                        let module_name = terms.deref_loc(module_name_loc);
+                                        let predicate_term = terms.deref_loc(predicate_term_loc);
+
+                                        read_heap_cell!(module_name,
+                                            (HeapCellValueTag::Atom, (module_name, arity)) => {
+                                                if arity == 0 {
+                                                    read_heap_cell!(predicate_term,
+                                                        (HeapCellValueTag::Str, s) => {
+                                                            let key = cell_as_atom_cell!(terms.heap[s])
+                                                                .get_name_and_arity();
+
+                                                            add_qualified_chunk!(
+                                                                self,
+                                                                module_name,
+                                                                key,
+                                                                HeapCellValueTag::Str,
+                                                                s
+                                                            );
+                                                        }
+                                                        (HeapCellValueTag::Atom, (predicate_name, predicate_arity)) => {
+                                                            debug_assert_eq!(predicate_arity, 0);
+                                                            let key = (predicate_name, predicate_arity);
+
+                                                            add_qualified_chunk!(
+                                                                self,
+                                                                module_name,
+                                                                key,
+                                                                HeapCellValueTag::Str,
+                                                                predicate_term_loc
+                                                            );
+                                                        }
+                                                        _ => {}
+                                                    );
+
+                                                    continue 'outer;
+                                                }
+                                            }
+                                            _ => {}
+                                        );
+
+                                        if update_chunk_data(self, (atom!("call"), 2)) {
+                                            build_stack.add_chunk();
+                                        }
+
+                                        self.probe_body_term(1, 0, terms, module_name_loc);
+                                        self.probe_body_term(2, 0, terms, predicate_term_loc);
+
+                                        let h = terms.heap.len();
+
+                                        terms.heap.push(atom_as_cell!(atom!("call"), 1));
+                                        terms.heap.push(str_loc_as_cell!(subterm_loc));
+
+                                        build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
+                                            loader,
+                                            (atom!("call"), 1),
+                                            terms.as_ref_mut(h),
+                                            str_loc_as_cell!(h),
+                                            self.call_policy,
+                                        )));
+                                    }
+                                    (atom!("$call_with_inference_counting"), 1) => {
+                                        let term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
+                                        let subterm  = terms.deref_loc(term_loc);
 
-                                    self.probe_body_term(1, 0, &module_name);
-                                    self.probe_body_term(2, 0, &predicate_name);
-
-                                    terms.push(module_name);
-                                    terms.push(predicate_name);
+                                        state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
+                                        state_stack.push(TraversalState::Term { subterm, term_loc });
 
-                                    build_stack.push_chunk_term(clause_to_query_term(
-                                        loader,
-                                        atom!("call"),
-                                        vec![Term::Clause(Cell::default(), atom!(":"), terms)],
-                                        self.call_policy,
-                                    ));
+                                        self.call_policy = CallPolicy::Counted;
+                                    }
+                                    (name, arity) => {
+                                        add_chunk!(self, (name, arity), HeapCellValueTag::Str, subterm_loc);
+                                    }
                                 }
                             }
-                        }
-                        Term::Clause(_, atom!("$call_with_inference_counting"), mut terms)
-                            if terms.len() == 1 =>
-                        {
-                            state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
-                            state_stack.push(TraversalState::Term(terms.pop().unwrap()));
+                            (HeapCellValueTag::Atom, (name, arity)) => {
+                                debug_assert_eq!(arity, 0);
 
-                            self.call_policy = CallPolicy::Counted;
-                        }
-                        Term::Clause(_, name, terms) => {
-                            add_chunk(self, name, terms);
-                        }
-                        var @ Term::Var(..) => {
-                            if update_chunk_data(self, atom!("call"), 1) {
-                                build_stack.add_chunk();
+                                if name == atom!("!") {
+                                    state_stack.push(self.new_cut_state());
+                                } else {
+                                    add_chunk!(self, (name, 0), HeapCellValueTag::Var, term_loc);
+                                }
                             }
-
-                            self.probe_body_term(1, 1, &var);
-
-                            build_stack.push_chunk_term(clause_to_query_term(
-                                loader,
-                                atom!("call"),
-                                vec![var],
-                                self.call_policy,
-                            ));
-                        }
-                        Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => {
-                            let (var_num, is_global) =
-                                if let Some(var_num) = self.global_cut_var_num_override {
-                                    (var_num, false)
-                                } else if let Some(var_num) = self.global_cut_var_num {
-                                    (var_num, true)
+                            (HeapCellValueTag::Char, c) => {
+                                if c == '!' {
+                                    state_stack.push(self.new_cut_state());
                                 } else {
-                                    let var_num = self.var_num;
-
-                                    self.global_cut_var_num = Some(var_num);
-                                    self.var_num += 1;
-
-                                    (var_num, true)
-                                };
-
-                            self.probe_in_situ_var(var_num);
+                                    return Err(CompilationError::InadmissibleQueryTerm);
+                                }
+                            }
+                            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                                if h != term_loc {
+                                    subterm = terms.heap[h];
+                                    term_loc = h;
+                                    continue;
+                                }
 
-                            state_stack.push(TraversalState::Cut { var_num, is_global });
-                        }
-                        Term::Literal(_, Literal::Atom(name)) => {
-                            if update_chunk_data(self, name, 0) {
-                                build_stack.add_chunk();
+                                add_chunk!(self, (atom!("call"), 1), HeapCellValueTag::Var, h);
+                            }
+                            _ => {
+                                return Err(CompilationError::InadmissibleQueryTerm);
                             }
+                        );
 
-                            build_stack.push_chunk_term(clause_to_query_term(
-                                loader,
-                                name,
-                                vec![],
-                                self.call_policy,
-                            ));
-                        }
-                        _ => {
-                            return Err(CompilationError::InadmissibleQueryTerm);
-                        }
+                        break;
                     }
                 }
             }
@@ -899,7 +1019,8 @@ impl BranchMap {
                     var_data.records[var_num].num_occurrences += chunk.vars.len();
 
                     for var_info in chunk.vars.iter_mut() {
-                        var_info.var_ptr.set(Var::Generated(var_num));
+                        let is_anon = var_info.var_ptr.is_anon();
+                        var_info.var_ptr.set(Var::Generated { is_anon, var_num });
                     }
                 }
             }
index a3ace102ff46b068699e25a6d8484542097f02a1..de40d8b7d45249dc5dfb011db01321044f8a86bd 100644 (file)
@@ -2632,6 +2632,8 @@ impl Machine {
                     &Instruction::CallNamed(arity, name, ref idx) => {
                         let idx = idx.get();
 
+                        // println!("calling {}/{}", name.as_str(), arity);
+
                         try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
 
                         if self.machine_st.fail {
@@ -2643,6 +2645,8 @@ impl Machine {
                     &Instruction::ExecuteNamed(arity, name, ref idx) => {
                         let idx = idx.get();
 
+                        // println!("executing {}/{}", name.as_str(), arity);
+
                         try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
 
                         if self.machine_st.fail {
@@ -2654,6 +2658,8 @@ impl Machine {
                     &Instruction::DefaultCallNamed(arity, name, ref idx) => {
                         let idx = idx.get();
 
+                        // println!("calling {}/{}", name.as_str(), arity);
+
                         try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
 
                         if self.machine_st.fail {
@@ -2663,6 +2669,8 @@ impl Machine {
                     &Instruction::DefaultExecuteNamed(arity, name, ref idx) => {
                         let idx = idx.get();
 
+                        // println!("executing {}/{}", name.as_str(), arity);
+
                         try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
 
                         if self.machine_st.fail {
@@ -3479,6 +3487,15 @@ impl Machine {
                             self.dynamic_module_resolution(arity - 2)
                         );
 
+                        /*
+                        println!(
+                            "(slow) calling {}:{}/{}",
+                            module_name.as_str(),
+                            key.0.as_str(),
+                            key.1,
+                        );
+                        */
+
                         try_or_throw!(self.machine_st, self.call_clause(module_name, key));
 
                         if self.machine_st.fail {
@@ -3491,6 +3508,15 @@ impl Machine {
                             self.dynamic_module_resolution(arity - 2)
                         );
 
+                        /*
+                        println!(
+                            "(slow) executing {}:{}/{}",
+                            module_name.as_str(),
+                            key.0.as_str(),
+                            key.1,
+                        );
+                        */
+
                         try_or_throw!(self.machine_st, self.execute_clause(module_name, key));
 
                         if self.machine_st.fail {
index e37178bf6be7da462d5c7c92610419acd70473cc..4d3d45ec04eab187692bb76780adc896d40f23bf 100644 (file)
@@ -7,6 +7,9 @@ use crate::types::*;
 #[cfg(test)]
 use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc};
 
+#[cfg(test)]
+use std::ops::Deref;
+
 pub(crate) trait UnmarkPolicy {
     fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue>
     where
@@ -103,6 +106,15 @@ pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> {
     iter_state: UMP,
 }
 
+#[cfg(test)]
+impl<'a> Deref for StacklessPreOrderHeapIter<'a, IteratorUMP> {
+    type Target = [HeapCellValue];
+
+    fn deref(&self) -> &Self::Target {
+        self.heap
+    }
+}
+
 #[cfg(test)]
 impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> {
     #[inline]
index e44e54e4eccc64b23c344267d30be59b980654b9..db9af51f26e911a760cd68c96c7b7d8ee7c99aa0 100644 (file)
@@ -1,12 +1,11 @@
 use std::collections::BTreeMap;
 
 use crate::atom_table;
-use crate::machine::machine_indices::VarKey;
+use crate::heap_print::{HCPrinter, HCValueOutputter, PrinterOutputter};
 use crate::machine::mock_wam::CompositeOpDir;
-use crate::machine::{BREAK_FROM_DISPATCH_LOOP_LOC, LIB_QUERY_SUCCESS};
+use crate::machine::{copy_and_align_iter, BREAK_FROM_DISPATCH_LOOP_LOC, LIB_QUERY_SUCCESS};
 use crate::parser::ast::{Var, VarPtr};
 use crate::parser::parser::{Parser, Tokens};
-use crate::read::{write_term_to_heap, TermWriteResult};
 use indexmap::IndexMap;
 
 use super::{
@@ -204,24 +203,15 @@ impl Machine {
         self.allocate_stub_choice_point();
 
         // Write parsed term to heap
-        let term_write_result =
-            write_term_to_heap(&term, &mut self.machine_st.heap, &self.machine_st.atom_tbl)
-                .expect("couldn't write term to heap");
-
-        let var_names: IndexMap<_, _> = term_write_result
-            .var_dict
-            .iter()
-            .map(|(var_key, cell)| match var_key {
-                // NOTE: not the intention behind Var::InSitu here but
-                // we can hijack it to store anonymous variables
-                // without creating problems.
-                VarKey::AnonVar(h) => (*cell, VarPtr::from(Var::InSitu(*h))),
-                VarKey::VarPtr(var_ptr) => (*cell, var_ptr.clone()),
-            })
-            .collect();
+        let heap_loc = self.machine_st.heap.len();
+        self.machine_st.heap.extend(copy_and_align_iter(
+            term.heap.iter().cloned(),
+            0,
+            heap_loc as i64,
+        ));
 
         // Write term to heap
-        self.machine_st.registers[1] = self.machine_st.heap[term_write_result.heap_loc];
+        self.machine_st.registers[1] = self.machine_st.heap[heap_loc + term.focus];
 
         self.machine_st.cp = LIB_QUERY_SUCCESS; // BREAK_FROM_DISPATCH_LOOP_LOC;
         let call_index_p = self
@@ -232,6 +222,24 @@ impl Machine {
             .local()
             .unwrap();
 
+        let var_names: IndexMap<_, _> = term
+            .var_locs
+            .iter()
+            .map(|(var_loc, var_ptrs)| {
+                let var_loc = var_loc + heap_loc;
+                let cell = self.machine_st.heap[var_loc];
+                let var_ptr = var_ptrs.front().unwrap();
+
+                match &*var_ptr.borrow() {
+                    // NOTE: not the intention behind Var::InSitu here but
+                    // we can hijack it to store anonymous variables
+                    // without creating problems.
+                    Var::Anon => (cell, VarPtr::from(Var::InSitu(var_loc))),
+                    _ => (cell, var_ptr.clone()),
+                }
+            })
+            .collect();
+
         self.machine_st.execute_at_index(1, call_index_p);
 
         let stub_b = self.machine_st.b;
index 86c1b68124c65592ae3714a0ba4cf2222a947537..f62e01f664525bda06f6f5a7e542b86eb1fcedd7 100644 (file)
@@ -436,7 +436,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
 
     pub(super) fn try_term_to_tl(
         &mut self,
-        term: Term,
+        term: FocusedHeap,
         preprocessor: &mut Preprocessor,
     ) -> Result<PredicateClause, SessionError> {
         let tl = preprocessor.try_term_to_tl(self, term)?;
@@ -1164,7 +1164,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
                 let mut path_buf = PathBuf::from(&*filename.as_str());
                 path_buf.set_extension("pl");
 
-                let file = File::open(&path_buf)?;
+                let file = File::open(&path_buf)
+                    .map_err(|err| ParserError::IO(err, ParserErrorSrc::default()))?;
 
                 (
                     Stream::from_file_as_input(
@@ -1245,7 +1246,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
             ModuleSource::File(filename) => {
                 let mut path_buf = PathBuf::from(&*filename.as_str());
                 path_buf.set_extension("pl");
-                let file = File::open(&path_buf)?;
+                let file = File::open(&path_buf)
+                    .map_err(|err| ParserError::IO(err, ParserErrorSrc::default()))?;
 
                 (
                     Stream::from_file_as_input(
index bf754bd0d986b3e89d7d46f1cd4bb1172a7ce51e..5daa9a6eeb14634ec4edbb7120aacdee7fd5eaef 100644 (file)
@@ -15,7 +15,6 @@ use crate::types::*;
 
 use indexmap::IndexSet;
 
-use std::cell::Cell;
 use std::collections::VecDeque;
 use std::convert::TryFrom;
 use std::fmt;
@@ -177,18 +176,18 @@ impl CompilationTarget {
 }
 
 pub struct PredicateQueue {
-    pub(super) predicates: Vec<Term>,
+    pub(super) predicates: Vec<FocusedHeap>,
     pub(super) compilation_target: CompilationTarget,
 }
 
 impl PredicateQueue {
     #[inline]
-    pub(super) fn push(&mut self, clause: Term) {
+    pub(super) fn push(&mut self, clause: FocusedHeap) {
         self.predicates.push(clause);
     }
 
     #[inline]
-    pub(crate) fn first(&self) -> Option<&Term> {
+    pub(crate) fn first(&self) -> Option<&FocusedHeap> {
         self.predicates.first()
     }
 
@@ -492,11 +491,23 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
         }
     }
 
-    pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Term {
+    pub(crate) fn copy_term_from_heap(&mut self, cell: HeapCellValue) -> FocusedHeap {
+        use crate::iterators::fact_iterator;
+
+        let mut term = FocusedHeap::empty();
+        let mut stack = Stack::uninitialized();
         let machine_st = LS::machine_st(&mut self.payload);
-        let cell = machine_st[r];
 
-        machine_st.read_term_from_heap(cell)
+        term.copy_term_from_machine_heap(machine_st, cell);
+        term.var_locs = var_locs_from_iter(
+            fact_iterator::<false>(
+                &mut term.heap,
+                &mut stack,
+                0,
+            ),
+        );
+
+        term
     }
 
     pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
@@ -513,18 +524,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
             let compilation_target = &load_state.compilation_target;
             let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
 
-            let term = load_state.term_stream.next(&composite_op_dir)?;
+            let mut term = load_state.term_stream.next(&composite_op_dir)?;
 
             if !term.is_consistent(&load_state.predicates) {
                 self.compile_and_submit()?;
             }
 
-            let term = match term {
-                Term::Clause(_, name, terms) if name == atom!(":-") && terms.len() == 1 => {
-                    return Ok(Some(setup_declaration(self, terms)?));
-                }
-                term => term,
-            };
+            if Some(atom!(":-")) == term.name(term.focus) && term.arity(term.focus) == 1 {
+                let new_focus = term.nth_arg(term.focus, 1).unwrap();
+                let term = term.as_ref_mut(new_focus);
+                return Ok(Some(setup_declaration(self, term)?));
+            }
 
             self.payload.predicates.push(term);
         }
@@ -1045,31 +1055,60 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
         let machine_st = LS::machine_st(&mut self.payload);
         let cell = machine_st[r];
 
-        let export_list = machine_st.read_term_from_heap(cell);
-        let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
-        let export_list = setup_module_export_list(export_list, atom_tbl)?;
+        let export_list = FocusedHeapRefMut::from_cell(&mut machine_st.heap, cell);
+        let export_list = setup_module_export_list(export_list)?;
 
         Ok(export_list.into_iter().collect())
     }
 
-    fn add_clause_clause(&mut self, term: Term) -> Result<(), CompilationError> {
-        match term {
-            Term::Clause(_, atom!(":-"), mut terms) if terms.len() == 2 => {
-                let body = terms.pop().unwrap();
-                let head = terms.pop().unwrap();
+    fn clause_clause(&mut self, cell: HeapCellValue) -> Result<FocusedHeap, CompilationError> {
+        let machine_st = LS::machine_st(&mut self.payload);
+        let mut term = FocusedHeap::empty();
+
+        read_heap_cell!(cell,
+            (HeapCellValueTag::Str, s) => {
+                let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
+                    .get_name_and_arity();
+
+                term.copy_term_from_machine_heap(machine_st, cell);
+                let focus = term.heap.len();
+
+                term.heap.push(str_loc_as_cell!(focus+1));
+                term.heap.push(atom_as_cell!(atom!("clause"), 2));
+
+                match (name, arity) {
+                    (atom!(":-"), 2) => {
+                        term.heap.push(heap_loc_as_cell!(2));
+                        term.heap.push(heap_loc_as_cell!(3));
+                    }
+                    _ => {
+                        term.heap.push(heap_loc_as_cell!(0));
+                        term.heap.push(atom_as_cell!(atom!("true")));
+                    }
+                }
 
-                self.payload.clause_clauses.push((head, body));
+                term.focus = focus;
             }
-            head @ Term::Literal(_, Literal::Atom(..)) | head @ Term::Clause(..) => {
-                let body = Term::Literal(Cell::default(), Literal::Atom(atom!("true")));
-                self.payload.clause_clauses.push((head, body));
+            (HeapCellValueTag::Atom, (name, arity)) => {
+                if arity == 0 {
+                    term.heap.push(str_loc_as_cell!(1));
+                    term.heap.push(atom_as_cell!(atom!("clause"), 2));
+                    term.heap.push(atom_as_cell!(name));
+                    term.heap.push(atom_as_cell!(atom!("true")));
+
+                    term.focus = 0;
+                } else {
+                    return Err(CompilationError::InadmissibleFact);
+                }
             }
             _ => {
                 return Err(CompilationError::InadmissibleFact);
             }
-        }
+        );
 
-        Ok(())
+        let value = term.heap[term.focus];
+        term.var_locs = var_locs_from_iter(eager_stackful_preorder_iter(&mut term.heap, value));
+        Ok(term)
     }
 
     fn add_extensible_predicate_declaration(
@@ -1287,9 +1326,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
         )
     }
 
-    fn add_clause_clause_if_dynamic(&mut self, term: &Term) -> Result<(), SessionError> {
-        if let Some(predicate_name) = ClauseInfo::name(term) {
-            let arity = ClauseInfo::arity(term);
+    fn add_clause_clause_if_dynamic(&mut self, value: HeapCellValue) -> Result<(), SessionError> {
+        let machine_st = LS::machine_st(&mut self.payload);
+        let term = FocusedHeapRefMut::from_cell(&mut machine_st.heap, value);
+
+        let name_opt = ClauseInfo::name(&term);
+
+        if let Some(predicate_name) = name_opt {
+            let arity = ClauseInfo::arity(&term);
             let predicates_compilation_target = self.payload.predicates.compilation_target;
 
             let is_dynamic = self
@@ -1300,7 +1344,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
                 .unwrap_or(false);
 
             if is_dynamic {
-                self.add_clause_clause(term.clone())?;
+                let clause_clause_term = self.clause_clause(value)?;
+                self.payload.clause_clauses.push(clause_clause_term);
             }
         }
 
@@ -1366,104 +1411,20 @@ impl<'a> MachinePreludeView<'a> {
     }
 }
 
+/*
 impl MachineState {
-    pub(super) fn read_term_from_heap(&mut self, term_addr: HeapCellValue) -> Term {
-        let mut term_stack = vec![];
-        let mut iter =
-            stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, term_addr);
-
-        while let Some(addr) = iter.next() {
-            let addr = unmark_cell_bits!(addr);
+    pub(super) fn read_term_from_heap(&mut self, term_addr: HeapCellValue) -> FocusedHeap {
+        let mut term = FocusedHeap::empty();
+        term.copy_term_from_machine_heap(self, term_addr);
 
-            read_heap_cell!(addr,
-                (HeapCellValueTag::Lis) => {
-                    use crate::parser::parser::as_partial_string;
+        let value = term.heap[0];
+        let iter = eager_stackful_preorder_iter(&mut term.heap, value);
 
-                    let tail = term_stack.pop().unwrap();
-                    let head = term_stack.pop().unwrap();
-
-                    match as_partial_string(head, tail) {
-                        Ok((string, Some(tail))) => {
-                            term_stack.push(Term::PartialString(Cell::default(), string, tail));
-                        }
-                        Ok((string, None)) => {
-                            let atom = AtomTable::build_with(&self.atom_tbl, &string);
-                            term_stack.push(Term::CompleteString(Cell::default(), atom));
-                        }
-                        Err(cons_term) => term_stack.push(cons_term),
-                    }
-                }
-                (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
-                    term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h))));
-                }
-                (HeapCellValueTag::Cons | HeapCellValueTag::CStr | HeapCellValueTag::Fixnum |
-                 HeapCellValueTag::Char | HeapCellValueTag::F64) => {
-                    term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap()));
-                }
-                (HeapCellValueTag::Atom, (name, arity)) => {
-                    let h = iter.focus().value() as usize;
-                    let mut arity = arity;
-
-                    if iter.heap.len() > h + arity + 1 {
-                        let value = iter.heap[h + arity + 1];
-
-                        if let Some(idx) = get_structure_index(value) {
-                            // in the second condition, arity == 0,
-                            // meaning idx cannot pertain to this atom
-                            // if it is the direct subterm of a larger
-                            // structure.
-                            if arity > 0 || !iter.direct_subterm_of_str(h) {
-                                term_stack.push(
-                                    Term::Literal(Cell::default(), Literal::CodeIndex(idx))
-                                );
-
-                                arity += 1;
-                            }
-                        }
-                    }
-
-                    if arity == 0 {
-                        term_stack.push(Term::Literal(Cell::default(), Literal::Atom(name)));
-                    } else {
-                        let subterms = term_stack
-                            .drain(term_stack.len() - arity ..)
-                            .collect();
-
-                        term_stack.push(Term::Clause(Cell::default(), name, subterms));
-                    }
-                }
-                (HeapCellValueTag::PStr, atom) => {
-                    let tail = term_stack.pop().unwrap();
-
-                    if let Term::Literal(_, Literal::Atom(atom!("[]"))) = &tail {
-                        term_stack.push(Term::CompleteString(Cell::default(), atom));
-                    } else {
-                        term_stack.push(Term::PartialString(
-                            Cell::default(),
-                            atom.as_str().to_owned(),
-                            Box::new(tail),
-                        ));
-                    }
-                }
-                (HeapCellValueTag::PStrLoc, h) => {
-                    let atom = cell_as_atom_cell!(iter.heap[h]).get_name();
-                    let tail = term_stack.pop().unwrap();
-
-                    term_stack.push(Term::PartialString(
-                        Cell::default(),
-                        atom.as_str().to_owned(),
-                        Box::new(tail),
-                    ));
-                }
-                _ => {
-                }
-            );
-        }
-
-        debug_assert!(term_stack.len() == 1);
-        term_stack.pop().unwrap()
+        term.var_locs = var_locs_from_iter(iter);
+        term
     }
 }
+*/
 
 impl Machine {
     pub(crate) fn use_module(&mut self) -> CallResult {
@@ -1625,10 +1586,11 @@ impl Machine {
     }
 
     pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
+        let value = self.machine_st.registers[1];
         let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
 
         let add_clause = || {
-            let term = loader.read_term_from_heap(temp_v!(1));
+            let term = loader.copy_term_from_heap(value);
 
             loader.incremental_compile_clause(
                 (atom!("term_expansion"), 2),
@@ -1650,6 +1612,7 @@ impl Machine {
             .machine_st
             .store(self.machine_st.deref(self.machine_st.registers[1])));
 
+        let value = self.machine_st.registers[2];
         let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
 
         let compilation_target = match target_module_name {
@@ -1658,21 +1621,21 @@ impl Machine {
         };
 
         let add_clause = || {
-            let term = loader.read_term_from_heap(temp_v!(2));
+            let term = loader.copy_term_from_heap(value);
 
-            let indexing_arg = match term.name() {
-                Some(atom!(":-")) => term.first_arg().and_then(Term::first_arg),
-                Some(_) => term.first_arg(),
+            let indexing_arg = match term.name(term.focus) {
+                Some(atom!(":-")) => term.nth_arg(term.focus, 1).and_then(|h| term.nth_arg(h, 1)),
+                Some(_) => term.nth_arg(term.focus, 1),
                 None => None,
             };
 
-            if let Some(indexing_term) = indexing_arg {
-                if let Some(indexing_name) = indexing_term.name() {
+            if let Some(indexing_term_loc) = indexing_arg {
+                if let Some(indexing_name) = term.name(indexing_term_loc) {
                     loader
                         .wam_prelude
                         .indices
                         .goal_expansion_indices
-                        .insert((indexing_name, indexing_term.arity()));
+                        .insert((indexing_name, term.arity(indexing_term_loc)));
                 }
             }
 
@@ -1978,30 +1941,24 @@ impl Machine {
         };
 
         let stub_gen = || functor_stub(key.0, key.1);
+        let assert_clause = self.machine_st.registers[2];
+        let (name, arity) = {
+            let term = FocusedHeapRefMut::from_cell(&mut self.machine_st.heap, assert_clause);
+            (ClauseInfo::name(&term), ClauseInfo::arity(&term))
+        };
 
-        let head = self.deref_register(2);
-
-        if head.is_var() {
-            let err = self.machine_st.instantiation_error();
-            return Err(self.machine_st.error_form(err, stub_gen()));
-        }
-
-        let mut compile_assert = || {
+        let mut compile_assert = |assert_clause, name, arity| {
             let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
                 Loader::new(self, LiveTermStream::new(ListingSource::User));
 
             loader.payload.compilation_target = compilation_target;
 
-            let head =
-                LiveLoadAndMachineState::machine_st(&mut loader.payload).read_term_from_heap(head);
-
-            let name = if let Some(name) = head.name() {
+            let name = if let Some(name) = name {
                 name
             } else {
                 return Err(SessionError::from(CompilationError::InvalidRuleHead));
             };
 
-            let arity = head.arity();
             let is_builtin = loader.wam_prelude.indices.builtin_property((name, arity));
 
             let is_dynamic_predicate = loader
@@ -2033,16 +1990,9 @@ impl Machine {
                 return LiveLoadAndMachineState::evacuate(loader);
             }
 
-            let body = loader.read_term_from_heap(temp_v!(3));
-
-            let asserted_clause = Term::Clause(
-                Cell::default(),
-                atom!(":-"),
-                vec![head.clone(), body.clone()],
-            );
-
             // if a new predicate was just created, make it dynamic.
             loader.add_dynamic_predicate(compilation_target, name, arity)?;
+            let asserted_clause = loader.copy_term_from_heap(assert_clause);
 
             loader.incremental_compile_clause(
                 (name, arity),
@@ -2052,20 +2002,22 @@ impl Machine {
                 append_or_prepend,
             )?;
 
+            let clause_clause_term = loader.clause_clause(assert_clause)?;
+
             // the global clock is incremented after each assertion.
             LiveLoadAndMachineState::machine_st(&mut loader.payload).global_clock += 1;
 
             loader.compile_clause_clauses(
                 (name, arity),
                 compilation_target,
-                std::iter::once((head, body)),
+                vec![clause_clause_term],
                 append_or_prepend,
             )?;
 
             LiveLoadAndMachineState::evacuate(loader)
         };
 
-        match compile_assert() {
+        match compile_assert(assert_clause, name, arity) {
             Ok(_) => Ok(()),
             Err(SessionError::CompilationError(
                 CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
@@ -2471,9 +2423,12 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
             self.payload.predicates.compilation_target = compilation_target;
         }
 
-        let term = self.read_term_from_heap(term_reg);
+        let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
+        let value = machine_st[term_reg];
+
+        self.add_clause_clause_if_dynamic(value)?;
 
-        self.add_clause_clause_if_dynamic(&term)?;
+        let term = self.copy_term_from_heap(value);
         self.payload.term_stream.term_queue.push_back(term);
 
         self.load()
index 82056f3a1173a4011ee46d5f3b592643d9a02744..511695d9cd049dbf5af3b8aad02beeb7d9b97123 100644 (file)
@@ -24,7 +24,7 @@ enum ErrorProvenance {
 #[derive(Debug)]
 pub(crate) struct MachineError {
     stub: MachineStub,
-    location: Option<(usize, usize)>, // line_num, col_num
+    location: Option<ParserErrorSrc>,
     from: ErrorProvenance,
 }
 
@@ -649,7 +649,7 @@ impl MachineState {
             stub[1] = err.stub[0];
         }
 
-        if let Some((line_num, _)) = location {
+        if let Some(ParserErrorSrc { line_num, .. }) = location {
             stub.push(atom_as_cell!(atom!(":"), 2));
             stub.push(str_loc_as_cell!(h + 6 + stub_addition_len));
             stub.push(integer_as_cell!(Number::arena_from(
@@ -741,9 +741,9 @@ impl From<ParserError> for CompilationError {
 }
 
 impl CompilationError {
-    pub(crate) fn line_and_col_num(&self) -> Option<(usize, usize)> {
+    pub(crate) fn line_and_col_num(&self) -> Option<ParserErrorSrc> {
         match self {
-            CompilationError::ParserError(err) => err.line_and_col_num(),
+            CompilationError::ParserError(err) => Some(err.err_src()),
             _ => None,
         }
     }
@@ -1044,13 +1044,6 @@ pub enum SessionError {
     PredicateNotMultifileOrDiscontiguous(CompilationTarget, PredicateKey),
 }
 
-impl From<std::io::Error> for SessionError {
-    #[inline]
-    fn from(err: std::io::Error) -> SessionError {
-        SessionError::from(ParserError::from(err))
-    }
-}
-
 impl From<ParserError> for SessionError {
     #[inline]
     fn from(err: ParserError) -> Self {
index 2f2591252307c0ab855f050d4f8f92e2e520d084..a08a8264eb1cc8660908904f9717c265d416f7c9 100644 (file)
@@ -20,6 +20,8 @@ use std::collections::BTreeSet;
 use std::ops::{Deref, DerefMut};
 
 use crate::types::*;
+// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+// pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
 
 // 7.2
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
@@ -211,30 +213,6 @@ impl CodeIndex {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum VarKey {
-    AnonVar(usize),
-    VarPtr(VarPtr),
-}
-
-impl VarKey {
-    #[allow(clippy::inherent_to_string)]
-    #[inline]
-    pub(crate) fn to_string(&self) -> String {
-        match self {
-            VarKey::AnonVar(h) => format!("_{}", h),
-            VarKey::VarPtr(var) => var.borrow().to_string(),
-        }
-    }
-
-    #[inline(always)]
-    pub(crate) fn is_anon(&self) -> bool {
-        matches!(self, VarKey::AnonVar(_))
-    }
-}
-
-pub(crate) type HeapVarDict = IndexMap<VarKey, HeapCellValue, FxBuildHasher>;
-
 pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;
 
 pub(crate) type StreamAliasDir = IndexMap<Atom, Stream, FxBuildHasher>;
@@ -291,11 +269,9 @@ impl IndexStore {
             _ => self
                 .get_meta_predicate_spec(key.0, key.1, &compilation_target)
                 .map(|meta_specs| {
-                    meta_specs.iter().find(|meta_spec| {
-                        matches!(
-                            meta_spec,
-                            MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_)
-                        )
+                    meta_specs.iter().find(|meta_spec| match meta_spec {
+                        MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_) => true,
+                        _ => false,
                     })
                 })
                 .map(|meta_spec_opt| meta_spec_opt.is_some())
index 5376042cee4d8fccbc349f9d4b2f3df6d283f473..bd2b217fe73900c255da7e3674f152e6f703eb57 100644 (file)
@@ -71,7 +71,7 @@ pub struct MachineState {
     pub(super) e: usize,
     pub(super) num_of_args: usize,
     pub(super) cp: usize,
-    pub(super) attr_var_init: AttrVarInitializer,
+    pub(crate) attr_var_init: AttrVarInitializer,
     pub(super) fail: bool,
     pub heap: Heap,
     pub(super) mode: MachineMode,
@@ -200,20 +200,21 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
     )
 }
 
-fn push_var_eq_functors<'a>(
+fn push_var_eq_functors(
     heap: &mut Heap,
-    iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
+    iter: impl Iterator<Item = (usize, VarPtr)>, // (&'a VarPtr, &'a HeapCellValue)>,
     atom_tbl: &AtomTable,
 ) -> Vec<HeapCellValue> {
     let mut list_of_var_eqs = vec![];
 
-    for (var, binding) in iter {
-        let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
+    for (var_loc, var_ptr) in iter { // (var, binding) in iter {
+        let var_atom = AtomTable::build_with(atom_tbl, &*var_ptr.borrow().to_string());
         let h = heap.len();
+        let binding = heap[var_loc];
 
         heap.push(atom_as_cell!(atom!("="), 2));
         heap.push(atom_as_cell!(var_atom));
-        heap.push(*binding);
+        heap.push(binding);
 
         list_of_var_eqs.push(str_loc_as_cell!(h));
     }
@@ -221,6 +222,16 @@ fn push_var_eq_functors<'a>(
     list_of_var_eqs
 }
 
+
+pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
+    iter: Iter,
+    boundary: i64,
+    h: i64,
+) -> impl Iterator<Item = HeapCellValue> {
+    let diff = boundary - h;
+    iter.map(move |heap_value| heap_value - diff)
+}
+
 #[derive(Debug)]
 pub struct Ball {
     pub(super) boundary: usize,
@@ -241,13 +252,7 @@ impl Ball {
     }
 
     pub(super) fn copy_and_align(&self, h: usize) -> Heap {
-        let diff = self.boundary as i64 - h as i64;
-
-        self.stub
-            .iter()
-            .cloned()
-            .map(|heap_value| heap_value - diff)
-            .collect()
+        copy_and_align_iter(self.stub.iter().cloned(), self.boundary as i64, h as i64).collect()
     }
 }
 
@@ -311,7 +316,7 @@ impl<'a> CopierTarget for CopyTerm<'a> {
 }
 
 #[derive(Debug)]
-pub(super) struct CopyBallTerm<'a> {
+pub(crate) struct CopyBallTerm<'a> {
     attr_var_queue: &'a mut Vec<usize>,
     stack: &'a mut Stack,
     heap: &'a mut Heap,
@@ -320,7 +325,7 @@ pub(super) struct CopyBallTerm<'a> {
 }
 
 impl<'a> CopyBallTerm<'a> {
-    pub(super) fn new(
+    pub(crate) fn new(
         attr_var_queue: &'a mut Vec<usize>,
         stack: &'a mut Stack,
         heap: &'a mut Heap,
@@ -536,18 +541,19 @@ impl MachineState {
 
     pub fn write_read_term_options(
         &mut self,
-        mut var_list: Vec<(VarKey, HeapCellValue, usize)>,
+        mut var_list: Vec<(VarPtr, HeapCellValue, usize)>,
         singleton_var_list: Vec<HeapCellValue>,
     ) -> CallResult {
         var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
 
         let list_of_var_eqs = push_var_eq_functors(
             &mut self.heap,
-            var_list.iter().filter_map(|(var_name, var, _)| {
-                if var_name.is_anon() {
+            var_list.iter().filter_map(|(var_ptr, var, _)| {
+                if var_ptr.is_anon() {
                     None
                 } else {
-                    Some((var_name, var))
+                    let var_loc = var.get_value() as usize;
+                    Some((var_loc, var_ptr.clone()))
                 }
             }),
             &self.atom_tbl,
@@ -586,13 +592,13 @@ impl MachineState {
         Ok(unify_fn!(*self, var_names_offset, var_names_addr))
     }
 
-    pub fn read_term_body(&mut self, mut term_write_result: TermWriteResult) -> CallResult {
-        let heap_loc = read_heap_cell!(self.heap[term_write_result.heap_loc],
+    pub fn read_term_body(&mut self, term: TermWriteResult) -> CallResult {
+        let heap_loc = read_heap_cell!(self.heap[term.heap_loc],
             (HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
-                pstr_loc_as_cell!(term_write_result.heap_loc)
+                pstr_loc_as_cell!(term.heap_loc)
             }
             _ => {
-                heap_loc_as_cell!(term_write_result.heap_loc)
+                heap_loc_as_cell!(term.heap_loc)
             }
         );
 
@@ -602,15 +608,15 @@ impl MachineState {
             return Ok(());
         }
 
+        /*
         for var in term_write_result.var_dict.values_mut() {
             *var = heap_bound_deref(&self.heap, *var);
         }
+        */
 
         let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
 
-        for cell in
-            stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, heap_loc)
-        {
+        for cell in eager_stackful_preorder_iter(&mut self.heap, heap_loc) {
             let cell = unmark_cell_bits!(cell);
 
             if let Some(var) = cell.as_var() {
@@ -624,34 +630,42 @@ impl MachineState {
 
         let singleton_var_list = push_var_eq_functors(
             &mut self.heap,
-            term_write_result
-                .var_dict
+            term.var_locs
                 .iter()
-                .filter(|(var_name, binding)| {
-                    if var_name.is_anon() {
-                        return false;
+                .filter_map(|(var_loc, var_ptrs)| {
+                    let var_ptr = var_ptrs.front().unwrap();
+
+                    if var_ptr.is_anon() {
+                        return None;
                     }
 
-                    if let Some(r) = binding.as_var() {
-                        *singleton_var_set.get(&r).unwrap_or(&false)
+                    // add h to offset the term variable into its heap location.
+                    let r = Ref::heap_cell(var_loc);
+
+                    if singleton_var_set.get(&r).cloned().unwrap_or(false) {
+                        Some((var_loc, var_ptr.clone()))
                     } else {
-                        false
+                        None
                     }
                 }),
             &self.atom_tbl,
         );
 
+        /*
         for var in term_write_result.var_dict.values_mut() {
             *var = heap_bound_deref(&self.heap, *var);
         }
+        */
 
         let mut var_list = Vec::with_capacity(singleton_var_set.len());
 
-        for (var_name, addr) in term_write_result.var_dict {
-            if let Some(var) = addr.as_var() {
-                if let Some(idx) = singleton_var_set.get_index_of(&var) {
-                    var_list.push((var_name, addr, idx));
-                }
+        for (var_loc, var_ptrs) in term.var_locs.iter() {
+            let var_ptr = var_ptrs.front().unwrap().clone();
+            let r = Ref::heap_cell(var_loc);
+            let cell = self.heap[var_loc];
+
+            if let Some(idx) = singleton_var_set.get_index_of(&r) {
+                var_list.push((var_ptr, cell, idx));
             }
         }
 
@@ -734,8 +748,8 @@ impl MachineState {
         }
 
         loop {
-            match self.read(stream, &indices.op_dir) {
-                Ok(term_write_result) => return self.read_term_body(term_write_result),
+            match self.read_to_heap(stream, &indices.op_dir) {
+                Ok(term) => return self.read_term_body(term),
                 Err(err) => {
                     match &err {
                         CompilationError::ParserError(e) if e.is_unexpected_eof() => {
@@ -881,13 +895,16 @@ impl MachineState {
                     }
                 );
 
+                let h = self.heap.len();
+                self.heap.push(term_to_be_printed);
+
                 let mut printer = HCPrinter::new(
                     &mut self.heap,
                     Arc::clone(&self.atom_tbl),
                     &mut self.stack,
                     op_dir,
                     PrinterOutputter::new(),
-                    term_to_be_printed,
+                    h,
                 );
 
                 printer.ignore_ops = ignore_ops;
index 90aefa0e7cd74309c48066f8c656a03a4276ee58..42500cbde4394c5de117847a51912e92512a22c1 100644 (file)
@@ -39,7 +39,7 @@ impl MockWAM {
         &mut self,
         input_stream: Stream,
     ) -> Result<TermWriteResult, CompilationError> {
-        self.machine_st.read(input_stream, &self.op_dir)
+        self.machine_st.read_to_heap(input_stream, &self.op_dir)
     }
 
     pub fn parse_and_write_parsed_term_to_heap(
@@ -58,23 +58,24 @@ impl MockWAM {
 
         print_heap_terms(self.machine_st.heap.iter(), term_write_result.heap_loc);
 
+        let var_names = term_write_result
+            .var_locs
+            .iter()
+            .map(|(var_loc, var_ptrs)| {
+                (self.machine_st.heap[var_loc], var_ptrs.front().unwrap().clone())
+            })
+            .collect();
+
         let mut printer = HCPrinter::new(
             &mut self.machine_st.heap,
             Arc::clone(&self.machine_st.atom_tbl),
             &mut self.machine_st.stack,
             &self.op_dir,
             PrinterOutputter::new(),
-            heap_loc_as_cell!(term_write_result.heap_loc),
+            term_write_result.heap_loc,
         );
 
-        printer.var_names = term_write_result
-            .var_dict
-            .into_iter()
-            .map(|(var, cell)| match var {
-                VarKey::VarPtr(var) => (cell, var.clone()),
-                VarKey::AnonVar(_) => (cell, VarPtr::from(var.to_string())),
-            })
-            .collect();
+        printer.var_names = var_names;
 
         Ok(printer.print().result())
     }
@@ -217,7 +218,7 @@ pub(crate) fn write_parsed_term_to_heap(
     input_stream: Stream,
     op_dir: &OpDir,
 ) -> Result<TermWriteResult, CompilationError> {
-    machine_st.read(input_stream, op_dir)
+    machine_st.read_to_heap(input_stream, op_dir)
 }
 
 #[cfg(test)]
@@ -289,14 +290,15 @@ mod tests {
         wam.heap.clear();
 
         {
-            parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
+            let term_write_result_1 =
+                parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
 
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(b,b).", &op_dir).unwrap();
 
             unify!(
                 wam,
-                str_loc_as_cell!(1),
+                heap_loc_as_cell!(term_write_result_1.heap_loc),
                 heap_loc_as_cell!(term_write_result_2.heap_loc)
             );
 
@@ -309,14 +311,15 @@ mod tests {
         wam.heap.clear();
 
         {
-            parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
+            let term_write_result_1 =
+                parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
 
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),Y).", &op_dir).unwrap();
 
             unify!(
                 wam,
-                heap_loc_as_cell!(0),
+                heap_loc_as_cell!(term_write_result_1.heap_loc),
                 heap_loc_as_cell!(term_write_result_2.heap_loc)
             );
 
@@ -329,14 +332,15 @@ mod tests {
         wam.heap.clear();
 
         {
-            parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
+            let term_write_result_1 =
+                parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
 
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),Y).", &op_dir).unwrap();
 
             unify!(
                 wam,
-                heap_loc_as_cell!(0),
+                heap_loc_as_cell!(term_write_result_1.heap_loc),
                 heap_loc_as_cell!(term_write_result_2.heap_loc)
             );
 
@@ -349,14 +353,15 @@ mod tests {
         wam.heap.clear();
 
         {
-            parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
+            let term_write_result_1 =
+                parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
 
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),A).", &op_dir).unwrap();
 
             unify!(
                 wam,
-                heap_loc_as_cell!(0),
+                heap_loc_as_cell!(term_write_result_1.heap_loc),
                 heap_loc_as_cell!(term_write_result_2.heap_loc)
             );
 
@@ -369,7 +374,8 @@ mod tests {
         wam.heap.clear();
 
         {
-            parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
+            let term_write_result_1 =
+                parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
 
             let term_write_result_2 =
                 parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
@@ -378,7 +384,7 @@ mod tests {
 
             unify!(
                 wam,
-                heap_loc_as_cell!(0),
+                heap_loc_as_cell!(term_write_result_1.heap_loc),
                 heap_loc_as_cell!(term_write_result_2.heap_loc)
             );
 
@@ -461,21 +467,8 @@ mod tests {
         wam.heap.push(heap_loc_as_cell!(0));
 
         unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
-
         assert!(!wam.fail);
         all_cells_unmarked(&wam.heap);
-        wam.heap.clear();
-
-        {
-            let term_write_result_1 =
-                parse_and_write_parsed_term_to_heap(&mut wam, "X = g(X,y).", &op_dir).unwrap();
-
-            print_heap_terms(wam.heap.iter(), term_write_result_1.heap_loc);
-
-            unify!(wam, heap_loc_as_cell!(2), str_loc_as_cell!(4));
-
-            assert_eq!(wam.heap[2], str_loc_as_cell!(4));
-        }
     }
 
     #[test]
@@ -498,8 +491,8 @@ mod tests {
 
             unify_with_occurs_check!(
                 wam,
-                str_loc_as_cell!(0),
-                str_loc_as_cell!(term_write_result_2.heap_loc)
+                heap_loc_as_cell!(0),
+                heap_loc_as_cell!(term_write_result_2.heap_loc)
             );
 
             assert!(wam.fail);
index 9fcd1825f26b93defbcf6c660fa3838818786dcf..0173285e4b62b6d14558d2fba511403e1e981bf9 100644 (file)
@@ -5,11 +5,14 @@ use crate::instructions::*;
 use crate::machine::disjuncts::*;
 use crate::machine::loader::*;
 use crate::machine::machine_errors::*;
+use crate::machine::CodeIndex;
 use crate::parser::ast::*;
+use crate::types::*;
 
+use fxhash::FxBuildHasher;
+use indexmap::IndexMap;
 use indexmap::IndexSet;
 
-use std::cell::Cell;
 use std::convert::TryFrom;
 pub(crate) fn to_op_decl(prec: u16, spec: OpDeclSpec, name: Atom) -> OpDecl {
     OpDecl::new(OpDesc::build_with(prec, spec), name)
@@ -21,44 +24,30 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError
     })
 }
 
-fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, CompilationError> {
-    // should allow non-partial lists?
-    let name = match terms.pop().unwrap() {
-        Term::Literal(_, Literal::Atom(name)) => name,
-        Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
-        other => {
-            return Err(CompilationError::InvalidDirective(
-                DirectiveError::InvalidOpDeclNameType(other),
-            ));
-        }
-    };
+fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
+    let (focus, _cell) = subterm_index(term.heap, term.focus);
 
-    let spec = match terms.pop().unwrap() {
-        Term::Literal(_, Literal::Atom(name)) => name,
-        other => {
-            return Err(CompilationError::InvalidDirective(
-                DirectiveError::InvalidOpDeclSpecDomain(other),
-            ))
-        }
+    let name = match term.name(focus+3) {
+        Some(name) => name,
+        None => return Err(CompilationError::InconsistentEntry),
     };
 
-    let spec = to_op_decl_spec(spec)?;
+    let spec = match term.name(focus+2) {
+        Some(name) => name,
+        None => return Err(CompilationError::InconsistentEntry),
+    };
 
-    let prec = match terms.pop().unwrap() {
-        Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) {
-            Ok(n) if n <= 1200 => n,
-            _ => {
-                return Err(CompilationError::InvalidDirective(
-                    DirectiveError::InvalidOpDeclPrecDomain(bi),
-                ));
+    let prec = read_heap_cell!(term.deref_loc(focus+1),
+        (HeapCellValueTag::Fixnum, n) => {
+            match u16::try_from(n.get_num()) {
+                Ok(n) if n <= 1200 => n,
+                _ => return Err(CompilationError::InconsistentEntry),
             }
-        },
-        other => {
-            return Err(CompilationError::InvalidDirective(
-                DirectiveError::InvalidOpDeclPrecType(other),
-            ));
         }
-    };
+        _ => {
+            return Err(CompilationError::InconsistentEntry);
+        }
+    );
 
     if name == "[]" || name == "{}" {
         return Err(CompilationError::InvalidDirective(
@@ -81,140 +70,166 @@ fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, C
     Ok(to_op_decl(prec, spec, name))
 }
 
-fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> {
-    match term {
-        Term::Clause(_, slash, ref mut terms)
-            if (*slash == atom!("/") || *slash == atom!("//")) && terms.len() == 2 =>
-        {
-            let arity = terms.pop().unwrap();
-            let name = terms.pop().unwrap();
-
-            let arity = match arity {
-                Term::Literal(_, Literal::Integer(n)) => (&*n).try_into().ok(),
-                Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
-                _ => None,
-            }
-            .ok_or(CompilationError::InvalidModuleExport)?;
+fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> {
+    let name_opt = term.name(term.focus);
+    let arity = term.arity(term.focus);
 
-            let name = match name {
-                Term::Literal(_, Literal::Atom(name)) => Some(name),
-                _ => None,
-            }
+    if let (Some(atom!("/") | atom!("//")), 2) = (name_opt, arity) {
+        let arity_loc = term.nth_arg(term.focus, 2).unwrap();
+
+        let arity = match Number::try_from(term.deref_loc(arity_loc)) {
+            Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
+            Ok(Number::Integer(n)) => (&*n).try_into().ok(),
+            _ => None,
+        }
+        .ok_or(CompilationError::InvalidModuleExport)?;
+
+        let name_loc = term.nth_arg(term.focus, 1).unwrap();
+        let name = term
+            .name(name_loc)
             .ok_or(CompilationError::InvalidModuleExport)?;
 
-            if *slash == atom!("/") {
-                Ok((name, arity))
-            } else {
-                Ok((name, arity + 2))
-            }
+        if name_opt == Some(atom!("/")) {
+            Ok((name, arity))
+        } else {
+            Ok((name, arity + 2))
         }
-        _ => Err(CompilationError::InvalidModuleExport),
+    } else {
+        Err(CompilationError::InvalidModuleExport)
     }
 }
 
-fn setup_module_export(
-    mut term: Term,
-    atom_tbl: &AtomTable,
-) -> Result<ModuleExport, CompilationError> {
-    setup_predicate_indicator(&mut term)
+fn setup_module_export(term: &FocusedHeapRefMut) -> Result<ModuleExport, CompilationError> {
+    setup_predicate_indicator(term)
         .map(ModuleExport::PredicateKey)
         .or_else(|_| {
-            if let Term::Clause(_, name, terms) = term {
-                if terms.len() == 3 && name == atom!("op") {
-                    Ok(ModuleExport::OpDecl(setup_op_decl(terms, atom_tbl)?))
-                } else {
-                    Err(CompilationError::InvalidModuleDecl)
-                }
+            let name_opt = term.name(term.focus);
+            let arity = term.arity(term.focus);
+
+            if let (Some(atom!("op")), 3) = (name_opt, arity) {
+                Ok(ModuleExport::OpDecl(setup_op_decl(term)?))
             } else {
                 Err(CompilationError::InvalidModuleDecl)
             }
         })
 }
 
+/* TODO: should be unnecessary now.
+
 pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
     let head_term = Term::Clause(Cell::default(), atom!(""), vars.to_vec());
     let rule = vec![head_term, body_term];
 
     Term::Clause(Cell::default(), atom!(":-"), rule)
 }
+*/
 
 pub(super) fn setup_module_export_list(
-    mut export_list: Term,
-    atom_tbl: &AtomTable,
+    term: FocusedHeapRefMut,
 ) -> Result<Vec<ModuleExport>, CompilationError> {
     let mut exports = vec![];
-
-    while let Term::Cons(_, t1, t2) = export_list {
-        let module_export = setup_module_export(*t1, atom_tbl)?;
-
-        exports.push(module_export);
-        export_list = *t2;
+    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;
+           }
+       );
     }
 
-    if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
-        Ok(exports)
-    } else {
-        Err(CompilationError::InvalidModuleDecl)
-    }
+    Err(CompilationError::InvalidModuleDecl)
 }
 
-fn setup_module_decl(
-    mut terms: Vec<Term>,
-    atom_tbl: &AtomTable,
-) -> Result<ModuleDecl, CompilationError> {
-    let export_list = terms.pop().unwrap();
-    let name = terms.pop().unwrap();
-
-    let name = match name {
-        Term::Literal(_, Literal::Atom(name)) => Some(name),
-        _ => None,
-    }
-    .ok_or(CompilationError::InvalidModuleDecl)?;
-
-    let exports = setup_module_export_list(export_list, atom_tbl)?;
+fn setup_module_decl(term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
+    let name = term
+        .name(term.focus + 1)
+        .ok_or(CompilationError::InvalidModuleDecl)?;
+    let export_list = FocusedHeapRefMut {
+        heap: term.heap,
+        focus: term.focus + 2,
+    };
+    let exports = setup_module_export_list(export_list)?;
 
     Ok(ModuleDecl { name, exports })
 }
 
-fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> {
-    match terms.pop().unwrap() {
-        Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
-            match terms.pop().unwrap() {
-                Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
-                _ => Err(CompilationError::InvalidModuleDecl),
+fn setup_use_module_decl(term: &FocusedHeapRefMut) -> Result<ModuleSource, CompilationError> {
+    read_heap_cell!(term.deref_loc(term.focus+1),
+        (HeapCellValueTag::Str, s) => {
+            let (name, arity) = cell_as_atom_cell!(term.heap[s]).get_name_and_arity();
+
+            if (name, arity) == (atom!("library"), 1) {
+                read_heap_cell!(term.deref_loc(s+1),
+                    (HeapCellValueTag::Atom, (name, arity)) => {
+                        if arity == 0 {
+                            return Ok(ModuleSource::Library(name));
+                        }
+                    }
+                    _ => {
+                    }
+                )
             }
+
+            return Err(CompilationError::InvalidModuleDecl);
         }
-        Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
-        _ => Err(CompilationError::InvalidUseModuleDecl),
-    }
+        (HeapCellValueTag::Atom, (name, arity)) => {
+            if arity == 0 {
+                Ok(ModuleSource::File(name))
+            } else {
+                Err(CompilationError::InvalidUseModuleDecl)
+            }
+        }
+        _ => {
+            Err(CompilationError::InvalidUseModuleDecl)
+        }
+    )
 }
 
 type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
 
-fn setup_qualified_import(
-    mut terms: Vec<Term>,
-    atom_tbl: &AtomTable,
-) -> Result<UseModuleExport, CompilationError> {
-    let mut export_list = terms.pop().unwrap();
-    let module_src = match terms.pop().unwrap() {
-        Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
-            match terms.pop().unwrap() {
-                Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
-                _ => Err(CompilationError::InvalidModuleDecl),
-            }
-        }
-        Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
-        _ => Err(CompilationError::InvalidUseModuleDecl),
-    }?;
-
+fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, CompilationError> {
+    let module_src = setup_use_module_decl(&term)?;
     let mut exports = IndexSet::new();
 
-    while let Term::Cons(_, t1, t2) = export_list {
-        exports.insert(setup_module_export(*t1, atom_tbl)?);
-        export_list = *t2;
+    let mut focus = term.focus + 2;
+
+    while let HeapCellValueTag::Lis = term.heap[focus].get_tag() {
+        focus = term.heap[focus].get_value() as usize;
+
+        let term = FocusedHeapRefMut {
+            heap: term.heap,
+            focus,
+        };
+        exports.insert(setup_module_export(&term)?);
+
+        focus = focus + 1;
     }
 
-    if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
+    if term.heap[focus] == empty_list_as_cell!() {
         Ok((module_src, exports))
     } else {
         Err(CompilationError::InvalidModuleDecl)
@@ -261,18 +276,20 @@ fn setup_qualified_import(
  */
 
 fn setup_meta_predicate<'a, LS: LoadState<'a>>(
-    mut terms: Vec<Term>,
+    term: FocusedHeapRefMut,
     loader: &mut Loader<'a, LS>,
 ) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
-    fn get_name_and_meta_specs(
-        name: Atom,
-        terms: &mut [Term],
-    ) -> Result<(Atom, Vec<MetaSpec>), CompilationError> {
+    fn get_meta_specs(
+        term: FocusedHeapRefMut,
+        arity: usize,
+    ) -> Result<Vec<MetaSpec>, CompilationError> {
         let mut meta_specs = vec![];
 
-        for meta_spec in terms.iter_mut() {
-            match meta_spec {
-                Term::Literal(_, Literal::Atom(meta_spec)) => {
+        for meta_spec_loc in term.focus + 1..term.focus + arity + 1 {
+            read_heap_cell!(term.deref_loc(meta_spec_loc),
+                (HeapCellValueTag::Atom, (meta_spec, arity)) => {
+                    debug_assert_eq!(arity, 0);
+
                     let meta_spec = match meta_spec {
                         atom!("+") => MetaSpec::Plus,
                         atom!("-") => MetaSpec::Minus,
@@ -283,271 +300,307 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
 
                     meta_specs.push(meta_spec);
                 }
-                Term::Literal(_, Literal::Fixnum(n)) => match usize::try_from(n.get_num()) {
-                    Ok(n) if n <= MAX_ARITY => {
-                        meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
-                    }
-                    _ => {
-                        return Err(CompilationError::InvalidMetaPredicateDecl);
+                (HeapCellValueTag::Fixnum, n) => {
+                    match usize::try_from(n.get_num()) {
+                        Ok(n) if n <= MAX_ARITY => {
+                            meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
+                        }
+                        _ => {
+                            return Err(CompilationError::InvalidMetaPredicateDecl);
+                        }
                     }
-                },
+                }
                 _ => {
                     return Err(CompilationError::InvalidMetaPredicateDecl);
                 }
-            }
+            );
         }
 
-        Ok((name, meta_specs))
+        Ok(meta_specs)
     }
 
-    match terms.pop().unwrap() {
-        Term::Clause(_, name, mut terms) if name == atom!(":") && terms.len() == 2 => {
-            let spec = terms.pop().unwrap();
-            let module_name = terms.pop().unwrap();
-
-            match module_name {
-                Term::Literal(_, Literal::Atom(module_name)) => match spec {
-                    Term::Clause(_, name, mut terms) => {
-                        let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
-                        Ok((module_name, name, meta_specs))
-                    }
-                    _ => Err(CompilationError::InvalidMetaPredicateDecl),
-                },
-                _ => Err(CompilationError::InvalidMetaPredicateDecl),
+    read_heap_cell!(term.deref_loc(term.focus+1),
+        (HeapCellValueTag::Str, s) => {
+            let (name, arity) = cell_as_atom_cell!(term.heap[s]).get_name_and_arity();
+
+            match (name, arity) {
+                (atom!(":"), 2) => {
+                    let module_name = term.heap[s+1];
+                    let spec = term.heap[s+2];
+
+                    read_heap_cell!(module_name,
+                        (HeapCellValueTag::Atom, (module_name, arity)) => {
+                            if arity == 0 {
+                                read_heap_cell!(spec,
+                                    (HeapCellValueTag::Str, s) => {
+                                        let (name, arity) = cell_as_atom_cell!(term.heap[s])
+                                            .get_name_and_arity();
+
+                                        let term = FocusedHeapRefMut { heap: term.heap, focus: s };
+                                        return Ok((module_name, name, get_meta_specs(term, arity)?));
+                                    }
+                                    _ => {
+                                    }
+                                );
+                            } else {
+                                return Err(CompilationError::InvalidMetaPredicateDecl);
+                            }
+                        }
+                        _ => {
+                        }
+                    );
+                }
+                _ => {
+                    let term = FocusedHeapRefMut { heap: term.heap, focus: s };
+                    let module_name = loader.payload.compilation_target.module_name();
+                    return Ok((module_name, name, get_meta_specs(term, arity)?));
+                }
             }
+
+            Err(CompilationError::InvalidMetaPredicateDecl)
         }
-        Term::Clause(_, name, mut terms) => {
-            let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
-            Ok((
-                loader.payload.compilation_target.module_name(),
-                name,
-                meta_specs,
-            ))
+        _ => {
+            Err(CompilationError::InvalidMetaPredicateDecl)
         }
-        _ => Err(CompilationError::InvalidMetaPredicateDecl),
-    }
+    )
 }
 
 pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
     loader: &mut Loader<'a, LS>,
-    mut terms: Vec<Term>,
+    term: FocusedHeapRefMut,
 ) -> Result<Declaration, CompilationError> {
-    let term = terms.pop().unwrap();
+    let mut focus = term.focus;
 
-    match term {
-        Term::Clause(_, name, mut terms) => match (name, terms.len()) {
-            (atom!("dynamic"), 1) => {
-                let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
-                Ok(Declaration::Dynamic(name, arity))
-            }
-            (atom!("module"), 2) => {
-                let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
-                Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?))
-            }
-            (atom!("op"), 3) => {
-                let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
-                Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?))
+    loop {
+        read_heap_cell!(term.heap[focus],
+            (HeapCellValueTag::Atom, (name, arity)) => {
+                let term = FocusedHeapRefMut { heap: term.heap, focus };
+
+                return match (name, arity) {
+                    (atom!("dynamic"), 1) => {
+                        let (name, arity) = setup_predicate_indicator(&term)?;
+                        Ok(Declaration::Dynamic(name, arity))
+                    }
+                    (atom!("module"), 2) => {
+                        Ok(Declaration::Module(setup_module_decl(term)?))
+                    }
+                    (atom!("op"), 3) => {
+                        Ok(Declaration::Op(setup_op_decl(&term)?))
+                    }
+                    (atom!("non_counted_backtracking"), 1) => {
+                        let focus = term.nth_arg(term.focus, 1).unwrap();
+                        let (name, arity) = setup_predicate_indicator(&FocusedHeapRefMut { heap: term.heap, focus })?;
+                        Ok(Declaration::NonCountedBacktracking(name, arity))
+                    }
+                    (atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&term)?)),
+                    (atom!("use_module"), 2) => {
+                        let (name, exports) = setup_qualified_import(term)?;
+
+                        Ok(Declaration::UseQualifiedModule(name, exports))
+                    }
+                    (atom!("meta_predicate"), 1) => {
+                        let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?;
+                        Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
+                    }
+                    _ => Err(CompilationError::InvalidDirective(
+                        DirectiveError::InvalidDirective(name, arity)
+                    ))
+                };
             }
-            (atom!("non_counted_backtracking"), 1) => {
-                let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
-                Ok(Declaration::NonCountedBacktracking(name, arity))
+            (HeapCellValueTag::Str, s) => {
+                focus = s;
             }
-            (atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
-            (atom!("use_module"), 2) => {
-                let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
-                let (name, exports) = setup_qualified_import(terms, atom_tbl)?;
-
-                Ok(Declaration::UseQualifiedModule(name, exports))
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                if focus != h {
+                    focus = h;
+                } else {
+                    return Err(CompilationError::InvalidDirective(
+                        DirectiveError::ExpectedDirective(heap_loc_as_cell!(h)),
+                    ));
+                }
             }
-            (atom!("meta_predicate"), 1) => {
-                let (module_name, name, meta_specs) = setup_meta_predicate(terms, loader)?;
-                Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
+            _ => {
+                return Err(CompilationError::InvalidDirective(
+                    DirectiveError::ExpectedDirective(term.heap[focus])
+                ));
             }
-            _ => Err(CompilationError::InvalidDirective(
-                DirectiveError::InvalidDirective(name, terms.len()),
-            )),
-        },
-        other => Err(CompilationError::InvalidDirective(
-            DirectiveError::ExpectedDirective(other),
-        )),
+        );
     }
 }
 
 fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
     loader: &mut Loader<'a, LS>,
     module_name: Atom,
-    terms: Vec<Term>,
+    arity: usize,
+    term: &FocusedHeapRefMut,
     meta_specs: Vec<MetaSpec>,
-) -> Vec<Term> {
-    let mut arg_terms = Vec::with_capacity(terms.len());
+) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
+    let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default());
 
-    for (term, meta_spec) in terms.into_iter().zip(meta_specs.iter()) {
+    for (subterm_loc, meta_spec) in (term.focus + 1..term.focus + arity + 1).zip(meta_specs) {
         if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
-            if let Some(name) = term.name() {
+            if let Some(name) = term.name(subterm_loc) {
                 if name == atom!("$call") {
-                    arg_terms.push(term);
                     continue;
                 }
 
-                let arity = term.arity();
+                let arity = term.arity(subterm_loc);
+
+                struct QualifiedNameInfo {
+                    module_name: Atom,
+                    name: Atom,
+                    qualified_term_loc: usize,
+                }
 
                 fn get_qualified_name(
-                    module_term: &Term,
-                    qualified_term: &Term,
-                ) -> Option<(Atom, Atom)> {
-                    if let Term::Literal(_, Literal::Atom(module_name)) = module_term {
-                        if let Some(name) = qualified_term.name() {
-                            return Some((*module_name, name));
+                    term: &FocusedHeapRefMut,
+                    module_term_loc: usize,
+                    qualified_term_loc: usize,
+                ) -> Option<QualifiedNameInfo> {
+                    let (module_term_loc, _) = subterm_index(term.heap, module_term_loc);
+                    let (qualified_term_loc, _) = subterm_index(term.heap, qualified_term_loc);
+
+                    read_heap_cell!(term.heap[module_term_loc],
+                        (HeapCellValueTag::Atom, (module_name, arity)) => {
+                            if arity == 0 {
+                                if let Some(name) = term.name(qualified_term_loc) {
+                                    return Some(QualifiedNameInfo {
+                                        module_name,
+                                        name,
+                                        qualified_term_loc,
+                                    });
+                                }
+                            }
                         }
-                    }
+                        _ => {}
+                    );
 
                     None
                 }
 
-                fn identity_fn(_module_name: Atom, term: Term) -> Term {
-                    term
-                }
+                let (subterm_loc, _) = subterm_index(term.heap, subterm_loc);
 
-                fn tag_with_module_name(module_name: Atom, term: Term) -> Term {
-                    Term::Clause(
-                        Cell::default(),
-                        atom!(":"),
-                        vec![
-                            Term::Literal(Cell::default(), Literal::Atom(module_name)),
-                            term,
-                        ],
-                    )
-                }
+                let subterm_arity = term.arity(subterm_loc);
+                let subterm_name_opt = term.name(subterm_loc);
 
-                let process_term: fn(Atom, Term) -> Term;
+                let (module_name, key, term_loc) =
+                    if subterm_name_opt == Some(atom!(":")) && subterm_arity == 2 {
+                        debug_assert_eq!(term.heap[subterm_loc].get_tag(), HeapCellValueTag::Atom);
 
-                let (module_name, key, term) = match term {
-                    Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => {
-                        if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1])
-                        {
-                            process_term = tag_with_module_name;
-                            (
+                        match get_qualified_name(term, subterm_loc + 1, subterm_loc + 2) {
+                            Some(QualifiedNameInfo {
                                 module_name,
-                                (name, terms[1].arity() + supp_args),
-                                terms.pop().unwrap(),
-                            )
-                        } else {
-                            arg_terms.push(Term::Clause(cell, atom!(":"), terms));
-                            continue;
-                        }
-                    }
-                    term => {
-                        process_term = identity_fn;
-                        (module_name, (name, arity + supp_args), term)
-                    }
-                };
-
-                let term = match term {
-                    Term::Clause(cell, name, mut terms) => {
-                        if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
-                            arg_terms
-                                .push(process_term(module_name, Term::Clause(cell, name, terms)));
-
-                            continue;
-                        }
-
-                        let idx = loader.get_or_insert_qualified_code_index(module_name, key);
-
-                        terms.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx)));
-                        process_term(module_name, Term::Clause(cell, name, terms))
-                    }
-                    Term::Literal(cell, Literal::Atom(name)) => {
-                        let idx = loader.get_or_insert_qualified_code_index(module_name, key);
-
-                        process_term(
-                            module_name,
-                            Term::Clause(
-                                cell,
                                 name,
-                                vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
+                                qualified_term_loc,
+                            }) => (
+                                module_name,
+                                (name, term.arity(qualified_term_loc) + supp_args),
+                                qualified_term_loc,
                             ),
-                        )
-                    }
-                    term => term,
-                };
+                            None => {
+                                continue;
+                            }
+                        }
+                    } else {
+                        (module_name, (name, arity + supp_args), subterm_loc)
+                    };
 
-                arg_terms.push(term);
-                continue;
+                if let Some(index_ptr) = fetch_index_ptr(term.heap, key.1, term_loc) {
+                    index_ptrs.insert(term_loc, index_ptr);
+                    continue;
+                }
+
+                index_ptrs.insert(
+                    term_loc,
+                    loader.get_or_insert_qualified_code_index(module_name, key),
+                );
             }
         }
-
-        arg_terms.push(term);
     }
 
-    arg_terms
+    index_ptrs
 }
 
 #[inline]
 pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
     loader: &mut Loader<'a, LS>,
-    name: Atom,
-    mut terms: Vec<Term>,
+    key: PredicateKey,
+    terms: FocusedHeapRefMut,
+    term: HeapCellValue,
     call_policy: CallPolicy,
-) -> QueryTerm {
-    if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
-        // supplementary code vector indices are unnecessary for
-        // root-level clauses.
-        terms.pop();
-    }
+) -> QueryClause {
+    // supplementary code vector indices are unnecessary for
+    // root-level clauses.
+    blunt_index_ptr(terms.heap, key, terms.focus);
 
-    let mut ct = loader.get_clause_type(name, terms.len());
+    let mut ct = loader.get_clause_type(key.0, key.1);
 
     if let ClauseType::Named(arity, name, idx) = ct {
         if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
             let module_name = loader.payload.compilation_target.module_name();
-            let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
-
-            return QueryTerm::Clause(
-                Cell::default(),
-                ClauseType::Named(arity, name, idx),
-                terms,
+            let code_indices =
+                build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs);
+
+            return QueryClause {
+                ct: ClauseType::Named(key.1, key.0, idx),
+                arity,
+                term,
+                code_indices,
                 call_policy,
-            );
+            };
         }
 
-        ct = ClauseType::Named(arity, name, idx);
+        ct = ClauseType::Named(key.1, key.0, idx);
     }
 
-    QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
+    QueryClause {
+        ct,
+        arity: key.1,
+        term,
+        code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
+        call_policy,
+    }
 }
 
 #[inline]
 pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
     loader: &mut Loader<'a, LS>,
+    key: PredicateKey,
     module_name: Atom,
-    name: Atom,
-    mut terms: Vec<Term>,
+    terms: FocusedHeapRefMut,
+    term: HeapCellValue,
     call_policy: CallPolicy,
-) -> QueryTerm {
-    if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
-        // supplementary code vector indices are unnecessary for
-        // root-level clauses.
-        terms.pop();
-    }
+) -> QueryClause {
+    // supplementary code vector indices are unnecessary for
+    // root-level clauses.
+    blunt_index_ptr(terms.heap, key, terms.focus);
 
-    let mut ct = loader.get_qualified_clause_type(module_name, name, terms.len());
+    let mut ct = loader.get_qualified_clause_type(module_name, key.0, key.1);
 
     if let ClauseType::Named(arity, name, idx) = ct {
         if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
-            let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
-
-            return QueryTerm::Clause(
-                Cell::default(),
-                ClauseType::Named(arity, name, idx),
-                terms,
+            let code_indices =
+                build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs);
+
+            return QueryClause {
+                ct: ClauseType::Named(key.1, key.0, idx),
+                arity,
+                term,
+                code_indices,
                 call_policy,
-            );
+            };
         }
 
-        ct = ClauseType::Named(arity, name, idx);
+        ct = ClauseType::Named(key.1, key.0, idx);
     }
 
-    QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
+    QueryClause {
+        ct,
+        arity: key.1,
+        term,
+        code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
+        call_policy,
+    }
 }
 
 #[derive(Debug)]
@@ -560,69 +613,50 @@ impl Preprocessor {
         Preprocessor { settings }
     }
 
-    fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
-        match term {
-            Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
-                let classifier = VariableClassifier::new(self.settings.default_call_policy());
-
-                let (head, var_data) = classifier.classify_fact(term)?;
-                Ok((Fact { head }, var_data))
-            }
-            _ => Err(CompilationError::InadmissibleFact),
+    pub fn setup_fact(
+        &mut self,
+        mut term: FocusedHeap,
+    ) -> Result<(Fact, VarData), CompilationError> {
+        if term.name(term.focus).is_some() {
+            let classifier = VariableClassifier::new(self.settings.default_call_policy());
+            let var_data = classifier.classify_fact(&mut term)?;
+
+            Ok((Fact { term }, var_data))
+        } else {
+            Err(CompilationError::InadmissibleFact)
         }
     }
 
     fn setup_rule<'a, LS: LoadState<'a>>(
         &mut self,
         loader: &mut Loader<'a, LS>,
-        head: Term,
-        body: Term,
+        mut term: FocusedHeap,
     ) -> Result<(Rule, VarData), CompilationError> {
         let classifier = VariableClassifier::new(self.settings.default_call_policy());
+        let (clauses, var_data) = classifier.classify_rule(loader, &mut term)?;
+        let head_loc = term.nth_arg(term.focus, 1).unwrap();
 
-        let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
-
-        match head {
-            Term::Clause(_, name, terms) => Ok((
-                Rule {
-                    head: (name, terms),
-                    clauses,
-                },
-                var_data,
-            )),
-            Term::Literal(_, Literal::Atom(name)) => Ok((
-                Rule {
-                    head: (name, vec![]),
-                    clauses,
-                },
-                var_data,
-            )),
-            _ => Err(CompilationError::InvalidRuleHead),
+        if term.name(head_loc).is_some() {
+            Ok((Rule { term, clauses }, var_data))
+        } else {
+            Err(CompilationError::InvalidRuleHead)
         }
     }
 
     pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
         &mut self,
         loader: &mut Loader<'a, LS>,
-        term: Term,
+        term: FocusedHeap,
     ) -> Result<TopLevel, CompilationError> {
-        match term {
-            Term::Clause(r, name, mut terms) => {
-                let is_rule = name == atom!(":-") && terms.len() == 2;
-
-                if is_rule {
-                    let tail = terms.pop().unwrap();
-                    let head = terms.pop().unwrap();
+        let name = term.name(term.focus);
+        let arity = term.arity(term.focus);
 
-                    let (rule, var_data) = self.setup_rule(loader, head, tail)?;
-                    Ok(TopLevel::Rule(rule, var_data))
-                } else {
-                    let term = Term::Clause(r, name, terms);
-                    let (fact, var_data) = self.setup_fact(term)?;
-                    Ok(TopLevel::Fact(fact, var_data))
-                }
+        match (name, arity) {
+            (Some(atom!(":-")), 2) => {
+                let (rule, var_data) = self.setup_rule(loader, term)?;
+                Ok(TopLevel::Rule(rule, var_data))
             }
-            term => {
+            _ => {
                 let (fact, var_data) = self.setup_fact(term)?;
                 Ok(TopLevel::Fact(fact, var_data))
             }
index 1b5d79fbeb6a570d1d2831df2b0ebea5f8278600..7e85eff4256a02d00a973a4951c094bbb2dbbf6f 100644 (file)
@@ -24,12 +24,7 @@ pub(crate) struct RawBlock<T: RawBlockTraits> {
 
 impl<T: RawBlockTraits> RawBlock<T> {
     pub(crate) fn new() -> Self {
-        let mut block = RawBlock {
-            size: 0,
-            base: ptr::null(),
-            top: ptr::null(),
-            _marker: PhantomData,
-        };
+        let mut block = Self::uninitialized();
 
         unsafe {
             block.grow();
@@ -38,6 +33,15 @@ impl<T: RawBlockTraits> RawBlock<T> {
         block
     }
 
+    pub(crate) fn uninitialized() -> Self {
+        Self {
+            size: 0,
+            base: ptr::null(),
+            top: ptr::null(),
+            _marker: PhantomData,
+        }
+    }
+
     unsafe fn init_at_size(&mut self, cap: usize) {
         let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
 
index 210a7cac48259b1c6044873ac6740850845ee5e5..bf330813dfc34c3312db373d59df18b5dc740f50 100644 (file)
@@ -168,6 +168,13 @@ impl Stack {
         }
     }
 
+    pub(crate) fn uninitialized() -> Self {
+        Stack {
+            buf: RawBlock::empty_block(),
+            _marker: PhantomData,
+        }
+    }
+
     #[inline(always)]
     unsafe fn alloc(&mut self, frame_size: usize) -> *mut u8 {
         loop {
index d434c569a7e5554777e86a4a8e093e617de2a1f5..ffb04a39835ef10f2acf50723d1035f4c36ca275 100644 (file)
@@ -1662,7 +1662,7 @@ impl MachineState {
     ) -> Result<Stream, ParserError> {
         match stream.peek_char() {
             None => Ok(stream), // empty stream is handled gracefully by Lexer::eof
-            Some(Err(e)) => Err(ParserError::IO(e)),
+            Some(Err(e)) => Err(ParserError::IO(e, ParserErrorSrc::default())),
             Some(Ok(c)) => {
                 if c == '\u{feff}' {
                     // skip UTF-8 BOM
index 752ae6b45c01ba2f844bf041b9941f1c1e81ddba..47533a7b20a7dcc64a6432f0dc1173b6f27f5efd 100644 (file)
@@ -28,7 +28,7 @@ use crate::machine::stack::*;
 use crate::machine::streams::*;
 use crate::machine::{get_structure_index, Machine, VERIFY_ATTR_INTERRUPT_LOC};
 use crate::parser::char_reader::*;
-use crate::parser::dashu::Integer;
+use crate::parser::dashu::{Integer, Rational};
 use crate::read::*;
 use crate::types::*;
 use rand::rngs::StdRng;
@@ -778,25 +778,30 @@ impl MachineState {
     ) {
         let mut seen_set = IndexSet::new();
 
-        {
-            let mut iter =
-                stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, term);
+        let outcome = if term.is_ref() {
+            {
+                let mut iter = stackful_post_order_iter::<NonListElider>(
+                    &mut self.heap, &mut self.stack, term.get_value() as usize,
+                );
 
-            while let Some(value) = iter.next() {
-                if iter.parent_stack_len() >= max_depth {
-                    iter.pop_stack();
-                    continue;
-                }
+                while let Some(value) = iter.next() {
+                    if iter.parent_stack_len() >= max_depth {
+                        iter.pop_stack();
+                        continue;
+                    }
 
-                let value = unmark_cell_bits!(value);
+                    let value = unmark_cell_bits!(value);
 
-                if value.is_var() {
-                    seen_set.insert(value);
+                    if value.is_var() {
+                        seen_set.insert(value);
+                    }
                 }
             }
-        }
 
-        let outcome = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, seen_set.into_iter(),));
+            heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, seen_set.into_iter()))
+        } else {
+            empty_list_as_cell!()
+        };
 
         unify_fn!(*self, list_of_vars, outcome);
     }
@@ -907,27 +912,42 @@ impl MachineState {
                     tokens.reverse();
 
                     match parser.read_term(&op_dir, Tokens::Provided(tokens)) {
-                        Err(err) => {
-                            let err = self.syntax_error(err);
-                            return Err(self.error_form(err, stub_gen()));
-                        }
-                        Ok(Term::Literal(_, Literal::Rational(n))) => {
-                            self.unify_rational(n, nx);
-                        }
-                        Ok(Term::Literal(_, Literal::Float(n))) => {
-                            self.unify_f64(n.as_ptr(), nx);
-                        }
-                        Ok(Term::Literal(_, Literal::Integer(n))) => {
-                            self.unify_big_int(n, nx);
-                        }
-                        Ok(Term::Literal(_, Literal::Fixnum(n))) => {
-                            self.unify_fixnum(n, nx);
-                        }
-                        _ => {
-                            let err = ParserError::ParseBigInt(0, 0);
-                            let err = self.syntax_error(err);
+                        Ok(term) => {
+                            let mut error_gen = || {
+                                let e = ParserError::ParseBigInt(ParserErrorSrc::default());
+                                let e = self.syntax_error(e);
+
+                                return Err(self.error_form(e, stub_gen()));
+                            };
 
-                            return Err(self.error_form(err, stub_gen()));
+                            read_heap_cell!(term.heap[term.focus],
+                                (HeapCellValueTag::Cons, c) => {
+                                    match_untyped_arena_ptr!(c,
+                                       (ArenaHeaderTag::Rational, n) => {
+                                           self.unify_rational(n, nx);
+                                       }
+                                       (ArenaHeaderTag::Integer, n) => {
+                                           self.unify_big_int(n, nx);
+                                       }
+                                       _ => {
+                                           return error_gen();
+                                       }
+                                    )
+                                }
+                                (HeapCellValueTag::F64, n) => {
+                                    self.unify_f64(n, nx);
+                                }
+                                (HeapCellValueTag::Fixnum, n) => {
+                                    self.unify_fixnum(n, nx);
+                                }
+                                _ => {
+                                    return error_gen();
+                                }
+                            );
+                        }
+                        Err(e) => {
+                            let e = self.syntax_error(e);
+                            return Err(self.error_form(e, stub_gen()));
                         }
                     }
 
@@ -937,9 +957,9 @@ impl MachineState {
                     lexer.skip_char('.');
                 }
                 Ok(c) => {
-                    let (line_num, col_num) = (lexer.line_num, lexer.col_num);
+                    let err_src = lexer.loc_to_err_src();
 
-                    let err = ParserError::UnexpectedChar(c, line_num, col_num);
+                    let err = ParserError::UnexpectedChar(c, err_src);
                     let err = self.syntax_error(err);
 
                     return Err(self.error_form(err, stub_gen()));
@@ -1378,6 +1398,8 @@ impl Machine {
                 .get_predicate_code_index(name, arity, module_name)
         });
 
+        // println!("(fast) calling {}/{}", name.as_str(), arity);
+
         if let Some(code_index) = index_cell {
             if !code_index.is_undefined() {
                 load_registers(&mut self.machine_st, goal, goal_arity);
@@ -1532,12 +1554,12 @@ impl Machine {
 
             let vars: Vec<_> = vars
                 .union(&result.supp_vars) // difference + union does not cancel.
-                .map(|v| Term::Var(Cell::default(), VarPtr::from(format!("_{}", v.get_value()))))
+                .cloned()
                 .collect();
 
             let helper_clause_loc = self.code.len();
 
-            match self.compile_standalone_clause(temp_v!(1), &vars) {
+            match self.compile_standalone_clause(temp_v!(1), vars) {
                 Err(e) => {
                     let err = self.machine_st.session_error(e);
                     let stub = functor_stub(atom!("call"), result.key.1);
@@ -3505,7 +3527,9 @@ impl Machine {
                     }
                     Some(Err(e)) => {
                         let stub = functor_stub(atom!("$get_n_chars"), 3);
-                        let err = self.machine_st.session_error(SessionError::from(e));
+                        let err = self.machine_st.session_error(SessionError::from(
+                            ParserError::IO(e, ParserErrorSrc::default()),
+                        ));
 
                         return Err(self.machine_st.error_form(err, stub));
                     }
@@ -6186,10 +6210,10 @@ impl Machine {
     }
 
     #[inline(always)]
-    fn read_term_and_write_to_heap(
+    fn read_term_from_atom(
         &mut self,
         atom_or_string: AtomOrString,
-    ) -> Result<Option<TermWriteResult>, MachineStub> {
+    ) -> Result<Option<FocusedHeap>, MachineStub> {
         let string = match atom_or_string {
             AtomOrString::Atom(atom!("[]")) => "".to_owned(),
             _ => atom_or_string.into(),
@@ -6199,15 +6223,12 @@ impl Machine {
         let mut parser = Parser::new(chars, &mut self.machine_st);
         let op_dir = CompositeOpDir::new(&self.indices.op_dir, None);
 
-        let term_write_result = parser
+        let term = parser
             .read_term(&op_dir, Tokens::Default)
-            .map_err(|err| error_after_read_term(err, 0, &parser))
-            .and_then(|term| {
-                write_term_to_heap(&term, &mut self.machine_st.heap, &self.machine_st.atom_tbl)
-            });
+            .map_err(|e| error_after_read_term(e, 0));
 
-        match term_write_result {
-            Ok(term_write_result) => Ok(Some(term_write_result)),
+        match term {
+            Ok(term) => Ok(Some(term)),
             Err(CompilationError::ParserError(e)) if e.is_unexpected_eof() => {
                 let value = self.machine_st.registers[2];
                 self.machine_st.unify_atom(atom!("end_of_file"), value);
@@ -6225,42 +6246,50 @@ impl Machine {
 
     #[inline(always)]
     pub(crate) fn read_from_chars(&mut self) -> CallResult {
-        if let Some(atom_or_string) = self
+        let atom_or_string = self
             .machine_st
             .value_to_str_like(self.machine_st.registers[1])
-        {
-            if let Some(term_write_result) = self.read_term_and_write_to_heap(atom_or_string)? {
-                let result = heap_loc_as_cell!(term_write_result.heap_loc);
-                let var = self.deref_register(2).as_var().unwrap();
+            .unwrap();
 
-                self.machine_st.bind(var, result);
-            }
+        if let Some(mut term) = self.read_term_from_atom(atom_or_string)? {
+            let heap_len = self.machine_st.heap.len();
 
-            Ok(())
-        } else {
-            unreachable!()
+            self.machine_st.heap.extend(
+                copy_and_align_iter(term.heap.drain(..), 0, heap_len as i64),
+            );
+
+            let result = heap_loc_as_cell!(heap_len + term.focus);
+            let var = self.deref_register(2).as_var().unwrap();
+
+            self.machine_st.bind(var, result);
         }
+
+        Ok(())
     }
 
     #[inline(always)]
     pub(crate) fn read_term_from_chars(&mut self) -> CallResult {
-        if let Some(atom_or_string) = self
+        let atom_or_string = self
             .machine_st
             .value_to_str_like(self.machine_st.registers[1])
-        {
-            if let Some(term_write_result) = self.read_term_and_write_to_heap(atom_or_string)? {
-                self.machine_st.read_term_body(term_write_result)
-            } else {
-                if !self.machine_st.fail {
-                    // wrote end_of_file term in this case.
-                    self.machine_st.write_read_term_options(vec![], vec![])?;
-                }
+            .unwrap();
 
-                Ok(())
-            }
-        } else {
-            unreachable!()
-        }
+        let string = match atom_or_string {
+            AtomOrString::Atom(atom!("[]")) => "".to_owned(),
+            _ => atom_or_string.into(),
+        };
+
+        let chars = CharReader::new(ByteStream::from_string(string));
+        let term_write_result = self.machine_st.read(chars, &self.indices.op_dir)
+            .map(|(term, _)| term.to_machine_heap(&mut self.machine_st))
+            .map_err(|e| {
+                let e = self.machine_st.session_error(SessionError::from(e));
+                let stub = functor_stub(atom!("read_term_from_chars"), 3);
+
+                self.machine_st.error_form(e, stub)
+            })?;
+
+        self.machine_st.read_term_body(term_write_result)
     }
 
     #[inline(always)]
@@ -8012,8 +8041,13 @@ impl Machine {
 
         match devour_whitespace(&mut parser) {
             Ok(false) => {
-                // not at EOF.
+                // not at EOF ...
                 stream.add_lines_read(parser.lines_read());
+
+                // ... unless we are.
+                if stream.at_end_of_stream() {
+                    self.machine_st.fail = true;
+                }
             }
             Ok(true) => {
                 stream.add_lines_read(parser.lines_read());
index 686a8c197bea9b69d327b46e4c32b09a65baf88f..58c6e2c88c4976a483a12c5b7319782334a7f1cd 100644 (file)
@@ -20,11 +20,11 @@ pub struct LoadStatePayload<TS> {
     pub(super) module_op_exports: ModuleOpExports,
     pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>,
     pub(super) predicates: PredicateQueue,
-    pub(super) clause_clauses: Vec<(Term, Term)>,
+    pub(super) clause_clauses: Vec<FocusedHeap>,
 }
 
 pub trait TermStream: Sized {
-    fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError>;
+    fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError>;
     fn eof(&mut self) -> Result<bool, CompilationError>;
     fn listing_src(&self) -> &ListingSource;
 }
@@ -52,7 +52,7 @@ impl<'a> BootstrappingTermStream<'a> {
 
 impl<'a> TermStream for BootstrappingTermStream<'a> {
     #[inline]
-    fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError> {
+    fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
         self.parser.reset();
         self.parser
             .read_term(op_dir, Tokens::Default)
@@ -72,7 +72,7 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
 }
 
 pub struct LiveTermStream {
-    pub(super) term_queue: VecDeque<Term>,
+    pub(super) term_queue: VecDeque<FocusedHeap>,
     pub(super) listing_src: ListingSource,
 }
 
@@ -108,7 +108,7 @@ impl<TS> LoadStatePayload<TS> {
 
 impl TermStream for LiveTermStream {
     #[inline]
-    fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
+    fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
         Ok(self.term_queue.pop_front().unwrap())
     }
 
@@ -126,8 +126,8 @@ impl TermStream for LiveTermStream {
 pub struct InlineTermStream {}
 
 impl TermStream for InlineTermStream {
-    fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
-        Err(CompilationError::from(ParserError::unexpected_eof()))
+    fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
+        Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default())))
     }
 
     fn eof(&mut self) -> Result<bool, CompilationError> {
index 2e9dd54b5c7fb7117c960b0afaeddc4e65a7026f..05ba4749dc60a933ada8f4ee5b1af4bd4cabf0d5 100644 (file)
@@ -705,13 +705,16 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
 
     let mut occurs_triggered = false;
 
-    if !value.is_constant() {
-        let machine_st: &mut MachineState = unifier.deref_mut();
+    let machine_st: &mut MachineState = unifier.deref_mut();
+    let value = machine_st.store(MachineState::deref(machine_st, value));
+
+    if value.is_ref() && !value.is_stack_var() {
+        let root_loc = value.get_value() as usize;
 
         for cell in stackful_preorder_iter::<NonListElider>(
             &mut machine_st.heap,
             &mut machine_st.stack,
-            value,
+            root_loc, // value,
         ) {
             let cell = unmark_cell_bits!(cell);
 
index 30a863cac21439ac9ca57cd1890febcaf1c660dc..0218a812f5df5d05eac9cd6a067760efa1269396 100644 (file)
@@ -349,6 +349,11 @@ macro_rules! read_heap_cell_pat_body {
         #[allow(unused_braces)]
         $code
     }};
+    ($cell:ident, Atom, (_, $arity:ident), $code:expr) => {{
+        let $arity = cell_as_atom_cell!($cell).get_arity();
+        #[allow(unused_braces)]
+        $code
+    }};
     ($cell:ident, PStr, $atom:ident, $code:expr) => {{
         let $atom = cell_as_atom!($cell);
         #[allow(unused_braces)]
index 06c1ab9e0eed4666f9c91fe682ab14449369f430..39259656c7b50ccad747d030e8f662c849d47d28 100644 (file)
@@ -2,15 +2,19 @@
 
 use crate::arena::*;
 use crate::atom_table::*;
+use crate::forms::PredicateKey;
+use crate::machine::copier::*;
+use crate::machine::heap::*;
 use crate::machine::machine_indices::*;
-use crate::parser::char_reader::*;
-use crate::types::HeapCellValueTag;
+use crate::machine::machine_state::*;
+use crate::types::*;
 
-use std::cell::{Cell, Ref, RefCell, RefMut};
+use std::cell::{Ref, RefCell, RefMut};
+use std::collections::VecDeque;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::io::{Error as IOError, ErrorKind};
-use std::ops::{Deref, Neg};
+use std::ops::{Deref, Neg, RangeBounds};
 use std::rc::Rc;
 use std::sync::Arc;
 use std::vec::Vec;
@@ -426,33 +430,40 @@ pub enum ArithmeticError {
     UninstantiatedVar,
 }
 
-#[allow(dead_code)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct ParserErrorSrc {
+    pub col_num: usize,
+    pub line_num: usize,
+}
+
 #[derive(Debug)]
 pub enum ParserError {
-    BackQuotedString(usize, usize),
-    IO(IOError),
-    IncompleteReduction(usize, usize),
-    InvalidSingleQuotedCharacter(char),
-    LexicalError(lexical::Error),
-    MissingQuote(usize, usize),
-    NonPrologChar(usize, usize),
-    ParseBigInt(usize, usize),
-    UnexpectedChar(char, usize, usize),
+    BackQuotedString(ParserErrorSrc),
+    IO(IOError, ParserErrorSrc),
+    IncompleteReduction(ParserErrorSrc),
+    InvalidSingleQuotedCharacter(char, ParserErrorSrc),
+    LexicalError(lexical::Error, ParserErrorSrc),
+    MissingQuote(ParserErrorSrc),
+    NonPrologChar(ParserErrorSrc),
+    ParseBigInt(ParserErrorSrc),
+    UnexpectedChar(char, ParserErrorSrc),
     // UnexpectedEOF,
-    Utf8Error(usize, usize),
+    Utf8Error(ParserErrorSrc),
 }
 
 impl ParserError {
-    pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
+    pub fn err_src(&self) -> ParserErrorSrc {
         match self {
-            &ParserError::BackQuotedString(line_num, col_num)
-            | &ParserError::IncompleteReduction(line_num, col_num)
-            | &ParserError::MissingQuote(line_num, col_num)
-            | &ParserError::NonPrologChar(line_num, col_num)
-            | &ParserError::ParseBigInt(line_num, col_num)
-            | &ParserError::UnexpectedChar(_, line_num, col_num)
-            | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
-            _ => None,
+            &ParserError::BackQuotedString(err_src)
+            | &ParserError::IO(_, err_src)
+            | &ParserError::IncompleteReduction(err_src)
+            | &ParserError::InvalidSingleQuotedCharacter(_, err_src)
+            | &ParserError::LexicalError(_, err_src)
+            | &ParserError::MissingQuote(err_src)
+            | &ParserError::NonPrologChar(err_src)
+            | &ParserError::ParseBigInt(err_src)
+            | &ParserError::UnexpectedChar(_, err_src)
+            | &ParserError::Utf8Error(err_src) => err_src,
         }
     }
 
@@ -463,14 +474,14 @@ impl ParserError {
             ParserError::InvalidSingleQuotedCharacter(..) => {
                 atom!("invalid_single_quoted_character")
             }
-            ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => {
+            ParserError::IO(e, _) if e.kind() == ErrorKind::UnexpectedEof => {
                 atom!("unexpected_end_of_file")
             }
-            ParserError::IO(e) if e.kind() == ErrorKind::InvalidData => {
+            ParserError::IO(e, _) if e.kind() == ErrorKind::InvalidData => {
                 atom!("invalid_data")
             }
-            ParserError::IO(_) => atom!("input_output_error"),
-            ParserError::LexicalError(_) => atom!("lexical_error"),
+            ParserError::IO(..) => atom!("input_output_error"),
+            ParserError::LexicalError(..) => atom!("lexical_error"),
             ParserError::MissingQuote(..) => atom!("missing_quote"),
             ParserError::NonPrologChar(..) => atom!("non_prolog_character"),
             ParserError::ParseBigInt(..) => atom!("cannot_parse_big_int"),
@@ -480,23 +491,23 @@ impl ParserError {
     }
 
     #[inline]
-    pub fn unexpected_eof() -> Self {
-        ParserError::IO(std::io::Error::from(ErrorKind::UnexpectedEof))
+    pub fn unexpected_eof(err_src: ParserErrorSrc) -> Self {
+        ParserError::IO(std::io::Error::from(ErrorKind::UnexpectedEof), err_src)
     }
 
     #[inline]
     pub fn is_unexpected_eof(&self) -> bool {
-        if let ParserError::IO(e) = self {
+        if let ParserError::IO(e, _) = self {
             e.kind() == ErrorKind::UnexpectedEof
         } else {
             false
         }
     }
 }
-
+/*
 impl From<lexical::Error> for ParserError {
-    fn from(e: lexical::Error) -> ParserError {
-        ParserError::LexicalError(e)
+    fn from((e, err_src): (lexical::Error, ParserErrorSrc)) -> ParserError {
+        ParserError::LexicalError(e, err_src)
     }
 }
 
@@ -515,7 +526,7 @@ impl From<&IOError> for ParserError {
         }
     }
 }
-
+*/
 #[derive(Debug, Clone, Copy)]
 pub struct CompositeOpDir<'a, 'b> {
     pub primary_op_dir: Option<&'b OpDir>,
@@ -689,6 +700,14 @@ impl Deref for VarPtr {
 }
 
 impl VarPtr {
+    #[inline]
+    pub(crate) fn is_anon(&self) -> bool {
+        match *self.borrow() {
+            Var::Anon | Var::Generated { is_anon: true, .. } => true,
+            _ => false,
+        }
+    }
+
     #[inline(always)]
     pub(crate) fn borrow(&self) -> Ref<'_, Var> {
         self.0.borrow()
@@ -701,7 +720,7 @@ impl VarPtr {
 
     pub(crate) fn to_var_num(&self) -> Option<usize> {
         match *self.borrow() {
-            Var::Generated(var_num) => Some(var_num),
+            Var::Generated { var_num, .. } => Some(var_num),
             _ => None,
         }
     }
@@ -735,7 +754,8 @@ impl From<&str> for VarPtr {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Var {
-    Generated(usize),
+    Anon,
+    Generated { is_anon: bool, var_num: usize },
     InSitu(usize),
     Named(String),
 }
@@ -759,12 +779,34 @@ impl Var {
     #[inline(always)]
     pub fn to_string(&self) -> String {
         match self {
-            Var::InSitu(n) | Var::Generated(n) => format!("_{}", n),
+            Var::Anon => "_".to_owned(),
+            Var::InSitu(var_num) | Var::Generated { var_num, .. } => format!("_{}", var_num),
             Var::Named(value) => value.to_owned(),
         }
     }
 }
 
+pub(crate) fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) {
+    let subterm = heap[subterm_loc];
+
+    if subterm.is_ref() {
+        let subterm = heap_bound_deref(heap, subterm);
+        let subterm_loc = subterm.get_value() as usize;
+        let subterm = heap_bound_store(heap, subterm);
+
+        let subterm_loc = if subterm.is_ref() {
+            subterm.get_value() as usize
+        } else {
+            subterm_loc
+        };
+
+        (subterm_loc, subterm)
+    } else {
+        (subterm_loc, subterm)
+    }
+}
+
+/*
 #[derive(Debug, Clone)]
 pub enum Term {
     AnonVar,
@@ -831,3 +873,441 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
     terms.push(term);
     terms
 }
+ */
+
+pub(crate) fn fetch_index_ptr(
+    heap: &[HeapCellValue],
+    arity: usize,
+    term_loc: usize,
+) -> Option<CodeIndex> {
+    if term_loc + arity + 1 >= heap.len() {
+        return None;
+    }
+
+    read_heap_cell!(heap[term_loc + arity + 1],
+        (HeapCellValueTag::Cons, c) => {
+            match_untyped_arena_ptr!(c,
+               (ArenaHeaderTag::IndexPtr, ptr) => {
+                   return Some(CodeIndex::from(ptr));
+               }
+               _ => {}
+            );
+        }
+        _ => {}
+    );
+
+    None
+}
+
+pub(crate) fn blunt_index_ptr(
+    heap: &mut [HeapCellValue],
+    key: PredicateKey,
+    term_loc: usize,
+) -> bool {
+    if fetch_index_ptr(heap, key.1, term_loc).is_some() {
+        heap[term_loc] = atom_as_cell!(key.0, key.1);
+        true
+    } else {
+        false
+    }
+}
+
+pub(crate) fn unfold_by_str_once(
+    heap: &mut [HeapCellValue],
+    start_term: HeapCellValue,
+    atom: Atom,
+) -> Option<usize> {
+    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;
+
+        let (s_atom, s_arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
+        blunt_index_ptr(heap, (s_atom, s_arity), s);
+
+        if (s_atom, s_arity) == (atom, 2) {
+            return Some(s+1);
+        }
+    }
+
+    None
+}
+
+pub fn unfold_by_str(
+    heap: &mut [HeapCellValue],
+    mut start_term: HeapCellValue,
+    atom: Atom,
+) -> Vec<HeapCellValue> {
+    let mut terms = vec![];
+    start_term = heap_bound_store(heap, heap_bound_deref(heap, start_term));
+
+    while let Some(fst_loc) = unfold_by_str_once(heap, start_term, atom) {
+        let (_, snd) = subterm_index(heap, fst_loc + 1);
+        let (_, fst) = subterm_index(heap, fst_loc);
+        terms.push(fst);
+        start_term = snd;
+    }
+
+    terms
+}
+
+/*
+pub fn unfold_by_str_locs(
+    heap: &mut [HeapCellValue],
+    mut term_loc: usize,
+    atom: Atom,
+) -> Vec<(HeapCellValue, usize)> {
+    let mut terms = vec![];
+    let mut current_term = heap_bound_store(
+        heap,
+        heap_bound_deref(heap, heap[term_loc]),
+    );
+
+    while let Some(fst_loc) = unfold_by_str_once(heap, current_term, atom) {
+        (term_loc, current_term) = subterm_index(heap, fst_loc + 1);
+        let (fst_loc, fst) = subterm_index(heap, fst_loc);
+        terms.push((fst, fst_loc));
+    }
+
+    terms.push((current_term, term_loc));
+    terms
+}
+*/
+
+pub fn unfold_by_str_locs(
+    heap: &mut [HeapCellValue],
+    mut term_loc: usize,
+    atom: Atom,
+) -> Vec<(HeapCellValue, usize)> {
+    let mut terms = vec![];
+    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;
+        current_term = heap[term_loc];
+        let fst = heap[fst_loc];
+        terms.push((fst, fst_loc));
+    }
+
+    terms.push((current_term, term_loc));
+    terms
+}
+
+pub fn term_name(heap: &[HeapCellValue], mut term_loc: usize) -> Option<Atom> {
+    loop {
+        read_heap_cell!(heap[term_loc],
+            (HeapCellValueTag::Atom, (name, _arity)) => {
+                return Some(name);
+            }
+            (HeapCellValueTag::Str, s) => {
+                term_loc = s;
+            }
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                if h != term_loc {
+                    term_loc = h;
+                } else {
+                    return None;
+                }
+            }
+            _ => {
+                return None;
+            }
+        );
+    }
+}
+
+pub fn term_arity(heap: &[HeapCellValue], mut term_loc: usize) -> usize {
+    loop {
+        read_heap_cell!(heap[term_loc],
+            (HeapCellValueTag::Atom, (_name, arity)) => {
+                return arity;
+            }
+            (HeapCellValueTag::Str, s) => {
+                term_loc = s;
+            }
+            (HeapCellValueTag::Lis) => {
+                return 2;
+            }
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                if h != term_loc {
+                    term_loc = h;
+                } else {
+                    return 0;
+                }
+            }
+            _ => {
+                return 0;
+            }
+        );
+    }
+}
+
+pub fn var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) -> VarLocs {
+    let mut occurrence_set: IndexMap<HeapCellValue, usize, FxBuildHasher> =
+        IndexMap::with_hasher(FxBuildHasher::default());
+
+    for term in iter {
+        if term.is_var() {
+            let var_count = occurrence_set.entry(term).or_insert(0);
+            *var_count += 1;
+        }
+    }
+
+    VarLocs(
+        occurrence_set
+        .into_iter()
+        .map(|(var, count)| {
+            let key = var.get_value() as usize;
+            let queue = if count > 1 {
+                (0 .. count).map(|_| VarPtr::from(format!("_{}", key))).collect()
+            } else {
+                (0 .. count).map(|_| VarPtr::from(Var::Anon)).collect()
+            };
+
+            (key, queue)
+        })
+        .collect()
+    )
+}
+
+/*
+pub fn term_deref(heap: &[HeapCellValue], mut term_loc: usize) -> HeapCellValue {
+    loop {
+        read_heap_cell!(heap[term_loc],
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                if h != term_loc {
+                    term_loc = h;
+                } else {
+                    return heap[h];
+                }
+            }
+            _ => {
+                return heap[term_loc];
+            }
+        )
+    }
+}
+*/
+
+pub fn term_nth_arg(heap: &[HeapCellValue], mut term_loc: usize, n: usize) -> Option<usize> {
+    loop {
+        read_heap_cell!(heap[term_loc],
+            (HeapCellValueTag::Str, s) => {
+                return if cell_as_atom_cell!(heap[s]).get_arity() >= n {
+                    Some(s+n)
+                } else {
+                    None
+                };
+            }
+            (HeapCellValueTag::Atom, (_name, arity)) => {
+                return if arity >= n {
+                    Some(term_loc + n)
+                } else {
+                    None
+                };
+            }
+            (HeapCellValueTag::Lis, l) => {
+                return if 1 <= n && n <= 2 {
+                    Some(l+n-1)
+                } else if n == 0 {
+                    Some(term_loc)
+                } else {
+                    None
+                };
+            }
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                if h != term_loc {
+                    term_loc = h;
+                } else {
+                    return None;
+                }
+            }
+            _ => {
+                return None;
+            }
+        );
+    }
+}
+
+pub type VarNamesToLocs = IndexMap<String, HeapCellValue, FxBuildHasher>;
+
+#[derive(Debug, Default)]
+pub struct VarLocs(IndexMap<usize, VecDeque<VarPtr>, FxBuildHasher>);
+
+impl VarLocs {
+    pub fn get(&self, key: usize) -> Option<&VarPtr> {
+        self.0.get(&key)
+            .and_then(|queue| {
+                queue.front()
+            })
+    }
+
+    // if a queue of VarPtr's is stored at location key, pop the front
+    // if it exists and pass it along to wrapper, returning a value of
+    // type R. A return value of None indicates that the key doesn't
+    // exist (the map containing a key necessarily means its queue
+    // value is non-empty).
+    fn rotate_latest_mut<R>(
+        &mut self,
+        key: usize,
+        wrapper: impl FnOnce(&VarPtr) -> R,
+    ) -> Option<R> {
+        self.0.get_mut(&key)
+            .and_then(move |queue| {
+                if let Some(var_ptr) = queue.pop_front() {
+                    let result = wrapper(&var_ptr);
+                    queue.push_back(var_ptr);
+                    Some(result)
+                } else {
+                    None
+                }
+            })
+    }
+
+    pub fn peek_next_var_ptr_at_key(&self, key: usize) -> Option<&VarPtr> {
+        self.0.get(&key).and_then(|queue| queue.front())
+    }
+
+    pub fn read_next_var_ptr_at_key(&mut self, key: usize) -> Option<VarPtr> {
+        self.rotate_latest_mut(key, VarPtr::clone)
+    }
+
+    pub fn push_at_key(&mut self, key: usize, var_ptr: VarPtr) {
+        let entry = self.0.entry(key).or_default();
+        entry.push_back(var_ptr);
+    }
+
+    #[inline]
+    pub fn iter(&self) -> impl Iterator<Item = (usize, &VecDeque<VarPtr>)> {
+        self.0.iter().map(|(&k, v)| (k, v))
+    }
+
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    #[inline]
+    pub fn drain<R>(&mut self, range: R) -> indexmap::map::Drain<usize, VecDeque<VarPtr>>
+        where R: RangeBounds<usize>
+    {
+        self.0.drain(range)
+    }
+
+    #[inline]
+    pub fn insert(&mut self, key: usize, var_ptrs: VecDeque<VarPtr>) {
+        self.0.insert(key, var_ptrs);
+    }
+}
+
+#[derive(Debug)]
+pub struct FocusedHeap {
+    pub heap: Vec<HeapCellValue>,
+    pub focus: usize,
+    pub var_locs: VarLocs,
+}
+
+impl FocusedHeap {
+    pub fn empty() -> Self {
+        Self {
+            heap: vec![],
+            focus: 0,
+            var_locs: VarLocs::default(),
+        }
+    }
+
+    pub fn copy_term_from_machine_heap(
+        &mut self,
+        machine_st: &mut MachineState,
+        cell: HeapCellValue,
+    ) {
+        let hb = machine_st.heap.len();
+
+        copy_term(
+            CopyBallTerm::new(
+                &mut machine_st.attr_var_init.attr_var_queue,
+                &mut machine_st.stack,
+                &mut machine_st.heap,
+                &mut self.heap,
+            ),
+            cell,
+            AttrVarPolicy::DeepCopy,
+        );
+
+        for cell in self.heap.iter_mut() {
+            *cell = *cell - hb;
+        }
+    }
+
+    pub fn as_ref_mut(&mut self, focus: usize) -> FocusedHeapRefMut {
+        FocusedHeapRefMut {
+            heap: &mut self.heap,
+            focus,
+            // var_locs: &self.var_locs,
+        }
+    }
+
+    pub fn deref_loc(&self, term_loc: usize) -> HeapCellValue {
+        use crate::machine::heap::*;
+
+        let cell = self.heap[term_loc];
+        heap_bound_store(&self.heap, heap_bound_deref(&self.heap, cell))
+    }
+
+    pub fn name(&self, term_loc: usize) -> Option<Atom> {
+        term_name(&self.heap, term_loc)
+    }
+
+    pub fn arity(&self, term_loc: usize) -> usize {
+        term_arity(&self.heap, term_loc)
+    }
+
+    pub fn nth_arg(&self, term_loc: usize, n: usize) -> Option<usize> {
+        term_nth_arg(&self.heap, term_loc, n)
+    }
+}
+
+pub struct FocusedHeapRefMut<'a> {
+    pub heap: &'a mut Vec<HeapCellValue>,
+    pub focus: usize,
+}
+
+impl<'a> FocusedHeapRefMut<'a> {
+    pub fn name(&self, term_loc: usize) -> Option<Atom> {
+        term_name(&self.heap, term_loc)
+    }
+
+    pub fn arity(&self, term_loc: usize) -> usize {
+        term_arity(&self.heap, term_loc)
+    }
+
+    pub fn deref_loc(&self, term_loc: usize) -> HeapCellValue {
+        use crate::machine::heap::*;
+
+        let cell = self.heap[term_loc];
+        heap_bound_store(&self.heap, heap_bound_deref(&self.heap, cell))
+    }
+
+    pub fn nth_arg(&self, term_loc: usize, n: usize) -> Option<usize> {
+        term_nth_arg(self.heap, term_loc, n)
+    }
+
+    pub fn from_cell(heap: &'a mut Vec<HeapCellValue>, cell: HeapCellValue) -> Self {
+        let focus = read_heap_cell!(cell,
+            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                h
+            }
+            _ => {
+                let h = heap.len();
+                heap.push(cell);
+
+                h
+            }
+        );
+
+        Self { heap, focus }
+    }
+}
index 06f8a326bf685d3ca90b65765ef371cd025d301d..05868fbfcdd791e74ee5c0f3a2b8a9b302810a93 100644 (file)
@@ -1,3 +1,6 @@
+use lexical::{FromLexicalLossy, parse_lossy};
+
+use crate::arena::ArenaAllocated;
 use crate::atom_table::*;
 pub use crate::machine::machine_state::*;
 use crate::parser::ast::*;
@@ -79,17 +82,22 @@ impl<'a, R: CharRead> Lexer<'a, R> {
     pub fn lookahead_char(&mut self) -> Result<char, ParserError> {
         match self.reader.peek_char() {
             Some(Ok(c)) => Ok(c),
-            _ => Err(ParserError::unexpected_eof()),
+            _ => Err(ParserError::unexpected_eof(self.loc_to_err_src())),
         }
     }
 
     pub fn read_char(&mut self) -> Result<char, ParserError> {
         match self.reader.read_char() {
             Some(Ok(c)) => Ok(c),
-            _ => Err(ParserError::unexpected_eof()),
+            _ => Err(ParserError::unexpected_eof(self.loc_to_err_src())),
         }
     }
 
+    #[inline]
+    pub fn loc_to_err_src(&self) -> ParserErrorSrc {
+        ParserErrorSrc { line_num: self.line_num, col_num: self.col_num }
+    }
+
     #[inline(always)]
     fn return_char(&mut self, c: char) {
         self.reader.put_back_char(c);
@@ -161,10 +169,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             match comment_loop() {
                 Err(e) if e.is_unexpected_eof() => {
-                    return Err(ParserError::IncompleteReduction(
-                        self.line_num,
-                        self.col_num,
-                    ));
+                    return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
                 }
                 Err(e) => {
                     return Err(e);
@@ -176,7 +181,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 self.skip_char(c);
                 Ok(true)
             } else {
-                Err(ParserError::NonPrologChar(self.line_num, self.col_num))
+                Err(ParserError::NonPrologChar(self.loc_to_err_src()))
             }
         } else {
             self.return_char('/');
@@ -193,7 +198,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             if !back_quote_char!(c2) {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.loc_to_err_src()))
             } else {
                 self.skip_char(c2);
                 Ok(c2)
@@ -218,7 +223,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 Ok(None)
             } else {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.loc_to_err_src()))
             }
         } else {
             self.get_back_quoted_char().map(Some)
@@ -240,10 +245,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 self.skip_char(c);
                 Ok(token)
             } else {
-                Err(ParserError::MissingQuote(self.line_num, self.col_num))
+                Err(ParserError::MissingQuote(self.loc_to_err_src()))
             }
         } else {
-            Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+            Err(ParserError::UnexpectedChar(c, self.loc_to_err_src()))
         }
     }
 
@@ -274,7 +279,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             if !single_quote_char!(c2) {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.loc_to_err_src()))
             } else {
                 self.skip_char(c2);
                 Ok(c2)
@@ -315,7 +320,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             if !double_quote_char!(c2) {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.loc_to_err_src()))
             } else {
                 self.skip_char(c2);
                 Ok(c2)
@@ -339,7 +344,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             't' => '\t',
             'n' => '\n',
             'r' => '\r',
-            c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)),
+            c => return Err(ParserError::UnexpectedChar(c, self.loc_to_err_src())),
         };
 
         self.skip_char(c);
@@ -357,10 +362,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         if hexadecimal_digit_char!(c) {
             self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16)
         } else {
-            Err(ParserError::IncompleteReduction(
-                self.line_num,
-                self.col_num,
-            ))
+            Err(ParserError::IncompleteReduction(self.loc_to_err_src()))
         }
     }
 
@@ -386,17 +388,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         if backslash_char!(c) {
             self.skip_char(c);
             u32::from_str_radix(&token, radix).map_or_else(
-                |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)),
+                |_| Err(ParserError::ParseBigInt(self.loc_to_err_src())),
                 |n| {
                     char::try_from(n)
-                        .map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num))
+                        .map_err(|_| ParserError::Utf8Error(self.loc_to_err_src()))
                 },
             )
         } else {
-            Err(ParserError::IncompleteReduction(
-                self.line_num,
-                self.col_num,
-            ))
+            Err(ParserError::IncompleteReduction(self.loc_to_err_src()))
         }
     }
 
@@ -408,7 +407,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             Ok(c)
         } else {
             if !backslash_char!(c) {
-                return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num));
+                return Err(ParserError::UnexpectedChar(c, self.loc_to_err_src()));
             }
 
             self.skip_char(c);
@@ -439,7 +438,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             self.skip_char(c);
             Ok(token)
         } else {
-            Err(ParserError::MissingQuote(self.line_num, self.col_num))
+            Err(ParserError::MissingQuote(self.loc_to_err_src()))
         }
     }
 
@@ -470,11 +469,11 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                 &mut self.machine_st.arena
                             )))
                         })
-                        .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                        .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                 })
         } else {
             self.return_char(start);
-            Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+            Err(ParserError::ParseBigInt(self.loc_to_err_src()))
         }
     }
 
@@ -505,11 +504,11 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                 &mut self.machine_st.arena
                             )))
                         })
-                        .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                        .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                 })
         } else {
             self.return_char(start);
-            Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+            Err(ParserError::ParseBigInt(self.loc_to_err_src()))
         }
     }
 
@@ -540,11 +539,11 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                 &mut self.machine_st.arena
                             )))
                         })
-                        .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                        .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                 })
         } else {
             self.return_char(start);
-            Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+            Err(ParserError::ParseBigInt(self.loc_to_err_src()))
         }
     }
 
@@ -615,11 +614,11 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                     }
                 }
             } else {
-                return Err(ParserError::InvalidSingleQuotedCharacter(c));
+                return Err(ParserError::InvalidSingleQuotedCharacter(c, self.loc_to_err_src()));
             }
         } else {
             match self.get_back_quoted_string() {
-                Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)),
+                Ok(_) => return Err(ParserError::BackQuotedString(self.loc_to_err_src())),
                 Err(e) => return Err(e),
             }
         }
@@ -634,15 +633,17 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         }
     }
 
+    fn parse_lossy_wrapper<T: FromLexicalLossy>(&self, token: String) -> Result<T, ParserError> {
+        match parse_lossy::<T, _>(token.as_bytes()) {
+            Ok(n) => Ok(n),
+            Err(e) => return Err(ParserError::LexicalError(e, self.loc_to_err_src())),
+        }
+    }
+
     fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> {
         self.return_char(token.pop().unwrap());
-
-        let n = parse_float_lossy(&token)?;
-
-        Ok(Token::Literal(Literal::from(float_alloc!(
-            n,
-            self.machine_st.arena
-        ))))
+        let n = self.parse_lossy_wrapper::<f64>(token)?;
+        Ok(Token::Literal(Literal::from(float_alloc!(n, self.machine_st.arena))))
     }
 
     fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
@@ -656,7 +657,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             if decimal_digit_char!(c) {
                 Ok(c)
             } else {
-                Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+                Err(ParserError::ParseBigInt(self.loc_to_err_src()))
             }
         } else {
             Ok(c)
@@ -694,7 +695,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                     &mut self.machine_st.arena
                                 )))
                             })
-                            .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                            .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                     })
             } else if decimal_digit_char!(self.lookahead_char()?) {
                 token.push('.');
@@ -756,7 +757,8 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                             }
                         }
 
-                        let n = parse_float_lossy(&token)?;
+                        let n = self.parse_lossy_wrapper::<f64>(token)?;
+
                         Ok(Token::Literal(Literal::from(float_alloc!(
                             n,
                             self.machine_st.arena
@@ -765,7 +767,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                         return self.vacate_with_float(token);
                     }
                 } else {
-                    let n = parse_float_lossy(&token)?;
+                    let n = self.parse_lossy_wrapper::<f64>(token)?;
                     Ok(Token::Literal(Literal::from(float_alloc!(
                         n,
                         self.machine_st.arena
@@ -786,7 +788,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                     &mut self.machine_st.arena
                                 )))
                             })
-                            .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                            .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                     })
             }
         } else if token.starts_with('0') && token.len() == 1 {
@@ -808,7 +810,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                         )))
                                     })
                                     .map_err(|_| {
-                                        ParserError::ParseBigInt(self.line_num, self.col_num)
+                                        ParserError::ParseBigInt(self.loc_to_err_src())
                                     })
                             })
                     } else {
@@ -833,7 +835,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                         )))
                                     })
                                     .map_err(|_| {
-                                        ParserError::ParseBigInt(self.line_num, self.col_num)
+                                        ParserError::ParseBigInt(self.loc_to_err_src())
                                     })
                             })
                     } else {
@@ -858,7 +860,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                         )))
                                     })
                                     .map_err(|_| {
-                                        ParserError::ParseBigInt(self.line_num, self.col_num)
+                                        ParserError::ParseBigInt(self.loc_to_err_src())
                                     })
                             })
                     } else {
@@ -908,7 +910,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                         )))
                                     })
                                     .map_err(|_| {
-                                        ParserError::ParseBigInt(self.line_num, self.col_num)
+                                        ParserError::ParseBigInt(self.loc_to_err_src())
                                     })
                             })
                     })
@@ -925,7 +927,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                     &mut self.machine_st.arena
                                 )))
                             })
-                            .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                            .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                     })
             }
         } else {
@@ -941,7 +943,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                                 &mut self.machine_st.arena
                             )))
                         })
-                        .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                        .map_err(|_| ParserError::ParseBigInt(self.loc_to_err_src()))
                 })
         }
     }
@@ -1093,7 +1095,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 }
 
                 if c == '\u{0}' {
-                    return Err(ParserError::unexpected_eof());
+                    return Err(ParserError::unexpected_eof(self.loc_to_err_src()));
                 }
 
                 self.name_token(c)
index eee22294d0758019e8ee537dcbd0bf967a4db5cc..bffc71670e4863993e6a3bd0a6140a5b2154cbcb 100644 (file)
@@ -3,17 +3,22 @@ use dashu::Rational;
 
 use crate::arena::*;
 use crate::atom_table::*;
+use crate::machine::heap::{heap_bound_deref, heap_bound_store};
+use crate::machine::partial_string::*;
 use crate::parser::ast::*;
 use crate::parser::char_reader::*;
 use crate::parser::lexer::*;
+use crate::types::*;
+
+use fxhash::FxBuildHasher;
+use indexmap::IndexMap;
 
-use std::cell::Cell;
 use std::mem;
 use std::ops::Neg;
 
 #[derive(Debug, Clone, Copy, PartialEq)]
 enum TokenType {
-    Term,
+    Term { heap_loc: HeapCellValue },
     Open,
     OpenCT,
     OpenList,          // '['
@@ -26,6 +31,23 @@ enum TokenType {
     End,
 }
 
+impl TokenType {
+    fn sep_to_atom(self) -> Option<Atom> {
+        match self {
+            TokenType::Open | TokenType::OpenCT => Some(atom!("(")),
+            TokenType::Close => Some(atom!(")")),
+            TokenType::OpenList => Some(atom!("[")),
+            TokenType::CloseList => Some(atom!("]")),
+            TokenType::OpenCurly => Some(atom!("{")),
+            TokenType::CloseCurly => Some(atom!("}")),
+            TokenType::HeadTailSeparator => Some(atom!("|")),
+            TokenType::Comma => Some(atom!(",")),
+            TokenType::End => Some(atom!(".")),
+            _ => None,
+        }
+    }
+}
+
 /*
 Specifies whether the token sequence should be read from the lexer or
 provided via the Provided variant.
@@ -61,80 +83,6 @@ struct TokenDesc {
     unfold_bounds: usize,
 }
 
-pub(crate) fn as_partial_string(
-    head: Term,
-    mut tail: Term,
-) -> Result<(String, Option<Box<Term>>), Term> {
-    let mut string = match &head {
-        Term::Literal(_, Literal::Atom(atom)) => {
-            if let Some(c) = atom.as_char() {
-                c.to_string()
-            } else {
-                return Err(Term::Cons(Cell::default(), Box::new(head), Box::new(tail)));
-            }
-        }
-        Term::Literal(_, Literal::Char(c)) => c.to_string(),
-        _ => {
-            return Err(Term::Cons(Cell::default(), Box::new(head), Box::new(tail)));
-        }
-    };
-
-    let mut orig_tail = Box::new(tail);
-    let mut tail_ref = &mut orig_tail;
-
-    loop {
-        match &mut **tail_ref {
-            Term::Cons(_, prev, succ) => {
-                match prev.as_ref() {
-                    Term::Literal(_, Literal::Atom(atom)) => {
-                        if let Some(c) = atom.as_char() {
-                            string.push(c);
-                        } else {
-                            return Err(Term::Cons(Cell::default(), Box::new(head), orig_tail));
-                        }
-                    }
-                    Term::Literal(_, Literal::Char(c)) => {
-                        string.push(*c);
-                    }
-                    _ => {
-                        tail = Term::Cons(
-                            Cell::default(),
-                            Box::new((**prev).clone()),
-                            Box::new((**succ).clone()),
-                        );
-                        break;
-                    }
-                }
-
-                tail_ref = succ;
-            }
-            Term::PartialString(_, pstr, tail) => {
-                string += pstr;
-                tail_ref = tail;
-            }
-            Term::CompleteString(_, cstr) => {
-                string += &*cstr.as_str();
-                tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
-                break;
-            }
-            tail_ref => {
-                tail = mem::replace(tail_ref, Term::AnonVar);
-                break;
-            }
-        }
-    }
-
-    match &tail {
-        Term::AnonVar | Term::Var(..) => Ok((string, Some(Box::new(tail)))),
-        Term::Literal(_, Literal::Atom(atom!("[]"))) => Ok((string, None)),
-        Term::Literal(_, Literal::String(tail)) => {
-            string += &*tail.as_str();
-            Ok((string, None))
-        }
-        _ => Ok((string, Some(Box::new(tail)))),
-    }
-}
-
 pub fn get_op_desc(name: Atom, op_dir: &CompositeOpDir) -> Option<CompositeOpDesc> {
     let mut op_desc = CompositeOpDesc {
         pre: 0,
@@ -234,7 +182,9 @@ pub struct Parser<'a, R> {
     pub lexer: Lexer<'a, R>,
     tokens: Vec<Token>,
     stack: Vec<TokenDesc>,
-    terms: Vec<Term>,
+    terms: Vec<HeapCellValue>,
+    var_locs: VarLocs,
+    var_names_to_locs: VarNamesToLocs,
 }
 
 fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserError> {
@@ -251,10 +201,7 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
                 }
             }
             Err(e) if e.is_unexpected_eof() && !tokens.is_empty() => {
-                return Err(ParserError::IncompleteReduction(
-                    lexer.line_num,
-                    lexer.col_num,
-                ));
+                return Err(ParserError::IncompleteReduction(lexer.loc_to_err_src()));
             }
             Err(e) => {
                 return Err(e);
@@ -267,14 +214,7 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
     Ok(tokens)
 }
 
-fn atomize_term(atom_tbl: &AtomTable, term: &Term) -> Option<Atom> {
-    match term {
-        Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
-        _ => None,
-    }
-}
-
-fn atomize_constant(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
+fn atomize_literal(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
     match c {
         Literal::Atom(ref name) => Some(*name),
         Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
@@ -282,6 +222,102 @@ fn atomize_constant(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
     }
 }
 
+pub(crate) fn as_partial_string(
+    heap: &[HeapCellValue],
+    head: HeapCellValue,
+    tail: HeapCellValue,
+) -> Option<(String, Option<HeapCellValue>)> {
+    let head = heap_bound_store(heap, heap_bound_deref(heap, head));
+    let mut tail = heap_bound_store(heap, heap_bound_deref(heap, tail));
+
+    let mut string = read_heap_cell!(head,
+       (HeapCellValueTag::Atom, (atom, arity)) => {
+           if arity == 0 {
+               if let Some(c) = atom.as_char() {
+                   c.to_string()
+               } else {
+                   return None;
+               }
+           } else {
+               return None;
+           }
+       }
+       (HeapCellValueTag::Char, c) => {
+           c.to_string()
+       }
+       _ => {
+           return None;
+       }
+    );
+
+    loop {
+        read_heap_cell!(tail,
+           (HeapCellValueTag::Lis, l) => {
+               read_heap_cell!(heap[l],
+                   (HeapCellValueTag::Atom, (atom, arity)) => {
+                       if arity == 0 {
+                           if let Some(c) = atom.as_char() {
+                               string.push(c);
+                           } else {
+                               return None;
+                           }
+                       } else {
+                           break;
+                       }
+                   }
+                   (HeapCellValueTag::Char, c) => {
+                       string.push(c);
+                   }
+                   _ => {
+                       return None;
+                   }
+               );
+
+               tail = heap[l+1];
+           }
+           (HeapCellValueTag::PStrLoc, l) => {
+               let (index, n) = pstr_loc_and_offset(&heap, l);
+               let n = n.get_num() as usize;
+
+               string += &*cell_as_string!(heap[index]).as_str_from(n);
+               tail = heap[l+1];
+           }
+           (HeapCellValueTag::CStr, cstr_atom) => {
+               string += &*cstr_atom.as_str();
+               tail = empty_list_as_cell!();
+               break;
+           }
+           (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+               if heap[h] != tail {
+                   tail = heap[h];
+               } else {
+                   break;
+               }
+           }
+           _ => {
+               // Anon
+               break;
+           }
+        );
+    }
+
+    read_heap_cell!(tail,
+       (HeapCellValueTag::Var) => {
+           Some((string, Some(tail)))
+       }
+       (HeapCellValueTag::Atom, (atom, arity)) => {
+           if atom == atom!("[]") && arity == 0 {
+               Some((string, None))
+           } else {
+               Some((string, Some(tail)))
+           }
+       }
+       _ => {
+           Some((string, Some(tail)))
+       }
+    )
+}
+
 impl<'a, R: CharRead> Parser<'a, R> {
     pub fn new(stream: R, machine_st: &'a mut MachineState) -> Self {
         Parser {
@@ -289,6 +325,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
             tokens: vec![],
             stack: vec![],
             terms: vec![],
+            var_locs: VarLocs::default(),
+            var_names_to_locs: IndexMap::with_hasher(FxBuildHasher::default()),
         }
     }
 
@@ -298,50 +336,67 @@ impl<'a, R: CharRead> Parser<'a, R> {
             tokens: vec![],
             stack: vec![],
             terms: vec![],
+            var_locs: VarLocs::default(),
+            var_names_to_locs: IndexMap::with_hasher(FxBuildHasher::default()),
         }
     }
 
-    fn sep_to_atom(&mut self, tt: TokenType) -> Option<Atom> {
-        match tt {
-            TokenType::Open | TokenType::OpenCT => Some(atom!("(")),
-            TokenType::Close => Some(atom!(")")),
-            TokenType::OpenList => Some(atom!("[")),
-            TokenType::CloseList => Some(atom!("]")),
-            TokenType::OpenCurly => Some(atom!("{")),
-            TokenType::CloseCurly => Some(atom!("}")),
-            TokenType::HeadTailSeparator => Some(atom!("|")),
-            TokenType::Comma => Some(atom!(",")),
-            TokenType::End => Some(atom!(".")),
-            _ => None,
-        }
-    }
-
-    fn get_term_name(&mut self, td: TokenDesc) -> Option<Atom> {
+    fn get_term_name(&self, td: TokenDesc) -> Option<Atom> {
         match td.tt {
             TokenType::HeadTailSeparator => Some(atom!("|")),
             TokenType::Comma => Some(atom!(",")),
-            TokenType::Term => match self.terms.pop() {
-                Some(Term::Literal(_, Literal::Atom(atom))) => Some(atom),
-                Some(term) => {
-                    self.terms.push(term);
+            TokenType::Term { heap_loc } => {
+                if heap_loc.is_ref() {
+                    term_name(&self.terms, heap_loc.get_value() as usize)
+                } else {
                     None
                 }
-                _ => None,
-            },
+            }
             _ => None,
         }
     }
 
-    fn push_binary_op(&mut self, td: TokenDesc, spec: Specifier) {
-        if let Some(arg2) = self.terms.pop() {
-            if let Some(name) = self.get_term_name(td) {
-                if let Some(arg1) = self.terms.pop() {
-                    let term = Term::Clause(Cell::default(), name, vec![arg1, arg2]);
+    #[inline]
+    pub fn line_num(&self) -> usize {
+        self.lexer.line_num
+    }
+
+    #[inline]
+    pub fn col_num(&self) -> usize {
+        self.lexer.col_num
+    }
+
+    fn push_binary_op(
+        &mut self,
+        op: TokenDesc,
+        operand_1: TokenDesc,
+        operand_2: TokenDesc,
+        spec: Specifier,
+    ) {
+        if let TokenDesc {
+            tt: TokenType::Term { heap_loc: arg2 },
+            ..
+        } = operand_2
+        {
+            if let TokenDesc {
+                tt: TokenType::Term { heap_loc: arg1 },
+                ..
+            } = operand_1
+            {
+                if let Some(name) = self.get_term_name(op) {
+                    let str_loc = self.terms.len();
+
+                    self.terms.push(atom_as_cell!(name, 2));
+                    self.terms.push(arg1);
+                    self.terms.push(arg2);
+
+                    self.terms.push(str_loc_as_cell!(str_loc));
 
-                    self.terms.push(term);
                     self.stack.push(TokenDesc {
-                        tt: TokenType::Term,
-                        priority: td.priority,
+                        tt: TokenType::Term {
+                            heap_loc: heap_loc_as_cell!(str_loc + 3),
+                        },
+                        priority: op.priority,
                         spec,
                         unfold_bounds: 0,
                     });
@@ -350,20 +405,33 @@ impl<'a, R: CharRead> Parser<'a, R> {
         }
     }
 
-    fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: OpDeclSpec) {
-        if let Some(mut arg1) = self.terms.pop() {
-            if let Some(mut name) = self.terms.pop() {
-                if assoc.is_postfix() {
-                    mem::swap(&mut arg1, &mut name);
-                }
+    fn push_unary_op(&mut self, op: TokenDesc, operand: TokenDesc, spec: Specifier) {
+        // if is_postfix!(assoc) {
+        //     mem::swap(&mut op, &mut operand);
+        // }
 
-                if let Term::Literal(_, Literal::Atom(name)) = name {
-                    let term = Term::Clause(Cell::default(), name, vec![arg1]);
+        if let TokenDesc {
+            tt: TokenType::Term { heap_loc: arg1 },
+            ..
+        } = operand
+        {
+            if let TokenDesc {
+                tt: TokenType::Term { .. },
+                ..
+            } = op
+            {
+                if let Some(name) = self.get_term_name(op) {
+                    let str_loc = self.terms.len();
+
+                    self.terms.push(atom_as_cell!(name, 1));
+                    self.terms.push(arg1);
+                    self.terms.push(str_loc_as_cell!(str_loc));
 
-                    self.terms.push(term);
                     self.stack.push(TokenDesc {
-                        tt: TokenType::Term,
-                        priority: td.priority,
+                        tt: TokenType::Term {
+                            heap_loc: heap_loc_as_cell!(str_loc + 2),
+                        },
+                        priority: op.priority,
                         spec,
                         unfold_bounds: 0,
                     });
@@ -373,10 +441,12 @@ impl<'a, R: CharRead> Parser<'a, R> {
     }
 
     fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
-        self.terms
-            .push(Term::Literal(Cell::default(), Literal::Atom(atom)));
+        let h = self.terms.len();
+        self.terms.push(atom_as_cell!(atom));
         self.stack.push(TokenDesc {
-            tt: TokenType::Term,
+            tt: TokenType::Term {
+                heap_loc: heap_loc_as_cell!(h),
+            },
             priority,
             spec: assoc,
             unfold_bounds: 0,
@@ -384,45 +454,81 @@ impl<'a, R: CharRead> Parser<'a, R> {
     }
 
     fn shift(&mut self, token: Token, priority: usize, spec: Specifier) {
+        let heap_loc = heap_loc_as_cell!(self.terms.len());
+
         let tt = match token {
             Token::Literal(Literal::String(s))
                 if self.lexer.machine_st.flags.double_quotes.is_codes() =>
             {
-                let mut list = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
+                let mut list = empty_list_as_cell!();
 
                 for c in s.as_str().chars().rev() {
-                    list = Term::Cons(
-                        Cell::default(),
-                        Box::new(Term::Literal(
-                            Cell::default(),
-                            Literal::Fixnum(Fixnum::build_with(c as i64)),
-                        )),
-                        Box::new(list),
-                    );
+                    let h = self.terms.len();
+
+                    self.terms
+                        .push(fixnum_as_cell!(Fixnum::build_with(c as i64)));
+                    self.terms.push(list);
+
+                    list = list_loc_as_cell!(h);
                 }
 
                 self.terms.push(list);
-                TokenType::Term
+
+                TokenType::Term { heap_loc: list }
             }
             Token::Literal(Literal::String(s))
                 if self.lexer.machine_st.flags.double_quotes.is_chars() =>
             {
-                self.terms.push(Term::CompleteString(Cell::default(), s));
-                TokenType::Term
+                if s.is_empty() {
+                    self.terms.push(empty_list_as_cell!());
+                } else {
+                    self.terms.push(string_as_cstr_cell!(s));
+                }
+
+                TokenType::Term { heap_loc }
+            }
+            Token::Literal(Literal::Char(c)) => {
+                // soon this will be gone due to chars being folded
+                // into atoms
+                self.terms.push(atom_as_cell!(atomize_literal(
+                    &self.lexer.machine_st.atom_tbl,
+                    Literal::Char(c),
+                ).unwrap()));
+
+                TokenType::Term { heap_loc }
             }
             Token::Literal(c) => {
-                self.terms.push(Term::Literal(Cell::default(), c));
-                TokenType::Term
+                self.terms.push(HeapCellValue::from(c));
+                TokenType::Term { heap_loc }
             }
-            Token::Var(v) => {
-                if v.trim() == "_" {
-                    self.terms.push(Term::AnonVar);
-                } else {
-                    self.terms.push(Term::Var(Cell::default(), VarPtr::from(v)));
+            Token::Var(var_string) => match self.var_names_to_locs.get(&var_string).cloned() {
+                Some(heap_loc) => {
+                    let heap_idx = heap_loc.get_value() as usize;
+
+                    self.var_locs.push_at_key(heap_idx, VarPtr::from(var_string));
+                    self.terms.push(heap_loc);
+
+                    TokenType::Term { heap_loc }
                 }
+                None => {
+                    self.terms.push(heap_loc);
 
-                TokenType::Term
-            }
+                    if var_string.trim() != "_" {
+                        self.var_names_to_locs.insert(var_string.clone(), heap_loc);
+                    }
+
+                    self.var_locs.push_at_key(
+                        heap_loc.get_value() as usize,
+                        if var_string.trim() == "_" {
+                            VarPtr::from(Var::Anon)
+                        } else {
+                            VarPtr::from(var_string)
+                        },
+                    );
+
+                    TokenType::Term { heap_loc }
+                }
+            },
             Token::Comma => TokenType::Comma,
             Token::Open => TokenType::Open,
             Token::Close => TokenType::Close,
@@ -451,10 +557,10 @@ impl<'a, R: CharRead> Parser<'a, R> {
                         if is_xfx!(desc2.spec) && affirm_xfx(priority, desc2, desc3, desc1)
                             || is_yfx!(desc2.spec) && affirm_yfx(priority, desc2, desc3, desc1)
                         {
-                            self.push_binary_op(desc2, LTERM);
+                            self.push_binary_op(desc2, desc3, desc1, LTERM);
                             continue;
                         } else if is_xfy!(desc2.spec) && affirm_xfy(priority, desc2, desc3, desc1) {
-                            self.push_binary_op(desc2, TERM);
+                            self.push_binary_op(desc2, desc3, desc1, TERM);
                             continue;
                         } else {
                             self.stack.push(desc3);
@@ -462,16 +568,16 @@ impl<'a, R: CharRead> Parser<'a, R> {
                     }
 
                     if is_yf!(desc1.spec) && affirm_yf(desc1, desc2) {
-                        self.push_unary_op(desc1, LTERM, YF);
+                        self.push_unary_op(desc1, desc2, LTERM);
                         continue;
                     } else if is_xf!(desc1.spec) && affirm_xf(desc1, desc2) {
-                        self.push_unary_op(desc1, LTERM, XF);
+                        self.push_unary_op(desc1, desc2, LTERM);
                         continue;
                     } else if is_fy!(desc2.spec) && affirm_fy(priority, desc1, desc2) {
-                        self.push_unary_op(desc2, TERM, FY);
+                        self.push_unary_op(desc2, desc1, TERM);
                         continue;
                     } else if is_fx!(desc2.spec) && affirm_fx(priority, desc1, desc2) {
-                        self.push_unary_op(desc2, TERM, FX);
+                        self.push_unary_op(desc2, desc1, TERM);
                         continue;
                     } else {
                         self.stack.push(desc2);
@@ -515,6 +621,14 @@ impl<'a, R: CharRead> Parser<'a, R> {
         None
     }
 
+    fn term_from_stack(&self, idx: usize) -> Option<HeapCellValue> {
+        if let TokenType::Term { heap_loc } = self.stack[idx].tt {
+            Some(heap_loc)
+        } else {
+            None
+        }
+    }
+
     fn reduce_term(&mut self) -> bool {
         if self.stack.is_empty() {
             return false;
@@ -541,45 +655,77 @@ impl<'a, R: CharRead> Parser<'a, R> {
             return false;
         }
 
-        if self.terms.len() < 1 + arity {
+        if self.terms.len() < arity {
             return false;
         }
 
         let stack_len = self.stack.len() - 2 * arity - 1;
-        let idx = self.terms.len() - arity;
+        let term_idx = self.terms.len();
 
-        if TokenType::Term == self.stack[stack_len].tt
-            && atomize_term(&self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some()
-        {
-            self.stack.truncate(stack_len + 1);
+        let push_structure = |parser: &mut Self, name: Atom| -> TokenType {
+            parser.terms.push(atom_as_cell!(name, arity));
 
-            let mut subterms: Vec<_> = self.terms.drain(idx..).collect();
+            for idx in (stack_len + 2..parser.stack.len()).step_by(2) {
+                let subterm = parser.term_from_stack(idx).unwrap();
+                parser.terms.push(subterm);
+            }
 
-            if let Some(name) = self
-                .terms
-                .pop()
-                .and_then(|t| atomize_term(&self.lexer.machine_st.atom_tbl, &t))
-            {
+            let str_loc_idx = parser.terms.len();
+            parser.terms.push(str_loc_as_cell!(term_idx));
+
+            TokenType::Term {
+                heap_loc: heap_loc_as_cell!(str_loc_idx),
+            }
+        };
+
+        if let TokenDesc {
+            tt: TokenType::Term { heap_loc },
+            ..
+        } = self.stack[stack_len]
+        {
+            let idx = heap_loc.get_value() as usize;
+
+            if let Some(name) = term_name(&self.terms, idx) {
                 // reduce the '.' functor to a cons cell if it applies.
-                if name == atom!(".") && subterms.len() == 2 {
-                    let tail = subterms.pop().unwrap();
-                    let head = subterms.pop().unwrap();
+                let new_tt = if name == atom!(".") && arity == 2 {
+                    let head = self.term_from_stack(stack_len + 2).unwrap();
+                    let tail = self.term_from_stack(stack_len + 4).unwrap();
 
-                    self.terms.push(match as_partial_string(head, tail) {
-                        Ok((string_buf, Some(tail))) => {
-                            Term::PartialString(Cell::default(), string_buf, tail)
+                    match as_partial_string(&self.terms, head, tail) {
+                        Some((string_buf, Some(tail))) => {
+                            let atom =
+                                AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
+
+                            self.terms.push(string_as_pstr_cell!(atom));
+                            self.terms.push(tail);
+                            self.terms.push(pstr_loc_as_cell!(term_idx));
+
+                            TokenType::Term {
+                                heap_loc: heap_loc_as_cell!(term_idx + 2),
+                            }
                         }
-                        Ok((string_buf, None)) => {
+                        Some((string_buf, None)) => {
                             let atom =
                                 AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
-                            Term::CompleteString(Cell::default(), atom)
+                            TokenType::Term {
+                                heap_loc: string_as_cstr_cell!(atom),
+                            }
                         }
-                        Err(term) => term,
-                    });
+                        None => {
+                            self.terms.push(head);
+                            self.terms.push(tail);
+                            self.terms.push(list_loc_as_cell!(term_idx));
+
+                            TokenType::Term {
+                                heap_loc: heap_loc_as_cell!(term_idx + 2),
+                            }
+                        }
+                    }
                 } else {
-                    self.terms
-                        .push(Term::Clause(Cell::default(), name, subterms));
-                }
+                    push_structure(self, name)
+                };
+
+                self.stack.truncate(stack_len + 1);
 
                 if let Some(&mut TokenDesc {
                     ref mut tt,
@@ -592,38 +738,62 @@ impl<'a, R: CharRead> Parser<'a, R> {
                         return false;
                     }
 
-                    *tt = TokenType::Term;
+                    *tt = new_tt;
                     *priority = 0;
                     *spec = TERM;
                     *unfold_bounds = 0;
                 }
+            } else {
+                return false;
+            };
 
-                return true;
-            }
+            return true;
         }
 
         false
     }
 
     pub fn reset(&mut self) {
-        self.stack.clear()
+        self.stack.clear();
+        self.var_names_to_locs.clear();
     }
 
     fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
-        if let Some(mut term) = self.terms.pop() {
+        if let Some(term) = self.term_from_stack(index - 1) {
             let mut op_desc = self.stack[index - 1];
-
-            if 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
                  * terms it compacted out again. */
-                if let (Some(atom!(",")), 2) = (term.name(), term.arity()) {
+
+                let focus = term.get_value() as usize;
+                let name_opt = term_name(&self.terms, focus);
+                let arity = term_arity(&self.terms, focus);
+
+                if name_opt == Some(atom!(",")) && arity == 2 {
                     let terms = if op_desc.unfold_bounds == 0 {
-                        unfold_by_str(term, atom!(","))
+                        unfold_by_str(&mut self.terms, term, atom!(","))
                     } else {
                         let mut terms = vec![];
 
-                        while let Some((fst, snd)) = unfold_by_str_once(&mut 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);
+
                             terms.push(fst);
                             term = snd;
 
@@ -639,13 +809,17 @@ impl<'a, R: CharRead> Parser<'a, R> {
                     };
 
                     let arity = terms.len() - 1;
-
-                    self.terms.extend(terms);
+                    self.stack.extend(terms.into_iter().map(|heap_loc| {
+                        TokenDesc {
+                            tt: TokenType::Term { heap_loc },
+                            priority: 0,
+                            spec: 0,
+                            unfold_bounds: 0,
+                        }
+                    }));
                     return arity;
                 }
             }
-
-            self.terms.push(term);
         }
 
         0
@@ -685,13 +859,17 @@ impl<'a, R: CharRead> Parser<'a, R> {
         }
 
         if let Some(ref mut td) = self.stack.last_mut() {
+            // parsed an empty list token
             if td.tt == TokenType::OpenList {
+                let h = self.terms.len();
+                self.terms.push(empty_list_as_cell!());
+
                 td.spec = TERM;
-                td.tt = TokenType::Term;
+                td.tt = TokenType::Term {
+                    heap_loc: heap_loc_as_cell!(h),
+                };
                 td.priority = 0;
 
-                self.terms
-                    .push(Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))));
                 return Ok(true);
             }
         }
@@ -705,52 +883,105 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
         // we know that self.stack.len() >= 2 by this point.
         let idx = self.stack.len() - 2;
-        let list_len = self.stack.len() - 2 * arity;
+        let list_start_idx = self.stack.len() - 2 * arity;
 
-        let end_term = if self.stack[idx].tt != TokenType::HeadTailSeparator {
-            Term::Literal(Cell::default(), Literal::Atom(atom!("[]")))
+        let mut tail_term = if self.stack[idx].tt != TokenType::HeadTailSeparator {
+            empty_list_as_cell!()
         } else {
-            let term = match self.terms.pop() {
+            let tail_term = match self.term_from_stack(idx + 1) {
                 Some(term) => term,
-                _ => {
+                None => {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
-                    ))
+                        self.lexer.loc_to_err_src(),
+                    ));
                 }
             };
 
+            self.stack.pop();
+
             if self.stack[idx].priority > 1000 {
                 arity += self.expand_comma_compacted_terms(idx);
             }
 
+            // decrement for the removal of tail term.
             arity -= 1;
-
-            term
+            tail_term
         };
 
         if arity > self.terms.len() {
             return Err(ParserError::IncompleteReduction(
-                self.lexer.line_num,
-                self.lexer.col_num,
+                self.lexer.loc_to_err_src(),
             ));
         }
 
-        let idx = self.terms.len() - arity;
+        let pre_terms_len = self.terms.len();
 
-        let list = self.terms.drain(idx..).rev().fold(end_term, |acc, t| {
-            Term::Cons(Cell::default(), Box::new(t), Box::new(acc))
-        });
+        while let Some(token_desc) = self.stack.pop() {
+            let subterm = match token_desc.tt {
+                TokenType::Term { heap_loc } => {
+                    heap_loc
+                }
+                _ => {
+                    continue;
+                }
+            };
+
+            arity -= 1;
+
+            let link_cell = list_loc_as_cell!(self.terms.len() + 1);
+
+            self.terms.push(link_cell);
+            self.terms.push(subterm);
+            self.terms.push(tail_term);
+
+            tail_term = link_cell;
+
+            if arity == 0 {
+                break;
+            }
+        }
+
+        debug_assert_eq!(arity, 0);
+
+        self.stack.truncate(list_start_idx);
+
+        let list_loc = self.terms.len() - 3;
+
+        let head_term = self.terms[list_loc + 1];
+        let tail_term = self.terms[list_loc + 2];
+
+        let heap_loc = match as_partial_string(&self.terms, head_term, tail_term) {
+            Some((string_buf, Some(tail))) => {
+                self.terms.truncate(pre_terms_len);
 
-        self.stack.truncate(list_len);
+                let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
+
+                self.terms.push(string_as_pstr_cell!(atom));
+                self.terms.push(tail);
+                self.terms.push(pstr_loc_as_cell!(pre_terms_len));
+
+                heap_loc_as_cell!(pre_terms_len + 2)
+            }
+            Some((string_buf, None)) => {
+                self.terms.truncate(pre_terms_len);
+                let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
+                self.terms.push(string_as_cstr_cell!(atom));
+
+                heap_loc_as_cell!(pre_terms_len)
+            }
+            None => {
+                heap_loc_as_cell!(list_loc) // head_term
+            }
+        };
 
         self.stack.push(TokenDesc {
-            tt: TokenType::Term,
+            tt: TokenType::Term { heap_loc },
             priority: 0,
             spec: TERM,
             unfold_bounds: 0,
         });
 
+        /*
         self.terms.push(match list {
             Term::Cons(_, head, tail) => match as_partial_string(*head, *tail) {
                 Ok((string_buf, Some(tail))) => {
@@ -764,6 +995,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             },
             term => term,
         });
+        */
 
         Ok(true)
     }
@@ -775,13 +1007,15 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
         if let Some(ref mut td) = self.stack.last_mut() {
             if td.tt == TokenType::OpenCurly {
-                td.tt = TokenType::Term;
+                let h = self.terms.len();
+                self.terms.push(atom_as_cell!(atom!("{}")));
+
+                td.tt = TokenType::Term {
+                    heap_loc: heap_loc_as_cell!(h),
+                };
                 td.priority = 0;
                 td.spec = TERM;
 
-                let term = Term::Literal(Cell::default(), Literal::Atom(atom!("{}")));
-
-                self.terms.push(term);
                 return Ok(true);
             }
         }
@@ -791,29 +1025,41 @@ impl<'a, R: CharRead> Parser<'a, R> {
         if self.stack.len() > 1 {
             if let Some(td) = self.stack.pop() {
                 if let Some(ref mut oc) = self.stack.last_mut() {
-                    if td.tt != TokenType::Term {
+                    if !matches!(td.tt, TokenType::Term { .. }) {
                         return Ok(false);
                     }
 
                     if oc.tt == TokenType::OpenCurly {
-                        oc.tt = TokenType::Term;
-                        oc.priority = 0;
-                        oc.spec = TERM;
-
-                        let term = match self.terms.pop() {
-                            Some(term) => term,
-                            _ => {
-                                return Err(ParserError::IncompleteReduction(
-                                    self.lexer.line_num,
-                                    self.lexer.col_num,
-                                ))
-                            }
-                        };
-
-                        self.terms
-                            .push(Term::Clause(Cell::default(), atom!("{}"), vec![term]));
-
-                        return Ok(true);
+                        if let TokenType::Term { heap_loc } = td.tt {
+                            let curly_idx = self.terms.len();
+
+                            oc.tt = TokenType::Term {
+                                heap_loc: heap_loc_as_cell!(curly_idx + 2),
+                            };
+                            oc.priority = 0;
+                            oc.spec = TERM;
+
+                            self.terms.push(atom_as_cell!(atom!("{}"), 1));
+                            self.terms.push(heap_loc);
+                            self.terms.push(str_loc_as_cell!(curly_idx));
+
+                            /*
+                            let term = match self.terms.pop() {
+                                Some(term) => term,
+                                _ => {
+                                    return Err(ParserError::IncompleteReduction(
+                                        self.lexer.line_num,
+                                        self.lexer.col_num,
+                                    ))
+                                }
+                            };
+
+                            self.terms
+                                .push(Term::Clause(Cell::default(), atom!("{}"), vec![term]));
+                            */
+
+                            return Ok(true);
+                        }
                     }
                 }
             }
@@ -833,8 +1079,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
             return false;
         }
 
-        if let Some(TokenType::Open | TokenType::OpenCT) = self.stack.last().map(|token| token.tt) {
-            return false;
+        match self.stack.last().map(|token| token.tt) {
+            Some(TokenType::Open | TokenType::OpenCT) => return false,
+            _ => {}
         }
 
         let idx = self.stack.len() - 2;
@@ -846,13 +1093,16 @@ impl<'a, R: CharRead> Parser<'a, R> {
                     return false;
                 }
 
-                if let Some(atom) = self.sep_to_atom(self.stack[idx].tt) {
-                    self.terms
-                        .push(Term::Literal(Cell::default(), Literal::Atom(atom)));
-                }
+                let term = if self.stack[idx].tt.sep_to_atom().is_some() {
+                    atom_as_cell!(atom!("|"))
+                    // self.terms
+                    //     .push(Term::Literal(Cell::default(), Literal::Atom(atom)));
+                } else {
+                    self.term_from_stack(idx).unwrap()
+                };
 
                 self.stack[idx].spec = BTERM;
-                self.stack[idx].tt = TokenType::Term;
+                self.stack[idx].tt = TokenType::Term { heap_loc: term };
                 self.stack[idx].priority = 0;
 
                 true
@@ -870,7 +1120,11 @@ impl<'a, R: CharRead> Parser<'a, R> {
         }) = get_op_desc(name, op_dir)
         {
             if (pre > 0 && inf + post > 0) || is_negate!(spec) {
-                match self.tokens.last().ok_or(ParserError::unexpected_eof())? {
+                match self
+                    .tokens
+                    .last()
+                    .ok_or(ParserError::unexpected_eof(self.lexer.loc_to_err_src()))?
+                {
                     // do this when layout hasn't been inserted,
                     // ie. why we don't match on Token::Open.
                     Token::OpenCT => {
@@ -927,15 +1181,17 @@ impl<'a, R: CharRead> Parser<'a, R> {
         Negator: Fn(N, &mut Arena) -> N,
         ToLiteral: Fn(N, &mut Arena) -> Literal,
     {
-        if let Some(desc) = self.stack.last().cloned() {
-            if let Some(term) = self.terms.last().cloned() {
-                match term {
-                    Term::Literal(_, Literal::Atom(name))
-                        if name == atom!("-")
-                            && (is_prefix!(desc.spec) || is_negate!(desc.spec)) =>
-                    {
+        match self.stack.last().cloned() {
+            Some(
+                td @ TokenDesc {
+                    tt: TokenType::Term { .. },
+                    spec,
+                    ..
+                },
+            ) => {
+                if let Some(name) = self.get_term_name(td) {
+                    if name == atom!("-") && (is_prefix!(spec) || is_negate!(spec)) {
                         self.stack.pop();
-                        self.terms.pop();
 
                         let arena = &mut self.lexer.machine_st.arena;
                         let literal = constr(negator(n, arena), arena);
@@ -944,9 +1200,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
                         return;
                     }
-                    _ => {}
                 }
             }
+            _ => {}
         }
 
         let literal = constr(n, &mut self.lexer.machine_st.arena);
@@ -982,7 +1238,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 |n, arena| Literal::from(float_alloc!(n, arena)),
             ),
             Token::Literal(c) => {
-                let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
+                let atomized = atomize_literal(&self.lexer.machine_st.atom_tbl, c);
 
                 if let Some(name) = atomized {
                     if !self.shift_op(name, op_dir)? {
@@ -998,8 +1254,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             Token::Close => {
                 if !self.reduce_term() && !self.reduce_brackets() {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.loc_to_err_src(),
                     ));
                 }
             }
@@ -1007,8 +1262,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             Token::CloseList => {
                 if !self.reduce_list()? {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.loc_to_err_src(),
                     ));
                 }
             }
@@ -1016,8 +1270,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             Token::CloseCurly => {
                 if !self.reduce_curly()? {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.loc_to_err_src(),
                     ));
                 }
             }
@@ -1053,8 +1306,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 | Some(TokenType::HeadTailSeparator)
                 | Some(TokenType::Comma) => {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.loc_to_err_src(),
                     ))
                 }
                 _ => {}
@@ -1064,11 +1316,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
         Ok(())
     }
 
-    #[inline]
-    pub fn add_lines_read(&mut self, lines_read: usize) {
-        self.lexer.line_num += lines_read;
-    }
-
     #[inline]
     pub fn lines_read(&self) -> usize {
         self.lexer.line_num
@@ -1079,7 +1326,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
         &mut self,
         op_dir: &CompositeOpDir,
         tokens: Tokens,
-    ) -> Result<Term, ParserError> {
+    ) -> Result<FocusedHeap, ParserError> {
         self.tokens = match tokens {
             Tokens::Default => read_tokens(&mut self.lexer)?,
             Tokens::Provided(tokens) => tokens,
@@ -1091,27 +1338,23 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
         self.reduce_op(1400);
 
-        if self.terms.len() > 1 || self.stack.len() > 1 {
+        if self.stack.len() > 1 || self.terms.is_empty() {
             return Err(ParserError::IncompleteReduction(
-                self.lexer.line_num,
-                self.lexer.col_num,
+                self.lexer.loc_to_err_src(),
             ));
         }
 
-        match self.terms.pop() {
-            Some(term) => {
-                if self.terms.is_empty() {
-                    Ok(term)
-                } else {
-                    Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
-                    ))
-                }
-            }
+        match self.stack.pop() {
+            Some(TokenDesc {
+                tt: TokenType::Term { heap_loc },
+                ..
+            }) => Ok(FocusedHeap {
+                heap: mem::replace(&mut self.terms, vec![]),
+                focus: heap_loc.get_value() as usize,
+                var_locs: mem::replace(&mut self.var_locs, VarLocs::default()),
+            }),
             _ => Err(ParserError::IncompleteReduction(
-                self.lexer.line_num,
-                self.lexer.col_num,
+                self.lexer.loc_to_err_src(),
             )),
         }
     }
index da75741529e6147210000537978aeb1f7a01a7bf..9e3b4a7baff6f2d6a2cc23e859b59f12a6cc2051 100644 (file)
@@ -19,7 +19,7 @@ pub struct RawBlock<T: RawBlockTraits> {
 
 impl<T: RawBlockTraits> RawBlock<T> {
     #[inline]
-    fn empty_block() -> Self {
+    pub(crate) fn empty_block() -> Self {
         RawBlock {
             base: ptr::null(),
             top: ptr::null(),
index c13c02504f4dd86104b16b4b9b0bc777fb75a7b3..9759caf37b96b85663170241fdd2efe587e25bbd 100644 (file)
@@ -2,19 +2,12 @@ use crate::parser::ast::*;
 use crate::parser::parser::*;
 
 use crate::atom_table::*;
-use crate::forms::*;
-use crate::iterators::*;
-use crate::machine::heap::*;
 use crate::machine::machine_errors::*;
-use crate::machine::machine_indices::*;
-use crate::machine::machine_state::MachineState;
+use crate::machine::machine_state::{MachineState, copy_and_align_iter};
 use crate::machine::streams::*;
 use crate::parser::char_reader::*;
 #[cfg(feature = "repl")]
 use crate::repl_helper::Helper;
-use crate::types::*;
-
-use fxhash::FxBuildHasher;
 
 #[cfg(feature = "repl")]
 use rustyline::error::ReadlineError;
@@ -23,14 +16,11 @@ use rustyline::history::DefaultHistory;
 #[cfg(feature = "repl")]
 use rustyline::{Config, Editor};
 
-use std::collections::VecDeque;
 use std::io::{Cursor, Read};
 #[cfg(feature = "repl")]
 use std::io::{Error, ErrorKind};
 use std::sync::Arc;
 
-type SubtermDeque = VecDeque<(usize, usize)>;
-
 pub(crate) fn devour_whitespace<R: CharRead>(
     parser: &mut Parser<'_, R>,
 ) -> Result<bool, ParserError> {
@@ -41,46 +31,72 @@ pub(crate) fn devour_whitespace<R: CharRead>(
     }
 }
 
-pub(crate) fn error_after_read_term<R>(
+pub(crate) fn error_after_read_term(
     err: ParserError,
     prior_num_lines_read: usize,
-    parser: &Parser<R>,
 ) -> CompilationError {
     if err.is_unexpected_eof() {
-        let line_num = parser.lexer.line_num;
-        let col_num = parser.lexer.col_num;
+        let ParserErrorSrc { line_num, col_num } = err.err_src();
 
         // rough overlap with errors 8.14.1.3 k) & l) of the ISO standard here
         if !(line_num == prior_num_lines_read && col_num == 0) {
-            return CompilationError::from(ParserError::IncompleteReduction(line_num, col_num));
+            return CompilationError::from(ParserError::IncompleteReduction(err.err_src()));
         }
     }
 
     CompilationError::from(err)
 }
 
+impl FocusedHeap {
+    pub fn to_machine_heap(mut self, machine_st: &mut MachineState) -> TermWriteResult {
+        let heap_len = machine_st.heap.len();
+        machine_st.heap.extend(copy_and_align_iter(self.heap.drain(..), 0, heap_len as i64));
+
+        let mut var_locs = VarLocs::default();
+
+        for (var_loc, var_ptrs) in self.var_locs.drain(..) {
+            var_locs.insert(var_loc + heap_len, var_ptrs);
+        }
+
+        TermWriteResult {
+            heap_loc: self.focus + heap_len,
+            var_locs,
+        }
+    }
+}
+
 impl MachineState {
-    pub(crate) fn read(
+    pub(crate) fn read<R: CharRead>(
         &mut self,
-        mut inner: Stream,
+        inner: R,
         op_dir: &OpDir,
-    ) -> Result<TermWriteResult, CompilationError> {
-        let (term, num_lines_read) = {
-            let prior_num_lines_read = inner.lines_read();
-            let mut parser = Parser::new(inner, self);
-            let op_dir = CompositeOpDir::new(op_dir, None);
+    ) -> Result<(FocusedHeap, usize), ParserError> {
+        let mut parser = Parser::new(inner, self);
+        let op_dir = CompositeOpDir::new(op_dir, None);
 
-            parser.add_lines_read(prior_num_lines_read);
+        let term_result = parser.read_term(&op_dir, Tokens::Default);
+        let lines_read  = parser.lines_read();
 
-            let term = parser
-                .read_term(&op_dir, Tokens::Default)
-                .map_err(|err| error_after_read_term(err, prior_num_lines_read, &parser))?; // CompilationError::from
+        term_result.map(|term| (term, lines_read))
+    }
 
-            (term, parser.lines_read() - prior_num_lines_read)
+    pub(crate) fn read_to_heap(
+        &mut self,
+        mut inner: Stream,
+        op_dir: &OpDir,
+    ) -> Result<TermWriteResult, CompilationError> {
+        let prior_num_lines_read = inner.lines_read();
+        let term = match self.read(inner, op_dir) {
+            Ok((term, num_lines_read)) => {
+                inner.add_lines_read(num_lines_read);
+                term
+            }
+            Err(e) => {
+                return Err(error_after_read_term(e, prior_num_lines_read));
+            }
         };
 
-        inner.add_lines_read(num_lines_read);
-        write_term_to_heap(&term, &mut self.heap, &self.atom_tbl)
+        Ok(term.to_machine_heap(self))
     }
 }
 
@@ -279,7 +295,6 @@ impl CharRead for ReadlineStream {
             }
         }
     }
-
     #[inline]
     fn consume(&mut self, nread: usize) {
         self.pending_input.consume(nread);
@@ -291,199 +306,8 @@ impl CharRead for ReadlineStream {
     }
 }
 
-#[inline]
-pub(crate) fn write_term_to_heap(
-    term: &Term,
-    heap: &mut Heap,
-    atom_tbl: &AtomTable,
-) -> Result<TermWriteResult, CompilationError> {
-    let term_writer = TermWriter::new(heap, atom_tbl);
-    term_writer.write_term_to_heap(term)
-}
-
-#[derive(Debug)]
-struct TermWriter<'a, 'b> {
-    heap: &'a mut Heap,
-    atom_tbl: &'b AtomTable,
-    queue: SubtermDeque,
-    var_dict: HeapVarDict,
-}
-
 #[derive(Debug)]
 pub struct TermWriteResult {
     pub heap_loc: usize,
-    pub var_dict: HeapVarDict,
-}
-
-impl<'a, 'b> TermWriter<'a, 'b> {
-    #[inline]
-    fn new(heap: &'a mut Heap, atom_tbl: &'b AtomTable) -> Self {
-        TermWriter {
-            heap,
-            atom_tbl,
-            queue: SubtermDeque::new(),
-            var_dict: HeapVarDict::with_hasher(FxBuildHasher::default()),
-        }
-    }
-
-    #[inline]
-    fn modify_head_of_queue(&mut self, term: &TermRef, h: usize) {
-        if let Some((arity, site_h)) = self.queue.pop_front() {
-            self.heap[site_h] = self.term_as_addr(term, h);
-
-            if arity > 1 {
-                self.queue.push_front((arity - 1, site_h + 1));
-            }
-        }
-    }
-
-    #[inline]
-    fn push_stub_addr(&mut self) {
-        let h = self.heap.len();
-        self.heap.push(heap_loc_as_cell!(h));
-    }
-
-    fn term_as_addr(&mut self, term: &TermRef, h: usize) -> HeapCellValue {
-        match term {
-            &TermRef::Cons(..) => list_loc_as_cell!(h),
-            &TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h),
-            TermRef::CompleteString(_, _, src) => {
-                if src.as_str().is_empty() {
-                    empty_list_as_cell!()
-                } else if self.heap[h].get_tag() == HeapCellValueTag::CStr {
-                    heap_loc_as_cell!(h)
-                } else {
-                    pstr_loc_as_cell!(h)
-                }
-            }
-            &TermRef::PartialString(..) => pstr_loc_as_cell!(h),
-            &TermRef::Literal(_, _, literal) => HeapCellValue::from(*literal),
-            &TermRef::Clause(_, _, _, subterms) if subterms.is_empty() => heap_loc_as_cell!(h),
-            &TermRef::Clause(..) => str_loc_as_cell!(h),
-        }
-    }
-
-    fn write_term_to_heap(mut self, term: &Term) -> Result<TermWriteResult, CompilationError> {
-        let heap_loc = self.heap.len();
-
-        for term in breadth_first_iter(term, RootIterationPolicy::Iterated) {
-            let h = self.heap.len();
-
-            match &term {
-                &TermRef::Cons(Level::Root, ..) => {
-                    self.queue.push_back((2, h + 1));
-                    self.heap.push(list_loc_as_cell!(h + 1));
-
-                    self.push_stub_addr();
-                    self.push_stub_addr();
-
-                    continue;
-                }
-                &TermRef::Cons(..) => {
-                    self.queue.push_back((2, h));
-
-                    self.push_stub_addr();
-                    self.push_stub_addr();
-                }
-                &TermRef::Clause(Level::Root, _, name, subterms) => {
-                    if subterms.len() > MAX_ARITY {
-                        return Err(CompilationError::ExceededMaxArity);
-                    }
-
-                    self.heap.push(if subterms.is_empty() {
-                        heap_loc_as_cell!(heap_loc + 1)
-                    } else {
-                        str_loc_as_cell!(heap_loc + 1)
-                    });
-
-                    self.queue.push_back((subterms.len(), h + 2));
-                    let named = atom_as_cell!(name, subterms.len());
-
-                    self.heap.push(named);
-
-                    for _ in 0..subterms.len() {
-                        self.push_stub_addr();
-                    }
-
-                    continue;
-                }
-                &TermRef::Clause(_, _, name, subterms) => {
-                    self.queue.push_back((subterms.len(), h + 1));
-                    let named = atom_as_cell!(name, subterms.len());
-
-                    self.heap.push(named);
-
-                    for _ in 0..subterms.len() {
-                        self.push_stub_addr();
-                    }
-                }
-                &TermRef::AnonVar(Level::Root) | TermRef::Literal(Level::Root, ..) => {
-                    let addr = self.term_as_addr(&term, h);
-                    self.heap.push(addr);
-                }
-                &TermRef::Var(Level::Root, _, ref var_ptr) => {
-                    let addr = self.term_as_addr(&term, h);
-                    self.var_dict.insert(VarKey::VarPtr(var_ptr.clone()), addr);
-                    self.heap.push(addr);
-                }
-                &TermRef::AnonVar(_) => {
-                    if let Some((arity, site_h)) = self.queue.pop_front() {
-                        self.var_dict
-                            .insert(VarKey::AnonVar(h), heap_loc_as_cell!(site_h));
-
-                        if arity > 1 {
-                            self.queue.push_front((arity - 1, site_h + 1));
-                        }
-                    }
-
-                    continue;
-                }
-                TermRef::CompleteString(_, _, src) => {
-                    let src = src.as_str().to_owned();
-                    put_complete_string(self.heap, &src, self.atom_tbl);
-                }
-                &TermRef::PartialString(lvl, _, src, _) => {
-                    if let Level::Root = lvl {
-                        // Var tags can't refer directly to partial strings,
-                        // so a PStrLoc cell must be pushed.
-                        self.heap.push(pstr_loc_as_cell!(heap_loc + 1));
-                    }
-
-                    allocate_pstr(self.heap, src.as_str(), self.atom_tbl);
-
-                    let h = self.heap.len();
-                    self.queue.push_back((1, h - 1));
-
-                    if let Level::Root = lvl {
-                        continue;
-                    }
-                }
-                TermRef::Var(.., var) => {
-                    if let Some((arity, site_h)) = self.queue.pop_front() {
-                        let var_key = VarKey::VarPtr(var.clone());
-
-                        if let Some(addr) = self.var_dict.get(&var_key).cloned() {
-                            self.heap[site_h] = addr;
-                        } else {
-                            self.var_dict.insert(var_key, heap_loc_as_cell!(site_h));
-                        }
-
-                        if arity > 1 {
-                            self.queue.push_front((arity - 1, site_h + 1));
-                        }
-                    }
-
-                    continue;
-                }
-                _ => {}
-            };
-
-            self.modify_head_of_queue(&term, h);
-        }
-
-        Ok(TermWriteResult {
-            heap_loc,
-            var_dict: self.var_dict,
-        })
-    }
+    pub var_locs: VarLocs,
 }
index 4a1ce362fe120c62b0bd62d89dbf7b43808afc47..c2d7cde93b1b62e2a8894b3a73a890a059d8f003 100644 (file)
@@ -3,17 +3,12 @@ use crate::parser::ast::*;
 use crate::atom_table::*;
 use crate::forms::*;
 use crate::instructions::*;
-use crate::iterators::*;
 use crate::types::*;
 
 pub(crate) struct FactInstruction;
 pub(crate) struct QueryInstruction;
 
 pub(crate) trait CompilationTarget<'a> {
-    type Iterator: Iterator<Item = TermRef<'a>>;
-
-    fn iter(term: &'a Term) -> Self::Iterator;
-
     fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Instruction;
     fn to_list(lvl: Level, r: RegType) -> Instruction;
     fn to_structure(lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction;
@@ -41,12 +36,6 @@ pub(crate) trait CompilationTarget<'a> {
 }
 
 impl<'a> CompilationTarget<'a> for FactInstruction {
-    type Iterator = FactIterator<'a>;
-
-    fn iter(term: &'a Term) -> Self::Iterator {
-        breadth_first_iter(term, RootIterationPolicy::NotIterated)
-    }
-
     fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
         Instruction::GetConstant(lvl, HeapCellValue::from(constant), reg)
     }
@@ -115,12 +104,6 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
 }
 
 impl<'a> CompilationTarget<'a> for QueryInstruction {
-    type Iterator = QueryIterator<'a>;
-
-    fn iter(term: &'a Term) -> Self::Iterator {
-        post_order_iter(term)
-    }
-
     fn to_structure(_lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction {
         Instruction::PutStructure(name, arity, r)
     }
index a87fc22a99ed7f661ee1ab2e12edf4f23a944ddf..1a437413696dd21f6c1c7b0b570ddabf2dbd5848 100644 (file)
@@ -46,7 +46,7 @@ test_queries_on_builtins :-
     \+ float([1,2,_]),
     \+ (X is 3 rdiv 4, float(X)),
     \+ \+ (X is 3 rdiv 4, rational(X)),
-    \+ rational(3),
+    rational(3),
     \+ rational(f(_)),
     \+ rational("sdfa"),
     \+ rational(atom),
index b3546f4c8b0ec039871e39cce91a2345eaf05f89..528ded35882aa9e073bbca78090665ad5cfae989 100644 (file)
@@ -87,7 +87,7 @@ pub enum VarAlloc {
         safety: VarSafetyStatus,
         to_perm_var_num: Option<usize>,
     },
-    Perm(usize, PermVarAllocation), // stack offset, allocation info
+    Perm { reg: usize, allocation: PermVarAllocation }, // stack offset, allocation info
 }
 
 impl VarAlloc {
@@ -95,14 +95,14 @@ impl VarAlloc {
     pub(crate) fn as_reg_type(&self) -> RegType {
         match *self {
             VarAlloc::Temp { temp_reg, .. } => RegType::Temp(temp_reg),
-            VarAlloc::Perm(r, _) => RegType::Perm(r),
+            VarAlloc::Perm { reg, .. } => RegType::Perm(reg),
         }
     }
 
     #[inline]
     pub(crate) fn set_register(&mut self, reg_num: usize) {
         match self {
-            VarAlloc::Perm(ref mut p, _) => *p = reg_num,
+            VarAlloc::Perm { ref mut reg, .. } => *reg = reg_num,
             VarAlloc::Temp {
                 ref mut temp_reg, ..
             } => *temp_reg = reg_num,
@@ -151,7 +151,7 @@ pub struct VariableRecord {
 impl Default for VariableRecord {
     fn default() -> Self {
         VariableRecord {
-            allocation: VarAlloc::Perm(0, PermVarAllocation::Pending),
+            allocation: VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending },
             num_occurrences: 0,
             running_count: 0,
         }
index f0edd5d866c6fb529f8e19391e2d980e1ef96d57..a187f14d50d3d1340e427b06f8c03df065c9177c 100644 (file)
@@ -35,7 +35,7 @@ fn hello_world() {
 fn syntax_error() {
     load_module_test(
         "tests-pl/syntax_error.pl",
-        "   error(syntax_error(incomplete_reduction),read_term/3:6).\n",
+        "   error(syntax_error(incomplete_reduction),read_term/3:3).\n",
     );
 }