From 33d8abfed868f31e0b6d475c98f48d6c1bec318f Mon Sep 17 00:00:00 2001 From: bakaq Date: Sat, 12 Oct 2024 16:42:56 -0300 Subject: [PATCH] Remove parsed_results.rs --- src/lib.rs | 1 - src/machine/lib_machine.rs | 451 ++++++++++++++++++++++++++++++++-- src/machine/mod.rs | 3 - src/machine/parsed_results.rs | 438 --------------------------------- 4 files changed, 427 insertions(+), 466 deletions(-) delete mode 100644 src/machine/parsed_results.rs diff --git a/src/lib.rs b/src/lib.rs index 6148ef5c..9a7a797e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] diff --git a/src/machine/lib_machine.rs b/src/machine/lib_machine.rs index c4f168b6..ba1be14c 100644 --- a/src/machine/lib_machine.rs +++ b/src/machine/lib_machine.rs @@ -1,45 +1,448 @@ +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, - 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, + /// Residual goals. + /// + /// Can be empty. + residual_goals: Vec, + }, } -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), + /// A Prolog compound term. + Compound(String, Vec), + /// A Prolog variable. + Var(String), +} + +impl PrologTerm { + /// Creates an integer term. + pub fn integer(value: impl Into) -> Self { + PrologTerm::Integer(value.into()) + } + + /// Creates a rational term. + pub fn rational(value: impl Into) -> Self { + PrologTerm::Rational(value.into()) + } + + /// Creates a float term. + pub fn float(value: impl Into) -> Self { + PrologTerm::Float(value.into()) + } + + /// Creates an atom term. + pub fn atom(value: impl Into) -> 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) -> Self { + PrologTerm::String(value.into()) + } + + /// Creates a list term. + pub fn list(value: impl IntoIterator) -> Self { + PrologTerm::List(value.into_iter().collect()) + } + + /// Creates a compound term. + pub fn compound( + functor: impl Into, + args: impl IntoIterator, + ) -> Self { + PrologTerm::Compound(functor.into(), args.into_iter().collect()) + } + + /// Creates a variable. + pub fn variable(value: impl Into) -> Self { + PrologTerm::Var(value.into()) + } + + /// Creates a conjunction, giving the atom `true` if empty. + pub fn conjunction(value: impl IntoIterator) -> Self { + PrologTerm::try_conjunction(value).unwrap_or(PrologTerm::atom("true")) } + + /// Creates a conjunction, giving `None` if empty. + pub fn try_conjunction(value: impl IntoIterator) -> Option { + 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) -> Self { + PrologTerm::try_disjunction(value).unwrap_or(PrologTerm::atom("false")) + } + + /// Creates a disjunction, giving `None` if empty. + pub fn try_disjunction(value: impl IntoIterator) -> Option { + 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 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, + ) -> Self { + // Adapted from MachineState::read_term_from_heap + let mut term_stack = vec![]; + let iter = stackful_post_order_iter::( + &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::>().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::>().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::>().len() == 1 => { + // Handle lists of char as strings + elems.insert(0, a.chars().next().unwrap()); + PrologTerm::String(elems) + }, + _ => { + let mut elems: Vec = 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 = 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 = 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, + 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![], })) } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 7da19146..22c2a032 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -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 index 4791c777..00000000 --- a/src/machine/parsed_results.rs +++ /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, - /// Residual goals. - /// - /// Can be empty. - residual_goals: Vec, - }, -} - -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), - /// A Prolog atom. - Atom(String), - /// A Prolog string. - /// - /// In particular, this represents Prolog lists of characters. - String(String), - /// A Prolog list. - List(Vec), - /// A Prolog compound term. - Compound(String, Vec), - /// A Prolog variable. - Var(String), -} - -impl PrologTerm { - /// Creates an integer term. - pub fn integer(value: impl Into) -> Self { - PrologTerm::Integer(value.into()) - } - - /// Creates a rational term. - pub fn rational(value: impl Into) -> Self { - PrologTerm::Rational(value.into()) - } - - /// Creates a float term. - pub fn float(value: impl Into>) -> Self { - PrologTerm::Float(value.into()) - } - - /// Creates an atom term. - pub fn atom(value: impl Into) -> 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) -> Self { - PrologTerm::String(value.into()) - } - - /// Creates a list term. - pub fn list(value: impl IntoIterator) -> Self { - PrologTerm::List(value.into_iter().collect()) - } - - /// Creates a compound term. - pub fn compound( - functor: impl Into, - args: impl IntoIterator, - ) -> Self { - PrologTerm::Compound(functor.into(), args.into_iter().collect()) - } - - /// Creates a variable. - pub fn variable(value: impl Into) -> Self { - PrologTerm::Var(value.into()) - } - - /// Creates a conjunction, giving the atom `true` if empty. - pub fn conjunction(value: impl IntoIterator) -> Self { - PrologTerm::try_conjunction(value).unwrap_or(PrologTerm::atom("true")) - } - - /// Creates a conjunction, giving `None` if empty. - pub fn try_conjunction(value: impl IntoIterator) -> Option { - 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) -> Self { - PrologTerm::try_disjunction(value).unwrap_or(PrologTerm::atom("false")) - } - - /// Creates a disjunction, giving `None` if empty. - pub fn try_disjunction(value: impl IntoIterator) -> Option { - 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 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, - ) -> Self { - // Adapted from MachineState::read_term_from_heap - let mut term_stack = vec![]; - let iter = stackful_post_order_iter::( - &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::>().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::>().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::>().len() == 1 => { - // Handle lists of char as strings - elems.insert(0, a.chars().next().unwrap()); - PrologTerm::String(elems) - }, - _ => { - let mut elems: Vec = 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 = 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 = 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() - } -} -- 2.54.0