; ClauseQualifier = Module
),
ClauseQualifier:'$clause'(Head, Body),
- '$get_clause_p'(Head, P, Module).
+ % ensure '$get_clause_p'/3 is not the last clause so it can
+ % recover the choice point of '$clause' if necessary.
+ '$get_clause_p'(Head, P, Module),
+ true.
call_retract(Head, Body, Name, Arity, Module) :-
findall(P, builtins:call_retract_helper(Head, Body, P, Module), Ps),
self.machine_st.heap.truncate(target_h);
+ // these registers don't need to be reset here and MUST
+ // NOT be (nor in indexed_try! trust_epilogue is an
+ // exception, see next paragraph)! oip could be reset
+ // without any adverse effects but iip is needed by
+ // get_clause_p to find the last executed clause/2 clause.
+
+ // trust_epilogue must reset these for the sake of
+ // subsequent predicates beginning with
+ // switch_to_term. get_clause_p copes by checking
+ // self.machine_st.b > self.machine.e: if true, it is safe
+ // to use self.machine_st.iip; if false, use the choice
+ // point left at the top of the stack by '$clause'
+ // (specifically its biip value).
+
// self.machine_st.oip = 0;
// self.machine_st.iip = 0;
} else {
self.machine_st.stack.truncate(b);
self.machine_st.heap.truncate(target_h);
- // these registers don't need to be reset here and MUST NOT be
- // (nor in indexed_try to trust_epilogue)! oip could be reset
- // without any adverse effects but iip is needed by
- // get_clause_p to find the last executed clause/2 clause.
-
- // self.machine_st.oip = 0;
- // self.machine_st.iip = 0;
+ self.machine_st.oip = 0;
+ self.machine_st.iip = 0;
}
#[inline(always)]
}
}
- /*
- fn try_term_to_query<'a, LS: LoadState<'a>>(
- &mut self,
- loader: &mut Loader<'a, LS>,
- terms: Vec<Term>,
- cut_context: CutContext,
- ) -> Result<TopLevel, CompilationError> {
- Ok(TopLevel::Query(self.setup_query(
- loader,
- terms,
- cut_context,
- )?))
- }
- */
-
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
}
}
}
-
- /*
- fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>, LS: LoadState<'a>>(
- &mut self,
- loader: &mut Loader<'a, LS>,
- terms: I,
- ) -> Result<VecDeque<TopLevel>, CompilationError> {
- let mut results = VecDeque::new();
-
- for term in terms.into_iter() {
- results.push_back(self.try_term_to_tl(loader, term)?);
- }
-
- Ok(results)
- }
- */
}
}
}
+ pub(crate) fn top(&self) -> usize {
+ unsafe {
+ (*self.buf.ptr.get()) as usize - self.buf.base as usize
+ }
+ }
+
pub(crate) fn allocate_or_frame(&mut self, num_cells: usize) -> usize {
let frame_size = OrFrame::size_of(num_cells);
CompilationTarget::Module(target) => target,
};
- let bp = self
+ let mut bp = self
.indices
.get_predicate_code_index(atom!("$clause"), 2, module_name)
.and_then(|idx| idx.local())
.unwrap();
- let p = self.machine_st.iip as usize;
-
macro_rules! extract_ptr {
($ptr: expr) => {
match $ptr {
};
}
- match &self.code[bp] {
- Instruction::IndexingCode(ref indexing_code) => {
- let indexing_code_ptr = match &indexing_code[0] {
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, c, _, s)) => {
- if key.1 > 0 {
- s
- } else {
- c
+ loop {
+ match &self.code[bp] {
+ Instruction::IndexingCode(ref indexing_code) => {
+ let indexing_code_ptr = match &indexing_code[0] {
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, c, _, s)) => {
+ if key.1 > 0 {
+ s
+ } else {
+ c
+ }
}
- }
- _ => {
- unreachable!()
- }
- };
+ _ => {
+ unreachable!()
+ }
+ };
- let boip = extract_ptr!(indexing_code_ptr);
+ let boip = extract_ptr!(indexing_code_ptr);
- let boip = match &indexing_code[boip] {
- IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
- boip + extract_ptr!(hm.get(&key).cloned().unwrap())
- }
- IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
- boip + extract_ptr!(hm.get(&Literal::Atom(key.0)).cloned().unwrap())
- }
- _ => boip,
- };
+ let boip = match &indexing_code[boip] {
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
+ boip + extract_ptr!(hm.get(&key).cloned().unwrap())
+ }
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
+ boip + extract_ptr!(hm.get(&Literal::Atom(key.0)).cloned().unwrap())
+ }
+ _ => boip,
+ };
- match &indexing_code[boip] {
- IndexingLine::IndexedChoice(indexed_choice) => {
- return (
- skeleton.core.clause_clause_locs[p],
- bp + indexed_choice[p].offset(),
- );
+ match &indexing_code[boip] {
+ IndexingLine::IndexedChoice(indexed_choice) => {
+ let p = if self.machine_st.b > self.machine_st.e {
+ // this means the last
+ // self.machine_st.iip value has yet
+ // to be overwritten by the Trust
+ // instruction. In this case, return
+ // it.
+ self.machine_st.iip as usize
+ } else {
+ // otherwise, read the '$clause'
+ // choicepoint from the top of the
+ // stack. this is very volatile in
+ // that it depends on '$clause'
+ // immediately preceding
+ // '$get_clause_p', which cannot be
+ // the last clause of the retract
+ // helper to delay deallocation of its
+ // environment frame.
+ let clause_b = self.machine_st.stack.top();
+ self.machine_st.stack.index_or_frame(clause_b).prelude.biip as usize
+ };
+
+ return (
+ skeleton.core.clause_clause_locs[p],
+ bp + indexed_choice[p].offset(),
+ );
+ }
+ _ => unreachable!(),
}
- _ => unreachable!(),
}
- }
- _ => {
- return (skeleton.core.clause_clause_locs[p], bp);
+ &Instruction::RevJmpBy(offset) => {
+ bp -= offset;
+ }
+ _ => {
+ return (skeleton.core.clause_clause_locs.back().cloned().unwrap(), bp);
+ }
}
}
}