]> Repositorios git - scryer-prolog.git/commitdiff
Remove parsed_results.rs
authorbakaq <[email protected]>
Sat, 12 Oct 2024 19:42:56 +0000 (16:42 -0300)
committerbakaq <[email protected]>
Sun, 8 Dec 2024 23:18:06 +0000 (20:18 -0300)
src/lib.rs
src/machine/lib_machine.rs
src/machine/mod.rs
src/machine/parsed_results.rs [deleted file]

index 6148ef5c705cec555a366ea84a9c2d2b1b5d7784..9a7a797e044d0eccc8113a870952c921e344f0ae 100644 (file)
@@ -48,7 +48,6 @@ use wasm_bindgen::prelude::*;
 // Re-exports
 pub use machine::config::*;
 pub use machine::lib_machine::*;
-pub use machine::parsed_results::*;
 pub use machine::Machine;
 
 #[cfg(target_arch = "wasm32")]
index c4f168b6e06a88d7db737d795da583c1640afbb6..ba1be14cc53ce7b3f616ace5079856a8b60ec487 100644 (file)
+use std::cmp::Ordering;
 use std::collections::BTreeMap;
 
 use crate::atom_table;
+use crate::heap_iter::{stackful_post_order_iter, NonListElider};
 use crate::machine::machine_indices::VarKey;
 use crate::machine::mock_wam::CompositeOpDir;
