milestone marker for surgery
This commit is contained in:
@@ -1644,6 +1644,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::CallDeleteAllAttributesFromVar(_) |
|
&Instruction::CallDeleteAllAttributesFromVar(_) |
|
||||||
&Instruction::CallUnattributedVar(_) |
|
&Instruction::CallUnattributedVar(_) |
|
||||||
&Instruction::CallGetDBRefs(_) |
|
&Instruction::CallGetDBRefs(_) |
|
||||||
|
&Instruction::CallEnqueueAttributedVar(_) |
|
||||||
&Instruction::CallFetchGlobalVar(_) |
|
&Instruction::CallFetchGlobalVar(_) |
|
||||||
&Instruction::CallFirstStream(_) |
|
&Instruction::CallFirstStream(_) |
|
||||||
&Instruction::CallFlushOutput(_) |
|
&Instruction::CallFlushOutput(_) |
|
||||||
@@ -1866,6 +1867,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::ExecuteDeleteAllAttributesFromVar(_) |
|
&Instruction::ExecuteDeleteAllAttributesFromVar(_) |
|
||||||
&Instruction::ExecuteUnattributedVar(_) |
|
&Instruction::ExecuteUnattributedVar(_) |
|
||||||
&Instruction::ExecuteGetDBRefs(_) |
|
&Instruction::ExecuteGetDBRefs(_) |
|
||||||
|
&Instruction::ExecuteEnqueueAttributedVar(_) |
|
||||||
&Instruction::ExecuteFetchGlobalVar(_) |
|
&Instruction::ExecuteFetchGlobalVar(_) |
|
||||||
&Instruction::ExecuteFirstStream(_) |
|
&Instruction::ExecuteFirstStream(_) |
|
||||||
&Instruction::ExecuteFlushOutput(_) |
|
&Instruction::ExecuteFlushOutput(_) |
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ impl<'a> ArithInstructionIterator<'a> {
|
|||||||
2,
|
2,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Term::Var(cell, var) => TermIterState::Var(Level::Shallow, cell, var.clone()),
|
Term::Var(cell, var) => TermIterState::Var(Level::Shallow, cell, RcMutPtr::new(var)),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ArithInstructionIterator {
|
Ok(ArithInstructionIterator {
|
||||||
@@ -116,7 +116,7 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
}
|
}
|
||||||
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
|
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
|
||||||
TermIterState::Var(lvl, cell, var) => {
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
return Some(Ok(ArithTermRef::Var(lvl, cell, var.clone())));
|
return Some(Ok(ArithTermRef::Var(lvl, cell, var.owned())));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Some(Err(ArithmeticError::NonEvaluableFunctor(
|
return Some(Err(ArithmeticError::NonEvaluableFunctor(
|
||||||
|
|||||||
105
src/iterators.rs
105
src/iterators.rs
@@ -6,6 +6,8 @@ use crate::parser::ast::*;
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::iter::*;
|
use std::iter::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
@@ -35,6 +37,58 @@ impl<'a> TermRef<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) struct RcMutPtr<T: Debug> {
|
||||||
|
owned: Rc<T>,
|
||||||
|
ptr: *mut Rc<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Debug> RcMutPtr<T> {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn new(rc: &Rc<T>) -> Self {
|
||||||
|
Self { owned: rc.clone(), ptr: rc as *const _ as *mut _ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn owned(&self) -> Rc<T> {
|
||||||
|
self.owned.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn set(&mut self, var_b_marker: &Rc<T>) {
|
||||||
|
self.owned = var_b_marker.clone();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if !self.ptr.is_null() {
|
||||||
|
*self.ptr = self.owned.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Debug> From<T> for RcMutPtr<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(value: T) -> RcMutPtr<T> {
|
||||||
|
let owned = Rc::new(value);
|
||||||
|
RcMutPtr { owned, ptr: std::ptr::null_mut() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Debug + PartialEq> PartialEq for RcMutPtr<T> {
|
||||||
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
|
&self.owned == &rhs.owned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Debug + Eq> Eq for RcMutPtr<T> {}
|
||||||
|
|
||||||
|
impl<T: Debug + Hash> Hash for RcMutPtr<T> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||||
|
self.owned.hash(hasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum TermIterState<'a> {
|
pub(crate) enum TermIterState<'a> {
|
||||||
AnonVar(Level),
|
AnonVar(Level),
|
||||||
@@ -45,7 +99,7 @@ pub(crate) enum TermIterState<'a> {
|
|||||||
InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
|
InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
|
||||||
FinalPartialString(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),
|
CompleteString(Level, &'a Cell<RegType>, Atom),
|
||||||
Var(Level, &'a Cell<VarReg>, Rc<String>),
|
Var(Level, &'a Cell<VarReg>, RcMutPtr<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TermIterState<'a> {
|
impl<'a> TermIterState<'a> {
|
||||||
@@ -65,7 +119,7 @@ impl<'a> TermIterState<'a> {
|
|||||||
Term::CompleteString(cell, atom) => {
|
Term::CompleteString(cell, atom) => {
|
||||||
TermIterState::CompleteString(lvl, cell, *atom)
|
TermIterState::CompleteString(lvl, cell, *atom)
|
||||||
}
|
}
|
||||||
Term::Var(cell, var) => TermIterState::Var(lvl, cell, var.clone()),
|
Term::Var(cell, var) => TermIterState::Var(lvl, cell, RcMutPtr::new(var)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +160,7 @@ impl<'a> QueryIterator<'a> {
|
|||||||
*name,
|
*name,
|
||||||
terms,
|
terms,
|
||||||
),
|
),
|
||||||
Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, var.clone()),
|
Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, RcMutPtr::new(var)),
|
||||||
};
|
};
|
||||||
|
|
||||||
QueryIterator {
|
QueryIterator {
|
||||||
@@ -129,13 +183,13 @@ impl<'a> QueryIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&QueryTerm::UnblockedCut(ref cell) => {
|
&QueryTerm::UnblockedCut(ref cell) => {
|
||||||
let state = TermIterState::Var(Level::Root, cell, Rc::new("!".to_string()));
|
let state = TermIterState::Var(Level::Root, cell, RcMutPtr::from("!".to_string()));
|
||||||
QueryIterator {
|
QueryIterator {
|
||||||
state_stack: vec![state],
|
state_stack: vec![state],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
|
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
|
||||||
let state = TermIterState::Var(Level::Root, cell, var.clone());
|
let state = TermIterState::Var(Level::Root, cell, RcMutPtr::new(var));
|
||||||
QueryIterator {
|
QueryIterator {
|
||||||
state_stack: vec![state],
|
state_stack: vec![state],
|
||||||
}
|
}
|
||||||
@@ -213,7 +267,7 @@ impl<'a> Iterator for QueryIterator<'a> {
|
|||||||
return Some(TermRef::Literal(lvl, cell, constant));
|
return Some(TermRef::Literal(lvl, cell, constant));
|
||||||
}
|
}
|
||||||
TermIterState::Var(lvl, cell, var) => {
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
return Some(TermRef::Var(lvl, cell, var));
|
return Some(TermRef::Var(lvl, cell, var.owned()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -279,7 +333,7 @@ impl<'a> FactIterator<'a> {
|
|||||||
vec![TermIterState::Literal(Level::Root, cell, constant)]
|
vec![TermIterState::Literal(Level::Root, cell, constant)]
|
||||||
}
|
}
|
||||||
Term::Var(cell, var) => {
|
Term::Var(cell, var) => {
|
||||||
vec![TermIterState::Var(Level::Root, cell, var.clone())]
|
vec![TermIterState::Var(Level::Root, cell, RcMutPtr::new(var))]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -326,7 +380,7 @@ impl<'a> Iterator for FactIterator<'a> {
|
|||||||
return Some(TermRef::Literal(lvl, cell, constant))
|
return Some(TermRef::Literal(lvl, cell, constant))
|
||||||
}
|
}
|
||||||
TermIterState::Var(lvl, cell, var) => {
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
return Some(TermRef::Var(lvl, cell, var));
|
return Some(TermRef::Var(lvl, cell, var.owned()));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -530,38 +584,3 @@ impl<'a> Iterator for ChunkedIterator<'a> {
|
|||||||
self.iter.next().map(|term| self.take_chunk(term))
|
self.iter.next().map(|term| self.take_chunk(term))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
This is a disjunction compilation experiment attempting to
|
|
||||||
adapt the paper "Compiling Large Disjunctions" to Scryer Prolog.
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum VarInfo {
|
|
||||||
Perm,
|
|
||||||
Temp,
|
|
||||||
Void
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ChunkInfo {
|
|
||||||
chunk_num: usize,
|
|
||||||
vars: Vec<(Rc<Var>, VarInfo)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct BranchInfo {
|
|
||||||
branch_num: usize, // TODO: Rational?? or own type?
|
|
||||||
delta: usize, // TODO: Rational??
|
|
||||||
chunks: Vec<ChunkInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ControlIterator<'a> {
|
|
||||||
current_branch_num: usize, // TODO: same as above
|
|
||||||
state_stack: Vec<TermIterState<'a>>,
|
|
||||||
branch_map: IndexMap<Rc<Var>, Vec<BranchInfo>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ControlIterator {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ pub mod instructions {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/instructions.rs"));
|
include!(concat!(env!("OUT_DIR"), "/instructions.rs"));
|
||||||
}
|
}
|
||||||
mod iterators;
|
mod iterators;
|
||||||
|
mod disjuncts;
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
mod raw_block;
|
mod raw_block;
|
||||||
pub mod read;
|
pub mod read;
|
||||||
|
|||||||
@@ -5253,7 +5253,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
&Instruction::ExecuteUnattributedVar(_) => {
|
&Instruction::ExecuteUnattributedVar(_) => {
|
||||||
self.machine_st.unattributed_var();
|
self.machine_st.unattributed_var();
|
||||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
&Instruction::CallGetDBRefs(_) => {
|
&Instruction::CallGetDBRefs(_) => {
|
||||||
self.get_db_refs();
|
self.get_db_refs();
|
||||||
|
|||||||
@@ -465,6 +465,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Result<Term, SessionError> {
|
||||||
|
let machine_st = LS::machine_st(&mut self.payload);
|
||||||
|
machine_st.read_term_from_heap(r)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
|
pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
|
||||||
while let Some(decl) = self.dequeue_terms()? {
|
while let Some(decl) = self.dequeue_terms()? {
|
||||||
self.load_decl(decl)?;
|
self.load_decl(decl)?;
|
||||||
@@ -531,106 +536,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn read_term_from_heap(&mut self, heap_term_loc: RegType) -> Result<Term, SessionError> {
|
|
||||||
let machine_st = LS::machine_st(&mut self.payload);
|
|
||||||
let term_addr = machine_st[heap_term_loc];
|
|
||||||
|
|
||||||
let mut term_stack = vec![];
|
|
||||||
let mut iter = stackful_post_order_iter(&mut machine_st.heap, term_addr);
|
|
||||||
|
|
||||||
while let Some(addr) = iter.next() {
|
|
||||||
let addr = unmark_cell_bits!(addr);
|
|
||||||
|
|
||||||
read_heap_cell!(addr,
|
|
||||||
(HeapCellValueTag::Lis) => {
|
|
||||||
use crate::parser::parser::as_partial_string;
|
|
||||||
|
|
||||||
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 = machine_st.atom_tbl.build_with(&string);
|
|
||||||
term_stack.push(Term::CompleteString(Cell::default(), atom));
|
|
||||||
}
|
|
||||||
Err(cons_term) => term_stack.push(cons_term),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
|
|
||||||
let offset_string = format!("_{}", h);
|
|
||||||
term_stack.push(Term::Var(Cell::default(), Rc::new(offset_string)));
|
|
||||||
}
|
|
||||||
(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();
|
|
||||||
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);
|
|
||||||
Ok(term_stack.pop().unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset_machine(&mut self) {
|
fn reset_machine(&mut self) {
|
||||||
while let Some(record) = self.payload.retraction_info.records.pop() {
|
while let Some(record) = self.payload.retraction_info.records.pop() {
|
||||||
match record {
|
match record {
|
||||||
@@ -1143,7 +1048,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
r: RegType,
|
r: RegType,
|
||||||
) -> Result<IndexSet<ModuleExport>, SessionError> {
|
) -> Result<IndexSet<ModuleExport>, SessionError> {
|
||||||
let export_list = self.read_term_from_heap(r)?;
|
let machine_st = LS::machine_st(&mut self.payload);
|
||||||
|
|
||||||
|
let export_list = machine_st.read_term_from_heap(r)?;
|
||||||
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
|
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 = setup_module_export_list(export_list, atom_tbl)?;
|
||||||
|
|
||||||
@@ -1493,6 +1400,107 @@ impl<'a> MachinePreludeView<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MachineState {
|
||||||
|
pub(super) fn read_term_from_heap(&mut self, r: RegType) -> Result<Term, SessionError> {
|
||||||
|
let term_addr = self[r];
|
||||||
|
|
||||||
|
let mut term_stack = vec![];
|
||||||
|
let mut iter = stackful_post_order_iter(&mut self.heap, term_addr);
|
||||||
|
|
||||||
|
while let Some(addr) = iter.next() {
|
||||||
|
let addr = unmark_cell_bits!(addr);
|
||||||
|
|
||||||
|
read_heap_cell!(addr,
|
||||||
|
(HeapCellValueTag::Lis) => {
|
||||||
|
use crate::parser::parser::as_partial_string;
|
||||||
|
|
||||||
|
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 = self.atom_tbl.build_with(&string);
|
||||||
|
term_stack.push(Term::CompleteString(Cell::default(), atom));
|
||||||
|
}
|
||||||
|
Err(cons_term) => term_stack.push(cons_term),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
|
||||||
|
let offset_string = format!("_{}", h);
|
||||||
|
term_stack.push(Term::Var(Cell::default(), Rc::new(offset_string)));
|
||||||
|
}
|
||||||
|
(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();
|
||||||
|
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);
|
||||||
|
Ok(term_stack.pop().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub(crate) fn use_module(&mut self) -> CallResult {
|
pub(crate) fn use_module(&mut self) -> CallResult {
|
||||||
let subevacuable_addr = self
|
let subevacuable_addr = self
|
||||||
|
|||||||
@@ -667,3 +667,30 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
|
|||||||
terms.push(term);
|
terms.push(term);
|
||||||
terms
|
terms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unfold_by_str_ref_once(term: &Term, s: Atom) -> Option<(&Term, &Term)> {
|
||||||
|
if let Term::Clause(_, ref name, ref subterms) = term {
|
||||||
|
if name == &s && subterms.len() == 2 {
|
||||||
|
let fst = &subterms[0];
|
||||||
|
let snd = &subterms[1];
|
||||||
|
|
||||||
|
return Some((fst, snd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unfold_by_str_ref(mut term: &Term, s: Atom) -> Vec<&Term> {
|
||||||
|
let mut terms = vec![];
|
||||||
|
|
||||||
|
while let Some((fst, snd)) = unfold_by_str_ref_once(&term, s) {
|
||||||
|
terms.push(fst);
|
||||||
|
term = snd;
|
||||||
|
}
|
||||||
|
|
||||||
|
terms.push(term);
|
||||||
|
terms
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user