-use crate::machine::{BREAK_FROM_DISPATCH_LOOP_LOC, LIB_QUERY_SUCCESS};
+use crate::machine::{
+    F64Offset, F64Ptr, Fixnum, Number, 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 dashu::{Integer, Rational};
 use indexmap::IndexMap;
 
-use super::{
-    streams::Stream, Atom, AtomCell, HeapCellValue, HeapCellValueTag, LeafAnswer, Machine,
-    PrologTerm,
-};
+use super::{streams::Stream, Atom, AtomCell, HeapCellValue, HeapCellValueTag, Machine};
 
-/// An iterator though the leaf answers of a query.
-pub struct QueryState<'a> {
-    machine: &'a mut Machine,
-    term: TermWriteResult,
-    stub_b: usize,
-    var_names: IndexMap<HeapCellValue, VarPtr>,
-    called: bool,
+/// Represents a leaf answer from a query.
+#[derive(Debug, Clone, PartialEq)]
+pub enum LeafAnswer {
+    /// A `true` leaf answer.
+    True,
+    /// A `false` leaf answer.
+    ///
+    /// This means that there are no more answers for the query.
+    False,
+    /// An exception leaf answer.
+    Exception(PrologTerm),
+    /// A leaf answer with bindings and residual goals.
+    LeafAnswer {
+        /// The bindings of variables in the query.
+        ///
+        /// Can be empty.
+        bindings: BTreeMap<String, PrologTerm>,
+        /// Residual goals.
+        ///
+        /// Can be empty.
+        residual_goals: Vec<PrologTerm>,
+    },
 }
 
-impl QueryState<'_> {
-    /// True if the query fails.
+impl LeafAnswer {
+    /// True if leaf answer failed.
     ///
-    /// Consumes the query. Gives [`false`] if an exception occurs.
-    pub fn fails(&mut self) -> bool {
-        todo!()
+    /// This gives [`false`] for exceptions.
+    pub fn failed(&self) -> bool {
+        matches!(self, LeafAnswer::False)
     }
 
-    /// True if the query maybe succeeded.
+    /// True if leaf answer may have succeeded.
     ///
-    /// If a leaf answer has residual goals, it's only successful if the constraints they represent
-    /// are satisfiable.
+    /// When a leaf answer has residual goals the success is conditional on the satisfiability of
+    /// the contraints they represent. This gives [`false`] for exceptions.
+    pub fn maybe_succeeded(&self) -> bool {
+        matches!(self, LeafAnswer::True | LeafAnswer::LeafAnswer { .. })
+    }
+}
+
+/// Represents a Prolog term.
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq)]
+pub enum PrologTerm {
+    /// An arbitrary precision integer.
+    Integer(Integer),
+    /// An arbitrary precision rational.
+    Rational(Rational),
+    /// A float.
+    Float(f64),
+    /// A Prolog atom.
+    Atom(String),
+    /// A Prolog string.
+    ///
+    /// In particular, this represents Prolog lists of characters.
+    String(String),
+    /// A Prolog list.
+    List(Vec<PrologTerm>),
+    /// A Prolog compound term.
+    Compound(String, Vec<PrologTerm>),
+    /// A Prolog variable.
+    Var(String),
+}
+
+impl PrologTerm {
+    /// Creates an integer term.
+    pub fn integer(value: impl Into<Integer>) -> Self {
+        PrologTerm::Integer(value.into())
+    }
+
+    /// Creates a rational term.
+    pub fn rational(value: impl Into<Rational>) -> Self {
+        PrologTerm::Rational(value.into())
+    }
+
+    /// Creates a float term.
+    pub fn float(value: impl Into<f64>) -> Self {
+        PrologTerm::Float(value.into())
+    }
+
+    /// Creates an atom term.
+    pub fn atom(value: impl Into<String>) -> Self {
+        PrologTerm::Atom(value.into())
+    }
+
+    /// Creates a string term.
     ///
-    /// Consumes the query. Gives [`false`] if an exception occurs.
-    pub fn maybe_suceeded() -> bool {
-        todo!()
+    /// In specific, this represents a list of chars in Prolog.
+    pub fn string(value: impl Into<String>) -> Self {
+        PrologTerm::String(value.into())
+    }
+
+    /// Creates a list term.
+    pub fn list(value: impl IntoIterator<Item = PrologTerm>) -> Self {
+        PrologTerm::List(value.into_iter().collect())
+    }
+
+    /// Creates a compound term.
+    pub fn compound(
+        functor: impl Into<String>,
+        args: impl IntoIterator<Item = PrologTerm>,
+    ) -> Self {
+        PrologTerm::Compound(functor.into(), args.into_iter().collect())
+    }
+
+    /// Creates a variable.
+    pub fn variable(value: impl Into<String>) -> Self {
+        PrologTerm::Var(value.into())
+    }
+
+    /// Creates a conjunction, giving the atom `true` if empty.
+    pub fn conjunction(value: impl IntoIterator<Item = PrologTerm>) -> Self {
+        PrologTerm::try_conjunction(value).unwrap_or(PrologTerm::atom("true"))
     }
+
+    /// Creates a conjunction, giving `None` if empty.
+    pub fn try_conjunction(value: impl IntoIterator<Item = PrologTerm>) -> Option<Self> {
+        let mut iter = value.into_iter();
+        iter.next().map(|first| {
+            PrologTerm::try_conjunction(iter)
+                .map(|rest| PrologTerm::compound(",", [first.clone(), rest]))
+                .unwrap_or(first)
+        })
+    }
+
+    /// Creates a disjunction, giving the atom `false` if empty.
+    pub fn disjunction(value: impl IntoIterator<Item = PrologTerm>) -> Self {
+        PrologTerm::try_disjunction(value).unwrap_or(PrologTerm::atom("false"))
+    }
+
+    /// Creates a disjunction, giving `None` if empty.
+    pub fn try_disjunction(value: impl IntoIterator<Item = PrologTerm>) -> Option<Self> {
+        let mut iter = value.into_iter();
+        iter.next().map(|first| {
+            PrologTerm::try_disjunction(iter)
+                .map(|rest| PrologTerm::compound(";", [first.clone(), rest]))
+                .unwrap_or(first)
+        })
+    }
+}
+
+impl From<LeafAnswer> for PrologTerm {
+    fn from(value: LeafAnswer) -> Self {
+        match value {
+            LeafAnswer::True => PrologTerm::atom("true"),
+            LeafAnswer::False => PrologTerm::atom("false"),
+            LeafAnswer::Exception(inner) => match inner.clone() {
+                PrologTerm::Compound(functor, args) if functor == "error" && args.len() == 2 => {
+                    inner
+                }
+                _ => PrologTerm::compound("throw", [inner]),
+            },
+            LeafAnswer::LeafAnswer {
+                bindings: _,
+                residual_goals: _,
+            } => {
+                todo!()
+            }
+        }
+    }
+}
+
+/// This is an auxiliary function to turn a count into names of anonymous variables like _A, _B,
+/// _AB, etc...
+fn count_to_letter_code(mut count: usize) -> String {
+    let mut letters = Vec::new();
+
+    loop {
+        let letter_idx = (count % 26) as u32;
+        letters.push(char::from_u32('A' as u32 + letter_idx).unwrap());
+        count /= 26;
+
+        if count == 0 {
+            break;
+        }
+    }
+
+    letters.into_iter().chain("_".chars()).rev().collect()
+}
+
+impl PrologTerm {
+    pub(crate) fn from_heapcell(
+        machine: &mut Machine,
+        heap_cell: HeapCellValue,
+        var_names: &mut IndexMap<HeapCellValue, VarPtr>,
+    ) -> Self {
+        // Adapted from MachineState::read_term_from_heap
+        let mut term_stack = vec![];
+        let iter = stackful_post_order_iter::<NonListElider>(
+            &mut machine.machine_st.heap,
+            &mut machine.machine_st.stack,
+            heap_cell,
+        );
+
+        let mut anon_count: usize = 0;
+        let var_ptr_cmp = |a, b| match a {
+            Var::Named(name_a) => match b {
+                Var::Named(name_b) => name_a.cmp(&name_b),
+                _ => Ordering::Less,
+            },
+            _ => match b {
+                Var::Named(_) => Ordering::Greater,
+                _ => Ordering::Equal,
+            },
+        };
+
+        for addr in iter {
+            let addr = unmark_cell_bits!(addr);
+
+            read_heap_cell!(addr,
+                (HeapCellValueTag::Lis) => {
+                    let tail = term_stack.pop().unwrap();
+                    let head = term_stack.pop().unwrap();
+
+                    let list = match tail {
+                        PrologTerm::Atom(atom) if atom == "[]" => match head {
+                            PrologTerm::Atom(ref a) if a.chars().collect::<Vec<_>>().len() == 1 => {
+                                // Handle lists of char as strings
+                                PrologTerm::String(a.to_string())
+                            }
+                            _ => PrologTerm::List(vec![head]),
+                        },
+                        PrologTerm::List(elems) if elems.is_empty() => match head {
+                            PrologTerm::Atom(ref a) if a.chars().collect::<Vec<_>>().len() == 1 => {
+                                // Handle lists of char as strings
+                                PrologTerm::String(a.to_string())
+                            },
+                            _ => PrologTerm::List(vec![head]),
+                        },
+                        PrologTerm::List(mut elems) => {
+                            elems.insert(0, head);
+                            PrologTerm::List(elems)
+                        },
+                        PrologTerm::String(mut elems) => match head {
+                            PrologTerm::Atom(ref a) if a.chars().collect::<Vec<_>>().len() == 1 => {
+                                // Handle lists of char as strings
+                                elems.insert(0, a.chars().next().unwrap());
+                                PrologTerm::String(elems)
+                            },
+                            _ => {
+                                let mut elems: Vec<PrologTerm> = elems
+                                    .chars()
+                                    .map(|x| PrologTerm::Atom(x.into()))
+                                    .collect();
+                                elems.insert(0, head);
+                                PrologTerm::List(elems)
+                            }
+                        },
+                        _ => {
+                            PrologTerm::Compound(".".into(), vec![head, tail])
+                        }
+                    };
+                    term_stack.push(list);
+                }
+                (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
+                    let var = var_names.get(&addr).map(|x| x.borrow().clone());
+                    match var {
+                        Some(Var::Named(name)) => term_stack.push(PrologTerm::Var(name)),
+                        _ => {
+                            let anon_name = loop {
+                                // Generate a name for the anonymous variable
+                                let anon_name = count_to_letter_code(anon_count);
+
+                                // Find if this name is already being used
+                                var_names.sort_by(|_, a, _, b| {
+                                    var_ptr_cmp(a.borrow().clone(), b.borrow().clone())
+                                });
+                                let binary_result = var_names.binary_search_by(|_,a| {
+                                    let var_ptr = Var::Named(anon_name.clone());
+                                    var_ptr_cmp(a.borrow().clone(), var_ptr.clone())
+                                });
+
+                                match binary_result {
+                                    Ok(_) => anon_count += 1, // Name already used
+                                    Err(_) => {
+                                        // Name not used, assign it to this variable
+                                        let var_ptr = VarPtr::from(Var::Named(anon_name.clone()));
+                                        var_names.insert(addr, var_ptr);
+                                        break anon_name;
+                                    },
+                                }
+                            };
+                            term_stack.push(PrologTerm::Var(anon_name));
+                        },
+                    }
+                }
+                (HeapCellValueTag::F64, f) => {
+                    term_stack.push(PrologTerm::Float((*f).into()));
+                }
+                (HeapCellValueTag::Char, c) => {
+                    term_stack.push(PrologTerm::Atom(c.into()));
+                }
+                (HeapCellValueTag::Fixnum, n) => {
+                    term_stack.push(PrologTerm::Integer(n.into()));
+                }
+                (HeapCellValueTag::Cons) => {
+                    match Number::try_from(addr) {
+                        Ok(Number::Integer(i)) => term_stack.push(PrologTerm::Integer((*i).clone())),
+                        Ok(Number::Rational(r)) => term_stack.push(PrologTerm::Rational((*r).clone())),
+                        _ => {}
+                    }
+                }
+                (HeapCellValueTag::CStr, s) => {
+                    term_stack.push(PrologTerm::String(s.as_str().to_string()));
+                }
+                (HeapCellValueTag::Atom, (name, arity)) => {
+                    //let h = iter.focus().value() as usize;
+                    //let mut arity = arity;
+
+                    // Not sure why/if this is needed.
+                    // Might find out with better testing later.
+                    /*
+                    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 {
+                        let atom_name = name.as_str().to_string();
+                        if atom_name == "[]" {
+                            term_stack.push(PrologTerm::List(vec![]));
+                        } else {
+                            term_stack.push(PrologTerm::Atom(atom_name));
+                        }
+                    } else {
+                        let subterms = term_stack
+                            .drain(term_stack.len() - arity ..)
+                            .collect();
+
+                        term_stack.push(PrologTerm::Compound(name.as_str().to_string(), subterms));
+                    }
+                }
+                (HeapCellValueTag::PStr, atom) => {
+                    let tail = term_stack.pop().unwrap();
+
+                    match tail {
+                        PrologTerm::Atom(atom) => {
+                            if atom == "[]" {
+                                term_stack.push(PrologTerm::String(atom.as_str().to_string()));
+                            }
+                        },
+                        PrologTerm::List(l) => {
+                            let mut list: Vec<PrologTerm> = atom
+                                .as_str()
+                                .to_string()
+                                .chars()
+                                .map(|x| PrologTerm::Atom(x.to_string()))
+                                .collect();
+                            list.extend(l.into_iter());
+                            term_stack.push(PrologTerm::List(list));
+                        },
+                        _ => {
+                            let mut list: Vec<PrologTerm> = atom
+                                .as_str()
+                                .to_string()
+                                .chars()
+                                .map(|x| PrologTerm::Atom(x.to_string()))
+                                .collect();
+
+                            let mut partial_list = PrologTerm::Compound(
+                                ".".into(),
+                                vec![
+                                    list.pop().unwrap(),
+                                    tail,
+                                ],
+                            );
+
+                            while let Some(last) = list.pop() {
+                                partial_list = PrologTerm::Compound(
+                                    ".".into(),
+                                    vec![
+                                        last,
+                                        partial_list,
+                                    ],
+                                );
+                            }
+
+                            term_stack.push(partial_list);
+                        }
+                    }
+                }
+                // I dont know if this is needed here.
+                /*
+                (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_eq!(term_stack.len(), 1);
+        term_stack.pop().unwrap()
+    }
+}
+
+/// An iterator though the leaf answers of a query.
+pub struct QueryState<'a> {
+    machine: &'a mut Machine,
+    term: TermWriteResult,
+    stub_b: usize,
+    var_names: IndexMap<HeapCellValue, VarPtr>,
+    called: bool,
 }
 
 impl Drop for QueryState<'_> {
@@ -159,7 +562,7 @@ impl Iterator for QueryState<'_> {
         self.machine.machine_st.backtrack();
 
         Some(Ok(LeafAnswer::LeafAnswer {
-            bindings: bindings,
+            bindings,
             residual_goals: vec![],
         }))
     }
index 7da191467544ef15d492a2eb2a5a00014378b39b..22c2a0322d7480b56a8df38cd082637f37866906 100644 (file)
@@ -20,7 +20,6 @@ pub mod machine_indices;
 pub mod machine_state;
 pub mod machine_state_impl;
 pub mod mock_wam;
-pub mod parsed_results;
 pub mod partial_string;
 pub mod preprocessor;
 pub mod stack;
@@ -62,8 +61,6 @@ use std::path::PathBuf;
 use std::sync::atomic::AtomicBool;
 use std::sync::OnceLock;
 
-use self::parsed_results::*;
-
 lazy_static! {
     pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
 }
diff --git a/src/machine/parsed_results.rs b/src/machine/parsed_results.rs
deleted file mode 100644 (file)
index 4791c77..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-use crate::atom_table::*;
-use crate::heap_iter::{stackful_post_order_iter, NonListElider};
-use crate::machine::{F64Offset, F64Ptr, Fixnum, HeapCellValueTag};
-use crate::parser::ast::{Var, VarPtr};
-use dashu::*;
-use indexmap::IndexMap;
-use ordered_float::OrderedFloat;
-use std::cmp::Ordering;
-use std::collections::BTreeMap;
-
-use super::Machine;
-use super::{HeapCellValue, Number};
-
-/// Represents a leaf answer from a query.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum LeafAnswer {
-    /// A `true` leaf answer.
-    True,
-    /// A `false` leaf answer.
-    ///
-    /// This means that there are no more answers for the query.
-    False,
-    /// An exception leaf answer.
-    Exception(PrologTerm),
-    /// A leaf answer with bindings and residual goals.
-    LeafAnswer {
-        /// The bindings of variables in the query.
-        ///
-        /// Can be empty.
-        bindings: BTreeMap<String, PrologTerm>,
-        /// Residual goals.
-        ///
-        /// Can be empty.
-        residual_goals: Vec<PrologTerm>,
-    },
-}
-
-impl LeafAnswer {
-    /// True if leaf answer failed.
-    ///
-    /// This gives [`false`] for exceptions.
-    pub fn failed(&self) -> bool {
-        match self {
-            LeafAnswer::False => true,
-            _ => false,
-        }
-    }
-
-    /// True if leaf answer may have succeeded.
-    ///
-    /// When a leaf answer has residual goals the success is conditional on the satisfiability of
-    /// the contraints they represent. This gives [`false`] for exceptions.
-    pub fn maybe_succeeded(&self) -> bool {
-        match self {
-            LeafAnswer::True => true,
-            LeafAnswer::LeafAnswer { .. } => true,
-            _ => false,
-        }
-    }
-}
-
-/// Represents a Prolog term.
-#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum PrologTerm {
-    /// An arbitrary precision integer.
-    Integer(Integer),
-    /// An arbitrary precision rational.
-    Rational(Rational),
-    /// A float.
-    Float(OrderedFloat<f64>),
-    /// A Prolog atom.
-    Atom(String),
-    /// A Prolog string.
-    ///
-    /// In particular, this represents Prolog lists of characters.
-    String(String),
-    /// A Prolog list.
-    List(Vec<PrologTerm>),
-    /// A Prolog compound term.
-    Compound(String, Vec<PrologTerm>),
-    /// A Prolog variable.
-    Var(String),
-}
-
-impl PrologTerm {
-    /// Creates an integer term.
-    pub fn integer(value: impl Into<Integer>) -> Self {
-        PrologTerm::Integer(value.into())
-    }
-
-    /// Creates a rational term.
-    pub fn rational(value: impl Into<Rational>) -> Self {
-        PrologTerm::Rational(value.into())
-    }
-
-    /// Creates a float term.
-    pub fn float(value: impl Into<OrderedFloat<f64>>) -> Self {
-        PrologTerm::Float(value.into())
-    }
-
-    /// Creates an atom term.
-    pub fn atom(value: impl Into<String>) -> Self {
-        PrologTerm::Atom(value.into())
-    }
-
-    /// Creates a string term.
-    ///
-    /// In specific, this represents a list of chars in Prolog.
-    pub fn string(value: impl Into<String>) -> Self {
-        PrologTerm::String(value.into())
-    }
-
-    /// Creates a list term.
-    pub fn list(value: impl IntoIterator<Item = PrologTerm>) -> Self {
-        PrologTerm::List(value.into_iter().collect())
-    }
-
-    /// Creates a compound term.
-    pub fn compound(
-        functor: impl Into<String>,
-        args: impl IntoIterator<Item = PrologTerm>,
-    ) -> Self {
-        PrologTerm::Compound(functor.into(), args.into_iter().collect())
-    }
-
-    /// Creates a variable.
-    pub fn variable(value: impl Into<String>) -> Self {
-        PrologTerm::Var(value.into())
-    }
-
-    /// Creates a conjunction, giving the atom `true` if empty.
-    pub fn conjunction(value: impl IntoIterator<Item = PrologTerm>) -> Self {
-        PrologTerm::try_conjunction(value).unwrap_or(PrologTerm::atom("true"))
-    }
-
-    /// Creates a conjunction, giving `None` if empty.
-    pub fn try_conjunction(value: impl IntoIterator<Item = PrologTerm>) -> Option<Self> {
-        let mut iter = value.into_iter();
-        iter.next().map(|first| {
-            PrologTerm::try_conjunction(iter)
-                .map(|rest| PrologTerm::compound(",", [first.clone(), rest]))
-                .unwrap_or(first)
-        })
-    }
-
-    /// Creates a disjunction, giving the atom `false` if empty.
-    pub fn disjunction(value: impl IntoIterator<Item = PrologTerm>) -> Self {
-        PrologTerm::try_disjunction(value).unwrap_or(PrologTerm::atom("false"))
-    }
-
-    /// Creates a disjunction, giving `None` if empty.
-    pub fn try_disjunction(value: impl IntoIterator<Item = PrologTerm>) -> Option<Self> {
-        let mut iter = value.into_iter();
-        iter.next().map(|first| {
-            PrologTerm::try_disjunction(iter)
-                .map(|rest| PrologTerm::compound(";", [first.clone(), rest]))
-                .unwrap_or(first)
-        })
-    }
-}
-
-impl From<LeafAnswer> for PrologTerm {
-    fn from(value: LeafAnswer) -> Self {
-        match value {
-            LeafAnswer::True => PrologTerm::atom("true"),
-            LeafAnswer::False => PrologTerm::atom("false"),
-            LeafAnswer::Exception(inner) => match inner.clone() {
-                PrologTerm::Compound(functor, args) if functor == "error" && args.len() == 2 => {
-                    inner
-                }
-                _ => PrologTerm::compound("throw", [inner]),
-            },
-            LeafAnswer::LeafAnswer {
-                bindings: _,
-                residual_goals: _,
-            } => {
-                todo!()
-            }
-        }
-    }
-}
-
-/// This is an auxiliary function to turn a count into names of anonymous variables like _A, _B,
-/// _AB, etc...
-fn count_to_letter_code(mut count: usize) -> String {
-    let mut letters = Vec::new();
-
-    loop {
-        let letter_idx = (count % 26) as u32;
-        letters.push(char::from_u32('A' as u32 + letter_idx).unwrap());
-        count /= 26;
-
-        if count == 0 {
-            break;
-        }
-    }
-
-    letters.into_iter().chain("_".chars()).rev().collect()
-}
-
-impl PrologTerm {
-    pub(crate) fn from_heapcell(
-        machine: &mut Machine,
-        heap_cell: HeapCellValue,
-        var_names: &mut IndexMap<HeapCellValue, VarPtr>,
-    ) -> Self {
-        // Adapted from MachineState::read_term_from_heap
-        let mut term_stack = vec![];
-        let iter = stackful_post_order_iter::<NonListElider>(
-            &mut machine.machine_st.heap,
-            &mut machine.machine_st.stack,
-            heap_cell,
-        );
-
-        let mut anon_count: usize = 0;
-        let var_ptr_cmp = |a, b| match a {
-            Var::Named(name_a) => match b {
-                Var::Named(name_b) => name_a.cmp(&name_b),
-                _ => Ordering::Less,
-            },
-            _ => match b {
-                Var::Named(_) => Ordering::Greater,
-                _ => Ordering::Equal,
-            },
-        };
-
-        for addr in iter {
-            let addr = unmark_cell_bits!(addr);
-
-            read_heap_cell!(addr,
-                (HeapCellValueTag::Lis) => {
-                    let tail = term_stack.pop().unwrap();
-                    let head = term_stack.pop().unwrap();
-
-                    let list = match tail {
-                        PrologTerm::Atom(atom) if atom == "[]" => match head {
-                            PrologTerm::Atom(ref a) if a.chars().collect::<Vec<_>>().len() == 1 => {
-                                // Handle lists of char as strings
-                                PrologTerm::String(a.to_string())
-                            }
-                            _ => PrologTerm::List(vec![head]),
-                        },
-                        PrologTerm::List(elems) if elems.is_empty() => match head {
-                            PrologTerm::Atom(ref a) if a.chars().collect::<Vec<_>>().len() == 1 => {
-                                // Handle lists of char as strings
-                                PrologTerm::String(a.to_string())
-                            },
-                            _ => PrologTerm::List(vec![head]),
-                        },
-                        PrologTerm::List(mut elems) => {
-                            elems.insert(0, head);
-                            PrologTerm::List(elems)
-                        },
-                        PrologTerm::String(mut elems) => match head {
-                            PrologTerm::Atom(ref a) if a.chars().collect::<Vec<_>>().len() == 1 => {
-                                // Handle lists of char as strings
-                                elems.insert(0, a.chars().next().unwrap());
-                                PrologTerm::String(elems)
-                            },
-                            _ => {
-                                let mut elems: Vec<PrologTerm> = elems
-                                    .chars()
-                                    .map(|x| PrologTerm::Atom(x.into()))
-                                    .collect();
-                                elems.insert(0, head);
-                                PrologTerm::List(elems)
-                            }
-                        },
-                        _ => {
-                            PrologTerm::Compound(".".into(), vec![head, tail])
-                        }
-                    };
-                    term_stack.push(list);
-                }
-                (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
-                    let var = var_names.get(&addr).map(|x| x.borrow().clone());
-                    match var {
-                        Some(Var::Named(name)) => term_stack.push(PrologTerm::Var(name)),
-                        _ => {
-                            let anon_name = loop {
-                                // Generate a name for the anonymous variable
-                                let anon_name = count_to_letter_code(anon_count);
-
-                                // Find if this name is already being used
-                                var_names.sort_by(|_, a, _, b| {
-                                    var_ptr_cmp(a.borrow().clone(), b.borrow().clone())
-                                });
-                                let binary_result = var_names.binary_search_by(|_,a| {
-                                    let var_ptr = Var::Named(anon_name.clone());
-                                    var_ptr_cmp(a.borrow().clone(), var_ptr.clone())
-                                });
-
-                                match binary_result {
-                                    Ok(_) => anon_count += 1, // Name already used
-                                    Err(_) => {
-                                        // Name not used, assign it to this variable
-                                        let var_ptr = VarPtr::from(Var::Named(anon_name.clone()));
-                                        var_names.insert(addr, var_ptr);
-                                        break anon_name;
-                                    },
-                                }
-                            };
-                            term_stack.push(PrologTerm::Var(anon_name));
-                        },
-                    }
-                }
-                (HeapCellValueTag::F64, f) => {
-                    term_stack.push(PrologTerm::Float(*f));
-                }
-                (HeapCellValueTag::Char, c) => {
-                    term_stack.push(PrologTerm::Atom(c.into()));
-                }
-                (HeapCellValueTag::Fixnum, n) => {
-                    term_stack.push(PrologTerm::Integer(n.into()));
-                }
-                (HeapCellValueTag::Cons) => {
-                    match Number::try_from(addr) {
-                        Ok(Number::Integer(i)) => term_stack.push(PrologTerm::Integer((*i).clone())),
-                        Ok(Number::Rational(r)) => term_stack.push(PrologTerm::Rational((*r).clone())),
-                        _ => {}
-                    }
-                }
-                (HeapCellValueTag::CStr, s) => {
-                    term_stack.push(PrologTerm::String(s.as_str().to_string()));
-                }
-                (HeapCellValueTag::Atom, (name, arity)) => {
-                    //let h = iter.focus().value() as usize;
-                    //let mut arity = arity;
-
-                    // Not sure why/if this is needed.
-                    // Might find out with better testing later.
-                    /*
-                    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 {
-                        let atom_name = name.as_str().to_string();
-                        if atom_name == "[]" {
-                            term_stack.push(PrologTerm::List(vec![]));
-                        } else {
-                            term_stack.push(PrologTerm::Atom(atom_name));
-                        }
-                    } else {
-                        let subterms = term_stack
-                            .drain(term_stack.len() - arity ..)
-                            .collect();
-
-                        term_stack.push(PrologTerm::Compound(name.as_str().to_string(), subterms));
-                    }
-                }
-                (HeapCellValueTag::PStr, atom) => {
-                    let tail = term_stack.pop().unwrap();
-
-                    match tail {
-                        PrologTerm::Atom(atom) => {
-                            if atom == "[]" {
-                                term_stack.push(PrologTerm::String(atom.as_str().to_string()));
-                            }
-                        },
-                        PrologTerm::List(l) => {
-                            let mut list: Vec<PrologTerm> = atom
-                                .as_str()
-                                .to_string()
-                                .chars()
-                                .map(|x| PrologTerm::Atom(x.to_string()))
-                                .collect();
-                            list.extend(l.into_iter());
-                            term_stack.push(PrologTerm::List(list));
-                        },
-                        _ => {
-                            let mut list: Vec<PrologTerm> = atom
-                                .as_str()
-                                .to_string()
-                                .chars()
-                                .map(|x| PrologTerm::Atom(x.to_string()))
-                                .collect();
-
-                            let mut partial_list = PrologTerm::Compound(
-                                ".".into(),
-                                vec![
-                                    list.pop().unwrap(),
-                                    tail,
-                                ],
-                            );
-
-                            while let Some(last) = list.pop() {
-                                partial_list = PrologTerm::Compound(
-                                    ".".into(),
-                                    vec![
-                                        last,
-                                        partial_list,
-                                    ],
-                                );
-                            }
-
-                            term_stack.push(partial_list);
-                        }
-                    }
-                }
-                // I dont know if this is needed here.
-                /*
-                (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_eq!(term_stack.len(), 1);
-        term_stack.pop().unwrap()
-    }
-}