From 46317c3a39a381af89ae3906637244212d800272 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 1 Sep 2022 17:03:00 -0600 Subject: [PATCH 01/40] begin adapting the techniques of "Compiling Large Disjunctions" --- src/iterators.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/iterators.rs b/src/iterators.rs index 62054b04..de091d4a 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -530,3 +530,38 @@ impl<'a> Iterator for ChunkedIterator<'a> { 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, VarInfo)>, +} + +pub struct BranchInfo { + branch_num: usize, // TODO: Rational?? or own type? + delta: usize, // TODO: Rational?? + chunks: Vec, +} + +pub struct ControlIterator<'a> { + current_branch_num: usize, // TODO: same as above + state_stack: Vec>, + branch_map: IndexMap, Vec>, +} + +impl ControlIterator { +} From d565f5901b5744fed571d9f7c33cea6220169743 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 27 Sep 2022 21:04:52 -0600 Subject: [PATCH 02/40] milestone marker for surgery --- build/instructions_template.rs | 2 + src/arithmetic.rs | 4 +- src/iterators.rs | 105 ++++++++++------- src/lib.rs | 1 + src/machine/dispatch.rs | 2 +- src/machine/loader.rs | 210 +++++++++++++++++---------------- src/parser/ast.rs | 27 +++++ 7 files changed, 204 insertions(+), 147 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index bec70e7e..a7ea3d21 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -1644,6 +1644,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::CallDeleteAllAttributesFromVar(_) | &Instruction::CallUnattributedVar(_) | &Instruction::CallGetDBRefs(_) | + &Instruction::CallEnqueueAttributedVar(_) | &Instruction::CallFetchGlobalVar(_) | &Instruction::CallFirstStream(_) | &Instruction::CallFlushOutput(_) | @@ -1866,6 +1867,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::ExecuteDeleteAllAttributesFromVar(_) | &Instruction::ExecuteUnattributedVar(_) | &Instruction::ExecuteGetDBRefs(_) | + &Instruction::ExecuteEnqueueAttributedVar(_) | &Instruction::ExecuteFetchGlobalVar(_) | &Instruction::ExecuteFirstStream(_) | &Instruction::ExecuteFlushOutput(_) | diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 0cbb1eab..fcfd9599 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -74,7 +74,7 @@ impl<'a> ArithInstructionIterator<'a> { 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 { @@ -116,7 +116,7 @@ impl<'a> Iterator for ArithInstructionIterator<'a> { } TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))), 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( diff --git a/src/iterators.rs b/src/iterators.rs index de091d4a..6bf92a5f 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -6,6 +6,8 @@ use crate::parser::ast::*; use std::cell::Cell; use std::collections::VecDeque; use std::fmt; +use std::fmt::Debug; +use std::hash::{Hash, Hasher}; use std::iter::*; use std::rc::Rc; use std::vec::Vec; @@ -35,6 +37,58 @@ impl<'a> TermRef<'a> { } } +#[derive(Clone, Debug)] +pub(crate) struct RcMutPtr { + owned: Rc, + ptr: *mut Rc, +} + +impl RcMutPtr { + #[inline] + pub(crate) fn new(rc: &Rc) -> Self { + Self { owned: rc.clone(), ptr: rc as *const _ as *mut _ } + } + + #[inline] + pub(crate) fn owned(&self) -> Rc { + self.owned.clone() + } + + #[inline] + pub(crate) fn set(&mut self, var_b_marker: &Rc) { + self.owned = var_b_marker.clone(); + + unsafe { + if !self.ptr.is_null() { + *self.ptr = self.owned.clone(); + } + } + } +} + +impl From for RcMutPtr { + #[inline] + fn from(value: T) -> RcMutPtr { + let owned = Rc::new(value); + RcMutPtr { owned, ptr: std::ptr::null_mut() } + } +} + +impl PartialEq for RcMutPtr { + fn eq(&self, rhs: &Self) -> bool { + &self.owned == &rhs.owned + } +} + +impl Eq for RcMutPtr {} + +impl Hash for RcMutPtr { + #[inline(always)] + fn hash(&self, hasher: &mut H) { + self.owned.hash(hasher) + } +} + #[derive(Debug)] pub(crate) enum TermIterState<'a> { AnonVar(Level), @@ -45,7 +99,7 @@ pub(crate) enum TermIterState<'a> { InitialPartialString(Level, &'a Cell, &'a String, &'a Box), FinalPartialString(Level, &'a Cell, &'a String, &'a Box), CompleteString(Level, &'a Cell, Atom), - Var(Level, &'a Cell, Rc), + Var(Level, &'a Cell, RcMutPtr), } impl<'a> TermIterState<'a> { @@ -65,7 +119,7 @@ impl<'a> TermIterState<'a> { Term::CompleteString(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, 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 { @@ -129,13 +183,13 @@ impl<'a> QueryIterator<'a> { } } &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 { state_stack: vec![state], } } &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 { state_stack: vec![state], } @@ -213,7 +267,7 @@ impl<'a> Iterator for QueryIterator<'a> { return Some(TermRef::Literal(lvl, cell, constant)); } 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)] } 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)) } 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)) } } - -/* -================================================================================ - -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, VarInfo)>, -} - -pub struct BranchInfo { - branch_num: usize, // TODO: Rational?? or own type? - delta: usize, // TODO: Rational?? - chunks: Vec, -} - -pub struct ControlIterator<'a> { - current_branch_num: usize, // TODO: same as above - state_stack: Vec>, - branch_map: IndexMap, Vec>, -} - -impl ControlIterator { -} diff --git a/src/lib.rs b/src/lib.rs index 45dc2385..b117ab16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ pub mod instructions { include!(concat!(env!("OUT_DIR"), "/instructions.rs")); } mod iterators; +mod disjuncts; pub mod machine; mod raw_block; pub mod read; diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 3067ecb9..04f39428 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -5253,7 +5253,7 @@ impl Machine { } &Instruction::ExecuteUnattributedVar(_) => { 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(_) => { self.get_db_refs(); diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 616fe7ee..f268c0f7 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -465,6 +465,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { } } + pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Result { + let machine_st = LS::machine_st(&mut self.payload); + machine_st.read_term_from_heap(r) + } + pub(crate) fn load(mut self) -> Result { while let Some(decl) = self.dequeue_terms()? { self.load_decl(decl)?; @@ -531,106 +536,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { Ok(()) } - pub(super) fn read_term_from_heap(&mut self, heap_term_loc: RegType) -> Result { - 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) { while let Some(record) = self.payload.retraction_info.records.pop() { match record { @@ -1143,7 +1048,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { &mut self, r: RegType, ) -> Result, 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 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 { + 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 { pub(crate) fn use_module(&mut self) -> CallResult { let subevacuable_addr = self diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 0933b11c..cf7bf946 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -667,3 +667,30 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec { terms.push(term); 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 +} + + From b9c9de522256f7ec2b56fd8c5e0348153fbb53b0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 4 Oct 2022 09:24:37 -0600 Subject: [PATCH 03/40] add classifications and occurrence counting --- src/allocator.rs | 11 ++-- src/arithmetic.rs | 11 ++-- src/codegen.rs | 19 +++--- src/debray_allocator.rs | 25 ++++---- src/fixtures.rs | 21 +++---- src/forms.rs | 5 +- src/heap_print.rs | 24 ++++--- src/iterators.rs | 110 ++++++++++++++------------------- src/machine/loader.rs | 4 +- src/machine/machine_indices.rs | 5 +- src/machine/machine_state.rs | 13 ++-- src/machine/preprocessor.rs | 7 +-- src/machine/system_calls.rs | 3 +- src/parser/ast.rs | 40 +++++++++++- src/parser/parser.rs | 3 +- 15 files changed, 153 insertions(+), 148 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 5be3aae1..76bdfb53 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -8,7 +8,6 @@ use crate::machine::machine_indices::*; use crate::targets::*; use std::cell::Cell; -use std::rc::Rc; pub(crate) trait Allocator { fn new() -> Self; @@ -30,7 +29,7 @@ pub(crate) trait Allocator { fn mark_reserved_var<'a, Target: CompilationTarget<'a>>( &mut self, - var_name: Rc, + var_name: Var, lvl: Level, cell: &'a Cell, term_loc: GenContext, @@ -41,7 +40,7 @@ pub(crate) trait Allocator { fn mark_var<'a, Target: CompilationTarget<'a>>( &mut self, - var_name: Rc, + var_name: Var, lvl: Level, cell: &'a Cell, context: GenContext, @@ -88,17 +87,17 @@ pub(crate) trait Allocator { perm_vs } - fn get(&self, var: Rc) -> RegType { + fn get(&self, var: Var) -> RegType { self.bindings() .get(&var) .map_or(temp_v!(0), |v| v.as_reg_type()) } - fn is_unbound(&self, var: Rc) -> bool { + fn is_unbound(&self, var: Var) -> bool { self.get(var).reg_num() == 0 } - fn record_register(&mut self, var: Rc, r: RegType) { + fn record_register(&mut self, var: Var, r: RegType) { match self.bindings_mut().get_mut(&var).unwrap() { &mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(), &mut VarData::Perm(ref mut s) => *s = r.reg_num(), diff --git a/src/arithmetic.rs b/src/arithmetic.rs index fcfd9599..94974a51 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -22,7 +22,6 @@ use std::convert::TryFrom; use std::f64; use std::num::FpCategory; use std::ops::Div; -use std::rc::Rc; use std::vec::Vec; #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -74,7 +73,7 @@ impl<'a> ArithInstructionIterator<'a> { 2, )) } - Term::Var(cell, var) => TermIterState::Var(Level::Shallow, cell, RcMutPtr::new(var)), + Term::Var(cell, var) => TermIterState::Var(Level::Shallow, cell, VarPtr::from(var)), }; Ok(ArithInstructionIterator { @@ -87,7 +86,7 @@ impl<'a> ArithInstructionIterator<'a> { pub(crate) enum ArithTermRef<'a> { Literal(&'a Literal), Op(Atom, usize), // name, arity. - Var(Level, &'a Cell, Rc), + Var(Level, &'a Cell, Var), } impl<'a> Iterator for ArithInstructionIterator<'a> { @@ -115,8 +114,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> { } } TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))), - TermIterState::Var(lvl, cell, var) => { - return Some(Ok(ArithTermRef::Var(lvl, cell, var.owned()))); + TermIterState::Var(lvl, cell, var_ref) => { + return Some(Ok(ArithTermRef::Var(lvl, cell, Var::from(var_ref)))); } _ => { return Some(Err(ArithmeticError::NonEvaluableFunctor( @@ -317,7 +316,7 @@ impl<'a> ArithmeticEvaluator<'a> { ArithTermRef::Var(lvl, cell, name) => { let r = if lvl == Level::Shallow { self.marker.mark_non_callable( - name.clone(), + name, arg, term_loc, cell, diff --git a/src/codegen.rs b/src/codegen.rs index 1aea58d2..a3fdc99b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -20,7 +20,6 @@ use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::collections::VecDeque; -use std::rc::Rc; #[derive(Debug)] pub(crate) struct ConjunctInfo<'a> { @@ -170,7 +169,7 @@ impl CodeGenSettings { pub(crate) struct CodeGenerator<'a> { pub(crate) atom_tbl: &'a mut AtomTable, marker: DebrayAllocator, - pub(crate) var_count: IndexMap, usize>, + pub(crate) var_count: IndexMap, settings: CodeGenSettings, pub(crate) skeleton: PredicateSkeleton, pub(crate) jmp_by_locs: Vec, @@ -180,7 +179,7 @@ pub(crate) struct CodeGenerator<'a> { impl DebrayAllocator { fn mark_var_in_non_callable( &mut self, - name: Rc, + name: Var, term_loc: GenContext, vr: &Cell, code: &mut Code, @@ -190,7 +189,7 @@ impl DebrayAllocator { } #[inline(always)] - pub(crate) fn get_binding(&self, name: &String) -> Option { + pub(crate) fn get_binding(&self, name: &Var) -> Option { match self.bindings().get(name) { Some(&VarData::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)), Some(&VarData::Perm(p)) if p != 0 => Some(RegType::Perm(p)), @@ -200,7 +199,7 @@ impl DebrayAllocator { pub(crate) fn mark_non_callable( &mut self, - name: Rc, + name: Var, arg: usize, term_loc: GenContext, vr: &Cell, @@ -299,7 +298,7 @@ impl<'b> CodeGenerator<'b> { } } - fn get_var_count(&self, var: &String) -> usize { + fn get_var_count(&self, var: &Var) -> usize { *self.var_count.get(var).unwrap() } @@ -320,7 +319,7 @@ impl<'b> CodeGenerator<'b> { fn deep_var_instr<'a, Target: crate::targets::CompilationTarget<'a>>( &mut self, cell: &'a Cell, - var: &Rc, + var: &Var, term_loc: GenContext, target: &mut Code, ) { @@ -429,7 +428,7 @@ impl<'b> CodeGenerator<'b> { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); target.push(Target::to_pstr(lvl, atom, cell.get(), false)); } - TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => { + TermRef::Var(lvl @ Level::Shallow, cell, var) if var.as_str() == Some("!") => { if self.marker.is_unbound(var.clone()) { if term_loc != GenContext::Head { self.marker.mark_reserved_var::( @@ -835,7 +834,7 @@ impl<'b> CodeGenerator<'b> { #[inline] fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &Cell) { - let r = self.marker.get(Rc::new(String::from("!"))); + let r = self.marker.get(Var::from("!")); cell.set(VarReg::Norm(r)); code.push(instr!("$set_cp", cell.get().norm(), 0)); } @@ -844,7 +843,7 @@ impl<'b> CodeGenerator<'b> { &mut self, code: &mut Code, cell: &Cell, - var: Rc, + var: Var, term_loc: GenContext, ) { let mut target = Code::new(); diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index e9cc73c7..73645929 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -14,28 +14,27 @@ use fxhash::FxBuildHasher; use std::cell::Cell; use std::collections::BTreeSet; -use std::rc::Rc; #[derive(Debug)] pub(crate) struct DebrayAllocator { - bindings: IndexMap, VarData, FxBuildHasher>, + bindings: IndexMap, arg_c: usize, temp_lb: usize, arity: usize, // 0 if not at head. - contents: IndexMap, FxBuildHasher>, + contents: IndexMap, in_use: BTreeSet, free_list: Vec, } impl DebrayAllocator { - fn is_curr_arg_distinct_from(&self, var: &String) -> bool { + fn is_curr_arg_distinct_from(&self, var: &Var) -> bool { match self.contents.get(&self.arg_c) { - Some(t_var) if **t_var != *var => true, + Some(t_var) if *t_var != *var => true, _ => false, } } - fn occurs_shallowly_in_head(&self, var: &String, r: usize) -> bool { + fn occurs_shallowly_in_head(&self, var: &Var, r: usize) -> bool { match self.bindings.get(var).unwrap() { &VarData::Temp(_, _, ref tvd) => tvd.use_set.contains(&(GenContext::Head, r)), _ => false, @@ -48,7 +47,7 @@ impl DebrayAllocator { in_use_range || self.in_use.contains(&r) } - fn alloc_with_cr(&self, var: &String) -> usize { + fn alloc_with_cr(&self, var: &Var) -> usize { match self.bindings.get(var) { Some(&VarData::Temp(_, _, ref tvd)) => { for &(_, reg) in tvd.use_set.iter() { @@ -74,7 +73,7 @@ impl DebrayAllocator { } } - fn alloc_with_ca(&self, var: &String) -> usize { + fn alloc_with_ca(&self, var: &Var) -> usize { match self.bindings.get(var) { Some(&VarData::Temp(_, _, ref tvd)) => { for &(_, reg) in tvd.use_set.iter() { @@ -102,7 +101,7 @@ impl DebrayAllocator { } } - fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(Rc, usize)> { + fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(Var, usize)> { // we want to allocate a register to the k^{th} parameter, par_k. // par_k may not be a temporary variable. let k = self.arg_c; @@ -154,7 +153,7 @@ impl DebrayAllocator { fn alloc_reg_to_var<'a, Target: CompilationTarget<'a>>( &mut self, - var: &String, + var: &Var, lvl: Level, term_loc: GenContext, target: &mut Vec, @@ -202,7 +201,7 @@ impl DebrayAllocator { final_index } - fn in_place(&self, var: &String, term_loc: GenContext, r: RegType, k: usize) -> bool { + fn in_place(&self, var: &Var, term_loc: GenContext, r: RegType, k: usize) -> bool { match term_loc { GenContext::Head if !r.is_perm() => r.reg_num() == k, _ => match self.bindings().get(var).unwrap() { @@ -293,7 +292,7 @@ impl Allocator for DebrayAllocator { fn mark_var<'a, Target: CompilationTarget<'a>>( &mut self, - var: Rc, + var: Var, lvl: Level, cell: &'a Cell, term_loc: GenContext, @@ -321,7 +320,7 @@ impl Allocator for DebrayAllocator { fn mark_reserved_var<'a, Target: CompilationTarget<'a>>( &mut self, - var: Rc, + var: Var, lvl: Level, cell: &'a Cell, term_loc: GenContext, diff --git a/src/fixtures.rs b/src/fixtures.rs index 65340da0..1433b092 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -9,7 +9,6 @@ use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::collections::BTreeSet; use std::mem::swap; -use std::rc::Rc; use std::vec::Vec; // labeled with chunk numbers. @@ -84,8 +83,8 @@ type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); #[derive(Debug)] pub(crate) struct VariableFixtures<'a> { - perm_vars: IndexMap, VariableFixture<'a>>, - last_chunk_temp_vars: IndexSet>, + perm_vars: IndexMap>, + last_chunk_temp_vars: IndexSet, } impl<'a> VariableFixtures<'a> { @@ -96,11 +95,11 @@ impl<'a> VariableFixtures<'a> { } } - pub(crate) fn insert(&mut self, var: Rc, vs: VariableFixture<'a>) { + pub(crate) fn insert(&mut self, var: Var, vs: VariableFixture<'a>) { self.perm_vars.insert(var, vs); } - pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Rc) { + pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Var) { self.last_chunk_temp_vars.insert(var); } @@ -115,7 +114,7 @@ impl<'a> VariableFixtures<'a> { // Compute the conflict set of u. // 1. - let mut use_sets: IndexMap, OccurrenceSet> = IndexMap::new(); + let mut use_sets: IndexMap = IndexMap::new(); for (var, &mut (ref mut var_status, _)) in self.iter_mut() { if let &mut VarStatus::Temp(_, ref mut var_data) = var_status { @@ -132,7 +131,7 @@ impl<'a> VariableFixtures<'a> { if let GenContext::Last(cn_u) = term_loc { for (ref t, &mut (ref mut var_status, _)) in self.iter_mut() { if let &mut VarStatus::Temp(cn_t, ref mut t_data) = var_status { - if cn_u == cn_t && *u != ***t { + if cn_u == cn_t && u != **t { if !t_data.uses_reg(reg) { t_data.no_use_set.insert(reg); } @@ -153,11 +152,11 @@ impl<'a> VariableFixtures<'a> { } } - fn get_mut(&mut self, u: Rc) -> Option<&mut VariableFixture<'a>> { + fn get_mut(&mut self, u: Var) -> Option<&mut VariableFixture<'a>> { self.perm_vars.get_mut(&u) } - fn iter_mut(&mut self) -> indexmap::map::IterMut, VariableFixture<'a>> { + fn iter_mut(&mut self) -> indexmap::map::IterMut> { self.perm_vars.iter_mut() } @@ -218,11 +217,11 @@ impl<'a> VariableFixtures<'a> { } } - pub(crate) fn into_iter(self) -> indexmap::map::IntoIter, VariableFixture<'a>> { + pub(crate) fn into_iter(self) -> indexmap::map::IntoIter> { self.perm_vars.into_iter() } - fn values(&self) -> indexmap::map::Values, VariableFixture<'a>> { + fn values(&self) -> indexmap::map::Values> { self.perm_vars.values() } diff --git a/src/forms.rs b/src/forms.rs index 1c014587..9db69581 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -21,7 +21,6 @@ use std::convert::TryFrom; use std::fmt; use std::ops::AddAssign; use std::path::PathBuf; -use std::rc::Rc; use crate::{is_infix, is_postfix}; @@ -85,8 +84,8 @@ pub enum QueryTerm { Clause(Cell, ClauseType, Vec, CallPolicy), BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. UnblockedCut(Cell), - GetLevelAndUnify(Cell, Rc), - Jump(JumpStub), + GetLevelAndUnify(Cell, Var), + Jump(JumpStub), // SOON: Branch(Vec), } impl QueryTerm { diff --git a/src/heap_print.rs b/src/heap_print.rs index 54f52cd6..d09211d1 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -472,7 +472,7 @@ pub struct HCPrinter<'a, Outputter> { state_stack: Vec, toplevel_spec: Option, last_item_idx: usize, - pub var_names: IndexMap>, + pub var_names: IndexMap, pub numbervars_offset: Integer, pub numbervars: bool, pub quoted: bool, @@ -803,7 +803,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { if let Some(var) = self.var_names.get(&addr) { read_heap_cell!(addr, (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { - return Some(format!("{}", var.as_str())); + return Some(var.to_string()); } _ => { self.iter.push_stack(h); @@ -847,10 +847,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { // short-circuits handle_heap_term. // self.iter.pop_stack(); - let var_str = var.as_str(); + let var_str = var.to_string(); - push_space_if_amb!(self, var_str, { - append_str!(self, var_str); + push_space_if_amb!(self, &var_str, { + append_str!(self, &var_str); }); None @@ -862,8 +862,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { Some(var) => { // If the term is bound to a named variable, // print the variable's name to output. - push_space_if_amb!(self, &var, { - append_str!(self, &var); + let var_str = var.to_string(); + + push_space_if_amb!(self, &var_str, { + append_str!(self, &var_str); }); } None => { @@ -1715,9 +1717,7 @@ mod tests { heap_loc_as_cell!(0) ); - printer - .var_names - .insert(list_loc_as_cell!(1), Rc::new("L".to_string())); + printer.var_names.insert(list_loc_as_cell!(1), Var::from("L")); let output = printer.print(); @@ -1778,9 +1778,7 @@ mod tests { heap_loc_as_cell!(0) ); - printer - .var_names - .insert(list_loc_as_cell!(1), Rc::new("L".to_string())); + printer.var_names.insert(list_loc_as_cell!(1), Var::from("L")); let output = printer.print(); diff --git a/src/iterators.rs b/src/iterators.rs index 6bf92a5f..ac87a451 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -7,11 +7,40 @@ use std::cell::Cell; use std::collections::VecDeque; use std::fmt; use std::fmt::Debug; -use std::hash::{Hash, Hasher}; +use std::hash::{Hash}; use std::iter::*; -use std::rc::Rc; use std::vec::Vec; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub(crate) struct VarPtr { + ptr: std::ptr::NonNull, +} + +impl From<&Var> for VarPtr { + #[inline] + fn from(value: &Var) -> VarPtr { + unsafe { + VarPtr { ptr: std::ptr::NonNull::new_unchecked(value as *const _ as *mut _) } + } + } +} + +impl From for Var { + #[inline] + fn from(value: VarPtr) -> Var { + unsafe { + (*value.ptr.as_ptr()).clone() + } + } +} + +impl VarPtr { + pub(crate) fn set(&mut self, value: Var) { + unsafe { *self.ptr.as_mut() = value; } + } +} + + #[derive(Debug, Clone)] pub(crate) enum TermRef<'a> { AnonVar(Level), @@ -20,7 +49,7 @@ pub(crate) enum TermRef<'a> { Clause(Level, &'a Cell, Atom, &'a Vec), PartialString(Level, &'a Cell, &'a String, &'a Box), CompleteString(Level, &'a Cell, Atom), - Var(Level, &'a Cell, Rc), + Var(Level, &'a Cell, Var), } impl<'a> TermRef<'a> { @@ -37,58 +66,6 @@ impl<'a> TermRef<'a> { } } -#[derive(Clone, Debug)] -pub(crate) struct RcMutPtr { - owned: Rc, - ptr: *mut Rc, -} - -impl RcMutPtr { - #[inline] - pub(crate) fn new(rc: &Rc) -> Self { - Self { owned: rc.clone(), ptr: rc as *const _ as *mut _ } - } - - #[inline] - pub(crate) fn owned(&self) -> Rc { - self.owned.clone() - } - - #[inline] - pub(crate) fn set(&mut self, var_b_marker: &Rc) { - self.owned = var_b_marker.clone(); - - unsafe { - if !self.ptr.is_null() { - *self.ptr = self.owned.clone(); - } - } - } -} - -impl From for RcMutPtr { - #[inline] - fn from(value: T) -> RcMutPtr { - let owned = Rc::new(value); - RcMutPtr { owned, ptr: std::ptr::null_mut() } - } -} - -impl PartialEq for RcMutPtr { - fn eq(&self, rhs: &Self) -> bool { - &self.owned == &rhs.owned - } -} - -impl Eq for RcMutPtr {} - -impl Hash for RcMutPtr { - #[inline(always)] - fn hash(&self, hasher: &mut H) { - self.owned.hash(hasher) - } -} - #[derive(Debug)] pub(crate) enum TermIterState<'a> { AnonVar(Level), @@ -99,7 +76,8 @@ pub(crate) enum TermIterState<'a> { InitialPartialString(Level, &'a Cell, &'a String, &'a Box), FinalPartialString(Level, &'a Cell, &'a String, &'a Box), CompleteString(Level, &'a Cell, Atom), - Var(Level, &'a Cell, RcMutPtr), + UnblockedCut(Level, &'a Cell), + Var(Level, &'a Cell, VarPtr), } impl<'a> TermIterState<'a> { @@ -119,7 +97,7 @@ impl<'a> TermIterState<'a> { Term::CompleteString(cell, atom) => { TermIterState::CompleteString(lvl, cell, *atom) } - Term::Var(cell, var) => TermIterState::Var(lvl, cell, RcMutPtr::new(var)), + Term::Var(cell, var) => TermIterState::Var(lvl, cell, VarPtr::from(var)), } } } @@ -160,7 +138,7 @@ impl<'a> QueryIterator<'a> { *name, terms, ), - Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, RcMutPtr::new(var)), + Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, VarPtr::from(var)), }; QueryIterator { @@ -183,13 +161,14 @@ impl<'a> QueryIterator<'a> { } } &QueryTerm::UnblockedCut(ref cell) => { - let state = TermIterState::Var(Level::Root, cell, RcMutPtr::from("!".to_string())); + let state = TermIterState::UnblockedCut(Level::Root, cell); + QueryIterator { state_stack: vec![state], } } &QueryTerm::GetLevelAndUnify(ref cell, ref var) => { - let state = TermIterState::Var(Level::Root, cell, RcMutPtr::new(var)); + let state = TermIterState::Var(Level::Root, cell, VarPtr::from(var)); QueryIterator { state_stack: vec![state], } @@ -267,7 +246,10 @@ impl<'a> Iterator for QueryIterator<'a> { return Some(TermRef::Literal(lvl, cell, constant)); } TermIterState::Var(lvl, cell, var) => { - return Some(TermRef::Var(lvl, cell, var.owned())); + return Some(TermRef::Var(lvl, cell, Var::from(var))); + } + TermIterState::UnblockedCut(lvl, cell) => { + return Some(TermRef::Var(lvl, cell, Var::from("!"))); } }; } @@ -333,7 +315,7 @@ impl<'a> FactIterator<'a> { vec![TermIterState::Literal(Level::Root, cell, constant)] } Term::Var(cell, var) => { - vec![TermIterState::Var(Level::Root, cell, RcMutPtr::new(var))] + vec![TermIterState::Var(Level::Root, cell, VarPtr::from(var))] } }; @@ -380,7 +362,7 @@ impl<'a> Iterator for FactIterator<'a> { return Some(TermRef::Literal(lvl, cell, constant)) } TermIterState::Var(lvl, cell, var) => { - return Some(TermRef::Var(lvl, cell, var.owned())); + return Some(TermRef::Var(lvl, cell, Var::from(var))); } _ => {} } @@ -420,7 +402,7 @@ impl<'a> ChunkedTerm<'a> { fn contains_cut_var<'a, Iter: Iterator>(terms: Iter) -> bool { for term in terms { if let &Term::Var(_, ref var) = term { - if var.as_str() == "!" { + if var.as_str() == Some("!") { return true; } } diff --git a/src/machine/loader.rs b/src/machine/loader.rs index f268c0f7..bb093a0e 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -21,7 +21,6 @@ use std::convert::TryFrom; use std::fmt; use std::mem; use std::ops::{Deref, DerefMut}; -use std::rc::Rc; /* * The loader compiles Prolog terms read from a TermStream instance, @@ -1429,8 +1428,7 @@ impl MachineState { } } (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => { - let offset_string = format!("_{}", h); - term_stack.push(Term::Var(Cell::default(), Rc::new(offset_string))); + term_stack.push(Term::Var(Cell::default(), Var::Generated(h))); } (HeapCellValueTag::Cons | HeapCellValueTag::CStr | HeapCellValueTag::Fixnum | HeapCellValueTag::Char | HeapCellValueTag::F64) => { diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 11a9d6e8..3f49e1ce 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -16,7 +16,6 @@ use modular_bitfield::specifiers::*; use std::cmp::Ordering; use std::collections::BTreeSet; use std::ops::{Deref, DerefMut}; -use std::rc::Rc; use crate::types::*; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -228,8 +227,8 @@ impl CodeIndex { } } -pub(crate) type HeapVarDict = IndexMap, HeapCellValue, FxBuildHasher>; -pub(crate) type AllocVarDict = IndexMap, VarData, FxBuildHasher>; +pub(crate) type HeapVarDict = IndexMap; +pub(crate) type AllocVarDict = IndexMap; pub(crate) type GlobalVarDir = IndexMap), FxBuildHasher>; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index bdaf048c..6d0de7d9 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -21,7 +21,6 @@ use indexmap::IndexMap; use std::convert::TryFrom; use std::fmt; use std::ops::{Index, IndexMut}; -use std::rc::Rc; pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1]; @@ -501,13 +500,13 @@ impl MachineState { pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult { fn push_var_eq_functors<'a>( heap: &mut Heap, - iter: impl Iterator, &'a HeapCellValue)>, + iter: impl Iterator, atom_tbl: &mut AtomTable, ) -> Vec { let mut list_of_var_eqs = vec![]; for (var, binding) in iter { - let var_atom = atom_tbl.build_with(&var); + let var_atom = atom_tbl.build_with(&var.to_string()); let h = heap.len(); heap.push(atom_as_cell!(atom!("="), 2)); @@ -673,7 +672,7 @@ impl MachineState { let printer = match self.try_from_list(self.registers[6], stub_gen) { Ok(addrs) => { - let mut var_names: IndexMap> = IndexMap::new(); + let mut var_names: IndexMap = IndexMap::new(); for addr in addrs { read_heap_cell!(addr, @@ -691,18 +690,18 @@ impl MachineState { read_heap_cell!(atom, (HeapCellValueTag::Char, c) => { - var_names.insert(var, Rc::new(c.to_string())); + var_names.insert(var, Var::from(c.to_string())); } (HeapCellValueTag::Atom, (name, _arity)) => { debug_assert_eq!(_arity, 0); - var_names.insert(var, Rc::new(name.as_str().to_owned())); + var_names.insert(var, Var::from(name.as_str())); } (HeapCellValueTag::Str, s) => { let (name, arity) = cell_as_atom_cell!(self.heap[s]) .get_name_and_arity(); debug_assert_eq!(arity, 0); - var_names.insert(var, Rc::new(name.as_str().to_owned())); + var_names.insert(var, Var::from(name.as_str())); } _ => { unreachable!(); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 7f0cc264..d2c33b06 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -12,7 +12,6 @@ use indexmap::IndexSet; use std::cell::Cell; use std::collections::VecDeque; use std::convert::TryFrom; -use std::rc::Rc; /* * The preprocessor fabricates if-then-else ( .. -> ... ; ...) @@ -373,7 +372,7 @@ fn mark_cut_variable(term: &mut Term) -> bool { }; if cut_var_found { - *term = Term::Var(Cell::default(), Rc::new(String::from("!"))); + *term = Term::Var(Cell::default(), Var::from("!")); true } else { false @@ -656,7 +655,7 @@ fn compute_head(term: &Term) -> Vec { } } - vars.insert(Rc::new(String::from("!"))); + vars.insert(Var::from("!")); vars.into_iter() .map(|v| Term::Var(Cell::default(), v)) .collect() @@ -767,7 +766,7 @@ impl Preprocessor { } } Term::Literal(_, Literal::Char('!')) => Ok(QueryTerm::BlockedCut), - Term::Var(_, ref v) if v.as_str() == "!" => { + Term::Var(_, ref v) if v.as_str() == Some("!") => { Ok(QueryTerm::UnblockedCut(Cell::default())) } Term::Clause(r, name, mut terms) => match (name, source_arity(&terms)) { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index e457a611..d26468da 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -51,7 +51,6 @@ use std::net::{TcpListener, TcpStream, SocketAddr, ToSocketAddrs}; use std::num::NonZeroU32; use std::ops::Sub; use std::process; -use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; @@ -1410,7 +1409,7 @@ impl Machine { let vars: Vec<_> = vars .union(&result.supp_vars) // difference + union does not cancel. - .map(|v| Term::Var(Cell::default(), Rc::new(format!("_{}", v.get_value())))) + .map(|v| Term::Var(Cell::default(), Var::Generated(v.get_value()))) .collect(); let helper_clause_loc = self.code.len(); diff --git a/src/parser/ast.rs b/src/parser/ast.rs index cf7bf946..78bd55b4 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -572,6 +572,44 @@ impl Literal { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Var { + Generated(usize), + Named(Rc), +} + +impl From for Var { + #[inline(always)] + fn from(value: String) -> Var { + Var::Named(Rc::new(value)) + } +} + +impl From<&str> for Var { + #[inline(always)] + fn from(value: &str) -> Var { + Var::Named(Rc::new(value.to_owned())) + } +} + +impl Var { + #[inline(always)] + pub fn as_str(&self) -> Option<&str> { + match self { + Var::Generated(_) => None, + Var::Named(value) => Some(&value), + } + } + + #[inline(always)] + pub fn to_string(&self) -> String { + match self { + Var::Generated(n) => format!("_{}", n), + Var::Named(value) => value.to_string(), + } + } +} + #[derive(Debug, Clone)] pub enum Term { AnonVar, @@ -582,7 +620,7 @@ pub enum Term { // other PartialString variants in as_partial_string. PartialString(Cell, String, Box), CompleteString(Cell, Atom), - Var(Cell, Rc), + Var(Cell, Var), } impl Term { diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 74f1b930..ce633b94 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -8,7 +8,6 @@ use crate::parser::rug::ops::NegAssign; use std::cell::Cell; use std::mem; -use std::rc::Rc; #[derive(Debug, Clone, Copy, PartialEq)] enum TokenType { @@ -427,7 +426,7 @@ impl<'a, R: CharRead> Parser<'a, R> { if v.trim() == "_" { self.terms.push(Term::AnonVar); } else { - self.terms.push(Term::Var(Cell::default(), Rc::new(v))); + self.terms.push(Term::Var(Cell::default(), Var::from(v))); } TokenType::Term From e41d1b319bb9d55f3b0a8467fc112406cba9854b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 17 Oct 2022 22:56:08 -0600 Subject: [PATCH 04/40] adapt code generation --- src/allocator.rs | 3 + src/fixtures.rs | 2 +- src/forms.rs | 23 +- src/lib.rs | 1 - src/machine/disjuncts.rs | 640 ++++++++++++++++++++++++++++++++++++ src/machine/load_state.rs | 2 +- src/machine/mod.rs | 1 + src/machine/preprocessor.rs | 455 +++---------------------- 8 files changed, 700 insertions(+), 427 deletions(-) create mode 100644 src/machine/disjuncts.rs diff --git a/src/allocator.rs b/src/allocator.rs index 76bdfb53..bc0d2f44 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -60,6 +60,9 @@ pub(crate) trait Allocator { fn take_bindings(self) -> AllocVarDict; fn max_reg_allocated(&self) -> usize; + // TODO: wha.. why?? grrr. it drains the VarStatus data from vs (which it owns!) + // into self.bindings and perm_vs after all is computed (i.e. vs.populate_restricting_sets() + // and vs.set_perm_vals(has_deep_cut) have both been called). fn drain_var_data<'a>( &mut self, vs: VariableFixtures<'a>, diff --git a/src/fixtures.rs b/src/fixtures.rs index 1433b092..67740989 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -84,7 +84,7 @@ type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); #[derive(Debug)] pub(crate) struct VariableFixtures<'a> { perm_vars: IndexMap>, - last_chunk_temp_vars: IndexSet, + last_chunk_temp_vars: IndexSet, // TODO: has no use at all! } impl<'a> VariableFixtures<'a> { diff --git a/src/forms.rs b/src/forms.rs index 9db69581..d571e2d9 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,6 +1,7 @@ use crate::arena::*; use crate::atom_table::*; use crate::instructions::*; +use crate::machine::disjuncts::VarRecord; use crate::machine::heap::*; use crate::machine::loader::PredicateQueue; use crate::machine::machine_errors::*; @@ -34,7 +35,7 @@ pub type JumpStub = Vec; #[derive(Debug, Clone)] pub enum TopLevel { - Fact(Term), // Term, line_num, col_num + Fact(Fact), // Term, line_num, col_num Predicate(Predicate), Query(Vec), Rule(Rule), // Rule, line_num, col_num @@ -82,10 +83,11 @@ pub enum CallPolicy { pub enum QueryTerm { // register, clause type, subterms, clause call policy. Clause(Cell, ClauseType, Vec, CallPolicy), - BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. - UnblockedCut(Cell), + Cut, + Not(Vec), + IfThen(Vec, Vec), + Branch(Vec>), GetLevelAndUnify(Cell, Var), - Jump(JumpStub), // SOON: Branch(Vec), } impl QueryTerm { @@ -99,17 +101,24 @@ impl QueryTerm { pub(crate) fn arity(&self) -> usize { match self { &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, - &QueryTerm::Jump(ref vars) => vars.len(), - &QueryTerm::GetLevelAndUnify(..) => 1, + &QueryTerm::Cut | &QueryTerm::Branch(_) => 0, + &QueryTerm::IfThen(..) => 2, + &QueryTerm::Not(_) | &QueryTerm::GetLevelAndUnify(..) => 1, } } } +#[derive(Debug, Clone)] +pub struct Fact { + pub(crate) head: Term, + pub(crate) var_records: Vec, +} + #[derive(Debug, Clone)] pub struct Rule { pub(crate) head: (Atom, Vec, QueryTerm), pub(crate) clauses: Vec, + pub(crate) var_records: Vec, } #[derive(Clone, Debug, Hash)] diff --git a/src/lib.rs b/src/lib.rs index b117ab16..45dc2385 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,6 @@ pub mod instructions { include!(concat!(env!("OUT_DIR"), "/instructions.rs")); } mod iterators; -mod disjuncts; pub mod machine; mod raw_block; pub mod read; diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs new file mode 100644 index 00000000..a97f08c5 --- /dev/null +++ b/src/machine/disjuncts.rs @@ -0,0 +1,640 @@ + +/* +================================================================================ + +This is a disjunction compilation experiment attempting to adapt the +paper "Compiling Large Disjunctions" to Scryer Prolog. + +================================================================================ + */ + +use crate::atom_table::*; +use crate::forms::*; +use crate::instructions::*; +use crate::iterators::*; +use crate::machine::loader::*; +use crate::machine::machine_errors::CompilationError; +use crate::machine::preprocessor::*; +use crate::parser::ast::*; +use crate::parser::rug::Rational; + +use indexmap::{IndexMap, IndexSet}; + +use std::cell::Cell; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; +use std::ops::{Deref, DerefMut}; + +#[derive(Debug, Clone)] +struct BranchNumber { + branch_num: Rational, + delta: Rational, +} + +impl Default for BranchNumber { + fn default() -> Self { + Self { + branch_num: Rational::from(1 << 10), + delta: Rational::from(1), + } + } +} + +impl PartialEq for BranchNumber { + #[inline] + fn eq(&self, rhs: &BranchNumber) -> bool { + self.branch_num == rhs.branch_num + } +} + +impl Eq for BranchNumber {} + +impl Hash for BranchNumber { + #[inline(always)] + fn hash(&self, hasher: &mut H) { + self.branch_num.hash(hasher) + } +} + +impl PartialOrd for BranchNumber { + #[inline] + fn partial_cmp(&self, rhs: &BranchNumber) -> Option { + self.branch_num.partial_cmp(&rhs.branch_num) + } +} + +impl BranchNumber { + fn split(&self) -> BranchNumber { + BranchNumber { + branch_num: self.branch_num.clone() + &self.delta / Rational::from(2), + delta: &self.delta / Rational::from(4), + } + } + + fn incr_by_delta(&self) -> BranchNumber { + BranchNumber { + branch_num: self.branch_num.clone() + &self.delta, + delta: self.delta.clone(), + } + } + + fn halve_delta(&self) -> BranchNumber { + BranchNumber { + branch_num: self.branch_num.clone(), + delta : &self.delta / Rational::from(2), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ChunkInfo { + chunk_num: usize, + vars: Vec, // pointer to incidence +} + +impl ChunkInfo { + fn new(chunk_num: usize) -> Self { + ChunkInfo { chunk_num, vars: vec![] } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BranchInfo { + branch_num: BranchNumber, + chunks: Vec, +} + +impl BranchInfo { + fn new(branch_num: BranchNumber) -> Self { + Self { branch_num, chunks: vec![] } + } +} + +type BranchMapInt = IndexMap>; + +#[derive(Debug, Clone)] +pub struct BranchMap(BranchMapInt); + +impl Deref for BranchMap { + type Target = BranchMapInt; + + #[inline(always)] + fn deref(&self) -> &BranchMapInt { + &self.0 + } +} + +impl DerefMut for BranchMap { + #[inline(always)] + fn deref_mut(&mut self) -> &mut BranchMapInt { + &mut self.0 + } +} + +type RootSet = IndexSet; + +enum TraversalState { + BuildDisjunct(usize), // construct a QueryTerm::Branch with number of disjuncts. + BuildIf(usize, Term), // build the P term of P -> Q + BuildThen(usize, Vec), // build the Q term of P -> Q + BuildNot(usize), // build the P term of \+ P + ResetCallPolicy(CallPolicy), + Term(Term), + AddBranchNum(BranchNumber), // set current_branch_number, add it to the root set + RemoveBranchNum, // remove latest branch number from the root set + RepBranchNum(BranchNumber), // replace current_branch_number and the latest in the root set + IncrChunkNum, // increment self.current_chunk_number +} + +impl Term { + #[inline] + fn is_var(&self) -> bool { + if let Term::Var(..) = self { + true + } else { + false + } + } + + #[inline] + fn is_compound(&self) -> bool { + match self { + Term::Clause(..) | Term::Cons(..) => true, + _ => false, + } + } +} + +pub struct VariableClassifier { + call_policy: CallPolicy, + current_branch_num: BranchNumber, + current_chunk_num: usize, + branch_map: BranchMap, + root_set: RootSet, +} + +#[derive(Debug)] +pub enum VarClassification { + Void, + Temp, + Perm, +} + +pub struct VarRecord { + pub classification: VarClassification, + pub chunk_occurrences: Vec, + pub num_occurrences: usize, +} + +pub type ClassifyFactResult = (Term, Vec); +pub type ClassifyRuleResult = (Term, Vec, Vec); + +fn merge_branch_seq>(branches: Iter) -> BranchInfo { + let mut branch_info = BranchInfo::new(BranchNumber::default()); + + for mut branch in branches { + branch_info.branch_num = branch.branch_num; + + if let Some(last_chunk) = branch_info.chunks.last_mut() { + if let Some(first_moved_chunk) = branch.chunks.first_mut() { + if last_chunk.chunk_num == first_moved_chunk.chunk_num { + last_chunk.vars.extend(first_moved_chunk.vars.drain(..)); + branch_info.chunks.extend(branch.chunks.drain(1 ..)); + + continue; + } + } + } + + branch_info.chunks.extend(branch.chunks.drain(..)); + } + + branch_info.branch_num.delta *= 2; + branch_info.branch_num.branch_num -= &branch_info.branch_num.delta; + + branch_info +} + +impl VariableClassifier { + pub fn new(call_policy: CallPolicy) -> Self { + Self { + call_policy, + current_branch_num: BranchNumber::default(), + current_chunk_num: 0, + branch_map: BranchMap(BranchMapInt::new()), + root_set: RootSet::new(), + } + } + + pub fn classify_fact(mut self, term: Term) -> Result { + self.classify_head_variables(&term)?; + Ok((term, self.branch_map.separate_and_classify_variables())) + } + + pub fn classify_rule<'a, LS: LoadState<'a>>( + mut self, + loader: &mut Loader<'a, LS>, + head: Term, + body: Term, + ) -> Result { + self.classify_head_variables(&head)?; + let query_terms = self.classify_body_variables(loader, body)?; + + Ok((head, query_terms, self.branch_map.separate_and_classify_variables())) + } + + /* + pub fn to_branch_map(mut self, term: Term) -> Result { + self.root_set.insert(BranchNumber::default()); + + let (head_term, query_terms) = match term { + Term::Clause(_, atom!(":-"), terms) if terms.len() == 2 => { + let head_term = terms[0]; + + self.classify_head_variables(&head_term)?; + (head_term, self.classify_body_variables(terms[1])?) + } + _ => { + self.classify_head_variables(&term)?; + (term, vec![]) + } + }; + + self.merge_branches(); + Ok((head_term, query_terms, self.branch_map)) + } + */ + + fn merge_branches(&mut self) { + for branches in self.branch_map.values_mut() { + let mut old_branches = std::mem::replace(branches, vec![]); + + while let Some(last_branch_num) = old_branches.last().map(|bi| &bi.branch_num) { + let mut old_branches_len = old_branches.len(); + + for (rev_idx, bi) in old_branches.iter().rev().enumerate() { + if &bi.branch_num > last_branch_num { + old_branches_len = old_branches.len() - rev_idx; + } + } + + let iter = old_branches.drain(old_branches_len - 1 ..); + branches.push(merge_branch_seq(iter)); + } + + branches.reverse(); + } + } + + fn probe_body_term(&mut self, term: &Term) { + // true to iterate the root, which may be a variable! + for term_ref in breadth_first_iter(term, true) { + if let TermRef::Var(_, _, var_name) = term_ref { + self.probe_body_var(Var::from(var_name)); + } + } + } + + fn probe_body_var(&mut self, var_name: Var) { + let branch_info_v = self.branch_map.entry(var_name) + .or_insert_with(|| vec![]); + + let needs_new_branch = if let Some(last_bi) = branch_info_v.last() { + !self.root_set.contains(&last_bi.branch_num) + } else { + true + }; + + 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 = if let Some(last_ci) = branch_info.chunks.last() { + last_ci.chunk_num != self.current_chunk_num + } else { + true + }; + + if needs_new_chunk { + branch_info.chunks.push(ChunkInfo::new(self.current_chunk_num)); + } + + let chunk_info = branch_info.chunks.last_mut().unwrap(); + chunk_info.vars.push(VarPtr::from(&var_name)); + } + + fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> { + match term { + Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => { + } + _ => return Err(CompilationError::InvalidRuleHead), + } + + // false argument to breadth_first_iter because the root is not iterable. + for term_ref in breadth_first_iter(term, false) { + if let TermRef::Var(_, _, var_name) = term_ref { + // 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::from(var_name)) + .or_insert_with(|| vec![]); + + let needs_new_branch = branch_info_v.is_empty(); + + 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(); + + if needs_new_chunk { + branch_info.chunks.push(ChunkInfo::new(self.current_chunk_num)); + } + + let chunk_info = branch_info.chunks.last_mut().unwrap(); + chunk_info.vars.push(VarPtr::from(&var_name)); + } + } + + Ok(()) + } + + fn classify_body_variables<'a, LS: LoadState<'a>>( + &mut self, + loader: &mut Loader<'a, LS>, + term: Term, + ) -> Result, CompilationError> { + let mut state_stack = vec![TraversalState::Term(term)]; + let mut build_stack = vec![]; + + while let Some(traversal_st) = state_stack.pop() { + match traversal_st { + TraversalState::AddBranchNum(branch_num) => { + self.root_set.insert(branch_num.clone()); + self.current_branch_num = branch_num; + } + TraversalState::RemoveBranchNum => { + self.root_set.pop(); + } + TraversalState::RepBranchNum(branch_num) => { + self.root_set.pop(); + self.root_set.insert(branch_num.clone()); + self.current_branch_num = branch_num; + } + TraversalState::IncrChunkNum => { + self.current_chunk_num += 1; + } + TraversalState::BuildDisjunct(preceding_len) => { + let iter = build_stack.drain(preceding_len ..); + + if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { + disjuncts.push(iter.collect()); + } + } + TraversalState::BuildIf(preceding_len, then_term) => { + let iter = build_stack.drain(preceding_len ..); + let build_stack_len = build_stack.len(); + + state_stack.push(TraversalState::BuildThen(build_stack_len, iter.collect())); + } + TraversalState::BuildThen(preceding_len, if_terms) => { + let iter = build_stack.drain(preceding_len ..); + build_stack.push(QueryTerm::IfThen(if_terms, iter.collect())); + } + TraversalState::BuildNot(preceding_len) => { + let iter = build_stack.drain(preceding_len ..); + build_stack.push(QueryTerm::Not(iter.collect())); + } + TraversalState::ResetCallPolicy(call_policy) => { + self.call_policy = call_policy; + } + TraversalState::Term(term) => { + match term { + Term::Clause(_, atom!(","), terms) if terms.len() == 2 => { + state_stack.extend( + unfold_by_str(terms[1], atom!(",")) + .into_iter() + .rev() + .map(TraversalState::Term), + ); + + state_stack.push(TraversalState::Term(terms[0])); + } + Term::Clause(_, atom!(";"), terms) if terms.len() == 2 => { + let first_branch_num = self.current_branch_num.split(); + let branches: Vec<_> = std::iter::once(terms[0]) + .chain(unfold_by_str(terms[1], 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.push(QueryTerm::Branch(vec![])); + state_stack.push(TraversalState::BuildDisjunct(build_stack_len)); + + state_stack.push(TraversalState::RepBranchNum( + self.current_branch_num.halve_delta(), + )); + + let iter = branches.into_iter().zip(branch_numbers.into_iter()); + + 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)); + } + } + Term::Clause(_, atom!("->"), mut terms) if terms.len() == 2 => { + let then_term = terms.pop().unwrap(); + let if_term = terms.pop().unwrap(); + let build_stack_len = build_stack.len(); + + state_stack.push(TraversalState::BuildIf(build_stack_len, then_term)); + state_stack.push(TraversalState::Term(if_term)); + } + Term::Clause(_, atom!("\\+"), terms) if terms.len() == 1 => { + let build_stack_len = build_stack.len(); + + state_stack.push(TraversalState::BuildNot(build_stack_len)); + state_stack.push(TraversalState::Term(terms[0])); + } + Term::Clause(_, atom!("$get_level"), terms) if terms.len() == 1 => { + state_stack.push(TraversalState::IncrChunkNum); + + if let Term::Var(_, ref var) = &terms[0] { + build_stack.push(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone())); + } else { + return Err(CompilationError::InadmissibleQueryTerm); + } + } + 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 !ClauseType::is_inbuilt(name, 0) { + state_stack.push(TraversalState::IncrChunkNum); + } + + build_stack.push( + 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 !ClauseType::is_inbuilt(name, terms.len()) { + state_stack.push(TraversalState::IncrChunkNum); + } + + build_stack.push( + qualified_clause_to_query_term( + loader, + module_name, + name, + terms, + self.call_policy, + ), + ); + } + (module_name, predicate_name) => { + state_stack.push(TraversalState::IncrChunkNum); + + terms.push(module_name); + terms.push(predicate_name); + + build_stack.push( + clause_to_query_term( + loader, + atom!("call"), + vec![Term::Clause(Cell::default(), atom!(":"), terms)], + self.call_policy, + ), + ); + } + } + } + Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 2 => { + state_stack.push(TraversalState::ResetCallPolicy(self.call_policy)); + state_stack.push(TraversalState::Term(terms[0])); + + self.call_policy = CallPolicy::Counted; + } + Term::Clause(cell, name, terms) => { + if !ClauseType::is_inbuilt(name, terms.len()) { + state_stack.push(TraversalState::IncrChunkNum); + } + + for term in terms.iter() { + self.probe_body_term(term); + } + + build_stack.push( + clause_to_query_term( + loader, + name, + terms, + self.call_policy, + ), + ); + } + Term::Literal(_, Literal::Atom(atom!("!"))) | + Term::Literal(_, Literal::Char('!')) => { + build_stack.push(QueryTerm::Cut); + } + Term::Literal(cell, Literal::Atom(name)) => { + if !ClauseType::is_inbuilt(name, 0) { + state_stack.push(TraversalState::IncrChunkNum); + } + + build_stack.push( + clause_to_query_term( + loader, + name, + vec![], + self.call_policy, + ), + ); + } + _ => { + return Err(CompilationError::InadmissibleQueryTerm); + } + } + } + } + } + + Ok(build_stack) + } +} + +impl BranchMap { + pub fn separate_and_classify_variables(&mut self) -> Vec { + let mut var_num = 0usize; + let mut records = vec![]; + + for branches in self.values_mut() { + for branch in branches.iter_mut() { + let mut num_occurrences = 0; + let mut chunk_occurrences = vec![]; + + for chunk in branch.chunks.iter_mut() { + num_occurrences += chunk.vars.len(); + + for var in chunk.vars.iter_mut() { + var.set(Var::Generated(var_num)); + } + + chunk_occurrences.push(chunk.chunk_num); + } + + let classification = if branch.chunks.len() > 1 { + VarClassification::Perm + } else { + branch.chunks + .first() + .map(|chunk| if chunk.vars.len() > 1 { + VarClassification::Temp + } else { + VarClassification::Void + }) + .unwrap_or(VarClassification::Void) + }; + + records.push(VarRecord { classification, chunk_occurrences, num_occurrences }); + var_num += 1; + } + } + + debug_assert_eq!(records.len(), var_num); + + records + } +} diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 802d51eb..3d0a638a 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -441,7 +441,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { term: Term, preprocessor: &mut Preprocessor, ) -> Result { - let tl = preprocessor.try_term_to_tl(self, term, CutContext::BlocksCuts)?; + let tl = preprocessor.try_term_to_tl(self, term)?; Ok(match tl { TopLevel::Fact(fact) => PredicateClause::Fact(fact), diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 5193eb66..dab4c54c 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -16,6 +16,7 @@ pub mod machine_state; pub mod machine_state_impl; pub mod mock_wam; pub mod partial_string; +pub mod disjuncts; pub mod preprocessor; pub mod stack; pub mod streams; diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index d2c33b06..0564af8c 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -2,7 +2,7 @@ use crate::atom_table::*; use crate::codegen::CodeGenSettings; use crate::forms::*; use crate::instructions::*; -use crate::iterators::*; +use crate::machine::disjuncts::*; use crate::machine::loader::*; use crate::machine::machine_errors::*; use crate::parser::ast::*; @@ -13,21 +13,6 @@ use std::cell::Cell; use std::collections::VecDeque; use std::convert::TryFrom; -/* - * The preprocessor fabricates if-then-else ( .. -> ... ; ...) - * clauses into nameless standalone predicates, which it queues for - * later preprocessing and compilation. Fabricated predicates inherit - * explicit "cut variables" from the handwritten predicate - * surrounding their source if-then-else. They must be specially - * handled. - */ - -#[derive(Clone, Copy, Debug)] -pub(crate) enum CutContext { - BlocksCuts, - HasCutVariable, -} - pub(crate) fn fold_by_str(terms: I, mut term: Term, sym: Atom) -> Term where I: DoubleEndedIterator, @@ -131,6 +116,13 @@ fn setup_module_export( }) } +pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term { + let head_term = Term::Clause(Cell::default(), atom!(""), vars.iter().cloned().collect()); + 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: &mut AtomTable, @@ -324,110 +316,6 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>( } } -fn merge_clauses(tls: &mut VecDeque) -> Result { - let mut clauses = vec![]; - - while let Some(tl) = tls.pop_front() { - match tl { - TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => { - return Ok(tl); - } - TopLevel::Query(_) => { - return Err(CompilationError::InconsistentEntry); - } - TopLevel::Fact(fact) => { - let clause = PredicateClause::Fact(fact); - clauses.push(clause); - } - TopLevel::Rule(rule) => { - let clause = PredicateClause::Rule(rule); - clauses.push(clause); - } - TopLevel::Predicate(predicate) => clauses.extend(predicate.into_iter()), - } - } - - if clauses.is_empty() { - Err(CompilationError::InconsistentEntry) - } else { - Ok(TopLevel::Predicate(clauses)) - } -} - -fn mark_cut_variables_as(terms: &mut Vec, name: Atom) { - for term in terms.iter_mut() { - match term { - &mut Term::Literal(_, Literal::Atom(ref mut var)) if *var == atom!("!") => { - *var = name; - } - _ => {} - } - } -} - -fn mark_cut_variable(term: &mut Term) -> bool { - let cut_var_found = match term { - &mut Term::Literal(_, Literal::Atom(ref var)) if *var == atom!("!") => true, - _ => false, - }; - - if cut_var_found { - *term = Term::Var(Cell::default(), Var::from("!")); - true - } else { - false - } -} - -fn mark_cut_variables(terms: &mut Vec) -> bool { - let mut found_cut_var = false; - - for item in terms.iter_mut() { - found_cut_var = mark_cut_variable(item) || found_cut_var; - } - - found_cut_var -} - -// terms is a list of goals composing one clause in a (;) functor. it -// checks that the first (and only) of these clauses is a ->. if so, -// it expands its terms using a blocked_!. -fn check_for_internal_if_then(terms: &mut Vec) { - if terms.len() != 1 { - return; - } - - if let Some(Term::Clause(_, name, ref subterms)) = terms.last() { - if *name != atom!("->") || source_arity(subterms) != 2 { - return; - } - } else { - return; - } - - if let Some(Term::Clause(_, _, mut subterms)) = terms.pop() { - let mut conq_terms = VecDeque::from(unfold_by_str(subterms.pop().unwrap(), atom!(","))); - let mut pre_cut_terms = VecDeque::from(unfold_by_str(subterms.pop().unwrap(), atom!(","))); - - conq_terms.push_front(Term::Literal( - Cell::default(), - Literal::Atom(atom!("blocked_!")), - )); - - while let Some(term) = pre_cut_terms.pop_back() { - conq_terms.push_front(term); - } - - let tail_term = conq_terms.pop_back().unwrap(); - - terms.push(fold_by_str( - conq_terms.into_iter(), - tail_term, - atom!(","), - )); - } -} - pub(super) fn setup_declaration<'a, LS: LoadState<'a>>( loader: &mut Loader<'a, LS>, mut terms: Vec, @@ -569,7 +457,7 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>( } #[inline] -fn clause_to_query_term<'a, LS: LoadState<'a>>( +pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>( loader: &mut Loader<'a, LS>, name: Atom, mut terms: Vec, @@ -608,7 +496,7 @@ fn clause_to_query_term<'a, LS: LoadState<'a>>( } #[inline] -fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>( +pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>( loader: &mut Loader<'a, LS>, module_name: Atom, name: Atom, @@ -646,308 +534,65 @@ fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>( QueryTerm::Clause(Cell::default(), ct, terms, call_policy) } -fn compute_head(term: &Term) -> Vec { - let mut vars = IndexSet::new(); - - for term in post_order_iter(term) { - if let TermRef::Var(_, _, v) = term { - vars.insert(v.clone()); - } - } - - vars.insert(Var::from("!")); - vars.into_iter() - .map(|v| Term::Var(Cell::default(), v)) - .collect() -} - -pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term { - let head_term = Term::Clause(Cell::default(), atom!(""), vars.iter().cloned().collect()); - let rule = vec![head_term, body_term]; - - Term::Clause(Cell::default(), atom!(":-"), rule) -} - -// the terms form the body of the rule. We create a head, by -// gathering variables from the body of terms and recording them -// in the head clause. -fn build_rule(body_term: Term) -> (JumpStub, VecDeque) { - // collect the vars of body_term into a head, return the num_vars - // (the arity) as well. - let vars = compute_head(&body_term); - let rule = build_rule_body(&vars, body_term); - - (vars, VecDeque::from(vec![rule])) -} - -fn build_disjunct(body_term: Term) -> (JumpStub, VecDeque) { - let vars = compute_head(&body_term); - let results = unfold_by_str(body_term, atom!(";")) - .into_iter() - .map(|term| { - let mut subterms = unfold_by_str(term, atom!(",")); - mark_cut_variables(&mut subterms); - - check_for_internal_if_then(&mut subterms); - - let term = subterms.pop().unwrap(); - let clause = fold_by_str(subterms.into_iter(), term, atom!(",")); - - build_rule_body(&vars, clause) - }) - .collect(); - - (vars, results) -} - -fn build_if_then(prec: Term, conq: Term) -> (JumpStub, VecDeque) { - let mut prec_seq = unfold_by_str(prec, atom!(",")); - let comma_sym = atom!(","); - let cut_sym = Literal::Atom(atom!("!")); - - prec_seq.push(Term::Literal(Cell::default(), cut_sym)); - - mark_cut_variables_as(&mut prec_seq, atom!("blocked_!")); - - let mut conq_seq = unfold_by_str(conq, atom!(",")); - - mark_cut_variables(&mut conq_seq); - prec_seq.extend(conq_seq.into_iter()); - - let back_term = prec_seq.pop().unwrap(); - let front_term = prec_seq.pop().unwrap(); - - let body_term = Term::Clause( - Cell::default(), - comma_sym, - vec![front_term, back_term], - ); - - build_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym)) -} - #[derive(Debug)] pub(crate) struct Preprocessor { - queue: VecDeque>, settings: CodeGenSettings, } impl Preprocessor { pub(super) fn new(settings: CodeGenSettings) -> Self { Preprocessor { - queue: VecDeque::new(), settings, } } - fn setup_fact(&mut self, term: Term) -> Result { + fn setup_fact(&mut self, term: Term) -> Result { match term { - Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => Ok(term), + Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => { + let mut classifier = VariableClassifier::new( + self.settings.default_call_policy(), + ); + + let (head, var_records) = classifier.classify_fact(term)?; + + Ok(Fact { head, var_records }) + } _ => Err(CompilationError::InadmissibleFact), } } - fn to_query_term<'a, LS: LoadState<'a>>( - &mut self, - loader: &mut Loader<'a, LS>, - term: Term, - ) -> Result { - match term { - Term::Literal(_, Literal::Atom(name)) => { - if name == atom!("!") || name == atom!("blocked_!") { - Ok(QueryTerm::BlockedCut) - } else { - Ok(clause_to_query_term( - loader, - name, - vec![], - self.settings.default_call_policy(), - )) - } - } - Term::Literal(_, Literal::Char('!')) => Ok(QueryTerm::BlockedCut), - Term::Var(_, ref v) if v.as_str() == Some("!") => { - Ok(QueryTerm::UnblockedCut(Cell::default())) - } - Term::Clause(r, name, mut terms) => match (name, source_arity(&terms)) { - (atom!(";"), 2) => { - let term = Term::Clause(r, name, terms); - - let (stub, clauses) = build_disjunct(term); - self.queue.push_back(clauses); - - Ok(QueryTerm::Jump(stub)) - } - (atom!("->"), 2) => { - let conq = terms.pop().unwrap(); - let prec = terms.pop().unwrap(); - - let (stub, clauses) = build_if_then(prec, conq); - self.queue.push_back(clauses); - - Ok(QueryTerm::Jump(stub)) - } - (atom!("\\+"), 1) => { - terms.push(Term::Literal( - Cell::default(), - Literal::Atom(atom!("$fail")), - )); - - let conq = Term::Literal(Cell::default(), Literal::Atom(atom!("true"))); - - let prec = Term::Clause(Cell::default(), atom!("->"), terms); - let terms = vec![prec, conq]; - - let term = Term::Clause(Cell::default(), atom!(";"), terms); - let (stub, clauses) = build_disjunct(term); - - debug_assert!(clauses.len() > 0); - self.queue.push_back(clauses); - - Ok(QueryTerm::Jump(stub)) - } - (atom!("$get_level"), 1) => { - if let Term::Var(_, ref var) = &terms[0] { - Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone())) - } else { - Err(CompilationError::InadmissibleQueryTerm) - } - } - (atom!(":"), 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)), - ) => Ok(qualified_clause_to_query_term( - loader, - module_name, - predicate_name, - vec![], - self.settings.default_call_policy(), - )), - ( - Term::Literal(_, Literal::Atom(module_name)), - Term::Clause(_, name, terms), - ) => Ok(qualified_clause_to_query_term( - loader, - module_name, - name, - terms, - self.settings.default_call_policy() - )), - (module_name, predicate_name) => { - terms.push(module_name); - terms.push(predicate_name); - - Ok(clause_to_query_term( - loader, - atom!("call"), - vec![Term::Clause(r, name, terms)], - self.settings.default_call_policy(), - )) - } - } - } - _ => Ok(clause_to_query_term(loader, name, terms, - self.settings.default_call_policy())), - }, - Term::Var(..) => Ok(QueryTerm::Clause( - Cell::default(), - ClauseType::CallN(1), - vec![term], - self.settings.default_call_policy(), - )), - _ => Err(CompilationError::InadmissibleQueryTerm), - } - } - - fn pre_query_term<'a, LS: LoadState<'a>>( - &mut self, - loader: &mut Loader<'a, LS>, - term: Term, - ) -> Result { - match term { - Term::Clause(r, name, mut subterms) => { - if subterms.len() == 1 && name == atom!("$call_with_inference_counting") { - self.to_query_term(loader, subterms.pop().unwrap()) - .map(|mut query_term| { - query_term.set_call_policy(CallPolicy::Counted); - query_term - }) - } else { - let clause = Term::Clause(r, name, subterms); - self.to_query_term(loader, clause) - } - } - _ => self.to_query_term(loader, term), - } - } - - fn setup_query<'a, LS: LoadState<'a>>( - &mut self, - loader: &mut Loader<'a, LS>, - terms: Vec, - cut_context: CutContext, - ) -> Result, CompilationError> { - let mut query_terms = vec![]; - let mut work_queue = VecDeque::from(terms); - - while let Some(term) = work_queue.pop_front() { - let mut term = term; - - if let Term::Clause(cell, name, terms) = term { - if name == atom!(",") && source_arity(&terms) == 2 { - let term = Term::Clause(cell, name, terms); - let mut subterms = unfold_by_str(term, atom!(",")); - - while let Some(subterm) = subterms.pop() { - work_queue.push_front(subterm); - } - - continue; - } else { - term = Term::Clause(cell, name, terms); - } - } - - if let CutContext::HasCutVariable = cut_context { - mark_cut_variable(&mut term); - } - - query_terms.push(self.pre_query_term(loader, term)?); - } - - Ok(query_terms) - } - fn setup_rule<'a, LS: LoadState<'a>>( &mut self, loader: &mut Loader<'a, LS>, - mut terms: Vec, - cut_context: CutContext, + head: Term, + body: Term, ) -> Result { - let post_head_terms: Vec<_> = terms.drain(1..).collect(); - let mut query_terms = self.setup_query(loader, post_head_terms, cut_context)?; + let mut classifier = VariableClassifier::new( + self.settings.default_call_policy(), + ); + + let (head, mut query_terms, var_records) = + classifier.classify_rule(loader, head, body)?; let clauses = query_terms.drain(1..).collect(); let qt = query_terms.pop().unwrap(); - match terms.pop().unwrap() { + match head { Term::Clause(_, name, terms) => Ok(Rule { head: (name, terms, qt), clauses, + var_records, }), Term::Literal(_, Literal::Atom(name)) => Ok(Rule { head: (name, vec![], qt), clauses, + var_records, }), _ => Err(CompilationError::InvalidRuleHead), } } + /* fn try_term_to_query<'a, LS: LoadState<'a>>( &mut self, loader: &mut Loader<'a, LS>, @@ -960,23 +605,19 @@ impl Preprocessor { cut_context, )?)) } + */ pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>( &mut self, loader: &mut Loader<'a, LS>, term: Term, - cut_context: CutContext, ) -> Result { match term { Term::Clause(r, name, terms) => { - if name == atom!("?-") { - self.try_term_to_query(loader, terms, cut_context) - } else if name == atom!(":-") && terms.len() == 2 { - Ok(TopLevel::Rule(self.setup_rule( - loader, - terms, - cut_context, - )?)) + let is_rule = name == atom!(":-") && terms.len() == 2; + + if is_rule { + Ok(TopLevel::Rule(self.setup_rule(loader, terms[0], terms[1])?)) } else { let term = Term::Clause(r, name, terms); Ok(TopLevel::Fact(self.setup_fact(term)?)) @@ -990,33 +631,13 @@ impl Preprocessor { &mut self, loader: &mut Loader<'a, LS>, terms: I, - cut_context: CutContext, ) -> Result, CompilationError> { let mut results = VecDeque::new(); for term in terms.into_iter() { - results.push_back(self.try_term_to_tl(loader, term, cut_context)?); + results.push_back(self.try_term_to_tl(loader, term)?); } Ok(results) } - - pub(super) fn parse_queue<'a, LS: LoadState<'a>>( - &mut self, - loader: &mut Loader<'a, LS>, - ) -> Result, CompilationError> { - let mut queue = VecDeque::new(); - - while let Some(terms) = self.queue.pop_front() { - let clauses = merge_clauses(&mut self.try_terms_to_tls( - loader, - terms, - CutContext::HasCutVariable, - )?)?; - - queue.push_back(clauses); - } - - Ok(queue) - } } From 170818759deeafbe841e45ca14a79c5e1d92f18e Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 1 Nov 2022 21:10:15 -0600 Subject: [PATCH 05/40] add more variable probing, chunk type labeling --- src/machine/disjuncts.rs | 173 ++++++++++++++++++++++++++++++++------- 1 file changed, 142 insertions(+), 31 deletions(-) diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index a97f08c5..adbf341c 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -133,8 +133,20 @@ impl DerefMut for BranchMap { type RootSet = IndexSet; +#[derive(Debug, Clone, Copy)] +enum ChunkType { + Head, + Mid, + Last, +} + enum TraversalState { - BuildDisjunct(usize), // construct a QueryTerm::Branch with number of disjuncts. + // construct a QueryTerm::Branch with number of disjuncts, reset + // the chunk type to that of the chunk preceding the disjunct. + BuildDisjunct(ChunkType, usize), + // add the last disjunct to a QueryTerm::Branch, continuing from + // where it leaves off. + BuildFinalDisjunct(usize), BuildIf(usize, Term), // build the P term of P -> Q BuildThen(usize, Vec), // build the Q term of P -> Q BuildNot(usize), // build the P term of \+ P @@ -144,6 +156,7 @@ enum TraversalState { RemoveBranchNum, // remove latest branch number from the root set RepBranchNum(BranchNumber), // replace current_branch_number and the latest in the root set IncrChunkNum, // increment self.current_chunk_number + SetLastChunkType, // consider remaining terms as belonging to a last chunk } impl Term { @@ -215,6 +228,62 @@ fn merge_branch_seq>(branches: Iter) -> Branch branch_info } +fn flatten_into_disjunct(build_stack: &mut Vec, preceding_len: usize) { + let iter = build_stack.drain(preceding_len ..); + + if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { + disjuncts.push(iter.collect()); + } +} + +fn term_in_other_chunk(term: &Term) -> Option { + match term { + Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(name, terms.len())), + Term::Literal(_, Literal::Atom(atom!("!"))) | + Term::Literal(_, Literal::Char('!')) => Some(false), + Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(name, 0)), + Term::Var(..) => Some(true), + _ => None, + } +} + +// returns true if the insertion of SetLastChunkType was the final push. +fn insert_set_last_chunk_type( + state_stack: &mut Vec, + iter: impl Iterator, +) -> bool { + let beg = state_stack.len(); + let mut idx = beg; + + while let Some(traversal_st) = iter.next() { + match traversal_st { + TraversalState::Term(term) | TraversalState::BuildIf(_, term) => { + let mut will_break = false; + + match term_in_other_chunk(&term) { + Some(true) if idx > beg => will_break = true, + Some(_) => idx += 1, + None => will_break = true, + } + + if will_break { + state_stack.push(TraversalState::SetLastChunkType); + state_stack.push(traversal_st); + break; + } else { + state_stack.push(traversal_st); + } + } + _ => { + unreachable!(); + } + } + } + + state_stack.extend(iter); + idx == state_stack.len() +} + impl VariableClassifier { pub fn new(call_policy: CallPolicy) -> Self { Self { @@ -286,16 +355,16 @@ impl VariableClassifier { } } - fn probe_body_term(&mut self, term: &Term) { - // true to iterate the root, which may be a variable! + fn probe_body_term(&mut self, term: &Term, term_loc: GenContext) { + // second arg is true to iterate the root, which may be a variable for term_ref in breadth_first_iter(term, true) { if let TermRef::Var(_, _, var_name) = term_ref { - self.probe_body_var(Var::from(var_name)); + self.probe_body_var(Var::from(var_name), term_loc); } } } - fn probe_body_var(&mut self, var_name: Var) { + fn probe_body_var(&mut self, var_name: Var, chunk_type: ChunkType) { let branch_info_v = self.branch_map.entry(var_name) .or_insert_with(|| vec![]); @@ -369,6 +438,7 @@ impl VariableClassifier { ) -> Result, CompilationError> { let mut state_stack = vec![TraversalState::Term(term)]; let mut build_stack = vec![]; + let mut chunk_type = ChunkType::Head; while let Some(traversal_st) = state_stack.pop() { match traversal_st { @@ -386,19 +456,26 @@ impl VariableClassifier { } TraversalState::IncrChunkNum => { self.current_chunk_num += 1; + chunk_type = ChunkType::Mid; } - TraversalState::BuildDisjunct(preceding_len) => { - let iter = build_stack.drain(preceding_len ..); - - if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { - disjuncts.push(iter.collect()); - } + TraversalState::ResetCallPolicy(call_policy) => { + self.call_policy = call_policy; + } + TraversalState::SetLastChunkType => { + chunk_type = ChunkType::Last; + } + TraversalState::BuildDisjunct(reset_chunk_type, preceding_len) => { + chunk_type = reset_chunk_type; + flatten_into_disjunct(&mut build_stack, preceding_len); + } + TraversalState::BuildFinalDisjunct(preceding_len) => { + flatten_into_disjunct(&mut build_stack, preceding_len); } TraversalState::BuildIf(preceding_len, then_term) => { let iter = build_stack.drain(preceding_len ..); - let build_stack_len = build_stack.len(); - state_stack.push(TraversalState::BuildThen(build_stack_len, iter.collect())); + state_stack.push(TraversalState::BuildThen(preceding_len, iter.collect())); + state_stack.push(TraversalState::Term(then_term)); } TraversalState::BuildThen(preceding_len, if_terms) => { let iter = build_stack.drain(preceding_len ..); @@ -408,20 +485,22 @@ impl VariableClassifier { let iter = build_stack.drain(preceding_len ..); build_stack.push(QueryTerm::Not(iter.collect())); } - TraversalState::ResetCallPolicy(call_policy) => { - self.call_policy = call_policy; - } TraversalState::Term(term) => { match term { Term::Clause(_, atom!(","), terms) if terms.len() == 2 => { - state_stack.extend( - unfold_by_str(terms[1], atom!(",")) - .into_iter() - .rev() - .map(TraversalState::Term), - ); + let iter = unfold_by_str(terms[1], atom!(",")) + .into_iter() + .rev() + .chain(std::iter::once(terms[0])) + .map(TraversalState::Term); - state_stack.push(TraversalState::Term(terms[0])); + if let ChunkType::Last = chunk_type { + if !insert_set_last_chunk_type(&mut state_stack, iter) { + chunk_type = ChunkType::Mid; + } + } else { + state_stack.extend(iter); + } } Term::Clause(_, atom!(";"), terms) if terms.len() == 2 => { let first_branch_num = self.current_branch_num.split(); @@ -442,31 +521,46 @@ impl VariableClassifier { } let build_stack_len = build_stack.len(); - build_stack.push(QueryTerm::Branch(vec![])); - state_stack.push(TraversalState::BuildDisjunct(build_stack_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 (term, branch_num) in iter.rev() { - state_stack.push(TraversalState::BuildDisjunct(build_stack_len)); + state_stack.push(TraversalState::BuildDisjunct(chunk_type, build_stack_len)); state_stack.push(TraversalState::RemoveBranchNum); state_stack.push(TraversalState::Term(term)); state_stack.push(TraversalState::AddBranchNum(branch_num)); } + + state_stack[final_disjunct_loc] = + TraversalState::BuildFinalDisjunct(build_stack_len); } Term::Clause(_, atom!("->"), mut terms) if terms.len() == 2 => { let then_term = terms.pop().unwrap(); let if_term = terms.pop().unwrap(); + let build_stack_len = build_stack.len(); - state_stack.push(TraversalState::BuildIf(build_stack_len, then_term)); - state_stack.push(TraversalState::Term(if_term)); + // TODO: insert GetLevelAndUnify between + // the two traversal states and detect + // that as a chunk boundary in + // insert_set_last_chunk_type ?? + + let iter = vec![TraversalState::BuildIf(build_stack_len, then_term), + TraversalState::Term(if_term)] + .into_iter(); + + if let ChunkType::Last = chunk_type { + if !insert_set_last_chunk_type(&mut state_stack, iter) { + chunk_type = ChunkType::Mid; + } + } } Term::Clause(_, atom!("\\+"), terms) if terms.len() == 1 => { let build_stack_len = build_stack.len(); @@ -477,8 +571,14 @@ impl VariableClassifier { Term::Clause(_, atom!("$get_level"), terms) if terms.len() == 1 => { state_stack.push(TraversalState::IncrChunkNum); + // TODO: need to classify this variable? if let Term::Var(_, ref var) = &terms[0] { - build_stack.push(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone())); + build_stack.push( + QueryTerm::GetLevelAndUnify( + Cell::default(), + var.clone(), + ), + ); } else { return Err(CompilationError::InadmissibleQueryTerm); } @@ -514,6 +614,10 @@ impl VariableClassifier { state_stack.push(TraversalState::IncrChunkNum); } + for term in terms.iter() { + self.probe_body_term(term, term_loc); + } + build_stack.push( qualified_clause_to_query_term( loader, @@ -527,6 +631,9 @@ impl VariableClassifier { (module_name, predicate_name) => { state_stack.push(TraversalState::IncrChunkNum); + self.probe_body_term(&module_name, term_loc); + self.probe_body_term(&predicate_name, term_loc); + terms.push(module_name); terms.push(predicate_name); @@ -541,7 +648,11 @@ impl VariableClassifier { } } } - Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 2 => { + Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 1 => { + for term in terms.iter() { + self.probe_body_term(term, term_loc); + } + state_stack.push(TraversalState::ResetCallPolicy(self.call_policy)); state_stack.push(TraversalState::Term(terms[0])); @@ -553,7 +664,7 @@ impl VariableClassifier { } for term in terms.iter() { - self.probe_body_term(term); + self.probe_body_term(term, term_loc); } build_stack.push( From a66d666beda87024691dda2ce9d17baeb149114e Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 13 Nov 2022 10:13:37 -0700 Subject: [PATCH 06/40] variable classification al a carte --- Cargo.lock | 1 + Cargo.toml | 1 + src/allocator.rs | 22 +++-- src/codegen.rs | 23 +++-- src/fixtures.rs | 180 ++++++++++++--------------------------- src/iterators.rs | 1 - src/machine/disjuncts.rs | 156 ++++++++++++++++++++++++--------- src/parser/ast.rs | 2 +- 8 files changed, 198 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46c5a14f..7cc11f21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1855,6 +1855,7 @@ version = "0.9.1" dependencies = [ "assert_cmd", "base64", + "bit-set", "blake2 0.8.1", "chrono", "cpu-time", diff --git a/Cargo.toml b/Cargo.toml index 975ba64f..f358126a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ to-syn-value_derive = "0.1.0" walkdir = "2" [dependencies] +bit-set = "0.5.3" cpu-time = "1.0.0" crossterm = "0.20.0" dirs-next = "2.0.0" diff --git a/src/allocator.rs b/src/allocator.rs index bc0d2f44..50e9c7c3 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -63,32 +63,30 @@ pub(crate) trait Allocator { // TODO: wha.. why?? grrr. it drains the VarStatus data from vs (which it owns!) // into self.bindings and perm_vs after all is computed (i.e. vs.populate_restricting_sets() // and vs.set_perm_vals(has_deep_cut) have both been called). + /* fn drain_var_data<'a>( &mut self, - vs: VariableFixtures<'a>, + vs: VariableFixtures, num_of_chunks: usize, - ) -> VariableFixtures<'a> { + ) -> VariableFixtures { let mut perm_vs = VariableFixtures::new(); - for (var, (var_status, cells)) in vs.into_iter() { + for (var, var_status) in vs.into_iter() { match var_status { VarStatus::Temp(chunk_num, tvd) => { self.bindings_mut() - .insert(var.clone(), VarData::Temp(chunk_num, 0, tvd)); - - if chunk_num + 1 == num_of_chunks { - perm_vs.insert_last_chunk_temp_var(var); - } + .insert(var.clone(), VarAlloc::Temp(chunk_num, 0, tvd)); } VarStatus::Perm(_) => { - self.bindings_mut().insert(var.clone(), VarData::Perm(0)); - perm_vs.insert(var, (var_status, cells)); + self.bindings_mut().insert(var.clone(), VarAlloc::Perm(0)); + perm_vs.insert(var, var_status); } }; } perm_vs } + */ fn get(&self, var: Var) -> RegType { self.bindings() @@ -102,8 +100,8 @@ pub(crate) trait Allocator { fn record_register(&mut self, var: Var, r: RegType) { match self.bindings_mut().get_mut(&var).unwrap() { - &mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(), - &mut VarData::Perm(ref mut s) => *s = r.reg_num(), + &mut VarAlloc::Temp(_, ref mut s, _) => *s = r.reg_num(), + &mut VarAlloc::Perm(ref mut s) => *s = r.reg_num(), } } } diff --git a/src/codegen.rs b/src/codegen.rs index a3fdc99b..65f49971 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,6 @@ use crate::atom_table::*; use crate::parser::ast::*; use crate::{perm_v, temp_v}; - use crate::allocator::*; use crate::arithmetic::*; use crate::debray_allocator::*; @@ -22,14 +21,14 @@ use std::cell::Cell; use std::collections::VecDeque; #[derive(Debug)] -pub(crate) struct ConjunctInfo<'a> { - pub(crate) perm_vs: VariableFixtures<'a>, +pub(crate) struct ConjunctInfo { + pub(crate) perm_vs: VariableFixtures, pub(crate) num_of_chunks: usize, pub(crate) has_deep_cut: bool, } -impl<'a> ConjunctInfo<'a> { - fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self { +impl ConjunctInfo { + fn new(perm_vs: VariableFixtures, num_of_chunks: usize, has_deep_cut: bool) -> Self { ConjunctInfo { perm_vs, num_of_chunks, @@ -191,8 +190,8 @@ impl DebrayAllocator { #[inline(always)] pub(crate) fn get_binding(&self, name: &Var) -> Option { match self.bindings().get(name) { - Some(&VarData::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)), - Some(&VarData::Perm(p)) if p != 0 => Some(RegType::Perm(p)), + Some(&VarAlloc::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)), + Some(&VarAlloc::Perm(p)) if p != 0 => Some(RegType::Perm(p)), _ => None, } } @@ -861,7 +860,7 @@ impl<'b> CodeGenerator<'b> { fn compile_seq<'a>( &mut self, iter: ChunkedIterator<'a>, - conjunct_info: &ConjunctInfo<'a>, + conjunct_info: &ConjunctInfo, code: &mut Code, ) -> Result<(), CompilationError> { for (chunk_num, _, terms) in iter.rule_body_iter() { @@ -925,11 +924,11 @@ impl<'b> CodeGenerator<'b> { } } - fn compile_cleanup<'a>( + fn compile_cleanup( &mut self, code: &mut Code, - conjunct_info: &ConjunctInfo<'a>, - toc: &'a QueryTerm, + conjunct_info: &ConjunctInfo, + toc: &QueryTerm, ) { // add a proceed to bookend any trailing cuts. match toc { @@ -937,7 +936,7 @@ impl<'b> CodeGenerator<'b> { code.push(instr!("proceed")); } _ => {} - }; + } // perform lco. let dealloc_index = Self::lco(code); diff --git a/src/fixtures.rs b/src/fixtures.rs index 67740989..f75a8042 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -4,6 +4,7 @@ use crate::forms::*; use crate::instructions::*; use crate::iterators::*; +use bit_set::*; use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; @@ -11,15 +12,23 @@ use std::collections::BTreeSet; use std::mem::swap; use std::vec::Vec; -// labeled with chunk numbers. +pub(crate) type OccurrenceSet = IndexSet<(GenContext, usize)>; + #[derive(Debug)] -pub(crate) enum VarStatus { - Perm(usize), - Temp(usize, TempVarData), // Perm(chunk_num) | Temp(chunk_num, _) +pub(crate) struct TempVarData { + pub(crate) last_term_arity: usize, + pub(crate) use_set: OccurrenceSet, + pub(crate) no_use_set: BitSet, + pub(crate) conflict_set: BitSet, } -pub(crate) type OccurrenceSet = BTreeSet<(GenContext, usize)>; +#[derive(Debug)] +pub(crate) struct TempVarStatus { + chunk_num: usize, + temp_var_data: TempVarData, +} +// TODO: get ridda this! I think. // Perm: 0 initially, a stack register once processed. // Temp: labeled with chunk_num and temp offset (unassigned if 0). #[derive(Debug)] @@ -37,21 +46,13 @@ impl VarData { } } -#[derive(Debug)] -pub(crate) struct TempVarData { - pub(crate) last_term_arity: usize, - pub(crate) use_set: OccurrenceSet, - pub(crate) no_use_set: BTreeSet, - pub(crate) conflict_set: BTreeSet, -} - impl TempVarData { pub(crate) fn new(last_term_arity: usize) -> Self { TempVarData { last_term_arity: last_term_arity, - use_set: BTreeSet::new(), - no_use_set: BTreeSet::new(), - conflict_set: BTreeSet::new(), + use_set: BitSet::new(), + no_use_set: BitSet::new(), + conflict_set: BitSet::new(), } } @@ -68,7 +69,7 @@ impl TempVarData { pub(crate) fn populate_conflict_set(&mut self) { if self.last_term_arity > 0 { let arity = self.last_term_arity; - let mut conflict_set: BTreeSet = (1..arity).collect(); + let mut conflict_set: BitSet = (1..arity).collect(); for &(_, reg) in self.use_set.iter() { conflict_set.remove(®); @@ -79,26 +80,26 @@ impl TempVarData { } } -type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); - #[derive(Debug)] -pub(crate) struct VariableFixtures<'a> { - perm_vars: IndexMap>, - last_chunk_temp_vars: IndexSet, // TODO: has no use at all! +pub(crate) struct VariableFixtures { + temp_vars: IndexMap, + last_chunk_temp_vars: IndexSet, // TODO: has no use at all! remove it. } impl<'a> VariableFixtures<'a> { pub(crate) fn new() -> Self { VariableFixtures { - perm_vars: IndexMap::new(), + temp_vars: IndexMap::new(), last_chunk_temp_vars: IndexSet::new(), } } + // TODO: get rid of this also. pub(crate) fn insert(&mut self, var: Var, vs: VariableFixture<'a>) { - self.perm_vars.insert(var, vs); + self.temp_vars.insert(var, vs); } + // TODO: used? pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Var) { self.last_chunk_temp_vars.insert(var); } @@ -114,27 +115,26 @@ impl<'a> VariableFixtures<'a> { // Compute the conflict set of u. // 1. - let mut use_sets: IndexMap = IndexMap::new(); + let mut use_sets: IndexMap = IndexMap::new(); - for (var, &mut (ref mut var_status, _)) in self.iter_mut() { - if let &mut VarStatus::Temp(_, ref mut var_data) = var_status { - let mut use_set = OccurrenceSet::new(); + for (var_gen_index, ref mut var_status) in self.temp_vars.iter_mut() { + let TempVarStatus { ref mut temp_var_data, .. } = var_status; + let mut use_set = OccurrenceSet::new(); - swap(&mut var_data.use_set, &mut use_set); - use_sets.insert((*var).clone(), use_set); - } + mem::swap(&mut temp_var_data.use_set, &mut use_set); + use_sets.insert(var_gen_index, use_set); } for (u, use_set) in use_sets.drain(..) { // 2. for &(term_loc, reg) in use_set.iter() { if let GenContext::Last(cn_u) = term_loc { - for (ref t, &mut (ref mut var_status, _)) in self.iter_mut() { - if let &mut VarStatus::Temp(cn_t, ref mut t_data) = var_status { - if cn_u == cn_t && u != **t { - if !t_data.uses_reg(reg) { - t_data.no_use_set.insert(reg); - } + for (var_gen_index, ref mut var_status) in self.terms_vars.iter_mut() { + let TempVarStatus { chunk_num, ref mut temp_var_data } = var_status; + + if cn_u == chunk_num && u != var_gen_index { + if !temp_var_data.uses_reg(reg) { + temp_var_data.no_use_set.insert(reg); } } } @@ -142,24 +142,13 @@ impl<'a> VariableFixtures<'a> { } // 3. - match self.get_mut(u).unwrap() { - &mut (VarStatus::Temp(_, ref mut u_data), _) => { - u_data.use_set = use_set; - u_data.populate_conflict_set(); - } - _ => {} - }; + let TempVarStatus { ref mut temp_var_data, ..} = self.temp_vars.get_mut(u).unwrap(); + + temp_var_data.use_set = use_set; + temp_var_data.populate_conflict_set(); } } - fn get_mut(&mut self, u: Var) -> Option<&mut VariableFixture<'a>> { - self.perm_vars.get_mut(&u) - } - - fn iter_mut(&mut self) -> indexmap::map::IterMut> { - self.perm_vars.iter_mut() - } - fn record_temp_info(&mut self, tvd: &mut TempVarData, arg_c: usize, term_loc: GenContext) { match term_loc { GenContext::Head | GenContext::Last(_) => { @@ -169,84 +158,27 @@ impl<'a> VariableFixtures<'a> { }; } - pub(crate) fn vars_above_threshold(&self, index: usize) -> usize { - let mut var_count = 0; - - for &(ref var_status, _) in self.values() { - if let &VarStatus::Perm(i) = var_status { - if i > index { - var_count += 1; - } - } - } - - var_count - } - - pub(crate) fn mark_vars_in_chunk(&mut self, iter: I, lt_arity: usize, term_loc: GenContext) - where - I: Iterator>, - { + pub(crate) fn mark_temp_var( + &mut self, + generated_var_index: usize, + lvl: Level, + classify_info: &ClassifyInfo, + term_loc: GenContext, + ) { let chunk_num = term_loc.chunk_num(); - let mut arg_c = 1; - for term_ref in iter { - if let &TermRef::Var(lvl, cell, ref var) = &term_ref { - let mut status = self.perm_vars.swap_remove(var).unwrap_or(( - VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), - Vec::new(), - )); - - status.1.push(cell); - - match status.0 { - VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => { - if let Level::Shallow = lvl { - self.record_temp_info(tvd, arg_c, term_loc); - } - } - _ => status.0 = VarStatus::Perm(chunk_num), - }; - - self.perm_vars.insert(var.clone(), status); + let mut status = self.temp_vars.swap_remove(generated_var_index).unwrap_or_else(|| { + TempVarStatus { + chunk_num, + temp_var_data: TempVarData::new(classify_info.arity), } + }); - if let Level::Shallow = term_ref.level() { - arg_c += 1; - } + if let Level::Shallow = lvl { + self.record_temp_info(&mut status, classify_info.arg_c, term_loc); } - } - pub(crate) fn into_iter(self) -> indexmap::map::IntoIter> { - self.perm_vars.into_iter() - } - - fn values(&self) -> indexmap::map::Values> { - self.perm_vars.values() - } - - pub(crate) fn size(&self) -> usize { - self.perm_vars.len() - } - - pub(crate) fn set_perm_vals(&self, has_deep_cuts: bool) { - let mut values_vec: Vec<_> = self - .values() - .filter_map(|ref v| match &v.0 { - &VarStatus::Perm(i) => Some((i, &v.1)), - _ => None, - }) - .collect(); - - values_vec.sort_by_key(|ref v| v.0); - - let offset = has_deep_cuts as usize; - - for (i, (_, cells)) in values_vec.into_iter().rev().enumerate() { - for cell in cells { - cell.set(VarReg::Norm(RegType::Perm(i + 1 + offset))); - } - } + self.temp_vars.insert(Var::Generated(generated_var_index), status); } } diff --git a/src/iterators.rs b/src/iterators.rs index ac87a451..bbd9fb70 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -40,7 +40,6 @@ impl VarPtr { } } - #[derive(Debug, Clone)] pub(crate) enum TermRef<'a> { AnonVar(Level), diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index adbf341c..19e460c3 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -9,6 +9,7 @@ paper "Compiling Large Disjunctions" to Scryer Prolog. */ use crate::atom_table::*; +use crate::fixtures::VariableFixtures; use crate::forms::*; use crate::instructions::*; use crate::iterators::*; @@ -34,7 +35,7 @@ struct BranchNumber { impl Default for BranchNumber { fn default() -> Self { Self { - branch_num: Rational::from(1 << 10), + branch_num: Rational::from(1 << 63), delta: Rational::from(1), } } @@ -86,16 +87,19 @@ impl BranchNumber { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct VarInfo { + var_ptr: VarPtr, + classify_info: ClassifyInfo, + lvl: Level, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ChunkInfo { chunk_num: usize, - vars: Vec, // pointer to incidence -} - -impl ChunkInfo { - fn new(chunk_num: usize) -> Self { - ChunkInfo { chunk_num, vars: vec![] } - } + term_loc: GenContext, + // pointer to incidence, term occurrence arity. + vars: Vec, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -140,6 +144,23 @@ enum ChunkType { Last, } +impl ChunkType { + #[inline(always)] + fn to_gen_context(self, chunk_num: usize) -> GenContext { + match self { + ChunkType::Head => GenContext::Head, + ChunkType::Mid => GenContext::Mid(chunk_num), + ChunkType::Last => GenContext::Last(chunk_num), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ClassifyInfo { + arg_c: usize, + arity: usize, +} + enum TraversalState { // construct a QueryTerm::Branch with number of disjuncts, reset // the chunk type to that of the chunk preceding the disjunct. @@ -199,8 +220,15 @@ pub struct VarRecord { pub num_occurrences: usize, } -pub type ClassifyFactResult = (Term, Vec); -pub type ClassifyRuleResult = (Term, Vec, Vec); +// TODO: already exists a VarData! although it may no longer exist?? +// Also, the name is too similar to VarInfo. Think of better names! +pub struct VarData { + pub records: Vec, + pub fixtures: VariableFixtures, +} + +pub type ClassifyFactResult = (Term, VarData); +pub type ClassifyRuleResult = (Term, Vec, VarData); fn merge_branch_seq>(branches: Iter) -> BranchInfo { let mut branch_info = BranchInfo::new(BranchNumber::default()); @@ -238,19 +266,20 @@ fn flatten_into_disjunct(build_stack: &mut Vec, preceding_len: usize) fn term_in_other_chunk(term: &Term) -> Option { match term { - Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(name, terms.len())), + Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(*name, terms.len())), Term::Literal(_, Literal::Atom(atom!("!"))) | Term::Literal(_, Literal::Char('!')) => Some(false), - Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(name, 0)), + Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(*name, 0)), Term::Var(..) => Some(true), _ => None, } } // returns true if the insertion of SetLastChunkType was the final push. +// expects that iter iterates over a conjunct of Terms in reverse order. fn insert_set_last_chunk_type( state_stack: &mut Vec, - iter: impl Iterator, + mut iter: impl Iterator, ) -> bool { let beg = state_stack.len(); let mut idx = beg; @@ -269,6 +298,7 @@ fn insert_set_last_chunk_type( if will_break { state_stack.push(TraversalState::SetLastChunkType); state_stack.push(traversal_st); + break; } else { state_stack.push(traversal_st); @@ -356,15 +386,22 @@ impl VariableClassifier { } fn probe_body_term(&mut self, term: &Term, term_loc: GenContext) { + let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() }; + // second arg is true to iterate the root, which may be a variable for term_ref in breadth_first_iter(term, true) { - if let TermRef::Var(_, _, var_name) = term_ref { - self.probe_body_var(Var::from(var_name), term_loc); + if let TermRef::Var(lvl, _, var_name) = term_ref { + let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), lvl, classify_info }; + self.probe_body_var(var_name, term_loc, var_info); + } + + if let Level::Shallow = term_ref.level() { + classify_info.arg_c += 1; } } } - fn probe_body_var(&mut self, var_name: Var, chunk_type: ChunkType) { + fn probe_body_var(&mut self, var_name: Var, term_loc: GenContext, var_info: VarInfo) { let branch_info_v = self.branch_map.entry(var_name) .or_insert_with(|| vec![]); @@ -387,11 +424,15 @@ impl VariableClassifier { }; if needs_new_chunk { - branch_info.chunks.push(ChunkInfo::new(self.current_chunk_num)); + branch_info.chunks.push(ChunkInfo { + chunk_num: self.current_chunk_num, + term_loc, + vars: vec![], + }); } let chunk_info = branch_info.chunks.last_mut().unwrap(); - chunk_info.vars.push(VarPtr::from(&var_name)); + chunk_info.vars.push(var_info); } fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> { @@ -401,9 +442,14 @@ impl VariableClassifier { _ => return Err(CompilationError::InvalidRuleHead), } + let mut classify_info = ClassifyInfo { + arg_c: 0, + arity: term.arity(), + }; + // false argument to breadth_first_iter because the root is not iterable. for term_ref in breadth_first_iter(term, false) { - if let TermRef::Var(_, _, var_name) = term_ref { + if let TermRef::Var(lvl, _, var_name) = term_ref { // the body of the if let here is an inlined // "probe_head_var". note the difference between it // and "probe_body_var". @@ -420,11 +466,21 @@ impl VariableClassifier { let needs_new_chunk = branch_info.chunks.is_empty(); if needs_new_chunk { - branch_info.chunks.push(ChunkInfo::new(self.current_chunk_num)); + 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(); - chunk_info.vars.push(VarPtr::from(&var_name)); + let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), classify_info, lvl }; + + chunk_info.vars.push(var_info); + } + + if let Level::Shallow = term_ref.level() { + classify_info.arg_c += 1; } } @@ -584,6 +640,8 @@ impl VariableClassifier { } } Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => { + let term_loc = chunk_type.to_gen_context(self.current_chunk_num); + let predicate_name = terms.pop().unwrap(); let module_name = terms.pop().unwrap(); @@ -592,7 +650,7 @@ impl VariableClassifier { Term::Literal(_, Literal::Atom(module_name)), Term::Literal(_, Literal::Atom(predicate_name)), ) => { - if !ClauseType::is_inbuilt(name, 0) { + if !ClauseType::is_inbuilt(predicate_name, 0) { state_stack.push(TraversalState::IncrChunkNum); } @@ -649,6 +707,8 @@ impl VariableClassifier { } } Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 1 => { + let term_loc = chunk_type.to_gen_context(self.current_chunk_num); + for term in terms.iter() { self.probe_body_term(term, term_loc); } @@ -663,6 +723,8 @@ impl VariableClassifier { state_stack.push(TraversalState::IncrChunkNum); } + let term_loc = chunk_type.to_gen_context(self.current_chunk_num); + for term in terms.iter() { self.probe_body_term(term, term_loc); } @@ -694,6 +756,7 @@ impl VariableClassifier { ), ); } + _ => { return Err(CompilationError::InadmissibleQueryTerm); } @@ -707,25 +770,18 @@ impl VariableClassifier { } impl BranchMap { - pub fn separate_and_classify_variables(&mut self) -> Vec { - let mut var_num = 0usize; - let mut records = vec![]; + pub fn separate_and_classify_variables(&mut self) -> VarData { + let mut var_num = 0usize; + let mut var_data = VarData { + records: vec![], + fixtures: VariableFixtures::new(), + }; for branches in self.values_mut() { for branch in branches.iter_mut() { let mut num_occurrences = 0; let mut chunk_occurrences = vec![]; - for chunk in branch.chunks.iter_mut() { - num_occurrences += chunk.vars.len(); - - for var in chunk.vars.iter_mut() { - var.set(Var::Generated(var_num)); - } - - chunk_occurrences.push(chunk.chunk_num); - } - let classification = if branch.chunks.len() > 1 { VarClassification::Perm } else { @@ -739,13 +795,37 @@ impl BranchMap { .unwrap_or(VarClassification::Void) }; - records.push(VarRecord { classification, chunk_occurrences, num_occurrences }); + for chunk in branch.chunks.iter_mut() { + num_occurrences += chunk.vars.len(); + + if let VarClassification::Temp = classification { + for var_info in chunk.vars.iter_mut() { + var_info.var_ptr.set(Var::Generated(var_num)); + var_data.fixtures.mark_temp_var( + var_num, + var_info.lvl, + &var_info.classify_info, + chunk.term_loc, + ); + } + } else { + for var_info in chunk.vars.iter_mut() { + var_info.var_ptr.set(Var::Generated(var_num)); + } + } + + chunk_occurrences.push(chunk.chunk_num); + } + + let record = VarRecord { classification, chunk_occurrences, num_occurrences }; + var_data.records.push(record); + var_num += 1; } } - debug_assert_eq!(records.len(), var_num); + debug_assert_eq!(var_data.records.len(), var_num); - records + var_data } } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 78bd55b4..73c91c6a 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -227,7 +227,7 @@ macro_rules! perm_v { }; } -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum GenContext { Head, Mid(usize), From 063cf0c60869d54310182eb2f3b48ca2f1fefdc8 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 5 Dec 2022 20:49:23 -0700 Subject: [PATCH 07/40] new TermIterState variants --- src/codegen.rs | 23 +++-- src/debray_allocator.rs | 12 +-- src/fixtures.rs | 39 ++------ src/forms.rs | 12 +-- src/iterators.rs | 178 ++++++++++++++++----------------- src/machine/compile.rs | 10 +- src/machine/disjuncts.rs | 3 + src/machine/machine_indices.rs | 2 +- src/machine/preprocessor.rs | 10 +- 9 files changed, 141 insertions(+), 148 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 65f49971..ec631564 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -456,6 +456,7 @@ impl<'b> CodeGenerator<'b> { target } + /* fn collect_var_data<'a>(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> { let mut vs = VariableFixtures::new(); @@ -486,6 +487,7 @@ impl<'b> CodeGenerator<'b> { let vs = self.marker.drain_var_data(vs, num_of_chunks); ConjunctInfo::new(vs, num_of_chunks, has_deep_cut) } + */ fn add_conditional_call(&mut self, code: &mut Code, qt: &QueryTerm, pvs: usize) { match qt { @@ -912,7 +914,8 @@ impl<'b> CodeGenerator<'b> { Ok(()) } - fn compile_seq_prelude(&mut self, conjunct_info: &ConjunctInfo, body: &mut Code) { + fn compile_seq_prelude(&mut self, var_data: &VarData, body: &mut Code) { + /* if conjunct_info.allocates() { let perm_vars = conjunct_info.perm_vars(); @@ -922,6 +925,7 @@ impl<'b> CodeGenerator<'b> { body.push(Instruction::GetLevel(perm_v!(1))); } } + */ } fn compile_cleanup( @@ -955,18 +959,19 @@ impl<'b> CodeGenerator<'b> { } pub(crate) fn compile_rule(&mut self, rule: &Rule) -> Result { - let iter = ChunkedIterator::from_rule(rule); - let conjunct_info = self.collect_var_data(iter); + // let iter = ChunkedIterator::from_rule(rule); + // let conjunct_info = self.collect_var_data(iter); let &Rule { head: (_, ref args, ref p1), ref clauses, + ref var_data, } = rule; let mut code = Code::new(); self.marker.reset_at_head(args); - self.compile_seq_prelude(&conjunct_info, &mut code); + self.compile_seq_prelude(&var_data, &mut code); let iter = FactIterator::from_rule_head_clause(args); let mut fact = self.compile_target::(iter, GenContext::Head); @@ -1015,15 +1020,15 @@ impl<'b> CodeGenerator<'b> { UnsafeVarMarker::from_fact_vars(safe_vars) } - pub(crate) fn compile_fact(&mut self, term: &Term) -> Result { + pub(crate) fn compile_fact(&mut self, fact: &Fact) -> Result { self.update_var_count(post_order_iter(term)); - let mut vs = VariableFixtures::new(); + // let mut vs = VariableFixtures::new(); - vs.mark_vars_in_chunk(post_order_iter(term), term.arity(), GenContext::Head); + // vs.mark_vars_in_chunk(post_order_iter(term), term.arity(), GenContext::Head); - vs.populate_restricting_sets(); - self.marker.drain_var_data(vs, 1); + // vs.populate_restricting_sets(); + // self.marker.drain_var_data(vs, 1); let mut code = Vec::new(); diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 73645929..2ad19cab 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -17,7 +17,7 @@ use std::collections::BTreeSet; #[derive(Debug)] pub(crate) struct DebrayAllocator { - bindings: IndexMap, + bindings: IndexMap, arg_c: usize, temp_lb: usize, arity: usize, // 0 if not at head. @@ -36,7 +36,7 @@ impl DebrayAllocator { fn occurs_shallowly_in_head(&self, var: &Var, r: usize) -> bool { match self.bindings.get(var).unwrap() { - &VarData::Temp(_, _, ref tvd) => tvd.use_set.contains(&(GenContext::Head, r)), + &VarAlloc::Temp(_, _, ref tvd) => tvd.use_set.contains(&(GenContext::Head, r)), _ => false, } } @@ -49,7 +49,7 @@ impl DebrayAllocator { fn alloc_with_cr(&self, var: &Var) -> usize { match self.bindings.get(var) { - Some(&VarData::Temp(_, _, ref tvd)) => { + Some(&VarAlloc::Temp(_, _, ref tvd)) => { for &(_, reg) in tvd.use_set.iter() { if !self.is_in_use(reg) { return reg; @@ -75,7 +75,7 @@ impl DebrayAllocator { fn alloc_with_ca(&self, var: &Var) -> usize { match self.bindings.get(var) { - Some(&VarData::Temp(_, _, ref tvd)) => { + Some(&VarAlloc::Temp(_, _, ref tvd)) => { for &(_, reg) in tvd.use_set.iter() { if !self.is_in_use(reg) { return reg; @@ -114,7 +114,7 @@ impl DebrayAllocator { // (GenContext::Last(_), k) is in t_var.use_set. let tvd = self.bindings.get(t_var).unwrap(); - if let &VarData::Temp(_, _, ref tvd) = tvd { + if let &VarAlloc::Temp(_, _, ref tvd) = tvd { if !tvd.use_set.contains(&(GenContext::Last(chunk_num), k)) { return Some((t_var.clone(), self.alloc_with_ca(t_var))); } @@ -205,7 +205,7 @@ impl DebrayAllocator { match term_loc { GenContext::Head if !r.is_perm() => r.reg_num() == k, _ => match self.bindings().get(var).unwrap() { - &VarData::Temp(_, o, _) if r.reg_num() == k => o == k, + &VarAlloc::Temp(_, o, _) if r.reg_num() == k => o == k, _ => false, }, } diff --git a/src/fixtures.rs b/src/fixtures.rs index f75a8042..5f73c716 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -1,17 +1,11 @@ -use crate::parser::ast::*; - use crate::forms::*; use crate::instructions::*; -use crate::iterators::*; +use crate::machine::disjuncts::ClassifyInfo; +use crate::parser::ast::*; use bit_set::*; use indexmap::{IndexMap, IndexSet}; -use std::cell::Cell; -use std::collections::BTreeSet; -use std::mem::swap; -use std::vec::Vec; - pub(crate) type OccurrenceSet = IndexSet<(GenContext, usize)>; #[derive(Debug)] @@ -28,20 +22,19 @@ pub(crate) struct TempVarStatus { temp_var_data: TempVarData, } -// TODO: get ridda this! I think. // Perm: 0 initially, a stack register once processed. // Temp: labeled with chunk_num and temp offset (unassigned if 0). #[derive(Debug)] -pub(crate) enum VarData { +pub(crate) enum VarAlloc { Perm(usize), Temp(usize, usize, TempVarData), } -impl VarData { +impl VarAlloc { pub(crate) fn as_reg_type(&self) -> RegType { match self { - &VarData::Temp(_, r, _) => RegType::Temp(r), - &VarData::Perm(r) => RegType::Perm(r), + &VarAlloc::Temp(_, r, _) => RegType::Temp(r), + &VarAlloc::Perm(r) => RegType::Perm(r), } } } @@ -50,7 +43,7 @@ impl TempVarData { pub(crate) fn new(last_term_arity: usize) -> Self { TempVarData { last_term_arity: last_term_arity, - use_set: BitSet::new(), + use_set: BitSet::::new(), no_use_set: BitSet::new(), conflict_set: BitSet::new(), } @@ -72,7 +65,7 @@ impl TempVarData { let mut conflict_set: BitSet = (1..arity).collect(); for &(_, reg) in self.use_set.iter() { - conflict_set.remove(®); + conflict_set.remove(reg); } self.conflict_set = conflict_set; @@ -83,27 +76,15 @@ impl TempVarData { #[derive(Debug)] pub(crate) struct VariableFixtures { temp_vars: IndexMap, - last_chunk_temp_vars: IndexSet, // TODO: has no use at all! remove it. } -impl<'a> VariableFixtures<'a> { +impl VariableFixtures { pub(crate) fn new() -> Self { VariableFixtures { temp_vars: IndexMap::new(), - last_chunk_temp_vars: IndexSet::new(), } } - // TODO: get rid of this also. - pub(crate) fn insert(&mut self, var: Var, vs: VariableFixture<'a>) { - self.temp_vars.insert(var, vs); - } - - // TODO: used? - pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Var) { - self.last_chunk_temp_vars.insert(var); - } - // computes no_use and conflict sets for all temp vars. pub(crate) fn populate_restricting_sets(&mut self) { // three stages: @@ -121,7 +102,7 @@ impl<'a> VariableFixtures<'a> { let TempVarStatus { ref mut temp_var_data, .. } = var_status; let mut use_set = OccurrenceSet::new(); - mem::swap(&mut temp_var_data.use_set, &mut use_set); + std::mem::swap(&mut temp_var_data.use_set, &mut use_set); use_sets.insert(var_gen_index, use_set); } diff --git a/src/forms.rs b/src/forms.rs index d571e2d9..2b46da2c 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,7 +1,7 @@ use crate::arena::*; use crate::atom_table::*; use crate::instructions::*; -use crate::machine::disjuncts::VarRecord; +use crate::machine::disjuncts::VarData; use crate::machine::heap::*; use crate::machine::loader::PredicateQueue; use crate::machine::machine_errors::*; @@ -57,7 +57,7 @@ impl AppendOrPrepend { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Level { Deep, Root, @@ -79,7 +79,7 @@ pub enum CallPolicy { Counted, } -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum QueryTerm { // register, clause type, subterms, clause call policy. Clause(Cell, ClauseType, Vec, CallPolicy), @@ -111,14 +111,14 @@ impl QueryTerm { #[derive(Debug, Clone)] pub struct Fact { pub(crate) head: Term, - pub(crate) var_records: Vec, + pub(crate) var_data: VarData, } #[derive(Debug, Clone)] pub struct Rule { pub(crate) head: (Atom, Vec, QueryTerm), pub(crate) clauses: Vec, - pub(crate) var_records: Vec, + pub(crate) var_data: VarData, } #[derive(Clone, Debug, Hash)] @@ -224,7 +224,7 @@ impl ClauseInfo for PredicateClause { #[derive(Debug, Clone)] pub enum PredicateClause { - Fact(Term), + Fact(Fact), Rule(Rule), } diff --git a/src/iterators.rs b/src/iterators.rs index bbd9fb70..8750fe87 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -43,24 +43,36 @@ impl VarPtr { #[derive(Debug, Clone)] pub(crate) enum TermRef<'a> { AnonVar(Level), + Cut(Level), + GetLevel(Level), Cons(Level, &'a Cell, &'a Term, &'a Term), + Fail(Level), Literal(Level, &'a Cell, &'a Literal), Clause(Level, &'a Cell, Atom, &'a Vec), PartialString(Level, &'a Cell, &'a String, &'a Box), CompleteString(Level, &'a Cell, Atom), Var(Level, &'a Cell, Var), + InitialBranch(Level), + MiddleBranch(Level), + FinalBranch(Level), } 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, + TermRef::AnonVar(lvl) | + TermRef::Cons(lvl, ..) | + TermRef::Cut(lvl) | + TermRef::GetLevel(lvl) | + TermRef::Literal(lvl, ..) | + TermRef::Var(lvl, ..) | + TermRef::Clause(lvl, ..) | + TermRef::CompleteString(lvl, ..) | + TermRef::PartialString(lvl, ..) | + TermRef::InitialBranch(lvl) | + TermRef::MiddleBranch(lvl) | + TermRef::FinalBranch(lvl) | + TermRef::Fail(lvl) => lvl, } } } @@ -68,14 +80,20 @@ impl<'a> TermRef<'a> { #[derive(Debug)] pub(crate) enum TermIterState<'a> { AnonVar(Level), - Literal(Level, &'a Cell, &'a Literal), Clause(Level, usize, &'a Cell, Atom, &'a Vec), + Cut(Level), + Fail(Level), + GetLevel(Level), + InitialBranch(Level, &'a Vec), + MiddleBranch(Level, &'a Vec), + FinalBranch(Level, &'a Vec), + Sequence(Level, &'a Vec), + Literal(Level, &'a Cell, &'a Literal), InitialCons(Level, &'a Cell, &'a Term, &'a Term), FinalCons(Level, &'a Cell, &'a Term, &'a Term), InitialPartialString(Level, &'a Cell, &'a String, &'a Box), FinalPartialString(Level, &'a Cell, &'a String, &'a Box), CompleteString(Level, &'a Cell, Atom), - UnblockedCut(Level, &'a Cell), Var(Level, &'a Cell, VarPtr), } @@ -108,8 +126,7 @@ pub(crate) struct QueryIterator<'a> { impl<'a> QueryIterator<'a> { fn push_subterm(&mut self, lvl: Level, term: &'a Term) { - self.state_stack - .push(TermIterState::subterm_to_state(lvl, term)); + self.state_stack.push(TermIterState::subterm_to_state(lvl, term)); } fn from_rule_head_clause(terms: &'a Vec) -> Self { @@ -145,47 +162,52 @@ impl<'a> QueryIterator<'a> { } } - fn new(term: &'a QueryTerm) -> Self { + fn extend_state(&mut self, lvl: Level, term: &'a QueryTerm) { match term { &QueryTerm::Clause(ref cell, ClauseType::CallN(_), ref terms, _) => { - let state = TermIterState::Clause(Level::Root, 1, cell, atom!("$call"), terms); - QueryIterator { - state_stack: vec![state], - } + self.state_stack.push(TermIterState::Clause(lvl, 1, cell, atom!("$call"), terms)); } &QueryTerm::Clause(ref cell, ref ct, ref terms, _) => { - let state = TermIterState::Clause(Level::Root, 0, cell, ct.name(), terms); - QueryIterator { - state_stack: vec![state], - } + self.state_stack.push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms)); } - &QueryTerm::UnblockedCut(ref cell) => { - let state = TermIterState::UnblockedCut(Level::Root, cell); - - QueryIterator { - state_stack: vec![state], - } + &QueryTerm::Cut => { + self.state_stack.push(TermIterState::Cut(lvl)); } &QueryTerm::GetLevelAndUnify(ref cell, ref var) => { - let state = TermIterState::Var(Level::Root, cell, VarPtr::from(var)); - QueryIterator { - state_stack: vec![state], - } + // TODO: get rid of it if possible. or! specialized TermIterState variant. + self.state_stack.push(TermIterState::Var(lvl, cell, VarPtr::from(var))); } - &QueryTerm::Jump(ref vars) => { - let state_stack = vars + &QueryTerm::Not(ref terms) => { + self.state_stack.push(TermIterState::Fail(lvl)); + self.state_stack.push(TermIterState::Cut(lvl)); + self.state_stack.push(TermIterState::Sequence(lvl, terms)); + } + &QueryTerm::IfThen(ref if_terms, ref then_terms) => { + self.state_stack.push(TermIterState::Sequence(lvl, then_terms)); + self.state_stack.push(TermIterState::Cut(lvl)); + self.state_stack.push(TermIterState::Sequence(lvl, if_terms)); + self.state_stack.push(TermIterState::GetLevel(lvl)); + } + &QueryTerm::Branch(ref branches) => { + let len = branches.len(); + self.state_stack.push(TermIterState::FinalBranch(lvl, &branches[len - 1])); + + self.state_stack.extend(branches[1 .. len - 1] .iter() .rev() - .map(|t| TermIterState::subterm_to_state(Level::Shallow, t)) - .collect(); + .map(|t| TermIterState::MiddleBranch(lvl, t)), + ); - QueryIterator { state_stack } + self.state_stack.push(TermIterState::InitialBranch(lvl, &branches[0])); } - &QueryTerm::BlockedCut => QueryIterator { - state_stack: vec![], - }, } } + + fn new(term: &'a QueryTerm) -> Self { + let mut iter = QueryIterator { state_stack: vec![] }; + iter.extend_state(Level::Root, term); + iter + } } impl<'a> Iterator for QueryIterator<'a> { @@ -247,8 +269,31 @@ impl<'a> Iterator for QueryIterator<'a> { TermIterState::Var(lvl, cell, var) => { return Some(TermRef::Var(lvl, cell, Var::from(var))); } - TermIterState::UnblockedCut(lvl, cell) => { - return Some(TermRef::Var(lvl, cell, Var::from("!"))); + TermIterState::Cut(lvl) => { + return Some(TermRef::Cut(lvl)); + } + TermIterState::GetLevel(lvl) => { + return Some(TermRef::GetLevel(lvl)); + } + TermIterState::InitialBranch(lvl, ref branch) => { + self.state_stack.push(TermIterState::Sequence(lvl, branch)); + return Some(TermRef::InitialBranch(lvl)); + } + TermIterState::MiddleBranch(lvl, ref branch) => { + self.state_stack.push(TermIterState::Sequence(lvl, branch)); + return Some(TermRef::MiddleBranch(lvl)); + } + TermIterState::FinalBranch(lvl, ref branch) => { + self.state_stack.push(TermIterState::Sequence(lvl, branch)); + return Some(TermRef::FinalBranch(lvl)); + } + TermIterState::Sequence(lvl, ref terms) => { + for term in branch.iter().rev() { + self.extend_state(lvl, term); + } + } + TermIterState::Fail(lvl) => { + return Some(TermRef::Fail(lvl)); } }; } @@ -398,23 +443,9 @@ impl<'a> ChunkedTerm<'a> { } } -fn contains_cut_var<'a, Iter: Iterator>(terms: Iter) -> bool { - for term in terms { - if let &Term::Var(_, ref var) = term { - if var.as_str() == Some("!") { - return true; - } - } - } - - false -} - pub(crate) struct ChunkedIterator<'a> { pub(crate) chunk_num: usize, iter: Box> + 'a>, - deep_cut_encountered: bool, - cut_var_in_head: bool, } impl<'a> fmt::Debug for ChunkedIterator<'a> { @@ -423,8 +454,6 @@ impl<'a> fmt::Debug for ChunkedIterator<'a> { .field("chunk_num", &self.chunk_num) // Hacky solution. .field("iter", &"Box> + 'a>") - .field("deep_cut_encountered", &self.deep_cut_encountered) - .field("cut_var_in_head", &self.cut_var_in_head) .finish() } } @@ -458,8 +487,6 @@ impl<'a> ChunkedIterator<'a> { ChunkedIterator { chunk_num: 0, iter: Box::new(iter), - deep_cut_encountered: false, - cut_var_in_head: false, } } @@ -467,6 +494,7 @@ impl<'a> ChunkedIterator<'a> { let &Rule { head: (ref name, ref args, ref p1), ref clauses, + .. } = rule; let iter = once(ChunkedTerm::HeadClause(name.clone(), args)); @@ -476,15 +504,9 @@ impl<'a> ChunkedIterator<'a> { ChunkedIterator { chunk_num: 0, iter: Box::new(iter), - deep_cut_encountered: false, - cut_var_in_head: false, } } - pub(crate) fn encountered_deep_cut(&self) -> bool { - self.deep_cut_encountered - } - fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec>) { let mut arity = 0; let mut item = Some(term); @@ -493,42 +515,18 @@ impl<'a> ChunkedIterator<'a> { while let Some(term) = item { match term { ChunkedTerm::HeadClause(_, terms) => { - if contains_cut_var(terms.iter()) { - self.cut_var_in_head = true; - } - result.push(term); } - ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => { + ChunkedTerm::BodyTerm(&QueryTerm::Cut) => { result.push(term); - arity = vars.len(); - - if contains_cut_var(vars.iter()) && !self.cut_var_in_head { - self.deep_cut_encountered = true; - } - - break; - } - ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => { - result.push(term); - - if self.chunk_num > 0 { - self.deep_cut_encountered = true; - } } ChunkedTerm::BodyTerm(&QueryTerm::GetLevelAndUnify(..)) => { - self.deep_cut_encountered = true; - result.push(term); arity = 1; break; } - ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut(..)) => { - self.deep_cut_encountered = true; - result.push(term); - } ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => { - result.push(term) + result.push(term); } ChunkedTerm::BodyTerm(&QueryTerm::Clause( _, diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 5f3d8e28..428e2952 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -57,6 +57,7 @@ pub(super) fn compile_relation( } } +/* pub(super) fn compile_appendix( code: &mut Code, mut queue: VecDeque, @@ -97,6 +98,7 @@ pub(super) fn compile_appendix( Ok(()) } +*/ fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize { if target_pos == 0 { @@ -1342,7 +1344,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let mut preprocessor = Preprocessor::new(settings); let clause = self.try_term_to_tl(term, &mut preprocessor)?; - let queue = preprocessor.parse_queue(self)?; + // let queue = preprocessor.parse_queue(self)?; let mut cg = CodeGenerator::new( &mut LS::machine_st(&mut self.payload).atom_tbl, @@ -1351,6 +1353,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let mut clause_code = cg.compile_predicate(&vec![clause])?; + /* compile_appendix( &mut clause_code, queue, @@ -1358,6 +1361,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { settings.non_counted_bt, cg.atom_tbl, )?; + */ Ok(StandaloneCompileResult { clause_code, @@ -1385,7 +1389,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { clauses.push(self.try_term_to_tl(term, &mut preprocessor)?); } - let queue = preprocessor.parse_queue(self)?; + // let queue = preprocessor.parse_queue(self)?; let mut cg = CodeGenerator::new( &mut LS::machine_st(&mut self.payload).atom_tbl, @@ -1394,6 +1398,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let mut code = cg.compile_predicate(&clauses)?; + /* compile_appendix( &mut code, queue, @@ -1401,6 +1406,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { settings.non_counted_bt, cg.atom_tbl, )?; + */ if settings.is_extensible { let mut clause_clause_locs = VecDeque::new(); diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 19e460c3..3231c652 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -487,6 +487,8 @@ impl VariableClassifier { Ok(()) } + // TODO: maybe replace Vec with an iterator that has, in the stream, + // with a 'QueryTerm' that toggles the chunk num and type, like we do here. fn classify_body_variables<'a, LS: LoadState<'a>>( &mut self, loader: &mut Loader<'a, LS>, @@ -826,6 +828,7 @@ impl BranchMap { debug_assert_eq!(var_data.records.len(), var_num); + var_data.fixtures.populate_restricting_sets(); var_data } } diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 3f49e1ce..afa2bea2 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -228,7 +228,7 @@ impl CodeIndex { } pub(crate) type HeapVarDict = IndexMap; -pub(crate) type AllocVarDict = IndexMap; +pub(crate) type AllocVarDict = IndexMap; pub(crate) type GlobalVarDir = IndexMap), FxBuildHasher>; diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 0564af8c..02e0e29f 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -553,9 +553,9 @@ impl Preprocessor { self.settings.default_call_policy(), ); - let (head, var_records) = classifier.classify_fact(term)?; + let (head, var_data) = classifier.classify_fact(term)?; - Ok(Fact { head, var_records }) + Ok(Fact { head, var_data }) } _ => Err(CompilationError::InadmissibleFact), } @@ -571,7 +571,7 @@ impl Preprocessor { self.settings.default_call_policy(), ); - let (head, mut query_terms, var_records) = + let (head, mut query_terms, var_data) = classifier.classify_rule(loader, head, body)?; let clauses = query_terms.drain(1..).collect(); @@ -581,12 +581,12 @@ impl Preprocessor { Term::Clause(_, name, terms) => Ok(Rule { head: (name, terms, qt), clauses, - var_records, + var_data, }), Term::Literal(_, Literal::Atom(name)) => Ok(Rule { head: (name, vec![], qt), clauses, - var_records, + var_data, }), _ => Err(CompilationError::InvalidRuleHead), } From c4783062ff14bb8f402b09bbaca96aacb612a98c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 27 Dec 2022 21:29:29 -0700 Subject: [PATCH 08/40] delete ChunkedTerm, chunked iteration --- src/iterators.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/iterators.rs b/src/iterators.rs index 8750fe87..eac1b185 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -424,6 +424,7 @@ pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: bool) -> Fac FactIterator::new(term, iterable_root) } +/* #[derive(Debug)] pub(crate) enum ChunkedTerm<'a> { HeadClause(Atom, &'a Vec), @@ -563,3 +564,4 @@ impl<'a> Iterator for ChunkedIterator<'a> { self.iter.next().map(|term| self.take_chunk(term)) } } +*/ From 097849385ee50ba49a1b7a06125ece28bab597b8 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 27 Dec 2022 23:19:18 -0700 Subject: [PATCH 09/40] add QueryTerm::ChunkTypeBoundary --- src/forms.rs | 19 +++++++++++++++ src/machine/disjuncts.rs | 50 +++++----------------------------------- 2 files changed, 25 insertions(+), 44 deletions(-) diff --git a/src/forms.rs b/src/forms.rs index 2b46da2c..4d7b7f47 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -79,6 +79,24 @@ pub enum CallPolicy { Counted, } +#[derive(Debug, Clone, Copy)] +enum ChunkType { + Head, + Mid, + Last, +} + +impl ChunkType { + #[inline(always)] + pub fn to_gen_context(self, chunk_num: usize) -> GenContext { + match self { + ChunkType::Head => GenContext::Head, + ChunkType::Mid => GenContext::Mid(chunk_num), + ChunkType::Last => GenContext::Last(chunk_num), + } + } +} + #[derive(Debug)] pub enum QueryTerm { // register, clause type, subterms, clause call policy. @@ -88,6 +106,7 @@ pub enum QueryTerm { IfThen(Vec, Vec), Branch(Vec>), GetLevelAndUnify(Cell, Var), + ChunkTypeBoundary(ChunkType), } impl QueryTerm { diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 3231c652..501aaddd 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -137,24 +137,6 @@ impl DerefMut for BranchMap { type RootSet = IndexSet; -#[derive(Debug, Clone, Copy)] -enum ChunkType { - Head, - Mid, - Last, -} - -impl ChunkType { - #[inline(always)] - fn to_gen_context(self, chunk_num: usize) -> GenContext { - match self { - ChunkType::Head => GenContext::Head, - ChunkType::Mid => GenContext::Mid(chunk_num), - ChunkType::Last => GenContext::Last(chunk_num), - } - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ClassifyInfo { arg_c: usize, @@ -257,7 +239,7 @@ fn merge_branch_seq>(branches: Iter) -> Branch } fn flatten_into_disjunct(build_stack: &mut Vec, preceding_len: usize) { - let iter = build_stack.drain(preceding_len ..); + let iter = build_stack.drain(preceding_len + 1 ..); if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { disjuncts.push(iter.collect()); @@ -342,28 +324,6 @@ impl VariableClassifier { Ok((head, query_terms, self.branch_map.separate_and_classify_variables())) } - /* - pub fn to_branch_map(mut self, term: Term) -> Result { - self.root_set.insert(BranchNumber::default()); - - let (head_term, query_terms) = match term { - Term::Clause(_, atom!(":-"), terms) if terms.len() == 2 => { - let head_term = terms[0]; - - self.classify_head_variables(&head_term)?; - (head_term, self.classify_body_variables(terms[1])?) - } - _ => { - self.classify_head_variables(&term)?; - (term, vec![]) - } - }; - - self.merge_branches(); - Ok((head_term, query_terms, self.branch_map)) - } - */ - fn merge_branches(&mut self) { for branches in self.branch_map.values_mut() { let mut old_branches = std::mem::replace(branches, vec![]); @@ -487,8 +447,6 @@ impl VariableClassifier { Ok(()) } - // TODO: maybe replace Vec with an iterator that has, in the stream, - // with a 'QueryTerm' that toggles the chunk num and type, like we do here. fn classify_body_variables<'a, LS: LoadState<'a>>( &mut self, loader: &mut Loader<'a, LS>, @@ -515,15 +473,18 @@ impl VariableClassifier { TraversalState::IncrChunkNum => { self.current_chunk_num += 1; chunk_type = ChunkType::Mid; + build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type)); } TraversalState::ResetCallPolicy(call_policy) => { self.call_policy = call_policy; } TraversalState::SetLastChunkType => { chunk_type = ChunkType::Last; + build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type)); } TraversalState::BuildDisjunct(reset_chunk_type, preceding_len) => { chunk_type = reset_chunk_type; + build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type)); flatten_into_disjunct(&mut build_stack, preceding_len); } TraversalState::BuildFinalDisjunct(preceding_len) => { @@ -579,7 +540,7 @@ impl VariableClassifier { } let build_stack_len = build_stack.len(); - build_stack.push(QueryTerm::Branch(vec![])); + build_stack.push(QueryTerm::Branch(Vec::with_capacity(branches.len()))); state_stack.push(TraversalState::RepBranchNum( self.current_branch_num.halve_delta(), @@ -630,6 +591,7 @@ impl VariableClassifier { state_stack.push(TraversalState::IncrChunkNum); // TODO: need to classify this variable? + // what is the difference between $get_cp and this exactly? if let Term::Var(_, ref var) = &terms[0] { build_stack.push( QueryTerm::GetLevelAndUnify( From 942095baa773706d136de550db13476d8a19c617 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 27 Dec 2022 23:42:35 -0700 Subject: [PATCH 10/40] remove GetLevelAndUnify and replace it with GetCutPoint --- build/instructions_template.rs | 6 ------ src/codegen.rs | 22 ---------------------- src/forms.rs | 3 +-- src/iterators.rs | 9 --------- src/lib/iso_ext.pl | 6 +++--- src/machine/disjuncts.rs | 18 +----------------- src/machine/dispatch.rs | 11 ----------- 7 files changed, 5 insertions(+), 70 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index a7ea3d21..d0a8c4d0 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -639,8 +639,6 @@ enum InstructionTemplate { Cut(RegType), #[strum_discriminants(strum(props(Arity = "1", Name = "get_level")))] GetLevel(RegType), - #[strum_discriminants(strum(props(Arity = "1", Name = "get_level_and_unify")))] - GetLevelAndUnify(RegType), #[strum_discriminants(strum(props(Arity = "0", Name = "neck_cut")))] NeckCut, // choice instruction @@ -1298,10 +1296,6 @@ fn generate_instruction_preface() -> TokenStream { let rt_stub = reg_type_into_functor(r); functor!(atom!("get_level"), [str(h, 0)], [rt_stub]) } - &Instruction::GetLevelAndUnify(r) => { - let rt_stub = reg_type_into_functor(r); - functor!(atom!("get_level_and_unify"), [str(h, 0)], [rt_stub]) - } &Instruction::NeckCut => { functor!(atom!("neck_cut")) } diff --git a/src/codegen.rs b/src/codegen.rs index ec631564..e7c6e2ac 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -840,25 +840,6 @@ impl<'b> CodeGenerator<'b> { code.push(instr!("$set_cp", cell.get().norm(), 0)); } - fn compile_get_level_and_unify( - &mut self, - code: &mut Code, - cell: &Cell, - var: Var, - term_loc: GenContext, - ) { - let mut target = Code::new(); - - self.marker.reset_arg(1); - self.marker.mark_var::(var, Level::Shallow, cell, term_loc, &mut target); - - if !target.is_empty() { - code.extend(target.into_iter()); - } - - code.push(instr!("get_level_and_unify", cell.get().norm())); - } - fn compile_seq<'a>( &mut self, iter: ChunkedIterator<'a>, @@ -874,9 +855,6 @@ impl<'b> CodeGenerator<'b> { }; match *term { - &QueryTerm::GetLevelAndUnify(ref cell, ref var) => { - self.compile_get_level_and_unify(code, cell, var.clone(), term_loc) - } &QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell), &QueryTerm::BlockedCut => code.push(if chunk_num == 0 { Instruction::NeckCut diff --git a/src/forms.rs b/src/forms.rs index 4d7b7f47..ac7649d5 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -105,7 +105,6 @@ pub enum QueryTerm { Not(Vec), IfThen(Vec, Vec), Branch(Vec>), - GetLevelAndUnify(Cell, Var), ChunkTypeBoundary(ChunkType), } @@ -122,7 +121,7 @@ impl QueryTerm { &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), &QueryTerm::Cut | &QueryTerm::Branch(_) => 0, &QueryTerm::IfThen(..) => 2, - &QueryTerm::Not(_) | &QueryTerm::GetLevelAndUnify(..) => 1, + &QueryTerm::Not(_) => 1, } } } diff --git a/src/iterators.rs b/src/iterators.rs index eac1b185..e1834113 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -173,10 +173,6 @@ impl<'a> QueryIterator<'a> { &QueryTerm::Cut => { self.state_stack.push(TermIterState::Cut(lvl)); } - &QueryTerm::GetLevelAndUnify(ref cell, ref var) => { - // TODO: get rid of it if possible. or! specialized TermIterState variant. - self.state_stack.push(TermIterState::Var(lvl, cell, VarPtr::from(var))); - } &QueryTerm::Not(ref terms) => { self.state_stack.push(TermIterState::Fail(lvl)); self.state_stack.push(TermIterState::Cut(lvl)); @@ -521,11 +517,6 @@ impl<'a> ChunkedIterator<'a> { ChunkedTerm::BodyTerm(&QueryTerm::Cut) => { result.push(term); } - ChunkedTerm::BodyTerm(&QueryTerm::GetLevelAndUnify(..)) => { - result.push(term); - arity = 1; - break; - } ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => { result.push(term); } diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index f22420af..d6f13df0 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -175,7 +175,7 @@ scc_helper(_, _, _) :- run_cleaners_with_handling :- '$get_scc_cleaner'(C), - '$get_level'(B), + '$get_cp'(B), catch(C, _, true), '$set_cp_by_default'(B), run_cleaners_with_handling. @@ -186,7 +186,7 @@ run_cleaners_with_handling :- run_cleaners_without_handling(Cp) :- '$get_scc_cleaner'(C), - '$get_level'(B), + '$get_cp'(B), call(C), '$set_cp_by_default'(B), run_cleaners_without_handling(Cp). @@ -258,7 +258,7 @@ call_with_inference_limit(_, _, R, Bb, B) :- '$remove_inference_counter'(B, _), ( '$get_ball'(Ball), '$push_ball_stack', - '$get_level'(Cp), + '$get_cp'(Cp), '$set_cp_by_default'(Cp) ; '$remove_call_policy_check'(B), '$fail' diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 501aaddd..ee1711e6 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -566,7 +566,7 @@ impl VariableClassifier { let build_stack_len = build_stack.len(); - // TODO: insert GetLevelAndUnify between + // TODO: insert GetCutPoint between // the two traversal states and detect // that as a chunk boundary in // insert_set_last_chunk_type ?? @@ -587,22 +587,6 @@ impl VariableClassifier { state_stack.push(TraversalState::BuildNot(build_stack_len)); state_stack.push(TraversalState::Term(terms[0])); } - Term::Clause(_, atom!("$get_level"), terms) if terms.len() == 1 => { - state_stack.push(TraversalState::IncrChunkNum); - - // TODO: need to classify this variable? - // what is the difference between $get_cp and this exactly? - if let Term::Var(_, ref var) = &terms[0] { - build_stack.push( - QueryTerm::GetLevelAndUnify( - Cell::default(), - var.clone(), - ), - ); - } else { - return Err(CompilationError::InadmissibleQueryTerm); - } - } Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => { let term_loc = chunk_type.to_gen_context(self.current_chunk_num); diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 04f39428..92eca80f 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -1152,17 +1152,6 @@ impl Machine { self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(b0 as i64)); self.machine_st.p += 1; } - &Instruction::GetLevelAndUnify(r) => { - // let b0 = self.machine_st[perm_v!(1)]; - let b0 = cell_as_fixnum!( - self.machine_st.stack[stack_loc!(AndFrame, self.machine_st.e, 1)] - ); - let a = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); - - // unify_fn!(&mut self.machine_st, a, b0); - self.machine_st.unify_fixnum(b0, a); - step_or_fail!(self, self.machine_st.p += 1); - } &Instruction::Cut(r) => { let value = self.machine_st[r]; self.machine_st.cut_body(value); From cb59c3003af10c872a1b13a36cae511ff2bfca94 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 1 Jan 2023 11:04:46 -0700 Subject: [PATCH 11/40] correct chunk type labeling --- Cargo.lock | 59 +++++++++++++++++++++++++++++++++++++++- src/fixtures.rs | 2 +- src/forms.rs | 10 +++++-- src/machine/disjuncts.rs | 44 ++++++++++++++++-------------- 4 files changed, 91 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cc11f21..542afd09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2608,9 +2608,30 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" +name = "windows-sys" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] @@ -2625,6 +2646,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + [[package]] name = "windows_i686_gnu" version = "0.36.1" @@ -2637,6 +2664,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + [[package]] name = "windows_i686_msvc" version = "0.36.1" @@ -2649,6 +2682,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" @@ -2667,6 +2706,18 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" @@ -2679,6 +2730,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + [[package]] name = "xmlparser" version = "0.13.5" diff --git a/src/fixtures.rs b/src/fixtures.rs index 5f73c716..9e1f28fe 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -148,7 +148,7 @@ impl VariableFixtures { ) { let chunk_num = term_loc.chunk_num(); - let mut status = self.temp_vars.swap_remove(generated_var_index).unwrap_or_else(|| { + let mut status = self.temp_vars.swap_remove(&generated_var_index).unwrap_or_else(|| { TempVarStatus { chunk_num, temp_var_data: TempVarData::new(classify_info.arity), diff --git a/src/forms.rs b/src/forms.rs index ac7649d5..9cc6f1ba 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -79,8 +79,8 @@ pub enum CallPolicy { Counted, } -#[derive(Debug, Clone, Copy)] -enum ChunkType { +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ChunkType { Head, Mid, Last, @@ -95,6 +95,11 @@ impl ChunkType { ChunkType::Last => GenContext::Last(chunk_num), } } + + #[inline(always)] + pub fn is_last(self) -> bool { + self == ChunkType::Last + } } #[derive(Debug)] @@ -104,6 +109,7 @@ pub enum QueryTerm { Cut, Not(Vec), IfThen(Vec, Vec), + LocalCut(Cell), // for IfThen. Branch(Vec>), ChunkTypeBoundary(ChunkType), } diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index ee1711e6..24969ff3 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -202,8 +202,6 @@ pub struct VarRecord { pub num_occurrences: usize, } -// TODO: already exists a VarData! although it may no longer exist?? -// Also, the name is too similar to VarInfo. Think of better names! pub struct VarData { pub records: Vec, pub fixtures: VariableFixtures, @@ -243,47 +241,50 @@ fn flatten_into_disjunct(build_stack: &mut Vec, preceding_len: usize) if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { disjuncts.push(iter.collect()); + } else { + unreachable!(); } } fn term_in_other_chunk(term: &Term) -> Option { match term { Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(*name, terms.len())), - Term::Literal(_, Literal::Atom(atom!("!"))) | - Term::Literal(_, Literal::Char('!')) => Some(false), + Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => Some(false), Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(*name, 0)), Term::Var(..) => Some(true), _ => None, } } -// returns true if the insertion of SetLastChunkType was the final push. +// returns true if SetLastChunkType was pushed. // expects that iter iterates over a conjunct of Terms in reverse order. fn insert_set_last_chunk_type( state_stack: &mut Vec, mut iter: impl Iterator, ) -> bool { let beg = state_stack.len(); - let mut idx = beg; + + let mut will_break = false; + let mut last_chunk_delim = beg; while let Some(traversal_st) = iter.next() { match traversal_st { TraversalState::Term(term) | TraversalState::BuildIf(_, term) => { - let mut will_break = false; + will_break = false; match term_in_other_chunk(&term) { - Some(true) if idx > beg => will_break = true, - Some(_) => idx += 1, + Some(true) if last_chunk_delim > beg => will_break = true, + Some(_) => last_chunk_delim += 1, None => will_break = true, } if will_break { + // recall that iter iterates in reverse order. + // therefore this is the correct push order. state_stack.push(TraversalState::SetLastChunkType); state_stack.push(traversal_st); break; - } else { - state_stack.push(traversal_st); } } _ => { @@ -293,7 +294,7 @@ fn insert_set_last_chunk_type( } state_stack.extend(iter); - idx == state_stack.len() + will_break } impl VariableClassifier { @@ -513,9 +514,11 @@ impl VariableClassifier { .chain(std::iter::once(terms[0])) .map(TraversalState::Term); - if let ChunkType::Last = chunk_type { - if !insert_set_last_chunk_type(&mut state_stack, iter) { - chunk_type = ChunkType::Mid; + if ChunkType::Mid != chunk_type { + if insert_set_last_chunk_type(&mut state_stack, iter) { + if chunk_type.is_last() { + chunk_type = ChunkType::Mid; + } } } else { state_stack.extend(iter); @@ -575,9 +578,11 @@ impl VariableClassifier { TraversalState::Term(if_term)] .into_iter(); - if let ChunkType::Last = chunk_type { - if !insert_set_last_chunk_type(&mut state_stack, iter) { - chunk_type = ChunkType::Mid; + if ChunkType::Mid != chunk_type { + if insert_set_last_chunk_type(&mut state_stack, iter) { + if chunk_type.is_last() { + chunk_type = ChunkType::Mid; + } } } } @@ -686,8 +691,7 @@ impl VariableClassifier { ), ); } - Term::Literal(_, Literal::Atom(atom!("!"))) | - Term::Literal(_, Literal::Char('!')) => { + Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => { build_stack.push(QueryTerm::Cut); } Term::Literal(cell, Literal::Atom(name)) => { From b205abe949c8234e9c2b343a0dae16b854c3d32e Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 30 Jan 2023 23:26:50 -0700 Subject: [PATCH 12/40] remove BuildIf, BuildNot, BuildThen TermIterState variants --- src/fixtures.rs | 19 ++--- src/forms.rs | 8 +-- src/iterators.rs | 23 ++++-- src/machine/disjuncts.rs | 146 ++++++++++++++++++++++----------------- 4 files changed, 112 insertions(+), 84 deletions(-) diff --git a/src/fixtures.rs b/src/fixtures.rs index 9e1f28fe..66734320 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -139,27 +139,22 @@ impl VariableFixtures { }; } - pub(crate) fn mark_temp_var( - &mut self, - generated_var_index: usize, - lvl: Level, - classify_info: &ClassifyInfo, - term_loc: GenContext, - ) { + pub(crate) fn mark_temp_var(&mut self, var_info: &VarInfo) { let chunk_num = term_loc.chunk_num(); + let var = Var::from(var_info.var_ptr); - let mut status = self.temp_vars.swap_remove(&generated_var_index).unwrap_or_else(|| { + let mut status = self.temp_vars.swap_remove(&var).unwrap_or_else(|| { TempVarStatus { chunk_num, - temp_var_data: TempVarData::new(classify_info.arity), + temp_var_data: TempVarData::new(var_info.classify_info.arity), } }); - if let Level::Shallow = lvl { - self.record_temp_info(&mut status, classify_info.arg_c, term_loc); + if let Level::Shallow = var_info.lvl { + self.record_temp_info(&mut status, var_info.classify_info.arg_c, term_loc); } - self.temp_vars.insert(Var::Generated(generated_var_index), status); + self.temp_vars.insert(var, status); } } diff --git a/src/forms.rs b/src/forms.rs index 9cc6f1ba..3ed83866 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -106,10 +106,10 @@ impl ChunkType { pub enum QueryTerm { // register, clause type, subterms, clause call policy. Clause(Cell, ClauseType, Vec, CallPolicy), - Cut, - Not(Vec), - IfThen(Vec, Vec), - LocalCut(Cell), // for IfThen. + Fail, + GlobalCut, + GetCutPoint(usize), + LocalCut(usize), Branch(Vec>), ChunkTypeBoundary(ChunkType), } diff --git a/src/iterators.rs b/src/iterators.rs index e1834113..529c453c 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -12,8 +12,9 @@ use std::iter::*; use std::vec::Vec; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub(crate) struct VarPtr { - ptr: std::ptr::NonNull, +pub(crate) enum VarPtr { + ToVar(std::ptr::NonNull), + InSitu(usize), } impl From<&Var> for VarPtr { @@ -26,17 +27,27 @@ impl From<&Var> for VarPtr { } impl From for Var { - #[inline] + #[inline(always)] fn from(value: VarPtr) -> Var { - unsafe { - (*value.ptr.as_ptr()).clone() + match value { + VarPtr::ToPtr(ptr) => unsafe { + (*ptr.ptr.as_ptr()).clone() + }, + VarPtr::InSitu(var_num) => { + Var::Generated(var_num) + } } } } impl VarPtr { pub(crate) fn set(&mut self, value: Var) { - unsafe { *self.ptr.as_mut() = value; } + match self { + VarPtr::ToVar(ref mut ptr) => + unsafe { *ptr.as_mut() = value }, + VarPtr::InSitu(_) => { + } + } } } diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 24969ff3..98875bc8 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -150,9 +150,9 @@ enum TraversalState { // add the last disjunct to a QueryTerm::Branch, continuing from // where it leaves off. BuildFinalDisjunct(usize), - BuildIf(usize, Term), // build the P term of P -> Q - BuildThen(usize, Vec), // build the Q term of P -> Q - BuildNot(usize), // build the P term of \+ P + Fail, + GetCutPoint(usize), + LocalCut(usize), ResetCallPolicy(CallPolicy), Term(Term), AddBranchNum(BranchNumber), // set current_branch_number, add it to the root set @@ -186,6 +186,7 @@ pub struct VariableClassifier { current_branch_num: BranchNumber, current_chunk_num: usize, branch_map: BranchMap, + var_num: usize, root_set: RootSet, } @@ -196,12 +197,23 @@ pub enum VarClassification { Perm, } +#[derive(Clone, Debug)] pub struct VarRecord { pub classification: VarClassification, pub chunk_occurrences: Vec, pub num_occurrences: usize, } +impl Default for VarRecord { + fn default() -> Self { + VarRecord { + classification: VarClassification::Void, + chunk_occurrences: vec![], + num_occurrences: 0, + } + } +} + pub struct VarData { pub records: Vec, pub fixtures: VariableFixtures, @@ -269,7 +281,7 @@ fn insert_set_last_chunk_type( while let Some(traversal_st) = iter.next() { match traversal_st { - TraversalState::Term(term) | TraversalState::BuildIf(_, term) => { + TraversalState::Term(term) => { will_break = false; match term_in_other_chunk(&term) { @@ -288,7 +300,7 @@ fn insert_set_last_chunk_type( } } _ => { - unreachable!(); + state_stack.push(traversal_st); } } } @@ -305,12 +317,13 @@ impl VariableClassifier { current_chunk_num: 0, branch_map: BranchMap(BranchMapInt::new()), root_set: RootSet::new(), + var_num: 0, } } pub fn classify_fact(mut self, term: Term) -> Result { self.classify_head_variables(&term)?; - Ok((term, self.branch_map.separate_and_classify_variables())) + Ok((term, self.branch_map.separate_and_classify_variables(self.var_num))) } pub fn classify_rule<'a, LS: LoadState<'a>>( @@ -322,7 +335,7 @@ impl VariableClassifier { self.classify_head_variables(&head)?; let query_terms = self.classify_body_variables(loader, body)?; - Ok((head, query_terms, self.branch_map.separate_and_classify_variables())) + Ok((head, query_terms, self.branch_map.separate_and_classify_variables(self.var_num))) } fn merge_branches(&mut self) { @@ -396,6 +409,20 @@ impl VariableClassifier { chunk_info.vars.push(var_info); } + fn probe_in_situ_var(&mut self, chunk_type: ChunkType, var_num: usize) { + let classify_info = ClassifyInfo { arg_c: 0, arity: 0 }; + + let var_info = VarInfo { + var_ptr: VarPtr::InSitu(var_num), + classify_info, + lvl: Level::Shallow, + }; + + let term_loc = chunk_type.to_gen_context(self.current_chunk_num); + + self.probe_body_var(Var::Generated(var_num), term_loc, var_info); + } + fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> { match term { Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => { @@ -403,10 +430,7 @@ impl VariableClassifier { _ => return Err(CompilationError::InvalidRuleHead), } - let mut classify_info = ClassifyInfo { - arg_c: 0, - arity: term.arity(), - }; + let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() }; // false argument to breadth_first_iter because the root is not iterable. for term_ref in breadth_first_iter(term, false) { @@ -491,19 +515,20 @@ impl VariableClassifier { TraversalState::BuildFinalDisjunct(preceding_len) => { flatten_into_disjunct(&mut build_stack, preceding_len); } - TraversalState::BuildIf(preceding_len, then_term) => { - let iter = build_stack.drain(preceding_len ..); + TraversalState::GetCutPoint(var_num) => { + let term_loc = chunk_type.to_gen_context(self.current_chunk_num); - state_stack.push(TraversalState::BuildThen(preceding_len, iter.collect())); - state_stack.push(TraversalState::Term(then_term)); + self.probe_in_situ_var(term_loc, var_num); + build_stack.push(QueryTerm::GetCutPoint(var_num)); } - TraversalState::BuildThen(preceding_len, if_terms) => { - let iter = build_stack.drain(preceding_len ..); - build_stack.push(QueryTerm::IfThen(if_terms, iter.collect())); + TraversalState::LocalCut(var_num) => { + let term_loc = chunk_type.to_gen_context(self.current_chunk_num); + + self.probe_in_situ_var(term_loc, var_num); + build_stack.push(QueryTerm::LocalCut(var_num)); } - TraversalState::BuildNot(preceding_len) => { - let iter = build_stack.drain(preceding_len ..); - build_stack.push(QueryTerm::Not(iter.collect())); + TraversalState::Fail => { + build_stack.push(QueryTerm::Fail); } TraversalState::Term(term) => { match term { @@ -567,17 +592,14 @@ impl VariableClassifier { let then_term = terms.pop().unwrap(); let if_term = terms.pop().unwrap(); - let build_stack_len = build_stack.len(); - - // TODO: insert GetCutPoint between - // the two traversal states and detect - // that as a chunk boundary in - // insert_set_last_chunk_type ?? - - let iter = vec![TraversalState::BuildIf(build_stack_len, then_term), - TraversalState::Term(if_term)] + let iter = vec![TraversalState::Term(then_term), + TraversalState::LocalCut(self.var_num), + TraversalState::Term(if_term), + TraversalState::GetCutPoint(self.var_num)] .into_iter(); + self.var_num += 1; + if ChunkType::Mid != chunk_type { if insert_set_last_chunk_type(&mut state_stack, iter) { if chunk_type.is_last() { @@ -587,10 +609,12 @@ impl VariableClassifier { } } Term::Clause(_, atom!("\\+"), terms) if terms.len() == 1 => { - let build_stack_len = build_stack.len(); - - state_stack.push(TraversalState::BuildNot(build_stack_len)); + state_stack.push(TraversalState::Fail); + state_stack.push(TraversalState::LocalCut(self.var_num)); state_stack.push(TraversalState::Term(terms[0])); + state_stack.push(TraversalState::GetCutPoint(self.var_num)); + + self.var_num += 1; } Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => { let term_loc = chunk_type.to_gen_context(self.current_chunk_num); @@ -692,7 +716,7 @@ impl VariableClassifier { ); } Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => { - build_stack.push(QueryTerm::Cut); + build_stack.push(QueryTerm::GlobalCut); } Term::Literal(cell, Literal::Atom(name)) => { if !ClauseType::is_inbuilt(name, 0) { @@ -722,43 +746,46 @@ impl VariableClassifier { } impl BranchMap { - pub fn separate_and_classify_variables(&mut self) -> VarData { - let mut var_num = 0usize; + pub fn separate_and_classify_variables(&mut self, mut var_num: usize) -> VarData { let mut var_data = VarData { - records: vec![], + records: vec![VarRecord::default(); self.len()], fixtures: VariableFixtures::new(), }; - for branches in self.values_mut() { + for (var, branches) in self.iter_mut() { for branch in branches.iter_mut() { let mut num_occurrences = 0; - let mut chunk_occurrences = vec![]; - let classification = if branch.chunks.len() > 1 { - VarClassification::Perm + let idx = if let Var::Generated(var_num) = var { + *var_num } else { - branch.chunks - .first() - .map(|chunk| if chunk.vars.len() > 1 { - VarClassification::Temp - } else { - VarClassification::Void - }) - .unwrap_or(VarClassification::Void) + var_num += 1; + var_num - 1 }; + var_data.records[idx].classification = + if branch.chunks.len() > 1 { + VarClassification::Perm + } else { + branch.chunks + .first() + .map(|chunk| if chunk.vars.len() > 1 { + VarClassification::Temp + } else { + VarClassification::Void + }) + .unwrap_or(VarClassification::Void) + }; + + var_data.records[idx].chunk_occurrences.reserve(branch.chunks.len()); + for chunk in branch.chunks.iter_mut() { - num_occurrences += chunk.vars.len(); + var_data.records[idx].num_occurrences += chunk.vars.len(); if let VarClassification::Temp = classification { for var_info in chunk.vars.iter_mut() { var_info.var_ptr.set(Var::Generated(var_num)); - var_data.fixtures.mark_temp_var( - var_num, - var_info.lvl, - &var_info.classify_info, - chunk.term_loc, - ); + var_data.fixtures.mark_temp_var(&var_info); } } else { for var_info in chunk.vars.iter_mut() { @@ -766,13 +793,8 @@ impl BranchMap { } } - chunk_occurrences.push(chunk.chunk_num); + var_data.records[idx].chunk_occurrences.push(chunk.chunk_num); } - - let record = VarRecord { classification, chunk_occurrences, num_occurrences }; - var_data.records.push(record); - - var_num += 1; } } From 0e583d620ab4ad95e55371905482c65dc5431bc9 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 17 Jun 2023 16:28:56 -0600 Subject: [PATCH 13/40] implement new disjunction compilation --- Cargo.lock | 101 ++- Cargo.toml | 1 + build/instructions_template.rs | 1264 ++++++++++++++++---------------- src/allocator.rs | 40 +- src/arithmetic.rs | 33 +- src/codegen.rs | 823 ++++++++++----------- src/debray_allocator.rs | 552 +++++++++++--- src/fixtures.rs | 342 --------- src/forms.rs | 144 +++- src/heap_iter.rs | 1 - src/heap_print.rs | 8 +- src/iterators.rs | 359 +++------ src/lib.rs | 2 +- src/lib/builtins.pl | 4 +- src/lib/format.pl | 2 + src/loader.pl | 4 +- src/machine/code_walker.rs | 6 +- src/machine/compile.rs | 82 +-- src/machine/disjuncts.rs | 648 ++++++++-------- src/machine/dispatch.rs | 1124 ++++++++++++++-------------- src/machine/load_state.rs | 6 +- src/machine/loader.rs | 2 +- src/machine/machine_indices.rs | 5 +- src/machine/machine_state.rs | 12 +- src/machine/mod.rs | 86 +-- src/machine/preprocessor.rs | 61 +- src/machine/system_calls.rs | 10 +- src/macros.rs | 18 +- src/parser/ast.rs | 86 ++- src/parser/parser.rs | 2 +- src/read.rs | 6 +- src/targets.rs | 23 +- 32 files changed, 2877 insertions(+), 2980 deletions(-) delete mode 100644 src/fixtures.rs diff --git a/Cargo.lock b/Cargo.lock index 542afd09..8b4fc8a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.8.1" @@ -536,6 +548,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -1526,6 +1544,12 @@ dependencies = [ "proc-macro2 1.0.47", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "radix_trie" version = "0.2.1" @@ -1856,6 +1880,7 @@ dependencies = [ "assert_cmd", "base64", "bit-set", + "bitvec", "blake2 0.8.1", "chrono", "cpu-time", @@ -2203,6 +2228,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.3.0" @@ -2592,21 +2623,6 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -2628,24 +2644,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" -[[package]] -name = "windows_aarch64_msvc" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" - [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - [[package]] name = "windows_aarch64_msvc" version = "0.42.1" @@ -2658,12 +2662,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" - [[package]] name = "windows_i686_gnu" version = "0.42.1" @@ -2676,12 +2674,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - [[package]] name = "windows_i686_msvc" version = "0.42.1" @@ -2694,18 +2686,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" - [[package]] name = "windows_x86_64_gnu" version = "0.42.1" @@ -2714,9 +2694,9 @@ checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" @@ -2724,18 +2704,21 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" - [[package]] name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "xmlparser" version = "0.13.5" diff --git a/Cargo.toml b/Cargo.toml index f358126a..1f4fa7aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ walkdir = "2" [dependencies] bit-set = "0.5.3" +bitvec = "1" cpu-time = "1.0.0" crossterm = "0.20.0" dirs-next = "2.0.0" diff --git a/build/instructions_template.rs b/build/instructions_template.rs index d0a8c4d0..25036607 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -639,6 +639,10 @@ enum InstructionTemplate { Cut(RegType), #[strum_discriminants(strum(props(Arity = "1", Name = "get_level")))] GetLevel(RegType), + #[strum_discriminants(strum(props(Arity = "1", Name = "get_prev_level")))] + GetPrevLevel(RegType), + #[strum_discriminants(strum(props(Arity = "1", Name = "get_cut_point")))] + GetCutPoint(RegType), #[strum_discriminants(strum(props(Arity = "0", Name = "neck_cut")))] NeckCut, // choice instruction @@ -740,10 +744,8 @@ enum InstructionTemplate { Allocate(usize), // num_frames. #[strum_discriminants(strum(props(Arity = "0", Name = "deallocate")))] Deallocate, - #[strum_discriminants(strum(props(Arity = "arity", Name = "jmp_by_call")))] - JmpByCall(usize, usize), // arity, relative offset. - #[strum_discriminants(strum(props(Arity = "arity", Name = "jmp_by_execute")))] - JmpByExecute(usize, usize), // arity, relative offset. + #[strum_discriminants(strum(props(Arity = "1", Name = "jmp_by_call")))] + JmpByCall(usize), // relative offset. #[strum_discriminants(strum(props(Arity = "1", Name = "rev_jmp_by")))] RevJmpBy(usize), #[strum_discriminants(strum(props(Arity = "0", Name = "proceed")))] @@ -1114,6 +1116,7 @@ fn generate_instruction_preface() -> TokenStream { } pub type Code = Vec; + pub type CodeDeque = VecDeque; impl Instruction { #[inline] @@ -1296,6 +1299,14 @@ fn generate_instruction_preface() -> TokenStream { let rt_stub = reg_type_into_functor(r); functor!(atom!("get_level"), [str(h, 0)], [rt_stub]) } + &Instruction::GetPrevLevel(r) => { + let rt_stub = reg_type_into_functor(r); + functor!(atom!("get_prev_level"), [str(h, 0)], [rt_stub]) + } + &Instruction::GetCutPoint(r) => { + let rt_stub = reg_type_into_functor(r); + functor!(atom!("get_cut_point"), [str(h, 0)], [rt_stub]) + } &Instruction::NeckCut => { functor!(atom!("neck_cut")) } @@ -1449,30 +1460,30 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::DefaultExecuteNamed(arity, name, ..) => { functor!(atom!("execute_default"), [atom(name), fixnum(arity)]) } - &Instruction::CallN(arity, _) => { + &Instruction::CallN(arity) => { functor!(atom!("call_n"), [fixnum(arity)]) } - &Instruction::ExecuteN(arity, _) => { + &Instruction::ExecuteN(arity) => { functor!(atom!("execute_n"), [fixnum(arity)]) } - &Instruction::DefaultCallN(arity, _) => { + &Instruction::DefaultCallN(arity) => { functor!(atom!("call_default_n"), [fixnum(arity)]) } - &Instruction::DefaultExecuteN(arity, _) => { + &Instruction::DefaultExecuteN(arity) => { functor!(atom!("execute_default_n"), [fixnum(arity)]) } - &Instruction::CallInlineCallN(arity, _) => { + &Instruction::CallInlineCallN(arity) => { functor!(atom!("call_n_inline"), [fixnum(arity)]) } - &Instruction::ExecuteInlineCallN(arity, _) => { + &Instruction::ExecuteInlineCallN(arity) => { functor!(atom!("call_n_inline"), [fixnum(arity)]) } - &Instruction::CallTermGreaterThan(_) | - &Instruction::CallTermLessThan(_) | - &Instruction::CallTermGreaterThanOrEqual(_) | - &Instruction::CallTermLessThanOrEqual(_) | - &Instruction::CallTermEqual(_) | - &Instruction::CallTermNotEqual(_) | + &Instruction::CallTermGreaterThan | + &Instruction::CallTermLessThan | + &Instruction::CallTermGreaterThanOrEqual | + &Instruction::CallTermLessThanOrEqual | + &Instruction::CallTermEqual | + &Instruction::CallTermNotEqual | &Instruction::CallNumberGreaterThan(..) | &Instruction::CallNumberLessThan(..) | &Instruction::CallNumberGreaterThanOrEqual(..) | @@ -1480,563 +1491,561 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::CallNumberEqual(..) | &Instruction::CallNumberNotEqual(..) | &Instruction::CallIs(..) | - &Instruction::CallAcyclicTerm(_) | - &Instruction::CallArg(_) | - &Instruction::CallCompare(_) | - &Instruction::CallCopyTerm(_) | - &Instruction::CallFunctor(_) | - &Instruction::CallGround(_) | - &Instruction::CallKeySort(_) | - &Instruction::CallRead(_) | - &Instruction::CallSort(_) => { + &Instruction::CallAcyclicTerm | + &Instruction::CallArg | + &Instruction::CallCompare | + &Instruction::CallCopyTerm | + &Instruction::CallFunctor | + &Instruction::CallGround | + &Instruction::CallKeySort | + &Instruction::CallRead | + &Instruction::CallSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("call"), [atom(name), fixnum(arity)]) } // - &Instruction::ExecuteTermGreaterThan(_) | - &Instruction::ExecuteTermLessThan(_) | - &Instruction::ExecuteTermGreaterThanOrEqual(_) | - &Instruction::ExecuteTermLessThanOrEqual(_) | - &Instruction::ExecuteTermEqual(_) | - &Instruction::ExecuteTermNotEqual(_) | + &Instruction::ExecuteTermGreaterThan | + &Instruction::ExecuteTermLessThan | + &Instruction::ExecuteTermGreaterThanOrEqual | + &Instruction::ExecuteTermLessThanOrEqual | + &Instruction::ExecuteTermEqual | + &Instruction::ExecuteTermNotEqual | &Instruction::ExecuteNumberGreaterThan(..) | &Instruction::ExecuteNumberLessThan(..) | &Instruction::ExecuteNumberGreaterThanOrEqual(..) | &Instruction::ExecuteNumberLessThanOrEqual(..) | &Instruction::ExecuteNumberEqual(..) | &Instruction::ExecuteNumberNotEqual(..) | - &Instruction::ExecuteAcyclicTerm(_) | - &Instruction::ExecuteArg(_) | - &Instruction::ExecuteCompare(_) | - &Instruction::ExecuteCopyTerm(_) | - &Instruction::ExecuteFunctor(_) | - &Instruction::ExecuteGround(_) | + &Instruction::ExecuteAcyclicTerm | + &Instruction::ExecuteArg | + &Instruction::ExecuteCompare | + &Instruction::ExecuteCopyTerm | + &Instruction::ExecuteFunctor | + &Instruction::ExecuteGround | &Instruction::ExecuteIs(..) | - &Instruction::ExecuteKeySort(_) | - &Instruction::ExecuteRead(_) | - &Instruction::ExecuteSort(_) => { + &Instruction::ExecuteKeySort | + &Instruction::ExecuteRead | + &Instruction::ExecuteSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("execute"), [atom(name), fixnum(arity)]) } // - &Instruction::DefaultCallTermGreaterThan(_) | - &Instruction::DefaultCallTermLessThan(_) | - &Instruction::DefaultCallTermGreaterThanOrEqual(_) | - &Instruction::DefaultCallTermLessThanOrEqual(_) | - &Instruction::DefaultCallTermEqual(_) | - &Instruction::DefaultCallTermNotEqual(_) | + &Instruction::DefaultCallTermGreaterThan | + &Instruction::DefaultCallTermLessThan | + &Instruction::DefaultCallTermGreaterThanOrEqual | + &Instruction::DefaultCallTermLessThanOrEqual | + &Instruction::DefaultCallTermEqual | + &Instruction::DefaultCallTermNotEqual | &Instruction::DefaultCallNumberGreaterThan(..) | &Instruction::DefaultCallNumberLessThan(..) | &Instruction::DefaultCallNumberGreaterThanOrEqual(..) | &Instruction::DefaultCallNumberLessThanOrEqual(..) | &Instruction::DefaultCallNumberEqual(..) | &Instruction::DefaultCallNumberNotEqual(..) | - &Instruction::DefaultCallAcyclicTerm(_) | - &Instruction::DefaultCallArg(_) | - &Instruction::DefaultCallCompare(_) | - &Instruction::DefaultCallCopyTerm(_) | - &Instruction::DefaultCallFunctor(_) | - &Instruction::DefaultCallGround(_) | + &Instruction::DefaultCallAcyclicTerm | + &Instruction::DefaultCallArg | + &Instruction::DefaultCallCompare | + &Instruction::DefaultCallCopyTerm | + &Instruction::DefaultCallFunctor | + &Instruction::DefaultCallGround | &Instruction::DefaultCallIs(..) | - &Instruction::DefaultCallKeySort(_) | - &Instruction::DefaultCallRead(_) | - &Instruction::DefaultCallSort(_) => { + &Instruction::DefaultCallKeySort | + &Instruction::DefaultCallRead | + &Instruction::DefaultCallSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("call_default"), [atom(name), fixnum(arity)]) } // - &Instruction::DefaultExecuteTermGreaterThan(_) | - &Instruction::DefaultExecuteTermLessThan(_) | - &Instruction::DefaultExecuteTermGreaterThanOrEqual(_) | - &Instruction::DefaultExecuteTermLessThanOrEqual(_) | - &Instruction::DefaultExecuteTermEqual(_) | - &Instruction::DefaultExecuteTermNotEqual(_) | + &Instruction::DefaultExecuteTermGreaterThan | + &Instruction::DefaultExecuteTermLessThan | + &Instruction::DefaultExecuteTermGreaterThanOrEqual | + &Instruction::DefaultExecuteTermLessThanOrEqual | + &Instruction::DefaultExecuteTermEqual | + &Instruction::DefaultExecuteTermNotEqual | &Instruction::DefaultExecuteNumberGreaterThan(..) | &Instruction::DefaultExecuteNumberLessThan(..) | &Instruction::DefaultExecuteNumberGreaterThanOrEqual(..) | &Instruction::DefaultExecuteNumberLessThanOrEqual(..) | &Instruction::DefaultExecuteNumberEqual(..) | &Instruction::DefaultExecuteNumberNotEqual(..) | - &Instruction::DefaultExecuteAcyclicTerm(_) | - &Instruction::DefaultExecuteArg(_) | - &Instruction::DefaultExecuteCompare(_) | - &Instruction::DefaultExecuteCopyTerm(_) | - &Instruction::DefaultExecuteFunctor(_) | - &Instruction::DefaultExecuteGround(_) | + &Instruction::DefaultExecuteAcyclicTerm | + &Instruction::DefaultExecuteArg | + &Instruction::DefaultExecuteCompare | + &Instruction::DefaultExecuteCopyTerm | + &Instruction::DefaultExecuteFunctor | + &Instruction::DefaultExecuteGround | &Instruction::DefaultExecuteIs(..) | - &Instruction::DefaultExecuteKeySort(_) | - &Instruction::DefaultExecuteRead(_) | - &Instruction::DefaultExecuteSort(_) => { + &Instruction::DefaultExecuteKeySort | + &Instruction::DefaultExecuteRead | + &Instruction::DefaultExecuteSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("execute_default"), [atom(name), fixnum(arity)]) } - &Instruction::CallIsAtom(_, _) | - &Instruction::CallIsAtomic(_, _) | - &Instruction::CallIsCompound(_, _) | - &Instruction::CallIsInteger(_, _) | - &Instruction::CallIsNumber(_, _) | - &Instruction::CallIsRational(_, _) | - &Instruction::CallIsFloat(_, _) | - &Instruction::CallIsNonVar(_, _) | - &Instruction::CallIsVar(_, _) => { + &Instruction::CallIsAtom(_) | + &Instruction::CallIsAtomic(_) | + &Instruction::CallIsCompound(_) | + &Instruction::CallIsInteger(_) | + &Instruction::CallIsNumber(_) | + &Instruction::CallIsRational(_) | + &Instruction::CallIsFloat(_) | + &Instruction::CallIsNonVar(_) | + &Instruction::CallIsVar(_) => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("call"), [atom(name), fixnum(arity)]) } - &Instruction::ExecuteIsAtom(_, _) | - &Instruction::ExecuteIsAtomic(_, _) | - &Instruction::ExecuteIsCompound(_, _) | - &Instruction::ExecuteIsInteger(_, _) | - &Instruction::ExecuteIsNumber(_, _) | - &Instruction::ExecuteIsRational(_, _) | - &Instruction::ExecuteIsFloat(_, _) | - &Instruction::ExecuteIsNonVar(_, _) | - &Instruction::ExecuteIsVar(_, _) => { + &Instruction::ExecuteIsAtom(_) | + &Instruction::ExecuteIsAtomic(_) | + &Instruction::ExecuteIsCompound(_) | + &Instruction::ExecuteIsInteger(_) | + &Instruction::ExecuteIsNumber(_) | + &Instruction::ExecuteIsRational(_) | + &Instruction::ExecuteIsFloat(_) | + &Instruction::ExecuteIsNonVar(_) | + &Instruction::ExecuteIsVar(_) => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("execute"), [atom(name), fixnum(arity)]) } // - &Instruction::CallAtomChars(_) | - &Instruction::CallAtomCodes(_) | - &Instruction::CallAtomLength(_) | - &Instruction::CallBindFromRegister(_) | - &Instruction::CallContinuation(_) | - &Instruction::CallCharCode(_) | - &Instruction::CallCharType(_) | - &Instruction::CallCharsToNumber(_) | - &Instruction::CallCodesToNumber(_) | - &Instruction::CallCopyTermWithoutAttrVars(_) | - &Instruction::CallCheckCutPoint(_) | - &Instruction::CallClose(_) | - &Instruction::CallCopyToLiftedHeap(_) | - &Instruction::CallCreatePartialString(_) | - &Instruction::CallCurrentHostname(_) | - &Instruction::CallCurrentInput(_) | - &Instruction::CallCurrentOutput(_) | - &Instruction::CallDirectoryFiles(_) | - &Instruction::CallFileSize(_) | - &Instruction::CallFileExists(_) | - &Instruction::CallDirectoryExists(_) | - &Instruction::CallDirectorySeparator(_) | - &Instruction::CallMakeDirectory(_) | - &Instruction::CallMakeDirectoryPath(_) | - &Instruction::CallDeleteFile(_) | - &Instruction::CallRenameFile(_) | - &Instruction::CallFileCopy(_) | - &Instruction::CallWorkingDirectory(_) | - &Instruction::CallDeleteDirectory(_) | - &Instruction::CallPathCanonical(_) | - &Instruction::CallFileTime(_) | + &Instruction::CallAtomChars | + &Instruction::CallAtomCodes | + &Instruction::CallAtomLength | + &Instruction::CallBindFromRegister | + &Instruction::CallContinuation | + &Instruction::CallCharCode | + &Instruction::CallCharType | + &Instruction::CallCharsToNumber | + &Instruction::CallCodesToNumber | + &Instruction::CallCopyTermWithoutAttrVars | + &Instruction::CallCheckCutPoint | + &Instruction::CallClose | + &Instruction::CallCopyToLiftedHeap | + &Instruction::CallCreatePartialString | + &Instruction::CallCurrentHostname | + &Instruction::CallCurrentInput | + &Instruction::CallCurrentOutput | + &Instruction::CallDirectoryFiles | + &Instruction::CallFileSize | + &Instruction::CallFileExists | + &Instruction::CallDirectoryExists | + &Instruction::CallDirectorySeparator | + &Instruction::CallMakeDirectory | + &Instruction::CallMakeDirectoryPath | + &Instruction::CallDeleteFile | + &Instruction::CallRenameFile | + &Instruction::CallFileCopy | + &Instruction::CallWorkingDirectory | + &Instruction::CallDeleteDirectory | + &Instruction::CallPathCanonical | + &Instruction::CallFileTime | &Instruction::CallDynamicModuleResolution(..) | &Instruction::CallPrepareCallClause(..) | - &Instruction::CallCompileInlineOrExpandedGoal(..) | - &Instruction::CallIsExpandedOrInlined(_) | - &Instruction::CallGetClauseP(_) | - &Instruction::CallInvokeClauseAtP(_) | - &Instruction::CallGetFromAttributedVarList(_) | - &Instruction::CallPutToAttributedVarList(_) | - &Instruction::CallDeleteFromAttributedVarList(_) | - &Instruction::CallDeleteAllAttributesFromVar(_) | - &Instruction::CallUnattributedVar(_) | - &Instruction::CallGetDBRefs(_) | - &Instruction::CallEnqueueAttributedVar(_) | - &Instruction::CallFetchGlobalVar(_) | - &Instruction::CallFirstStream(_) | - &Instruction::CallFlushOutput(_) | - &Instruction::CallGetByte(_) | - &Instruction::CallGetChar(_) | - &Instruction::CallGetNChars(_) | - &Instruction::CallGetCode(_) | - &Instruction::CallGetSingleChar(_) | - &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff(_) | - &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) | - &Instruction::CallGetAttributedVariableList(_) | - &Instruction::CallGetAttrVarQueueDelimiter(_) | - &Instruction::CallGetAttrVarQueueBeyond(_) | - &Instruction::CallGetBValue(_) | - &Instruction::CallGetContinuationChunk(_) | - &Instruction::CallGetNextOpDBRef(_) | - &Instruction::CallLookupDBRef(_) | - &Instruction::CallIsPartialString(_) | - &Instruction::CallHalt(_) | - &Instruction::CallGetLiftedHeapFromOffset(_) | - &Instruction::CallGetLiftedHeapFromOffsetDiff(_) | - &Instruction::CallGetSCCCleaner(_) | - &Instruction::CallHeadIsDynamic(_) | - &Instruction::CallInstallSCCCleaner(_) | - &Instruction::CallInstallInferenceCounter(_) | - &Instruction::CallLiftedHeapLength(_) | - &Instruction::CallLoadLibraryAsStream(_) | - &Instruction::CallModuleExists(_) | - &Instruction::CallNextEP(_) | - &Instruction::CallNoSuchPredicate(_) | - &Instruction::CallNumberToChars(_) | - &Instruction::CallNumberToCodes(_) | - &Instruction::CallOpDeclaration(_) | - &Instruction::CallOpen(_) | - &Instruction::CallSetStreamOptions(_) | - &Instruction::CallNextStream(_) | - &Instruction::CallPartialStringTail(_) | - &Instruction::CallPeekByte(_) | - &Instruction::CallPeekChar(_) | - &Instruction::CallPeekCode(_) | - &Instruction::CallPointsToContinuationResetMarker(_) | - &Instruction::CallPutByte(_) | - &Instruction::CallPutChar(_) | - &Instruction::CallPutChars(_) | - &Instruction::CallPutCode(_) | - &Instruction::CallReadQueryTerm(_) | - &Instruction::CallReadTerm(_) | - &Instruction::CallRedoAttrVarBinding(_) | - &Instruction::CallRemoveCallPolicyCheck(_) | - &Instruction::CallRemoveInferenceCounter(_) | - &Instruction::CallResetContinuationMarker(_) | - &Instruction::CallRestoreCutPolicy(_) | + &Instruction::CallCompileInlineOrExpandedGoal | + &Instruction::CallIsExpandedOrInlined | + &Instruction::CallGetClauseP | + &Instruction::CallInvokeClauseAtP | + &Instruction::CallGetFromAttributedVarList | + &Instruction::CallPutToAttributedVarList | + &Instruction::CallDeleteFromAttributedVarList | + &Instruction::CallDeleteAllAttributesFromVar | + &Instruction::CallUnattributedVar | + &Instruction::CallGetDBRefs | + &Instruction::CallFetchGlobalVar | + &Instruction::CallFirstStream | + &Instruction::CallFlushOutput | + &Instruction::CallGetByte | + &Instruction::CallGetChar | + &Instruction::CallGetNChars | + &Instruction::CallGetCode | + &Instruction::CallGetSingleChar | + &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff | + &Instruction::CallTruncateIfNoLiftedHeapGrowth | + &Instruction::CallGetAttributedVariableList | + &Instruction::CallGetAttrVarQueueDelimiter | + &Instruction::CallGetAttrVarQueueBeyond | + &Instruction::CallGetBValue | + &Instruction::CallGetContinuationChunk | + &Instruction::CallGetNextOpDBRef | + &Instruction::CallLookupDBRef | + &Instruction::CallIsPartialString | + &Instruction::CallHalt | + &Instruction::CallGetLiftedHeapFromOffset | + &Instruction::CallGetLiftedHeapFromOffsetDiff | + &Instruction::CallGetSCCCleaner | + &Instruction::CallHeadIsDynamic | + &Instruction::CallInstallSCCCleaner | + &Instruction::CallInstallInferenceCounter | + &Instruction::CallLiftedHeapLength | + &Instruction::CallLoadLibraryAsStream | + &Instruction::CallModuleExists | + &Instruction::CallNextEP | + &Instruction::CallNoSuchPredicate | + &Instruction::CallNumberToChars | + &Instruction::CallNumberToCodes | + &Instruction::CallOpDeclaration | + &Instruction::CallOpen | + &Instruction::CallSetStreamOptions | + &Instruction::CallNextStream | + &Instruction::CallPartialStringTail | + &Instruction::CallPeekByte | + &Instruction::CallPeekChar | + &Instruction::CallPeekCode | + &Instruction::CallPointsToContinuationResetMarker | + &Instruction::CallPutByte | + &Instruction::CallPutChar | + &Instruction::CallPutChars | + &Instruction::CallPutCode | + &Instruction::CallReadQueryTerm | + &Instruction::CallReadTerm | + &Instruction::CallRedoAttrVarBinding | + &Instruction::CallRemoveCallPolicyCheck | + &Instruction::CallRemoveInferenceCounter | + &Instruction::CallResetContinuationMarker | + &Instruction::CallRestoreCutPolicy | &Instruction::CallSetCutPoint(..) | - &Instruction::CallSetInput(_) | - &Instruction::CallSetOutput(_) | - &Instruction::CallStoreBacktrackableGlobalVar(_) | - &Instruction::CallStoreGlobalVar(_) | - &Instruction::CallStreamProperty(_) | - &Instruction::CallSetStreamPosition(_) | - &Instruction::CallInferenceLevel(_) | - &Instruction::CallCleanUpBlock(_) | - &Instruction::CallFail(_) | - &Instruction::CallGetBall(_) | - &Instruction::CallGetCurrentBlock(_) | - &Instruction::CallGetCutPoint(_) | - &Instruction::CallGetDoubleQuotes(_) | - &Instruction::CallInstallNewBlock(_) | - &Instruction::CallMaybe(_) | - &Instruction::CallCpuNow(_) | - &Instruction::CallDeterministicLengthRundown(_) | - &Instruction::CallHttpOpen(_) | - &Instruction::CallHttpListen(_) | - &Instruction::CallHttpAccept(_) | - &Instruction::CallHttpAnswer(_) | - &Instruction::CallLoadForeignLib(_) | - &Instruction::CallForeignCall(_) | - &Instruction::CallDefineForeignStruct(_) | - &Instruction::CallPredicateDefined(_) | - &Instruction::CallStripModule(_) | - &Instruction::CallCurrentTime(_) | - &Instruction::CallQuotedToken(_) | - &Instruction::CallReadTermFromChars(_) | - &Instruction::CallResetBlock(_) | - &Instruction::CallReturnFromVerifyAttr(_) | - &Instruction::CallSetBall(_) | - &Instruction::CallPushBallStack(_) | - &Instruction::CallPopBallStack(_) | - &Instruction::CallPopFromBallStack(_) | + &Instruction::CallSetInput | + &Instruction::CallSetOutput | + &Instruction::CallStoreBacktrackableGlobalVar | + &Instruction::CallStoreGlobalVar | + &Instruction::CallStreamProperty | + &Instruction::CallSetStreamPosition | + &Instruction::CallInferenceLevel | + &Instruction::CallCleanUpBlock | + &Instruction::CallFail | + &Instruction::CallGetBall | + &Instruction::CallGetCurrentBlock | + &Instruction::CallGetCutPoint | + &Instruction::CallGetDoubleQuotes | + &Instruction::CallInstallNewBlock | + &Instruction::CallMaybe | + &Instruction::CallCpuNow | + &Instruction::CallDeterministicLengthRundown | + &Instruction::CallHttpOpen | + &Instruction::CallHttpListen | + &Instruction::CallHttpAccept | + &Instruction::CallHttpAnswer | + &Instruction::CallLoadForeignLib | + &Instruction::CallForeignCall | + &Instruction::CallDefineForeignStruct | + &Instruction::CallPredicateDefined | + &Instruction::CallStripModule | + &Instruction::CallCurrentTime | + &Instruction::CallQuotedToken | + &Instruction::CallReadTermFromChars | + &Instruction::CallResetBlock | + &Instruction::CallReturnFromVerifyAttr | + &Instruction::CallSetBall | + &Instruction::CallPushBallStack | + &Instruction::CallPopBallStack | + &Instruction::CallPopFromBallStack | &Instruction::CallSetCutPointByDefault(..) | - &Instruction::CallSetDoubleQuotes(_) | - &Instruction::CallSetSeed(_) | - &Instruction::CallSkipMaxList(_) | - &Instruction::CallSleep(_) | - &Instruction::CallSocketClientOpen(_) | - &Instruction::CallSocketServerOpen(_) | - &Instruction::CallSocketServerAccept(_) | - &Instruction::CallSocketServerClose(_) | - &Instruction::CallTLSAcceptClient(_) | - &Instruction::CallTLSClientConnect(_) | - &Instruction::CallSucceed(_) | - &Instruction::CallTermAttributedVariables(_) | - &Instruction::CallTermVariables(_) | - &Instruction::CallTermVariablesUnderMaxDepth(_) | - &Instruction::CallTruncateLiftedHeapTo(_) | - &Instruction::CallUnifyWithOccursCheck(_) | - &Instruction::CallUnwindEnvironments(_) | - &Instruction::CallUnwindStack(_) | - &Instruction::CallWAMInstructions(_) | - &Instruction::CallInlinedInstructions(_) | - &Instruction::CallWriteTerm(_) | - &Instruction::CallWriteTermToChars(_) | - &Instruction::CallScryerPrologVersion(_) | - &Instruction::CallCryptoRandomByte(_) | - &Instruction::CallCryptoDataHash(_) | - &Instruction::CallCryptoDataHKDF(_) | - &Instruction::CallCryptoPasswordHash(_) | - &Instruction::CallCryptoDataEncrypt(_) | - &Instruction::CallCryptoDataDecrypt(_) | - &Instruction::CallCryptoCurveScalarMult(_) | - &Instruction::CallEd25519Sign(_) | - &Instruction::CallEd25519Verify(_) | - &Instruction::CallEd25519NewKeyPair(_) | - &Instruction::CallEd25519KeyPairPublicKey(_) | - &Instruction::CallCurve25519ScalarMult(_) | - &Instruction::CallFirstNonOctet(_) | - &Instruction::CallLoadHTML(_) | - &Instruction::CallLoadXML(_) | - &Instruction::CallGetEnv(_) | - &Instruction::CallSetEnv(_) | - &Instruction::CallUnsetEnv(_) | - &Instruction::CallShell(_) | - &Instruction::CallPID(_) | - &Instruction::CallCharsBase64(_) | - &Instruction::CallDevourWhitespace(_) | - &Instruction::CallIsSTOEnabled(_) | - &Instruction::CallSetSTOAsUnify(_) | - &Instruction::CallSetNSTOAsUnify(_) | - &Instruction::CallSetSTOWithErrorAsUnify(_) | - &Instruction::CallHomeDirectory(_) | - &Instruction::CallDebugHook(_) | - &Instruction::CallAddDiscontiguousPredicate(_) | - &Instruction::CallAddDynamicPredicate(_) | - &Instruction::CallAddMultifilePredicate(_) | - &Instruction::CallAddGoalExpansionClause(_) | - &Instruction::CallAddTermExpansionClause(_) | - &Instruction::CallAddInSituFilenameModule(_) | - &Instruction::CallClauseToEvacuable(_) | - &Instruction::CallScopedClauseToEvacuable(_) | - &Instruction::CallConcludeLoad(_) | - &Instruction::CallDeclareModule(_) | - &Instruction::CallLoadCompiledLibrary(_) | - &Instruction::CallLoadContextSource(_) | - &Instruction::CallLoadContextFile(_) | - &Instruction::CallLoadContextDirectory(_) | - &Instruction::CallLoadContextModule(_) | - &Instruction::CallLoadContextStream(_) | - &Instruction::CallPopLoadContext(_) | - &Instruction::CallPopLoadStatePayload(_) | - &Instruction::CallPushLoadContext(_) | - &Instruction::CallPushLoadStatePayload(_) | - &Instruction::CallUseModule(_) | - &Instruction::CallBuiltInProperty(_) | - &Instruction::CallMetaPredicateProperty(_) | - &Instruction::CallMultifileProperty(_) | - &Instruction::CallDiscontiguousProperty(_) | - &Instruction::CallDynamicProperty(_) | - &Instruction::CallAbolishClause(_) | - &Instruction::CallAsserta(_) | - &Instruction::CallAssertz(_) | - &Instruction::CallRetract(_) | - &Instruction::CallIsConsistentWithTermQueue(_) | - &Instruction::CallFlushTermQueue(_) | - &Instruction::CallRemoveModuleExports(_) | - &Instruction::CallAddNonCountedBacktracking(_) | - &Instruction::CallPopCount(_) => { + &Instruction::CallSetDoubleQuotes | + &Instruction::CallSetSeed | + &Instruction::CallSkipMaxList | + &Instruction::CallSleep | + &Instruction::CallSocketClientOpen | + &Instruction::CallSocketServerOpen | + &Instruction::CallSocketServerAccept | + &Instruction::CallSocketServerClose | + &Instruction::CallTLSAcceptClient | + &Instruction::CallTLSClientConnect | + &Instruction::CallSucceed | + &Instruction::CallTermAttributedVariables | + &Instruction::CallTermVariables | + &Instruction::CallTermVariablesUnderMaxDepth | + &Instruction::CallTruncateLiftedHeapTo | + &Instruction::CallUnifyWithOccursCheck | + &Instruction::CallUnwindEnvironments | + &Instruction::CallUnwindStack | + &Instruction::CallWAMInstructions | + &Instruction::CallInlinedInstructions | + &Instruction::CallWriteTerm | + &Instruction::CallWriteTermToChars | + &Instruction::CallScryerPrologVersion | + &Instruction::CallCryptoRandomByte | + &Instruction::CallCryptoDataHash | + &Instruction::CallCryptoDataHKDF | + &Instruction::CallCryptoPasswordHash | + &Instruction::CallCryptoDataEncrypt | + &Instruction::CallCryptoDataDecrypt | + &Instruction::CallCryptoCurveScalarMult | + &Instruction::CallEd25519Sign | + &Instruction::CallEd25519Verify | + &Instruction::CallEd25519NewKeyPair | + &Instruction::CallEd25519KeyPairPublicKey | + &Instruction::CallCurve25519ScalarMult | + &Instruction::CallFirstNonOctet | + &Instruction::CallLoadHTML | + &Instruction::CallLoadXML | + &Instruction::CallGetEnv | + &Instruction::CallSetEnv | + &Instruction::CallUnsetEnv | + &Instruction::CallShell | + &Instruction::CallPID | + &Instruction::CallCharsBase64 | + &Instruction::CallDevourWhitespace | + &Instruction::CallIsSTOEnabled | + &Instruction::CallSetSTOAsUnify | + &Instruction::CallSetNSTOAsUnify | + &Instruction::CallSetSTOWithErrorAsUnify | + &Instruction::CallHomeDirectory | + &Instruction::CallDebugHook | + &Instruction::CallAddDiscontiguousPredicate | + &Instruction::CallAddDynamicPredicate | + &Instruction::CallAddMultifilePredicate | + &Instruction::CallAddGoalExpansionClause | + &Instruction::CallAddTermExpansionClause | + &Instruction::CallAddInSituFilenameModule | + &Instruction::CallClauseToEvacuable | + &Instruction::CallScopedClauseToEvacuable | + &Instruction::CallConcludeLoad | + &Instruction::CallDeclareModule | + &Instruction::CallLoadCompiledLibrary | + &Instruction::CallLoadContextSource | + &Instruction::CallLoadContextFile | + &Instruction::CallLoadContextDirectory | + &Instruction::CallLoadContextModule | + &Instruction::CallLoadContextStream | + &Instruction::CallPopLoadContext | + &Instruction::CallPopLoadStatePayload | + &Instruction::CallPushLoadContext | + &Instruction::CallPushLoadStatePayload | + &Instruction::CallUseModule | + &Instruction::CallBuiltInProperty | + &Instruction::CallMetaPredicateProperty | + &Instruction::CallMultifileProperty | + &Instruction::CallDiscontiguousProperty | + &Instruction::CallDynamicProperty | + &Instruction::CallAbolishClause | + &Instruction::CallAsserta | + &Instruction::CallAssertz | + &Instruction::CallRetract | + &Instruction::CallIsConsistentWithTermQueue | + &Instruction::CallFlushTermQueue | + &Instruction::CallRemoveModuleExports | + &Instruction::CallAddNonCountedBacktracking | + &Instruction::CallPopCount => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("call"), [atom(name), fixnum(arity)]) } // - &Instruction::ExecuteAtomChars(_) | - &Instruction::ExecuteAtomCodes(_) | - &Instruction::ExecuteAtomLength(_) | - &Instruction::ExecuteBindFromRegister(_) | - &Instruction::ExecuteContinuation(_) | - &Instruction::ExecuteCharCode(_) | - &Instruction::ExecuteCharType(_) | - &Instruction::ExecuteCharsToNumber(_) | - &Instruction::ExecuteCodesToNumber(_) | - &Instruction::ExecuteCopyTermWithoutAttrVars(_) | - &Instruction::ExecuteCheckCutPoint(_) | - &Instruction::ExecuteClose(_) | - &Instruction::ExecuteCopyToLiftedHeap(_) | - &Instruction::ExecuteCreatePartialString(_) | - &Instruction::ExecuteCurrentHostname(_) | - &Instruction::ExecuteCurrentInput(_) | - &Instruction::ExecuteCurrentOutput(_) | - &Instruction::ExecuteDirectoryFiles(_) | - &Instruction::ExecuteFileSize(_) | - &Instruction::ExecuteFileExists(_) | - &Instruction::ExecuteDirectoryExists(_) | - &Instruction::ExecuteDirectorySeparator(_) | - &Instruction::ExecuteMakeDirectory(_) | - &Instruction::ExecuteMakeDirectoryPath(_) | - &Instruction::ExecuteDeleteFile(_) | - &Instruction::ExecuteRenameFile(_) | - &Instruction::ExecuteFileCopy(_) | - &Instruction::ExecuteWorkingDirectory(_) | - &Instruction::ExecuteDeleteDirectory(_) | - &Instruction::ExecutePathCanonical(_) | - &Instruction::ExecuteFileTime(_) | + &Instruction::ExecuteAtomChars | + &Instruction::ExecuteAtomCodes | + &Instruction::ExecuteAtomLength | + &Instruction::ExecuteBindFromRegister | + &Instruction::ExecuteContinuation | + &Instruction::ExecuteCharCode | + &Instruction::ExecuteCharType | + &Instruction::ExecuteCharsToNumber | + &Instruction::ExecuteCodesToNumber | + &Instruction::ExecuteCopyTermWithoutAttrVars | + &Instruction::ExecuteCheckCutPoint | + &Instruction::ExecuteClose | + &Instruction::ExecuteCopyToLiftedHeap | + &Instruction::ExecuteCreatePartialString | + &Instruction::ExecuteCurrentHostname | + &Instruction::ExecuteCurrentInput | + &Instruction::ExecuteCurrentOutput | + &Instruction::ExecuteDirectoryFiles | + &Instruction::ExecuteFileSize | + &Instruction::ExecuteFileExists | + &Instruction::ExecuteDirectoryExists | + &Instruction::ExecuteDirectorySeparator | + &Instruction::ExecuteMakeDirectory | + &Instruction::ExecuteMakeDirectoryPath | + &Instruction::ExecuteDeleteFile | + &Instruction::ExecuteRenameFile | + &Instruction::ExecuteFileCopy | + &Instruction::ExecuteWorkingDirectory | + &Instruction::ExecuteDeleteDirectory | + &Instruction::ExecutePathCanonical | + &Instruction::ExecuteFileTime | &Instruction::ExecuteDynamicModuleResolution(..) | &Instruction::ExecutePrepareCallClause(..) | - &Instruction::ExecuteCompileInlineOrExpandedGoal(..) | - &Instruction::ExecuteIsExpandedOrInlined(_) | - &Instruction::ExecuteGetClauseP(_) | - &Instruction::ExecuteInvokeClauseAtP(_) | - &Instruction::ExecuteGetFromAttributedVarList(_) | - &Instruction::ExecutePutToAttributedVarList(_) | - &Instruction::ExecuteDeleteFromAttributedVarList(_) | - &Instruction::ExecuteDeleteAllAttributesFromVar(_) | - &Instruction::ExecuteUnattributedVar(_) | - &Instruction::ExecuteGetDBRefs(_) | - &Instruction::ExecuteEnqueueAttributedVar(_) | - &Instruction::ExecuteFetchGlobalVar(_) | - &Instruction::ExecuteFirstStream(_) | - &Instruction::ExecuteFlushOutput(_) | - &Instruction::ExecuteGetByte(_) | - &Instruction::ExecuteGetChar(_) | - &Instruction::ExecuteGetNChars(_) | - &Instruction::ExecuteGetCode(_) | - &Instruction::ExecuteGetSingleChar(_) | - &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) | - &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) | - &Instruction::ExecuteGetAttributedVariableList(_) | - &Instruction::ExecuteGetAttrVarQueueDelimiter(_) | - &Instruction::ExecuteGetAttrVarQueueBeyond(_) | - &Instruction::ExecuteGetBValue(_) | - &Instruction::ExecuteGetContinuationChunk(_) | - &Instruction::ExecuteGetNextOpDBRef(_) | - &Instruction::ExecuteLookupDBRef(_) | - &Instruction::ExecuteIsPartialString(_) | - &Instruction::ExecuteHalt(_) | - &Instruction::ExecuteGetLiftedHeapFromOffset(_) | - &Instruction::ExecuteGetLiftedHeapFromOffsetDiff(_) | - &Instruction::ExecuteGetSCCCleaner(_) | - &Instruction::ExecuteHeadIsDynamic(_) | - &Instruction::ExecuteInstallSCCCleaner(_) | - &Instruction::ExecuteInstallInferenceCounter(_) | - &Instruction::ExecuteLiftedHeapLength(_) | - &Instruction::ExecuteLoadLibraryAsStream(_) | - &Instruction::ExecuteModuleExists(_) | - &Instruction::ExecuteNextEP(_) | - &Instruction::ExecuteNoSuchPredicate(_) | - &Instruction::ExecuteNumberToChars(_) | - &Instruction::ExecuteNumberToCodes(_) | - &Instruction::ExecuteOpDeclaration(_) | - &Instruction::ExecuteOpen(_) | - &Instruction::ExecuteSetStreamOptions(_) | - &Instruction::ExecuteNextStream(_) | - &Instruction::ExecutePartialStringTail(_) | - &Instruction::ExecutePeekByte(_) | - &Instruction::ExecutePeekChar(_) | - &Instruction::ExecutePeekCode(_) | - &Instruction::ExecutePointsToContinuationResetMarker(_) | - &Instruction::ExecutePutByte(_) | - &Instruction::ExecutePutChar(_) | - &Instruction::ExecutePutChars(_) | - &Instruction::ExecutePutCode(_) | - &Instruction::ExecuteReadQueryTerm(_) | - &Instruction::ExecuteReadTerm(_) | - &Instruction::ExecuteRedoAttrVarBinding(_) | - &Instruction::ExecuteRemoveCallPolicyCheck(_) | - &Instruction::ExecuteRemoveInferenceCounter(_) | - &Instruction::ExecuteResetContinuationMarker(_) | - &Instruction::ExecuteRestoreCutPolicy(_) | - &Instruction::ExecuteSetCutPoint(_, _) | - &Instruction::ExecuteSetInput(_) | - &Instruction::ExecuteSetOutput(_) | - &Instruction::ExecuteStoreBacktrackableGlobalVar(_) | - &Instruction::ExecuteStoreGlobalVar(_) | - &Instruction::ExecuteStreamProperty(_) | - &Instruction::ExecuteSetStreamPosition(_) | - &Instruction::ExecuteInferenceLevel(_) | - &Instruction::ExecuteCleanUpBlock(_) | - &Instruction::ExecuteFail(_) | - &Instruction::ExecuteGetBall(_) | - &Instruction::ExecuteGetCurrentBlock(_) | - &Instruction::ExecuteGetCutPoint(_) | - &Instruction::ExecuteGetDoubleQuotes(_) | - &Instruction::ExecuteInstallNewBlock(_) | - &Instruction::ExecuteMaybe(_) | - &Instruction::ExecuteCpuNow(_) | - &Instruction::ExecuteDeterministicLengthRundown(_) | - &Instruction::ExecuteHttpOpen(_) | - &Instruction::ExecuteHttpListen(_) | - &Instruction::ExecuteHttpAccept(_) | - &Instruction::ExecuteHttpAnswer(_) | - &Instruction::ExecuteLoadForeignLib(_) | - &Instruction::ExecuteForeignCall(_) | - &Instruction::ExecuteDefineForeignStruct(_) | - &Instruction::ExecutePredicateDefined(_) | - &Instruction::ExecuteStripModule(_) | - &Instruction::ExecuteCurrentTime(_) | - &Instruction::ExecuteQuotedToken(_) | - &Instruction::ExecuteReadTermFromChars(_) | - &Instruction::ExecuteResetBlock(_) | - &Instruction::ExecuteReturnFromVerifyAttr(_) | - &Instruction::ExecuteSetBall(_) | - &Instruction::ExecutePushBallStack(_) | - &Instruction::ExecutePopBallStack(_) | - &Instruction::ExecutePopFromBallStack(_) | - &Instruction::ExecuteSetCutPointByDefault(_, _) | - &Instruction::ExecuteSetDoubleQuotes(_) | - &Instruction::ExecuteSetSeed(_) | - &Instruction::ExecuteSkipMaxList(_) | - &Instruction::ExecuteSleep(_) | - &Instruction::ExecuteSocketClientOpen(_) | - &Instruction::ExecuteSocketServerOpen(_) | - &Instruction::ExecuteSocketServerAccept(_) | - &Instruction::ExecuteSocketServerClose(_) | - &Instruction::ExecuteTLSAcceptClient(_) | - &Instruction::ExecuteTLSClientConnect(_) | - &Instruction::ExecuteSucceed(_) | - &Instruction::ExecuteTermAttributedVariables(_) | - &Instruction::ExecuteTermVariables(_) | - &Instruction::ExecuteTermVariablesUnderMaxDepth(_) | - &Instruction::ExecuteTruncateLiftedHeapTo(_) | - &Instruction::ExecuteUnifyWithOccursCheck(_) | - &Instruction::ExecuteUnwindEnvironments(_) | - &Instruction::ExecuteUnwindStack(_) | - &Instruction::ExecuteWAMInstructions(_) | - &Instruction::ExecuteInlinedInstructions(_) | - &Instruction::ExecuteWriteTerm(_) | - &Instruction::ExecuteWriteTermToChars(_) | - &Instruction::ExecuteScryerPrologVersion(_) | - &Instruction::ExecuteCryptoRandomByte(_) | - &Instruction::ExecuteCryptoDataHash(_) | - &Instruction::ExecuteCryptoDataHKDF(_) | - &Instruction::ExecuteCryptoPasswordHash(_) | - &Instruction::ExecuteCryptoDataEncrypt(_) | - &Instruction::ExecuteCryptoDataDecrypt(_) | - &Instruction::ExecuteCryptoCurveScalarMult(_) | - &Instruction::ExecuteEd25519Sign(_) | - &Instruction::ExecuteEd25519Verify(_) | - &Instruction::ExecuteEd25519NewKeyPair(_) | - &Instruction::ExecuteEd25519KeyPairPublicKey(_) | - &Instruction::ExecuteCurve25519ScalarMult(_) | - &Instruction::ExecuteFirstNonOctet(_) | - &Instruction::ExecuteLoadHTML(_) | - &Instruction::ExecuteLoadXML(_) | - &Instruction::ExecuteGetEnv(_) | - &Instruction::ExecuteSetEnv(_) | - &Instruction::ExecuteUnsetEnv(_) | - &Instruction::ExecuteShell(_) | - &Instruction::ExecutePID(_) | - &Instruction::ExecuteCharsBase64(_) | - &Instruction::ExecuteDevourWhitespace(_) | - &Instruction::ExecuteIsSTOEnabled(_) | - &Instruction::ExecuteSetSTOAsUnify(_) | - &Instruction::ExecuteSetNSTOAsUnify(_) | - &Instruction::ExecuteSetSTOWithErrorAsUnify(_) | - &Instruction::ExecuteHomeDirectory(_) | - &Instruction::ExecuteDebugHook(_) | - &Instruction::ExecuteAddDiscontiguousPredicate(_) | - &Instruction::ExecuteAddDynamicPredicate(_) | - &Instruction::ExecuteAddMultifilePredicate(_) | - &Instruction::ExecuteAddGoalExpansionClause(_) | - &Instruction::ExecuteAddTermExpansionClause(_) | - &Instruction::ExecuteAddInSituFilenameModule(_) | - &Instruction::ExecuteClauseToEvacuable(_) | - &Instruction::ExecuteScopedClauseToEvacuable(_) | - &Instruction::ExecuteConcludeLoad(_) | - &Instruction::ExecuteDeclareModule(_) | - &Instruction::ExecuteLoadCompiledLibrary(_) | - &Instruction::ExecuteLoadContextSource(_) | - &Instruction::ExecuteLoadContextFile(_) | - &Instruction::ExecuteLoadContextDirectory(_) | - &Instruction::ExecuteLoadContextModule(_) | - &Instruction::ExecuteLoadContextStream(_) | - &Instruction::ExecutePopLoadContext(_) | - &Instruction::ExecutePopLoadStatePayload(_) | - &Instruction::ExecutePushLoadContext(_) | - &Instruction::ExecutePushLoadStatePayload(_) | - &Instruction::ExecuteUseModule(_) | - &Instruction::ExecuteBuiltInProperty(_) | - &Instruction::ExecuteMetaPredicateProperty(_) | - &Instruction::ExecuteMultifileProperty(_) | - &Instruction::ExecuteDiscontiguousProperty(_) | - &Instruction::ExecuteDynamicProperty(_) | - &Instruction::ExecuteAbolishClause(_) | - &Instruction::ExecuteAsserta(_) | - &Instruction::ExecuteAssertz(_) | - &Instruction::ExecuteRetract(_) | - &Instruction::ExecuteIsConsistentWithTermQueue(_) | - &Instruction::ExecuteFlushTermQueue(_) | - &Instruction::ExecuteRemoveModuleExports(_) | - &Instruction::ExecuteAddNonCountedBacktracking(_) | - &Instruction::ExecutePopCount(_) => { + &Instruction::ExecuteCompileInlineOrExpandedGoal | + &Instruction::ExecuteIsExpandedOrInlined | + &Instruction::ExecuteGetClauseP | + &Instruction::ExecuteInvokeClauseAtP | + &Instruction::ExecuteGetFromAttributedVarList | + &Instruction::ExecutePutToAttributedVarList | + &Instruction::ExecuteDeleteFromAttributedVarList | + &Instruction::ExecuteDeleteAllAttributesFromVar | + &Instruction::ExecuteUnattributedVar | + &Instruction::ExecuteGetDBRefs | + &Instruction::ExecuteFetchGlobalVar | + &Instruction::ExecuteFirstStream | + &Instruction::ExecuteFlushOutput | + &Instruction::ExecuteGetByte | + &Instruction::ExecuteGetChar | + &Instruction::ExecuteGetNChars | + &Instruction::ExecuteGetCode | + &Instruction::ExecuteGetSingleChar | + &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff | + &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth | + &Instruction::ExecuteGetAttributedVariableList | + &Instruction::ExecuteGetAttrVarQueueDelimiter | + &Instruction::ExecuteGetAttrVarQueueBeyond | + &Instruction::ExecuteGetBValue | + &Instruction::ExecuteGetContinuationChunk | + &Instruction::ExecuteGetNextOpDBRef | + &Instruction::ExecuteLookupDBRef | + &Instruction::ExecuteIsPartialString | + &Instruction::ExecuteHalt | + &Instruction::ExecuteGetLiftedHeapFromOffset | + &Instruction::ExecuteGetLiftedHeapFromOffsetDiff | + &Instruction::ExecuteGetSCCCleaner | + &Instruction::ExecuteHeadIsDynamic | + &Instruction::ExecuteInstallSCCCleaner | + &Instruction::ExecuteInstallInferenceCounter | + &Instruction::ExecuteLiftedHeapLength | + &Instruction::ExecuteLoadLibraryAsStream | + &Instruction::ExecuteModuleExists | + &Instruction::ExecuteNextEP | + &Instruction::ExecuteNoSuchPredicate | + &Instruction::ExecuteNumberToChars | + &Instruction::ExecuteNumberToCodes | + &Instruction::ExecuteOpDeclaration | + &Instruction::ExecuteOpen | + &Instruction::ExecuteSetStreamOptions | + &Instruction::ExecuteNextStream | + &Instruction::ExecutePartialStringTail | + &Instruction::ExecutePeekByte | + &Instruction::ExecutePeekChar | + &Instruction::ExecutePeekCode | + &Instruction::ExecutePointsToContinuationResetMarker | + &Instruction::ExecutePutByte | + &Instruction::ExecutePutChar | + &Instruction::ExecutePutChars | + &Instruction::ExecutePutCode | + &Instruction::ExecuteReadQueryTerm | + &Instruction::ExecuteReadTerm | + &Instruction::ExecuteRedoAttrVarBinding | + &Instruction::ExecuteRemoveCallPolicyCheck | + &Instruction::ExecuteRemoveInferenceCounter | + &Instruction::ExecuteResetContinuationMarker | + &Instruction::ExecuteRestoreCutPolicy | + &Instruction::ExecuteSetCutPoint(_) | + &Instruction::ExecuteSetInput | + &Instruction::ExecuteSetOutput | + &Instruction::ExecuteStoreBacktrackableGlobalVar | + &Instruction::ExecuteStoreGlobalVar | + &Instruction::ExecuteStreamProperty | + &Instruction::ExecuteSetStreamPosition | + &Instruction::ExecuteInferenceLevel | + &Instruction::ExecuteCleanUpBlock | + &Instruction::ExecuteFail | + &Instruction::ExecuteGetBall | + &Instruction::ExecuteGetCurrentBlock | + &Instruction::ExecuteGetCutPoint | + &Instruction::ExecuteGetDoubleQuotes | + &Instruction::ExecuteInstallNewBlock | + &Instruction::ExecuteMaybe | + &Instruction::ExecuteCpuNow | + &Instruction::ExecuteDeterministicLengthRundown | + &Instruction::ExecuteHttpOpen | + &Instruction::ExecuteHttpListen | + &Instruction::ExecuteHttpAccept | + &Instruction::ExecuteHttpAnswer | + &Instruction::ExecuteLoadForeignLib | + &Instruction::ExecuteForeignCall | + &Instruction::ExecuteDefineForeignStruct | + &Instruction::ExecutePredicateDefined | + &Instruction::ExecuteStripModule | + &Instruction::ExecuteCurrentTime | + &Instruction::ExecuteQuotedToken | + &Instruction::ExecuteReadTermFromChars | + &Instruction::ExecuteResetBlock | + &Instruction::ExecuteReturnFromVerifyAttr | + &Instruction::ExecuteSetBall | + &Instruction::ExecutePushBallStack | + &Instruction::ExecutePopBallStack | + &Instruction::ExecutePopFromBallStack | + &Instruction::ExecuteSetCutPointByDefault(_) | + &Instruction::ExecuteSetDoubleQuotes | + &Instruction::ExecuteSetSeed | + &Instruction::ExecuteSkipMaxList | + &Instruction::ExecuteSleep | + &Instruction::ExecuteSocketClientOpen | + &Instruction::ExecuteSocketServerOpen | + &Instruction::ExecuteSocketServerAccept | + &Instruction::ExecuteSocketServerClose | + &Instruction::ExecuteTLSAcceptClient | + &Instruction::ExecuteTLSClientConnect | + &Instruction::ExecuteSucceed | + &Instruction::ExecuteTermAttributedVariables | + &Instruction::ExecuteTermVariables | + &Instruction::ExecuteTermVariablesUnderMaxDepth | + &Instruction::ExecuteTruncateLiftedHeapTo | + &Instruction::ExecuteUnifyWithOccursCheck | + &Instruction::ExecuteUnwindEnvironments | + &Instruction::ExecuteUnwindStack | + &Instruction::ExecuteWAMInstructions | + &Instruction::ExecuteInlinedInstructions | + &Instruction::ExecuteWriteTerm | + &Instruction::ExecuteWriteTermToChars | + &Instruction::ExecuteScryerPrologVersion | + &Instruction::ExecuteCryptoRandomByte | + &Instruction::ExecuteCryptoDataHash | + &Instruction::ExecuteCryptoDataHKDF | + &Instruction::ExecuteCryptoPasswordHash | + &Instruction::ExecuteCryptoDataEncrypt | + &Instruction::ExecuteCryptoDataDecrypt | + &Instruction::ExecuteCryptoCurveScalarMult | + &Instruction::ExecuteEd25519Sign | + &Instruction::ExecuteEd25519Verify | + &Instruction::ExecuteEd25519NewKeyPair | + &Instruction::ExecuteEd25519KeyPairPublicKey | + &Instruction::ExecuteCurve25519ScalarMult | + &Instruction::ExecuteFirstNonOctet | + &Instruction::ExecuteLoadHTML | + &Instruction::ExecuteLoadXML | + &Instruction::ExecuteGetEnv | + &Instruction::ExecuteSetEnv | + &Instruction::ExecuteUnsetEnv | + &Instruction::ExecuteShell | + &Instruction::ExecutePID | + &Instruction::ExecuteCharsBase64 | + &Instruction::ExecuteDevourWhitespace | + &Instruction::ExecuteIsSTOEnabled | + &Instruction::ExecuteSetSTOAsUnify | + &Instruction::ExecuteSetNSTOAsUnify | + &Instruction::ExecuteSetSTOWithErrorAsUnify | + &Instruction::ExecuteHomeDirectory | + &Instruction::ExecuteDebugHook | + &Instruction::ExecuteAddDiscontiguousPredicate | + &Instruction::ExecuteAddDynamicPredicate | + &Instruction::ExecuteAddMultifilePredicate | + &Instruction::ExecuteAddGoalExpansionClause | + &Instruction::ExecuteAddTermExpansionClause | + &Instruction::ExecuteAddInSituFilenameModule | + &Instruction::ExecuteClauseToEvacuable | + &Instruction::ExecuteScopedClauseToEvacuable | + &Instruction::ExecuteConcludeLoad | + &Instruction::ExecuteDeclareModule | + &Instruction::ExecuteLoadCompiledLibrary | + &Instruction::ExecuteLoadContextSource | + &Instruction::ExecuteLoadContextFile | + &Instruction::ExecuteLoadContextDirectory | + &Instruction::ExecuteLoadContextModule | + &Instruction::ExecuteLoadContextStream | + &Instruction::ExecutePopLoadContext | + &Instruction::ExecutePopLoadStatePayload | + &Instruction::ExecutePushLoadContext | + &Instruction::ExecutePushLoadStatePayload | + &Instruction::ExecuteUseModule | + &Instruction::ExecuteBuiltInProperty | + &Instruction::ExecuteMetaPredicateProperty | + &Instruction::ExecuteMultifileProperty | + &Instruction::ExecuteDiscontiguousProperty | + &Instruction::ExecuteDynamicProperty | + &Instruction::ExecuteAbolishClause | + &Instruction::ExecuteAsserta | + &Instruction::ExecuteAssertz | + &Instruction::ExecuteRetract | + &Instruction::ExecuteIsConsistentWithTermQueue | + &Instruction::ExecuteFlushTermQueue | + &Instruction::ExecuteRemoveModuleExports | + &Instruction::ExecuteAddNonCountedBacktracking | + &Instruction::ExecutePopCount => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("execute"), [atom(name), fixnum(arity)]) } @@ -2044,12 +2053,9 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::Deallocate => { functor!(atom!("deallocate")) } - &Instruction::JmpByCall(_, offset, ..) => { + &Instruction::JmpByCall(offset) => { functor!(atom!("jmp_by_call"), [fixnum(offset)]) } - &Instruction::JmpByExecute(_, offset, ..) => { - functor!(atom!("jmp_by_execute"), [fixnum(offset)]) - } &Instruction::RevJmpBy(offset) => { functor!(atom!("rev_jmp_by"), [fixnum(offset)]) } @@ -2244,6 +2250,7 @@ pub fn generate_instructions_rs() -> TokenStream { let mut clause_type_to_instr_arms = vec![]; let mut clause_type_name_arms = vec![]; let mut is_inbuilt_arms = vec![]; + let mut is_inlined_arms = vec![]; for (name, arity, variant) in instr_data.compare_number_variants { let ident = variant.ident.clone(); @@ -2295,7 +2302,7 @@ pub fn generate_instructions_rs() -> TokenStream { quote! { ClauseType::Inlined( InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*)) - ) => Instruction::#instr_ident(#(#placeholder_ids),*, 0) + ) => Instruction::#instr_ident(#(*#placeholder_ids),*) } ); @@ -2330,7 +2337,7 @@ pub fn generate_instructions_rs() -> TokenStream { quote! { ClauseType::BuiltIn( BuiltInClauseType::CompareTerm(CompareTerm::#ident) - ) => Instruction::#instr_ident(0) + ) => Instruction::#instr_ident } ); @@ -2391,13 +2398,13 @@ pub fn generate_instructions_rs() -> TokenStream { quote! { ClauseType::BuiltIn( BuiltInClauseType::#ident(#(#placeholder_ids),*) - ) => Instruction::#instr_ident(#(#placeholder_ids),*,0) + ) => Instruction::#instr_ident(#(*#placeholder_ids),*) } } else { quote! { ClauseType::BuiltIn( BuiltInClauseType::#ident - ) => Instruction::#instr_ident(0) + ) => Instruction::#instr_ident } }); @@ -2462,7 +2469,7 @@ pub fn generate_instructions_rs() -> TokenStream { quote! { ClauseType::Inlined( InlinedClauseType::#ident(#(#placeholder_ids),*) - ) => Instruction::#instr_ident(#(#placeholder_ids),*,0) + ) => Instruction::#instr_ident(*#(#placeholder_ids),*) } ); @@ -2471,6 +2478,12 @@ pub fn generate_instructions_rs() -> TokenStream { (atom!(#name), #arity) => true } ); + + is_inlined_arms.push( + quote! { + (atom!(#name), #arity) => true + } + ); } for (name, arity, variant) in instr_data.system_clause_type_variants { @@ -2552,13 +2565,13 @@ pub fn generate_instructions_rs() -> TokenStream { quote! { ClauseType::System( SystemClauseType::#ident(#(#placeholder_ids),*) - ) => Instruction::#instr_ident(#(#placeholder_ids),*,0) + ) => Instruction::#instr_ident(#(*#placeholder_ids),*) } } else { quote! { ClauseType::System( SystemClauseType::#ident - ) => Instruction::#instr_ident(0) + ) => Instruction::#instr_ident } }); @@ -2629,13 +2642,13 @@ pub fn generate_instructions_rs() -> TokenStream { quote! { ClauseType::System(SystemClauseType::REPL( REPLCodePtr::#ident(#(#placeholder_ids),*) - )) => Instruction::#instr_ident(#(#placeholder_ids),*,0) + )) => Instruction::#instr_ident(#(*#placeholder_ids),*) } } else { quote! { ClauseType::System(SystemClauseType::REPL( REPLCodePtr::#ident - )) => Instruction::#instr_ident(0) + )) => Instruction::#instr_ident } }); @@ -2655,7 +2668,7 @@ pub fn generate_instructions_rs() -> TokenStream { }); clause_type_to_instr_arms.push(quote! { - ClauseType::Named(arity, name, idx) => Instruction::CallNamed(arity, name, idx, 0) + ClauseType::Named(arity, name, idx) => Instruction::CallNamed(*arity, *name, *idx) }); clause_type_name_arms.push(quote! { @@ -2706,11 +2719,11 @@ pub fn generate_instructions_rs() -> TokenStream { clause_type_to_instr_arms.push(if !variant_fields.is_empty() { quote! { ClauseType::#ident(#(#placeholder_ids),*) => - Instruction::#ident(#(#placeholder_ids),*,0) + Instruction::#ident(#(*#placeholder_ids),*) } } else { quote! { - ClauseType::#ident => Instruction::#ident(0) + ClauseType::#ident => Instruction::#ident } }); @@ -2767,11 +2780,6 @@ pub fn generate_instructions_rs() -> TokenStream { Instruction::#execute_ident(#(#placeholder_ids),*) } }) - } else if variant_string == "JmpByCall" { - Some(quote! { - Instruction::JmpByCall(#(#placeholder_ids),*) => - Instruction::JmpByExecute(#(#placeholder_ids),*) - }) } else { None } @@ -2835,16 +2843,23 @@ pub fn generate_instructions_rs() -> TokenStream { let enum_arity = if let Fields::Unnamed(fields) = &variant.fields { fields.unnamed.len() } else { - unreachable!() + 0 }; let placeholder_ids: Vec<_> = (0 .. enum_arity) .map(|n| format_ident!("f_{}", n)) .collect(); - Some(quote! { - Instruction::#variant_ident(#(#placeholder_ids),*) => - Instruction::#def_variant_ident(#(#placeholder_ids),*) + Some(if enum_arity == 0 { + quote! { + Instruction::#variant_ident => + Instruction::#def_variant_ident + } + } else { + quote! { + Instruction::#variant_ident(#(#placeholder_ids),*) => + Instruction::#def_variant_ident(#(#placeholder_ids),*) + } }) } else { None @@ -2852,38 +2867,6 @@ pub fn generate_instructions_rs() -> TokenStream { }) .collect(); - let perm_vars_mut_arms: Vec<_> = instr_data.instr_variants - .iter() - .cloned() - .filter_map(|(_, _, _, variant)| { - if !is_callable(&variant.ident) && !is_jmp(&variant.ident) { - return None; - } - - let variant_ident = variant.ident.clone(); - let enum_arity = if let Fields::Unnamed(fields) = &variant.fields { - fields.unnamed.len() - } else { - 0 - }; - - let placeholder_ids: Vec<_> = (1 .. enum_arity) - .map(|_| format_ident!("_")) - .collect(); - - Some(if enum_arity == 1 { - quote! { - Instruction::#variant_ident(ref mut perm_vars) => Some(perm_vars) - } - } else { - quote! { - Instruction::#variant_ident(#(#placeholder_ids),*, ref mut perm_vars) => - Some(perm_vars) - } - }) - }) - .collect(); - let control_flow_arms: Vec<_> = instr_data.instr_variants .iter() .cloned() @@ -2892,10 +2875,22 @@ pub fn generate_instructions_rs() -> TokenStream { return None; } + let enum_arity = if let Fields::Unnamed(fields) = &variant.fields { + fields.unnamed.len() + } else { + 0 + }; + let variant_ident = variant.ident.clone(); - Some(quote! { - Instruction::#variant_ident(..) => true + Some(if enum_arity == 0 { + quote! { + Instruction::#variant_ident => true + } + } else { + quote! { + Instruction::#variant_ident(..) => true + } }) }) .collect(); @@ -2913,27 +2908,59 @@ pub fn generate_instructions_rs() -> TokenStream { }; Some(if variant_string.starts_with("Execute") { - quote! { - (#name, execute, $($args:expr),*) => { - Instruction::#variant_ident($($args),*) + if arity == 0 { + quote! { + (#name, execute) => { + Instruction::#variant_ident + } + } + } else { + quote! { + (#name, execute, $($args:expr),*) => { + Instruction::#variant_ident($($args),*) + } } } } else if variant_string.starts_with("Call") { - quote! { - (#name, $($args:expr),*) => { - Instruction::#variant_ident($($args),*) + if arity == 0 { + quote! { + (#name) => { + Instruction::#variant_ident + } + } + } else { + quote! { + (#name, $($args:expr),*) => { + Instruction::#variant_ident($($args),*) + } } } } else if variant_string.starts_with("DefaultExecute") { - quote! { - (#name, execute, default, $($args:expr),*) => { - Instruction::#variant_ident($($args),*) + if arity == 0 { + quote! { + (#name, execute, default) => { + Instruction::#variant_ident + } + } + } else { + quote! { + (#name, execute, default, $($args:expr),*) => { + Instruction::#variant_ident($($args),*) + } } } } else if variant_string.starts_with("DefaultCall") { - quote! { - (#name, default, $($args:expr),*) => { - Instruction::#variant_ident($($args),*) + if arity == 0 { + quote! { + (#name, default) => { + Instruction::#variant_ident + } + } + } else { + quote! { + (#name, default, $($args:expr),*) => { + Instruction::#variant_ident($($args),*) + } } } } else { @@ -3061,7 +3088,7 @@ pub fn generate_instructions_rs() -> TokenStream { } } - pub fn to_instr(self) -> Instruction { + pub fn to_instr(&self) -> Instruction { match self { #( #clause_type_to_instr_arms, @@ -3085,6 +3112,15 @@ pub fn generate_instructions_rs() -> TokenStream { )* } } + + pub fn is_inlined(name: Atom, arity: usize) -> bool { + match (name, arity) { + #( + #is_inlined_arms, + )* + _ => false, + } + } } #[derive(Clone, Debug)] @@ -3130,15 +3166,6 @@ pub fn generate_instructions_rs() -> TokenStream { } } - pub fn perm_vars_mut(&mut self) -> Option<&mut usize> { - match self { - #( - #perm_vars_mut_arms, - )* - _ => None, - } - } - pub fn is_ctrl_instr(&self) -> bool { match self { &Instruction::Allocate(_) | @@ -3201,41 +3228,6 @@ fn is_jmp(id: &Ident) -> bool { } fn create_instr_variant(id: Ident, mut variant: Variant) -> Variant { - use proc_macro2::Span; - use syn::punctuated::Punctuated; - use syn::token::Paren; - - // add the perm_vars usize field to the variant. - - if is_callable(&id) || is_jmp(&id) { - let field = Field { - attrs: vec![], - vis: Visibility::Inherited, - ident: None, - colon_token: None, - ty: parse_quote! { usize }, - }; - - match &mut variant.fields { - Fields::Unnamed(ref mut fields) => { - fields.unnamed.push(field); - } - Fields::Unit => { - variant.fields = Fields::Unnamed(FieldsUnnamed { - paren_token: Paren(Span::call_site()), - unnamed: { - let mut fields_seq = Punctuated::new(); - fields_seq.push(field); - fields_seq - } - }); - } - _ => { - unreachable!(); - } - } - } - variant.ident = id; variant.attrs.clear(); diff --git a/src/allocator.rs b/src/allocator.rs index 50e9c7c3..f689a802 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1,10 +1,7 @@ use crate::parser::ast::*; -use crate::temp_v; -use crate::fixtures::*; use crate::forms::*; use crate::instructions::*; -use crate::machine::machine_indices::*; use crate::targets::*; use std::cell::Cell; @@ -16,7 +13,7 @@ pub(crate) trait Allocator { &mut self, lvl: Level, context: GenContext, - code: &mut Code, + code: &mut CodeDeque, ); fn mark_non_var<'a, Target: CompilationTarget<'a>>( @@ -24,40 +21,44 @@ pub(crate) trait Allocator { lvl: Level, context: GenContext, cell: &'a Cell, - code: &mut Code, + code: &mut CodeDeque, ); fn mark_reserved_var<'a, Target: CompilationTarget<'a>>( &mut self, - var_name: Var, + var_num: usize, lvl: Level, cell: &'a Cell, term_loc: GenContext, - code: &mut Code, + code: &mut CodeDeque, r: RegType, is_new_var: bool, ); + fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType; + fn mark_var<'a, Target: CompilationTarget<'a>>( &mut self, - var_name: Var, + var_num: usize, lvl: Level, cell: &'a Cell, context: GenContext, - code: &mut Code, + code: &mut CodeDeque, ); fn reset(&mut self); - fn reset_contents(&mut self) {} fn reset_arg(&mut self, arg_num: usize); fn reset_at_head(&mut self, args: &Vec); + fn reset_contents(&mut self); fn advance_arg(&mut self); + /* fn bindings(&self) -> &AllocVarDict; fn bindings_mut(&mut self) -> &mut AllocVarDict; - fn take_bindings(self) -> AllocVarDict; + */ + fn max_reg_allocated(&self) -> usize; // TODO: wha.. why?? grrr. it drains the VarStatus data from vs (which it owns!) @@ -87,21 +88,4 @@ pub(crate) trait Allocator { perm_vs } */ - - fn get(&self, var: Var) -> RegType { - self.bindings() - .get(&var) - .map_or(temp_v!(0), |v| v.as_reg_type()) - } - - fn is_unbound(&self, var: Var) -> bool { - self.get(var).reg_num() == 0 - } - - fn record_register(&mut self, var: Var, r: RegType) { - match self.bindings_mut().get_mut(&var).unwrap() { - &mut VarAlloc::Temp(_, ref mut s, _) => *s = r.reg_num(), - &mut VarAlloc::Perm(ref mut s) => *s = r.reg_num(), - } - } } diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 94974a51..0fbd91d5 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -52,7 +52,7 @@ pub(crate) struct ArithInstructionIterator<'a> { state_stack: Vec>, } -pub(crate) type ArithCont = (Code, Option); +pub(crate) type ArithCont = (CodeDeque, Option); impl<'a> ArithInstructionIterator<'a> { fn push_subterm(&mut self, lvl: Level, term: &'a Term) { @@ -73,7 +73,7 @@ impl<'a> ArithInstructionIterator<'a> { 2, )) } - Term::Var(cell, var) => TermIterState::Var(Level::Shallow, cell, VarPtr::from(var)), + Term::Var(cell, var_ptr) => TermIterState::Var(Level::Shallow, cell, var_ptr.clone()), }; Ok(ArithInstructionIterator { @@ -86,7 +86,7 @@ impl<'a> ArithInstructionIterator<'a> { pub(crate) enum ArithTermRef<'a> { Literal(&'a Literal), Op(Atom, usize), // name, arity. - Var(Level, &'a Cell, Var), + Var(Level, &'a Cell, VarPtr), } impl<'a> Iterator for ArithInstructionIterator<'a> { @@ -114,8 +114,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> { } } TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))), - TermIterState::Var(lvl, cell, var_ref) => { - return Some(Ok(ArithTermRef::Var(lvl, cell, Var::from(var_ref)))); + TermIterState::Var(lvl, cell, var_ptr) => { + return Some(Ok(ArithTermRef::Var(lvl, cell, var_ptr))); } _ => { return Some(Err(ArithmeticError::NonEvaluableFunctor( @@ -307,43 +307,48 @@ impl<'a> ArithmeticEvaluator<'a> { term_loc: GenContext, arg: usize, ) -> Result { - let mut code = vec![]; + let mut code = CodeDeque::new(); let mut iter = src.iter()?; while let Some(term_ref) = iter.next() { 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( - name, + var_num, arg, term_loc, cell, &mut code, ) } else if term_loc.is_last() || cell.get().norm().reg_num() == 0 { - if let Some(r) = self.marker.get_binding(&name) { - r - } else { + let r = self.marker.get_binding(var_num); + + if r.reg_num() == 0 { self.marker.mark_var::( - name.clone(), + var_num, lvl, cell, term_loc, &mut code, ); - - self.marker.get_binding(&name).unwrap() + } else { + self.marker.increment_running_count(var_num); } + + r } else { + self.marker.increment_running_count(var_num); cell.get().norm() }; self.interm.push(ArithmeticTerm::Reg(r)); } ArithTermRef::Op(name, arity) => { - code.push(self.instr_from_clause(name, arity)?); + code.push_back(self.instr_from_clause(name, arity)?); } } } diff --git a/src/codegen.rs b/src/codegen.rs index e7c6e2ac..794ec65b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,10 +1,9 @@ use crate::atom_table::*; use crate::parser::ast::*; -use crate::{perm_v, temp_v}; +use crate::temp_v; use crate::allocator::*; use crate::arithmetic::*; use crate::debray_allocator::*; -use crate::fixtures::*; use crate::forms::*; use crate::indexing::*; use crate::instructions::*; @@ -13,39 +12,139 @@ use crate::targets::*; use crate::types::*; use crate::instr; +use crate::machine::disjuncts::*; use crate::machine::machine_errors::*; -use indexmap::{IndexMap, IndexSet}; +use fxhash::FxBuildHasher; +use indexmap::IndexSet; use std::cell::Cell; use std::collections::VecDeque; #[derive(Debug)] -pub(crate) struct ConjunctInfo { - pub(crate) perm_vs: VariableFixtures, - pub(crate) num_of_chunks: usize, - pub(crate) has_deep_cut: bool, +pub struct BranchCodeStack { + pub stack: Vec>, } -impl ConjunctInfo { - fn new(perm_vs: VariableFixtures, num_of_chunks: usize, has_deep_cut: bool) -> Self { - ConjunctInfo { - perm_vs, - num_of_chunks, - has_deep_cut, +pub type SubsumedBranchHits = IndexSet; + +impl BranchCodeStack { + fn new() -> Self { + Self { stack: vec![] } + } + + fn add_new_branch_stack(&mut self) { + self.stack.push(vec![]); + } + + fn add_new_branch(&mut self) { + if self.stack.is_empty() { + self.add_new_branch_stack(); + } + + if let Some(branches) = self.stack.last_mut() { + branches.push(CodeDeque::new()); } } - fn allocates(&self) -> bool { - self.perm_vs.size() > 0 || self.num_of_chunks > 1 || self.has_deep_cut + fn code<'a>(&'a mut self, default_code: &'a mut CodeDeque) -> &'a mut CodeDeque { + self.stack.last_mut() + .and_then(|stack| stack.last_mut()) + .unwrap_or(default_code) } - fn perm_vars(&self) -> usize { - self.perm_vs.size() + self.perm_var_offset() + fn push_missing_vars(&mut self, depth: usize, marker: &mut DebrayAllocator) -> SubsumedBranchHits { + let mut subsumed_hits = SubsumedBranchHits::with_hasher(FxBuildHasher::default()); + + for idx in (self.stack.len() - depth .. self.stack.len()).rev() { + let branch = &mut marker.branch_stack[idx]; + let branch_hits = &branch.hits; + + for (&var_num, branches) in branch_hits.iter() { + let record = &marker.var_data.records[var_num]; + + if record.running_count < record.num_occurrences { + if !branches.all() { + branch.deep_safety.insert(var_num); + branch.shallow_safety.insert(var_num); + + let r = record.allocation.as_reg_type(); + + // iterate over unset bits. + for branch_idx in branches.iter_zeros() { + if branch_idx + 1 == branches.len() && idx + 1 != self.stack.len() { + break; + } + + self.stack[idx][branch_idx].push_back(instr!("put_variable", r, 0)); + } + } + + subsumed_hits.insert(var_num); + } + } + } + + subsumed_hits } - fn perm_var_offset(&self) -> usize { - self.has_deep_cut as usize + fn push_jump_instrs(&mut self, depth: usize) { + // add 2 in each arm length to compensate for each jump + // instruction and each branch instruction not yet added. + let mut jump_span: usize = self.stack[self.stack.len() - depth ..] + .iter() + .map(|branch| branch.iter().map(|code| code.len() + 2).sum::()) + .sum(); + + jump_span -= depth; + + for idx in self.stack.len() - depth .. self.stack.len() { + let inner_len = self.stack[idx].len(); + + for (inner_idx, code) in self.stack[idx].iter_mut().enumerate() { + if inner_idx + 1 == inner_len { + jump_span -= code.len() + 1; // = jump_span.saturating_sub(code.len() + 1); + } else { + jump_span -= code.len() + 1; + code.push_back(instr!("jmp_by_call", jump_span as usize)); + + // saturate at 0 if underflow happens, which only + // happens when jump_span is no longer needed + // anyway. still, we don't want to panic at + // underflow. + jump_span -= 1; + } + } + } + + // eliminate terminating jump instruction in last arm of last + // branch. + // self.stack.last_mut() + // .and_then(|branch| branch.last_mut()) + // .map(|code| code.pop_back()); + } + + fn pop_branch(&mut self, depth: usize, settings: CodeGenSettings) -> CodeDeque { + let mut combined_code = CodeDeque::new(); + + for mut branch_arm in self.stack.drain(self.stack.len() - depth ..).rev() { + let num_branch_arms = branch_arm.len(); + branch_arm.last_mut().map(|code| code.extend(combined_code.drain(..))); + + for (idx, code) in branch_arm.into_iter().enumerate() { + combined_code.push_back(if idx == 0 { + Instruction::TryMeElse(code.len() + 1) + } else if idx + 1 < num_branch_arms { + settings.retry_me_else(code.len() + 1) + } else { + settings.trust_me() + }); + + combined_code.extend(code.into_iter()); + } + } + + combined_code } } @@ -168,53 +267,49 @@ impl CodeGenSettings { pub(crate) struct CodeGenerator<'a> { pub(crate) atom_tbl: &'a mut AtomTable, marker: DebrayAllocator, - pub(crate) var_count: IndexMap, settings: CodeGenSettings, pub(crate) skeleton: PredicateSkeleton, - pub(crate) jmp_by_locs: Vec, - global_jmp_by_locs_offset: usize, } impl DebrayAllocator { fn mark_var_in_non_callable( &mut self, - name: Var, + var_num: usize, term_loc: GenContext, vr: &Cell, - code: &mut Code, + code: &mut CodeDeque, ) -> RegType { - self.mark_var::(name, Level::Shallow, vr, term_loc, code); - vr.get().norm() - } + self.mark_var::( + var_num, + Level::Shallow, + vr, + term_loc, + code, + ); - #[inline(always)] - pub(crate) fn get_binding(&self, name: &Var) -> Option { - match self.bindings().get(name) { - Some(&VarAlloc::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)), - Some(&VarAlloc::Perm(p)) if p != 0 => Some(RegType::Perm(p)), - _ => None, - } + vr.get().norm() } pub(crate) fn mark_non_callable( &mut self, - name: Var, + var_num: usize, arg: usize, term_loc: GenContext, vr: &Cell, - code: &mut Code, + code: &mut CodeDeque, ) -> RegType { - match self.get_binding(&name) { - Some(RegType::Temp(t)) => RegType::Temp(t), - Some(RegType::Perm(p)) => { + match self.get_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(name.clone(), term_loc, vr, code); + self.mark_var_in_non_callable(var_num, term_loc, vr, code); temp_v!(arg) } else { + self.increment_running_count(var_num); RegType::Perm(p) } } - None => self.mark_var_in_non_callable(name, term_loc, vr, code), + _ => self.mark_var_in_non_callable(var_num, term_loc, vr, code), } } } @@ -280,50 +375,34 @@ impl<'b> CodeGenerator<'b> { CodeGenerator { atom_tbl, marker: DebrayAllocator::new(), - var_count: IndexMap::new(), settings, skeleton: PredicateSkeleton::new(), - jmp_by_locs: vec![], - global_jmp_by_locs_offset: 0, } } - fn update_var_count<'a, Iter: Iterator>>(&mut self, iter: Iter) { - for term in iter { - if let TermRef::Var(_, _, var) = term { - let entry = self.var_count.entry(var).or_insert(0); - *entry += 1; - } - } - } - - fn get_var_count(&self, var: &Var) -> usize { - *self.var_count.get(var).unwrap() - } - - fn add_or_increment_void_instr<'a, Target>(target: &mut Code) + fn add_or_increment_void_instr<'a, Target>(target: &mut CodeDeque) where Target: crate::targets::CompilationTarget<'a>, { - if let Some(ref mut instr) = target.last_mut() { + if let Some(ref mut instr) = target.back_mut() { if Target::is_void_instr(&*instr) { Target::incr_void_instr(instr); return; } } - target.push(Target::to_void(1)); + target.push_back(Target::to_void(1)); } fn deep_var_instr<'a, Target: crate::targets::CompilationTarget<'a>>( &mut self, cell: &'a Cell, - var: &Var, + var_num: usize, term_loc: GenContext, - target: &mut Code, + target: &mut CodeDeque, ) { - if self.get_var_count(var.as_ref()) > 1 { - self.marker.mark_var::(var.clone(), Level::Deep, cell, term_loc, target); + if self.marker.var_data.records[var_num].num_occurrences > 1 { + self.marker.mark_var::(var_num, Level::Deep, cell, term_loc, target); } else { Self::add_or_increment_void_instr::(target); } @@ -333,7 +412,7 @@ impl<'b> CodeGenerator<'b> { &mut self, subterm: &'a Term, term_loc: GenContext, - target: &mut Code, + target: &mut CodeDeque, ) { match subterm { &Term::AnonVar => { @@ -344,13 +423,13 @@ impl<'b> CodeGenerator<'b> { Term::PartialString(ref cell, ..) | Term::CompleteString(ref cell, ..) => { self.marker.mark_non_var::(Level::Deep, term_loc, cell, target); - target.push(Target::clause_arg_to_instr(cell.get())); + target.push_back(Target::clause_arg_to_instr(cell.get())); } &Term::Literal(_, ref constant) => { - target.push(Target::constant_subterm(constant.clone())); + target.push_back(Target::constant_subterm(constant.clone())); } - &Term::Var(ref cell, ref var) => { - self.deep_var_instr::(cell, var, term_loc, target); + &Term::Var(ref cell, ref var_ptr) => { + self.deep_var_instr::(cell, var_ptr.to_var_num().unwrap(), term_loc, target); } }; } @@ -359,13 +438,13 @@ impl<'b> CodeGenerator<'b> { &mut self, iter: Iter, term_loc: GenContext, - ) -> Code + ) -> CodeDeque where Target: crate::targets::CompilationTarget<'a>, Iter: Iterator>, CodeGenerator<'b>: AddToFreeList<'a, Target> { - let mut target: Code = Vec::new(); + let mut target = CodeDeque::new(); for term in iter { match term { @@ -378,11 +457,11 @@ impl<'b> CodeGenerator<'b> { } TermRef::Clause(lvl, cell, name, terms) => { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); - target.push(Target::to_structure(name, terms.len(), cell.get())); + target.push_back(Target::to_structure(name, terms.len(), cell.get())); as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get()); - if let Some(instr) = target.last_mut() { + if let Some(instr) = target.back_mut() { if let Some(term) = terms.last() { trim_structure_by_last_arg(instr, term); } @@ -398,7 +477,7 @@ impl<'b> CodeGenerator<'b> { } TermRef::Cons(lvl, cell, head, tail) => { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); - target.push(Target::to_list(lvl, cell.get())); + target.push_back(Target::to_list(lvl, cell.get())); as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get()); @@ -410,44 +489,31 @@ impl<'b> CodeGenerator<'b> { } TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); - target.push(Target::to_pstr(lvl, *string, cell.get(), false)); + target.push_back(Target::to_pstr(lvl, *string, cell.get(), false)); } TermRef::Literal(lvl @ Level::Shallow, cell, constant) => { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); - target.push(Target::to_constant(lvl, *constant, cell.get())); + target.push_back(Target::to_constant(lvl, *constant, cell.get())); } TermRef::PartialString(lvl, cell, string, tail) => { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); let atom = self.atom_tbl.build_with(&string); - target.push(Target::to_pstr(lvl, atom, cell.get(), true)); + target.push_back(Target::to_pstr(lvl, atom, cell.get(), true)); self.subterm_to_instr::(tail, term_loc, &mut target); } TermRef::CompleteString(lvl, cell, atom) => { self.marker.mark_non_var::(lvl, term_loc, cell, &mut target); - target.push(Target::to_pstr(lvl, atom, cell.get(), false)); - } - TermRef::Var(lvl @ Level::Shallow, cell, var) if var.as_str() == Some("!") => { - if self.marker.is_unbound(var.clone()) { - if term_loc != GenContext::Head { - self.marker.mark_reserved_var::( - var.clone(), - lvl, - cell, - term_loc, - &mut target, - perm_v!(1), - false, - ); - - continue; - } - } - - self.marker.mark_var::(var.clone(), lvl, cell, term_loc, &mut target); + target.push_back(Target::to_pstr(lvl, atom, cell.get(), false)); } TermRef::Var(lvl @ Level::Shallow, cell, var) => { - self.marker.mark_var::(var.clone(), lvl, cell, term_loc, &mut target); + self.marker.mark_var::( + var.to_var_num().unwrap(), + lvl, + cell, + term_loc, + &mut target, + ); } _ => {} }; @@ -456,82 +522,27 @@ impl<'b> CodeGenerator<'b> { target } - /* - fn collect_var_data<'a>(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> { - let mut vs = VariableFixtures::new(); - - while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() { - for (i, chunked_term) in chunked_terms.iter().enumerate() { - let term_loc = match chunked_term { - &ChunkedTerm::HeadClause(..) => GenContext::Head, - &ChunkedTerm::BodyTerm(_) => { - if i < chunked_terms.len() - 1 { - GenContext::Mid(chunk_num) - } else { - GenContext::Last(chunk_num) - } - } - }; - - self.update_var_count(chunked_term.post_order_iter()); - vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc); - } + fn add_call(&mut self, code: &mut CodeDeque, call_instr: Instruction, call_policy: CallPolicy) { + if self.marker.in_tail_position && self.marker.var_data.allocates { + code.push_back(instr!("deallocate")); } - let num_of_chunks = iter.chunk_num; - let has_deep_cut = iter.encountered_deep_cut(); - - vs.populate_restricting_sets(); - vs.set_perm_vals(has_deep_cut); - - let vs = self.marker.drain_var_data(vs, num_of_chunks); - ConjunctInfo::new(vs, num_of_chunks, has_deep_cut) - } - */ - - fn add_conditional_call(&mut self, code: &mut Code, qt: &QueryTerm, pvs: usize) { - match qt { - &QueryTerm::Jump(ref vars) => { - self.jmp_by_locs.push(code.len()); - code.push(instr!("jmp_by_call", vars.len(), 0, pvs)); - } - &QueryTerm::Clause(_, ref ct, _, CallPolicy::Default) => { - code.push(call_clause_by_default!(ct.clone(), pvs)); - } - &QueryTerm::Clause(_, ref ct, _, CallPolicy::Counted) => { - code.push(call_clause!(ct.clone(), pvs)); - } - _ => {} - } - } - - fn lco(code: &mut Code) -> usize { - let mut dealloc_index = code.len() - 1; - let last_instr = code.pop(); - - match last_instr { - Some(instr @ Instruction::Proceed) => { - code.push(instr); - } - Some(instr @ Instruction::Cut(_)) => { - dealloc_index += 1; - code.push(instr); - } - Some(mut instr) if instr.is_ctrl_instr() => { - code.push(if instr.perm_vars_mut().is_some() { - instr.to_execute() + match call_policy { + CallPolicy::Default => { + if self.marker.in_tail_position { + code.push_back(call_instr.to_execute().to_default()); } else { - dealloc_index += 1; - instr - }); + code.push_back(call_instr.to_default()) + } } - Some(instr) => { - code.push(instr); + CallPolicy::Counted => { + if self.marker.in_tail_position { + code.push_back(call_instr.to_execute()); + } else { + code.push_back(call_instr) + } } - None => {} } - - dealloc_index } fn compile_inlined<'a>( @@ -539,9 +550,9 @@ impl<'b> CodeGenerator<'b> { ct: &InlinedClauseType, terms: &'a Vec, term_loc: GenContext, - code: &mut Code, + code: &mut CodeDeque, ) -> Result<(), CompilationError> { - match ct { + let call_instr = match ct { &InlinedClauseType::CompareNumber(mut cmp) => { self.marker.reset_arg(2); @@ -559,29 +570,29 @@ impl<'b> CodeGenerator<'b> { let at_1 = at_1.unwrap_or(interm!(1)); let at_2 = at_2.unwrap_or(interm!(2)); - code.push(compare_number_instr!(cmp, at_1, at_2)); + 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(..)) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("atom", r, 0)); + instr!("atom", r) } _ => { - code.push(instr!("$fail", 0)); + instr!("$fail") } }, &InlinedClauseType::IsAtomic(..) => match &terms[0] { @@ -590,26 +601,26 @@ impl<'b> CodeGenerator<'b> { &Term::Cons(..) | &Term::PartialString(..) | &Term::CompleteString(..) => { - code.push(instr!("$fail", 0)); + instr!("$fail") } &Term::Literal(_, Literal::String(_)) => { - code.push(instr!("$fail", 0)); + instr!("$fail") } &Term::Literal(..) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("atomic", r, 0)); + instr!("atomic", r) } }, &InlinedClauseType::IsCompound(..) => match &terms[0] { @@ -618,57 +629,57 @@ impl<'b> CodeGenerator<'b> { &Term::PartialString(..) | &Term::CompleteString(..) | &Term::Literal(_, Literal::String(..)) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("compound", r, 0)); + instr!("compound", r) } _ => { - code.push(instr!("$fail", 0)); + instr!("$fail") } }, &InlinedClauseType::IsRational(..) => match &terms[0] { &Term::Literal(_, Literal::Rational(_)) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.marker.mark_non_callable(name.clone(), 1, term_loc, vr, code); - code.push(instr!("rational", r, 0)); + let r = self.marker.mark_non_callable(name.to_var_num().unwrap(), 1, term_loc, vr, code); + instr!("rational", r) } _ => { - code.push(instr!("$fail", 0)); + instr!("$fail") } }, &InlinedClauseType::IsFloat(..) => match &terms[0] { &Term::Literal(_, Literal::Float(_)) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("float", r, 0)); + instr!("float", r) } _ => { - code.push(instr!("$fail", 0)); + instr!("$fail") } }, &InlinedClauseType::IsNumber(..) => match &terms[0] { @@ -676,66 +687,66 @@ impl<'b> CodeGenerator<'b> { &Term::Literal(_, Literal::Rational(_)) | &Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("number", r, 0)); + instr!("number", r) } _ => { - code.push(instr!("$fail", 0)); + instr!("$fail") } }, &InlinedClauseType::IsNonVar(..) => match &terms[0] { &Term::AnonVar => { - code.push(instr!("$fail", 0)); + instr!("$fail") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("nonvar", r, 0)); + instr!("nonvar", r) } _ => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } }, &InlinedClauseType::IsInteger(..) => match &terms[0] { &Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("integer", r, 0)); + instr!("integer", r) } _ => { - code.push(instr!("$fail", 0)); + instr!("$fail") } }, &InlinedClauseType::IsVar(..) => match &terms[0] { @@ -744,26 +755,29 @@ impl<'b> CodeGenerator<'b> { &Term::Cons(..) | &Term::PartialString(..) | &Term::CompleteString(..) => { - code.push(instr!("$fail", 0)); + instr!("$fail") } &Term::AnonVar => { - code.push(instr!("$succeed", 0)); + instr!("$succeed") } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); let r = self.marker.mark_non_callable( - name.clone(), + name.to_var_num().unwrap(), 1, term_loc, vr, code, ); - code.push(instr!("var", r, 0)); + instr!("var", r) } }, - } + }; + + // inlined predicates are never counted, so this overrides nothing. + self.add_call(code, call_instr, CallPolicy::Counted); Ok(()) } @@ -782,7 +796,7 @@ impl<'b> CodeGenerator<'b> { fn compile_is_call( &mut self, terms: &Vec, - code: &mut Code, + code: &mut CodeDeque, term_loc: GenContext, call_policy: CallPolicy, ) -> Result<(), CompilationError> { @@ -798,8 +812,11 @@ impl<'b> CodeGenerator<'b> { let at = match &terms[0] { &Term::Var(ref vr, ref name) => { + let var_num = name.to_var_num().unwrap(); + self.marker.mark_temp_to_safe_perm(var_num); + self.marker.mark_var::( - name.clone(), + var_num, Level::Shallow, vr, term_loc, @@ -813,208 +830,189 @@ impl<'b> CodeGenerator<'b> { c @ Literal::Rational(_) | c @ Literal::Fixnum(_)) => { let v = HeapCellValue::from(c); - code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1))); + 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(instr!("$fail", 0)); + 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); - Ok(if let CallPolicy::Default = call_policy { - code.push(instr!("is", default, temp_v!(1), at, 0)); - } else { - code.push(instr!("is", temp_v!(1), at, 0)); - }) - } - - #[inline] - fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &Cell) { - let r = self.marker.get(Var::from("!")); - cell.set(VarReg::Norm(r)); - code.push(instr!("$set_cp", cell.get().norm(), 0)); + Ok(()) } fn compile_seq<'a>( &mut self, - iter: ChunkedIterator<'a>, - conjunct_info: &ConjunctInfo, - code: &mut Code, + clauses: &ChunkedTermVec, + code: &mut CodeDeque, ) -> Result<(), CompilationError> { - for (chunk_num, _, terms) in iter.rule_body_iter() { - for (i, term) in terms.iter().enumerate() { - let term_loc = if i + 1 < terms.len() { - GenContext::Mid(chunk_num) - } else { - GenContext::Last(chunk_num) - }; + let mut chunk_num = 0; + let mut branch_code_stack = BranchCodeStack::new(); + let mut clause_iter = ClauseIterator::new(clauses); - match *term { - &QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell), - &QueryTerm::BlockedCut => code.push(if chunk_num == 0 { - Instruction::NeckCut - } else { - Instruction::Cut(perm_v!(1)) - }), - &QueryTerm::Clause( - _, - ClauseType::BuiltIn(BuiltInClauseType::Is(..)), - ref terms, - call_policy, - ) => self.compile_is_call(terms, code, term_loc, call_policy)?, - &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => { - self.compile_inlined(ct, terms, term_loc, code)? - } - _ => { - let num_perm_vars = if chunk_num == 0 { - conjunct_info.perm_vars() + while let Some(clause_item) = clause_iter.next() { + match clause_item { + ClauseItem::Chunk(chunk) => { + for (idx, term) in chunk.iter().enumerate() { + let term_loc = if idx + 1 < chunk.len() { + GenContext::Mid(chunk_num) } else { - conjunct_info.perm_vs.vars_above_threshold(i + 1) + self.marker.in_tail_position = clause_iter.in_tail_position(); + GenContext::Last(chunk_num) }; - self.compile_query_line(term, term_loc, code, num_perm_vars); + match term { + &QueryTerm::GetLevel(var_num) => { + let code = branch_code_stack.code(code); + let r = self.marker.mark_cut_var(var_num, chunk_num); + code.push_back(instr!("get_level", r)); + } + &QueryTerm::GetCutPoint { var_num, prev_b } => { + let code = branch_code_stack.code(code); + let r = self.marker.mark_cut_var(var_num, chunk_num); - if self.marker.max_reg_allocated() > MAX_ARITY { - return Err(CompilationError::ExceededMaxArity); + code.push_back(if prev_b { + instr!("get_prev_level", r) + } else { + instr!("get_cut_point", r) + }); + } + &QueryTerm::GlobalCut(var_num) => { + let code = branch_code_stack.code(code); + + if chunk_num == 0 { + code.push_back(instr!("neck_cut")); + } else { + let r = self.marker.get_binding(var_num); + // let r = self.marker.mark_cut_var(var_num, chunk_num); + code.push_back(instr!("cut", r)); + } + + if self.marker.in_tail_position { + if self.marker.var_data.allocates { + code.push_back(instr!("deallocate")); + } + + code.push_back(instr!("proceed")); + } + } + &QueryTerm::LocalCut(var_num) => { + let code = branch_code_stack.code(code); + let r = self.marker.get_binding(var_num); + // let r = self.marker.mark_cut_var(var_num, chunk_num); + code.push_back(instr!("cut", r)); + + if self.marker.in_tail_position { + if self.marker.var_data.allocates { + code.push_back(instr!("deallocate")); + } + + code.push_back(instr!("proceed")); + } + } + &QueryTerm::Clause( + _, + ClauseType::BuiltIn(BuiltInClauseType::Is(..)), + ref terms, + call_policy, + ) => self.compile_is_call(terms, branch_code_stack.code(code), term_loc, call_policy)?, + &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => { + self.compile_inlined(ct, terms, term_loc, branch_code_stack.code(code))? + } + &QueryTerm::Fail => { + branch_code_stack.code(code).push_back(instr!("$fail")); + } + term @ &QueryTerm::Clause(..) => { + self.compile_query_line(term, term_loc, branch_code_stack.code(code)); + + if self.marker.max_reg_allocated() > MAX_ARITY { + return Err(CompilationError::ExceededMaxArity); + } + } } } + + chunk_num += 1; + self.marker.in_tail_position = false; + self.marker.reset_contents(); + } + ClauseItem::FirstBranch(num_branches) => { + branch_code_stack.add_new_branch_stack(); + branch_code_stack.add_new_branch(); + + self.marker.add_branch_stack(num_branches); + self.marker.add_branch(); + } + ClauseItem::NextBranch => { + branch_code_stack.add_new_branch(); + self.marker.add_branch(); + self.marker.incr_current_branch(); + } + ClauseItem::BranchEnd(depth) => { + if !clause_iter.in_tail_position() { + let subsumed_hits = branch_code_stack.push_missing_vars(depth, &mut self.marker); + self.marker.pop_branch(depth, subsumed_hits); + branch_code_stack.push_jump_instrs(depth); + } else { + self.marker.drain_branches(depth); + } + + let settings = CodeGenSettings { + non_counted_bt: self.settings.non_counted_bt, + is_extensible: false, + global_clock_tick: None, + }; + + let branch_code = branch_code_stack.pop_branch(depth, settings); + branch_code_stack.code(code).extend(branch_code); } } + } - self.marker.reset_contents(); + if self.marker.var_data.allocates { + code.push_front(instr!("allocate", self.marker.num_perm_vars())); } Ok(()) } - fn compile_seq_prelude(&mut self, var_data: &VarData, body: &mut Code) { - /* - if conjunct_info.allocates() { - let perm_vars = conjunct_info.perm_vars(); - - body.push(Instruction::Allocate(perm_vars)); - - if conjunct_info.has_deep_cut { - body.push(Instruction::GetLevel(perm_v!(1))); - } - } - */ - } - - fn compile_cleanup( - &mut self, - code: &mut Code, - conjunct_info: &ConjunctInfo, - toc: &QueryTerm, - ) { - // add a proceed to bookend any trailing cuts. - match toc { - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => { - code.push(instr!("proceed")); - } - _ => {} - } - - // perform lco. - let dealloc_index = Self::lco(code); - - if conjunct_info.allocates() { - let offset = self.global_jmp_by_locs_offset; - - if let Some(jmp_by_offset) = self.jmp_by_locs[offset..].last_mut() { - if *jmp_by_offset == dealloc_index { - *jmp_by_offset += 1; - } - } - - code.insert(dealloc_index, instr!("deallocate")); - } - } - - pub(crate) fn compile_rule(&mut self, rule: &Rule) -> Result { - // let iter = ChunkedIterator::from_rule(rule); - // let conjunct_info = self.collect_var_data(iter); - - let &Rule { - head: (_, ref args, ref p1), - ref clauses, - ref var_data, - } = rule; - - let mut code = Code::new(); + pub(crate) fn compile_rule(&mut self, rule: &Rule, var_data: VarData) -> Result { + let Rule { head: (_, args), clauses } = rule; + self.marker.var_data = var_data; + let mut code = VecDeque::new(); self.marker.reset_at_head(args); - self.compile_seq_prelude(&var_data, &mut code); - let iter = FactIterator::from_rule_head_clause(args); - let mut fact = self.compile_target::(iter, GenContext::Head); + let iter = FactIterator::from_rule_head_clause(&args); + let fact = self.compile_target::(iter, GenContext::Head); if self.marker.max_reg_allocated() > MAX_ARITY { return Err(CompilationError::ExceededMaxArity); } self.marker.reset_free_list(); + code.extend(fact.into_iter()); - let mut unsafe_var_marker = UnsafeVarMarker::new(); + self.compile_seq(clauses, &mut code)?; - if !fact.is_empty() { - unsafe_var_marker = self.mark_unsafe_fact_vars(&mut fact); - code.extend(fact.into_iter()); - } - - let iter = ChunkedIterator::from_rule_body(p1, clauses); - self.compile_seq(iter, &conjunct_info, &mut code)?; - - unsafe_var_marker.mark_unsafe_instrs(&mut code); - - self.compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1)); - - Ok(code) + Ok(Vec::from(code)) } - fn mark_unsafe_fact_vars(&self, fact: &mut Code) -> UnsafeVarMarker { - let mut safe_vars = IndexSet::new(); - - for fact_instr in fact.iter_mut() { - match fact_instr { - &mut Instruction::UnifyValue(r) => { - if !safe_vars.contains(&r) { - *fact_instr = Instruction::UnifyLocalValue(r); - safe_vars.insert(r); - } - } - &mut Instruction::UnifyVariable(r) => { - safe_vars.insert(r); - } - _ => {} - } - } - - UnsafeVarMarker::from_fact_vars(safe_vars) - } - - pub(crate) fn compile_fact(&mut self, fact: &Fact) -> Result { - self.update_var_count(post_order_iter(term)); - - // let mut vs = VariableFixtures::new(); - - // vs.mark_vars_in_chunk(post_order_iter(term), term.arity(), GenContext::Head); - - // vs.populate_restricting_sets(); - // self.marker.drain_var_data(vs, 1); - + pub(crate) fn compile_fact(&mut self, fact: &Fact, var_data: VarData) -> Result { let mut code = Vec::new(); + self.marker.var_data = var_data; - if let &Term::Clause(_, _, ref args) = term { + if let Term::Clause(_, _, args) = &fact.head { self.marker.reset_at_head(args); - let iter = FactInstruction::iter(term); - let mut compiled_fact = self.compile_target::( + let iter = FactInstruction::iter(&fact.head); + let compiled_fact = self.compile_target::( iter, GenContext::Head, ); @@ -1023,40 +1021,27 @@ impl<'b> CodeGenerator<'b> { return Err(CompilationError::ExceededMaxArity); } - self.mark_unsafe_fact_vars(&mut compiled_fact); - - if !compiled_fact.is_empty() { - code.extend(compiled_fact.into_iter()); - } + code.extend(compiled_fact.into_iter()); } code.push(instr!("proceed")); Ok(code) } - fn compile_query_line( - &mut self, - term: &QueryTerm, - term_loc: GenContext, - code: &mut Code, - num_perm_vars_left: usize, - ) { + fn compile_query_line(&mut self, term: &QueryTerm, term_loc: GenContext, code: &mut CodeDeque) { self.marker.reset_arg(term.arity()); - let iter = query_term_post_order_iter(term); + let iter = QueryIterator::new(term); let query = self.compile_target::(iter, term_loc); code.extend(query.into_iter()); - self.add_conditional_call(code, term, num_perm_vars_left); - } - #[inline] - fn increment_jmp_by_locs_by(&mut self, incr: usize) { - let offset = self.global_jmp_by_locs_offset; - - for loc in &mut self.jmp_by_locs[offset..] { - *loc += incr; - } + match term { + &QueryTerm::Clause(_, ref ct, _, call_policy) => { + self.add_call(code, ct.to_instr(), call_policy); + } + _ => unreachable!() + }; } fn split_predicate(clauses: &[PredicateClause]) -> Vec { @@ -1121,30 +1106,35 @@ impl<'b> CodeGenerator<'b> { fn compile_pred_subseq( &mut self, - clauses: &[PredicateClause], + clauses: &mut [PredicateClause], optimal_index: usize, ) -> Result { let mut code = VecDeque::new(); let mut code_offsets = CodeOffsets::new(I::new(), optimal_index + 1); let mut skip_stub_try_me_else = false; - let jmp_by_locs_len = self.jmp_by_locs.len(); + let clauses_len = clauses.len(); - for (i, clause) in clauses.iter().enumerate() { + for (i, clause) in clauses.iter_mut().enumerate() { self.marker.reset(); let mut clause_index_info = ClauseIndexInfo::new(code.len()); - self.global_jmp_by_locs_offset = self.jmp_by_locs.len(); let clause_code = match clause { - &PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact)?, - &PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?, + PredicateClause::Fact(fact, var_data) => { + let var_data = std::mem::replace(var_data, VarData::default()); + self.compile_fact(&fact, var_data)? + } + PredicateClause::Rule(rule, var_data) => { + let var_data = std::mem::replace(var_data, VarData::default()); + self.compile_rule(&rule, var_data)? + } }; - if clauses.len() > 1 { + if clauses_len > 1 { let choice = match i { 0 => self.settings.internal_try_me_else(clause_code.len() + 1), - _ if i == clauses.len() - 1 => self.settings.internal_trust_me(), + _ if i + 1 == clauses_len => self.settings.internal_trust_me(), _ => self.settings.internal_retry_me_else(clause_code.len() + 1), }; @@ -1170,45 +1160,23 @@ impl<'b> CodeGenerator<'b> { if let Some(arg) = arg { let index = code.len(); - if clauses.len() > 1 || self.settings.is_extensible { + if clauses_len > 1 || self.settings.is_extensible { code_offsets.index_term(arg, index, &mut clause_index_info, self.atom_tbl); } } - if !(code_offsets.no_indices() && clauses.len() == 1 && self.settings.is_extensible) { - // the peculiar condition of this block, when false, - // anticipates code.pop_front() being called about a - // dozen lines below. - - if !skip_stub_try_me_else { - // if the condition is false, code_offsets.no_indices() is false, - // so don't repeat the work of the condition on skip_stub_try_me_else - // below. - self.increment_jmp_by_locs_by(code.len()); - } - } - self.skeleton.clauses.push_back(clause_index_info); code.extend(clause_code.into_iter()); } - let index_code = if clauses.len() > 1 || self.settings.is_extensible { + let index_code = if clauses_len > 1 || self.settings.is_extensible { code_offsets.compute_indices(skip_stub_try_me_else) } else { vec![] }; - self.global_jmp_by_locs_offset = jmp_by_locs_len; - if !index_code.is_empty() { code.push_front(Instruction::IndexingCode(index_code)); - - if skip_stub_try_me_else { - // skip the TryMeElse(0) also. - self.increment_jmp_by_locs_by(2); - } else { - self.increment_jmp_by_locs_by(1); - } } else if clauses.len() == 1 && self.settings.is_extensible { // the condition is the value of skip_stub_try_me_else, which is // true if the predicate is not dynamic. This operation must apply @@ -1223,7 +1191,7 @@ impl<'b> CodeGenerator<'b> { pub(crate) fn compile_predicate( &mut self, - clauses: &Vec, + mut clauses: Vec, ) -> Result { let mut code = Code::new(); @@ -1234,12 +1202,12 @@ impl<'b> CodeGenerator<'b> { let skel_lower_bound = self.skeleton.clauses.len(); let code_segment = if self.settings.is_dynamic() { self.compile_pred_subseq::( - &clauses[left..right], + &mut clauses[left..right], instantiated_arg_index, )? } else { self.compile_pred_subseq::( - &clauses[left..right], + &mut clauses[left..right], instantiated_arg_index, )? }; @@ -1271,12 +1239,17 @@ impl<'b> CodeGenerator<'b> { } } - self.increment_jmp_by_locs_by(code.len()); - self.global_jmp_by_locs_offset = self.jmp_by_locs.len(); - code.extend(code_segment.into_iter()); } + /* + for line in &code { + println!("{:?}", line); + } + + println!(""); + */ + Ok(code) } } diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 2ad19cab..2f8d442e 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -1,42 +1,179 @@ -use indexmap::IndexMap; - use crate::allocator::*; -use crate::fixtures::*; +use crate::codegen::SubsumedBranchHits; use crate::forms::Level; use crate::instructions::*; -use crate::machine::machine_indices::*; +use crate::machine::disjuncts::VarData; use crate::parser::ast::*; use crate::targets::*; +use crate::variable_records::*; -use crate::temp_v; - +use bit_set::*; +use bitvec::prelude::*; use fxhash::FxBuildHasher; +use indexmap::IndexMap; use std::cell::Cell; -use std::collections::BTreeSet; +use std::collections::VecDeque; + +pub type BranchHits = IndexMap; // key: var_num, value: branch arm occurrences. + +#[derive(Debug, Default)] +pub struct BranchOccurrences { + pub hits: BranchHits, + pub shallow_safety: BitSet, // unset means safe, set means unsafe (after the branch merge) + pub deep_safety: BitSet, + pub num_branches: usize, + pub current_branch: usize, + pub subsumed_hits: SubsumedBranchHits, +} + +impl BranchOccurrences { + fn new(num_branches: usize) -> Self { + Self { + hits: BranchHits::with_hasher(FxBuildHasher::default()), + shallow_safety: BitSet::default(), + deep_safety: BitSet::default(), + num_branches, + current_branch: 0, + subsumed_hits: SubsumedBranchHits::with_hasher(FxBuildHasher::default()), + } + } +} #[derive(Debug)] pub(crate) struct DebrayAllocator { - bindings: IndexMap, + pub(crate) var_data: VarData, // var_data replaces bindings. + pub(crate) branch_stack: Vec, + pub(crate) in_tail_position: bool, + // bindings: IndexMap, // VarNum -> VarWitness arg_c: usize, temp_lb: usize, + perm_lb: usize, arity: usize, // 0 if not at head. - contents: IndexMap, - in_use: BTreeSet, - free_list: Vec, + shallow_temp_mappings: IndexMap, + in_use: BitSet, // deep and non-var allocations + temp_free_list: Vec, + perm_free_list: VecDeque<(usize, usize)>, // chunk_num, var_num } impl DebrayAllocator { - fn is_curr_arg_distinct_from(&self, var: &Var) -> bool { - match self.contents.get(&self.arg_c) { - Some(t_var) if *t_var != *var => true, + pub(crate) fn add_branch_occurrence(&mut self, var_num: usize) { + if let Some(occurrences) = self.branch_stack.last_mut() { + debug_assert!(occurrences.current_branch < occurrences.num_branches); + + let num_branches = occurrences.num_branches; + + let entry = occurrences.hits.entry(var_num) + .or_insert_with(|| BitVec::repeat(false, num_branches)); + + entry.set(occurrences.current_branch, true); + occurrences.subsumed_hits.insert(var_num); + } + } + + pub(crate) fn add_branch_stack(&mut self, num_branches: usize) { + self.branch_stack.push(BranchOccurrences::new(num_branches)); + } + + pub(crate) fn add_branch(&mut self) { + let branch_occurrences = self.branch_stack.last_mut().unwrap(); + + for var_num in branch_occurrences.subsumed_hits.drain(..) { + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, ref mut allocation) => { + match allocation { + PermVarAllocation::Done { shallow_safety, deep_safety, .. } => { + if !shallow_safety.unneeded() { + branch_occurrences.shallow_safety.insert(var_num); + } + + if !deep_safety.unneeded() { + branch_occurrences.deep_safety.insert(var_num); + } + } + _ => { + unreachable!(); + } + } + + *allocation = PermVarAllocation::Pending; + } + _ => unreachable!(), + } + } + } + + #[inline] + pub(crate) fn incr_current_branch(&mut self) { + let branch_occurrences = self.branch_stack.last_mut().unwrap(); + branch_occurrences.current_branch += 1; + } + + #[inline] + pub(crate) fn drain_branches(&mut self, depth: usize) -> std::vec::Drain { + let start_idx = self.branch_stack.len() - depth; + self.branch_stack.drain(start_idx ..) + } + + pub(crate) fn pop_branch(&mut self, depth: usize, subsumed_hits: SubsumedBranchHits) { + let removed_branches = self.drain_branches(depth); + + let (deep_safety, shallow_safety) = removed_branches + .into_iter() + .fold((BitSet::default(), BitSet::default()), + |(mut deep_safety, mut shallow_safety), branch_occurrences| { + deep_safety.union_with(&branch_occurrences.deep_safety); + shallow_safety.union_with(&branch_occurrences.shallow_safety); + + (deep_safety, shallow_safety) + }); + + let (deep_safety, shallow_safety) = match self.branch_stack.last_mut() { + Some(latest_branch) => { + latest_branch.deep_safety.union_with(&deep_safety); + latest_branch.shallow_safety.union_with(&shallow_safety); + + (&latest_branch.deep_safety, &latest_branch.shallow_safety) + } + None => (&deep_safety, &shallow_safety) + }; + + for var_num in subsumed_hits.iter().cloned() { + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, ref mut allocation) => { + let shallow_safety = VarSafetyStatus::needed_if( + shallow_safety.contains(var_num), + ); + + let deep_safety = VarSafetyStatus::needed_if( + deep_safety.contains(var_num), + ); + + *allocation = PermVarAllocation::Done { shallow_safety, deep_safety }; + } + _ => unreachable!() + } + } + + if self.branch_stack.len() > 0 { + for var_num in subsumed_hits { + self.add_branch_occurrence(var_num); + } + } + } + + fn is_curr_arg_distinct_from(&self, var_num: usize) -> bool { + match self.shallow_temp_mappings.get(&self.arg_c).cloned() { + Some(t_var) => t_var != var_num, _ => false, } } - fn occurs_shallowly_in_head(&self, var: &Var, r: usize) -> bool { - match self.bindings.get(var).unwrap() { - &VarAlloc::Temp(_, _, ref tvd) => tvd.use_set.contains(&(GenContext::Head, r)), + fn occurs_shallowly_in_head(&self, var_num: usize, r: usize) -> bool { + match &self.var_data.records[var_num].allocation { + VarAlloc::Temp { temp_var_data, term_loc: GenContext::Head, .. } => { + temp_var_data.use_set.contains(&(GenContext::Head, r)) + } _ => false, } } @@ -44,13 +181,13 @@ impl DebrayAllocator { #[inline] fn is_in_use(&self, r: usize) -> bool { let in_use_range = r <= self.arity && r >= self.arg_c; - in_use_range || self.in_use.contains(&r) + in_use_range || self.in_use.contains(r) } - fn alloc_with_cr(&self, var: &Var) -> usize { - match self.bindings.get(var) { - Some(&VarAlloc::Temp(_, _, ref tvd)) => { - for &(_, reg) in tvd.use_set.iter() { + fn alloc_with_cr(&self, var_num: usize) -> usize { + match &self.var_data.records[var_num].allocation { + VarAlloc::Temp { temp_var_data, .. } => { + for &(_, reg) in temp_var_data.use_set.iter() { if !self.is_in_use(reg) { return reg; } @@ -60,7 +197,7 @@ impl DebrayAllocator { for reg in self.temp_lb.. { if !self.is_in_use(reg) { - if !tvd.no_use_set.contains(®) { + if !temp_var_data.no_use_set.contains(reg) { result = reg; break; } @@ -73,10 +210,10 @@ impl DebrayAllocator { } } - fn alloc_with_ca(&self, var: &Var) -> usize { - match self.bindings.get(var) { - Some(&VarAlloc::Temp(_, _, ref tvd)) => { - for &(_, reg) in tvd.use_set.iter() { + fn alloc_with_ca(&self, var_num: usize) -> usize { + match &self.var_data.records[var_num].allocation { + VarAlloc::Temp { temp_var_data, .. } => { + for &(_, reg) in temp_var_data.use_set.iter() { if !self.is_in_use(reg) { return reg; } @@ -86,8 +223,8 @@ impl DebrayAllocator { for reg in self.temp_lb.. { if !self.is_in_use(reg) { - if !tvd.no_use_set.contains(®) { - if !tvd.conflict_set.contains(®) { + if !temp_var_data.no_use_set.contains(reg) { + if !temp_var_data.conflict_set.contains(reg) { result = reg; break; } @@ -101,22 +238,25 @@ impl DebrayAllocator { } } - fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(Var, usize)> { + fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(usize, usize)> { // we want to allocate a register to the k^{th} parameter, par_k. // par_k may not be a temporary variable. let k = self.arg_c; - match self.contents.get(&k) { + match self.shallow_temp_mappings.get(&k).cloned() { Some(t_var) => { // suppose this branch fires. then t_var is a // temp. var. belonging to the current chunk. // consider its use set. T == par_k iff // (GenContext::Last(_), k) is in t_var.use_set. - let tvd = self.bindings.get(t_var).unwrap(); - if let &VarAlloc::Temp(_, _, ref tvd) = tvd { - if !tvd.use_set.contains(&(GenContext::Last(chunk_num), k)) { - return Some((t_var.clone(), self.alloc_with_ca(t_var))); + match &self.var_data.records[t_var].allocation { + VarAlloc::Temp { temp_var_data, .. } => { + if !temp_var_data.use_set.contains(&(GenContext::Last(chunk_num), k)) { + return Some((t_var, self.alloc_with_ca(t_var))); + } + } + _ => { } } @@ -129,21 +269,21 @@ impl DebrayAllocator { fn evacuate_arg<'a, Target: CompilationTarget<'a>>( &mut self, chunk_num: usize, - code: &mut Code, + code: &mut CodeDeque, ) { match self.alloc_in_last_goal_hint(chunk_num) { - Some((var, r)) => { + Some((var_num, r)) => { let k = self.arg_c; if r != k { let r = RegType::Temp(r); - code.push(Target::move_to_register(r, k)); + code.push_back(Target::move_to_register(r, k)); - self.contents.swap_remove(&k); - self.contents.insert(r.reg_num(), var.clone()); + self.shallow_temp_mappings.swap_remove(&k); + self.shallow_temp_mappings.insert(r.reg_num(), var_num); - self.record_register(var, r); + self.var_data.records[var_num].allocation.set_register(r.reg_num()); self.in_use.insert(r.reg_num()); } } @@ -153,27 +293,27 @@ impl DebrayAllocator { fn alloc_reg_to_var<'a, Target: CompilationTarget<'a>>( &mut self, - var: &Var, + var_num: usize, lvl: Level, term_loc: GenContext, - target: &mut Vec, + target: &mut CodeDeque, ) -> usize { match term_loc { GenContext::Head => { if let Level::Shallow = lvl { self.evacuate_arg::(0, target); - self.alloc_with_cr(var) + self.alloc_with_cr(var_num) } else { - self.alloc_with_ca(var) + self.alloc_with_ca(var_num) } } - GenContext::Mid(_) => self.alloc_with_ca(var), + GenContext::Mid(_) => self.alloc_with_ca(var_num), GenContext::Last(chunk_num) => { if let Level::Shallow = lvl { self.evacuate_arg::(chunk_num, target); - self.alloc_with_cr(var) + self.alloc_with_cr(var_num) } else { - self.alloc_with_ca(var) + self.alloc_with_ca(var_num) } } } @@ -182,15 +322,15 @@ impl DebrayAllocator { fn alloc_reg_to_non_var(&mut self) -> usize { let mut final_index = 0; - while let Some(r) = self.free_list.pop() { - if !self.in_use.contains(&r) { + while let Some(r) = self.temp_free_list.pop() { + if !self.is_in_use(r) { self.in_use.insert(r); return r; } } for index in self.temp_lb.. { - if !self.in_use.contains(&index) { + if !self.in_use.contains(index) { final_index = index; self.in_use.insert(final_index); break; @@ -201,38 +341,194 @@ impl DebrayAllocator { final_index } - fn in_place(&self, var: &Var, term_loc: GenContext, r: RegType, k: usize) -> bool { + fn in_place(&self, var_num: usize, term_loc: GenContext, r: RegType, k: usize) -> bool { match term_loc { GenContext::Head if !r.is_perm() => r.reg_num() == k, - _ => match self.bindings().get(var).unwrap() { - &VarAlloc::Temp(_, o, _) if r.reg_num() == k => o == k, - _ => false, + _ => { + match &self.var_data.records[var_num].allocation { + &VarAlloc::Temp { temp_reg, .. } if r.reg_num() == k => + temp_reg == k, + _ => false, + } }, } } + fn alloc_perm_var(&mut self, var_num: usize, chunk_num: usize) -> usize { + let p = if let Some(p) = self.pop_free_perm(chunk_num) { + p + } else { + let p = self.perm_lb; + self.perm_lb += 1; + + p + }; + + self.var_data.records[var_num].allocation = VarAlloc::Perm(p, PermVarAllocation::done()); + p + } + pub fn add_to_free_list(&mut self, r: RegType) { if let RegType::Temp(r) = r { - self.in_use.remove(&r); - self.free_list.push(r); + self.in_use.remove(r); + self.temp_free_list.push(r); } } pub fn reset_free_list(&mut self) { - self.free_list.clear(); + self.temp_free_list.clear(); + } + + #[inline(always)] + pub fn get_binding(&self, var_num: usize) -> RegType { + self.var_data.records[var_num].allocation.as_reg_type() + } + + pub fn num_perm_vars(&self) -> usize { + self.perm_lb - 1 + } + + pub fn increment_running_count(&mut self, var_num: usize) { + self.var_data.records[var_num].running_count += 1; + } + + fn pop_free_perm(&mut self, chunk_num: usize) -> Option { + if let Some((perm_chunk_num, var_num)) = self.perm_free_list.front().cloned() { + if chunk_num == perm_chunk_num { + None + } else { + self.perm_free_list.pop_front(); + + match &mut self.var_data.records[var_num].allocation { + &mut VarAlloc::Perm(p, ref mut allocation) => { + *allocation = PermVarAllocation::Pending; + Some(p) + } + _ => unreachable!() + } + } + } else { + None + } + } + + pub(crate) fn mark_temp_to_safe_perm(&mut self, var_num: usize) { + match &self.var_data.records[var_num].allocation { + &VarAlloc::Temp { to_perm_var_num: Some(perm_var_num), .. } => { + match &mut self.var_data.records[perm_var_num].allocation { + VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { + *deep_safety = VarSafetyStatus::Unneeded; + *shallow_safety = VarSafetyStatus::Unneeded; + } + _ => unreachable!() + } + } + _ => { + } + } + } + + fn mark_safe_var(&mut self, var_num: usize, lvl: Level, term_loc: GenContext) { + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { + // GetVariable in head chunk is considered safe. + if lvl == Level::Deep { + *deep_safety = VarSafetyStatus::Unneeded; + *shallow_safety = VarSafetyStatus::Unneeded; + } else if term_loc == GenContext::Head { + *shallow_safety = VarSafetyStatus::Unneeded; + } else { + if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() { + match &mut self.var_data.records[temp_var_num].allocation { + VarAlloc::Temp { ref mut to_perm_var_num, .. } => { + *to_perm_var_num = Some(var_num); + } + _ => unreachable!() + } + } + } + } + VarAlloc::Temp { ref mut safety, .. } => { + *safety = VarSafetyStatus::Unneeded; + } + _ => { + unreachable!() + } + } + } + + fn argument_to_value<'a, Target: CompilationTarget<'a>>( + &mut self, + var_num: usize, + r: RegType, + arg_c: usize, + ) -> Instruction { + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => { + if !self.in_tail_position || shallow_safety.unneeded() { + Target::argument_to_value(r, arg_c) + } else { + *shallow_safety = VarSafetyStatus::Unneeded; + Target::unsafe_argument_to_value(r, arg_c) + } + } + VarAlloc::Temp { ref mut safety, .. } => { + if safety.unneeded() { + Target::argument_to_value(r, arg_c) + } else { + *safety = VarSafetyStatus::Unneeded; + Target::unsafe_argument_to_value(r, arg_c) + } + } + _ => { + unreachable!() + } + } + } + + fn subterm_to_value<'a, Target: CompilationTarget<'a>>( + &mut self, + var_num: usize, + r: RegType, + ) -> Instruction { + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => { + if deep_safety.unneeded() { + Target::subterm_to_value(r) + } else { + *deep_safety = VarSafetyStatus::Unneeded; + Target::unsafe_subterm_to_value(r) + } + } + VarAlloc::Temp { ref mut safety, .. } => { + if safety.unneeded() { + Target::subterm_to_value(r) + } else { + *safety = VarSafetyStatus::Unneeded; + Target::unsafe_subterm_to_value(r) + } + } + _ => { + unreachable!() + } + } } } impl Allocator for DebrayAllocator { fn new() -> DebrayAllocator { - DebrayAllocator { + Self { + var_data: VarData::default(), + in_tail_position: false, arity: 0, arg_c: 1, temp_lb: 1, - bindings: IndexMap::with_hasher(FxBuildHasher::default()), - contents: IndexMap::with_hasher(FxBuildHasher::default()), - in_use: BTreeSet::new(), - free_list: vec![], + perm_lb: 1, + shallow_temp_mappings: IndexMap::with_hasher(FxBuildHasher::default()), + in_use: BitSet::default(), + temp_free_list: vec![], + perm_free_list: VecDeque::new(), + branch_stack: vec![], } } @@ -240,12 +536,12 @@ impl Allocator for DebrayAllocator { &mut self, lvl: Level, term_loc: GenContext, - code: &mut Code, + code: &mut CodeDeque, ) { let r = RegType::Temp(self.alloc_reg_to_non_var()); match lvl { - Level::Deep => code.push(Target::subterm_to_variable(r)), + Level::Deep => code.push_back(Target::subterm_to_variable(r)), Level::Root | Level::Shallow => { let k = self.arg_c; @@ -255,7 +551,7 @@ impl Allocator for DebrayAllocator { self.arg_c += 1; - code.push(Target::argument_to_variable(r, k)); + code.push_back(Target::argument_to_variable(r, k)); } }; } @@ -265,7 +561,7 @@ impl Allocator for DebrayAllocator { lvl: Level, term_loc: GenContext, cell: &'a Cell, - code: &mut Code, + code: &mut CodeDeque, ) { let r = cell.get(); @@ -292,39 +588,49 @@ impl Allocator for DebrayAllocator { fn mark_var<'a, Target: CompilationTarget<'a>>( &mut self, - var: Var, + var_num: usize, lvl: Level, cell: &'a Cell, term_loc: GenContext, - code: &mut Code, + code: &mut CodeDeque, ) { - let (r, is_new_var) = match self.get(var.clone()) { + let (r, is_new_var) = match self.get_binding(var_num) { RegType::Temp(0) => { - // here, r is temporary *and* unassigned. - let o = self.alloc_reg_to_var::(&var, lvl, term_loc, code); + let o = self.alloc_reg_to_var::(var_num, lvl, term_loc, code); cell.set(VarReg::Norm(RegType::Temp(o))); (RegType::Temp(o), true) } RegType::Perm(0) => { - let pr = cell.get().norm(); - self.record_register(var.clone(), pr); + let p = self.alloc_perm_var(var_num, term_loc.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) => if allocation.pending() { + *allocation = PermVarAllocation::done(); + true + } else { + false + }, + _ => unreachable!(), + }; - (pr, true) + (r, is_new_var) } r => (r, false), }; - self.mark_reserved_var::(var, lvl, cell, term_loc, code, r, is_new_var); + self.mark_reserved_var::(var_num, lvl, cell, term_loc, code, r, is_new_var); } fn mark_reserved_var<'a, Target: CompilationTarget<'a>>( &mut self, - var: Var, + var_num: usize, lvl: Level, cell: &'a Cell, term_loc: GenContext, - code: &mut Code, + code: &mut CodeDeque, r: RegType, is_new_var: bool, ) { @@ -332,86 +638,104 @@ impl Allocator for DebrayAllocator { Level::Root | Level::Shallow => { let k = self.arg_c; - if self.is_curr_arg_distinct_from(&var) { + if self.is_curr_arg_distinct_from(var_num) { self.evacuate_arg::(term_loc.chunk_num(), code); } - self.arg_c += 1; - cell.set(VarReg::ArgAndNorm(r, k)); - if !self.in_place(&var, term_loc, r, k) { + if !self.in_place(var_num, term_loc, r, k) { if is_new_var { - code.push(Target::argument_to_variable(r, k)); + self.mark_safe_var(var_num, lvl, term_loc); + code.push_back(Target::argument_to_variable(r, k)); } else { - code.push(Target::argument_to_value(r, k)); + code.push_back(self.argument_to_value::(var_num, r, k)); } } + + self.arg_c += 1; } Level::Deep if is_new_var => { if let GenContext::Head = term_loc { - if self.occurs_shallowly_in_head(&var, r.reg_num()) { - code.push(Target::subterm_to_value(r)); + if self.occurs_shallowly_in_head(var_num, r.reg_num()) { + code.push_back(self.subterm_to_value::(var_num, r)); } else { - code.push(Target::subterm_to_variable(r)); + self.mark_safe_var(var_num, lvl, term_loc); + code.push_back(Target::subterm_to_variable(r)); } } else { - code.push(Target::subterm_to_variable(r)); + self.mark_safe_var(var_num, lvl, term_loc); + code.push_back(Target::subterm_to_variable(r)); } } - Level::Deep => code.push(Target::subterm_to_value(r)), - }; + Level::Deep => code.push_back(self.subterm_to_value::(var_num, r)), + } + + let o = r.reg_num(); if !r.is_perm() { - let o = r.reg_num(); + self.shallow_temp_mappings.insert(o, var_num); + } else if r.is_perm() && is_new_var { + self.add_branch_occurrence(var_num); + } - self.contents.insert(o, var.clone()); - self.record_register(var.clone(), r); - self.in_use.insert(o); + let record = &mut self.var_data.records[var_num]; + + record.allocation.set_register(o); + + if record.running_count < record.num_occurrences { + record.running_count += 1; + } else if r.is_perm() { + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, allocation) => *allocation = PermVarAllocation::Pending, + _ => unreachable!(), + } + + self.perm_free_list.push_back((term_loc.chunk_num(), var_num)); + } + + self.in_use.insert(o); + } + + fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType { + match self.get_binding(var_num) { + RegType::Perm(0) | RegType::Temp(0) => { + RegType::Perm(self.alloc_perm_var(var_num, chunk_num)) + } + r => r, } } fn reset(&mut self) { - self.bindings.clear(); - self.contents.clear(); + self.perm_lb = 1; + self.shallow_temp_mappings.clear(); self.in_use.clear(); - self.free_list.clear(); + self.temp_free_list.clear(); } fn reset_contents(&mut self) { - self.contents.clear(); self.in_use.clear(); - self.free_list.clear(); + self.shallow_temp_mappings.clear(); + self.temp_free_list.clear(); } fn advance_arg(&mut self) { self.arg_c += 1; } - fn bindings(&self) -> &AllocVarDict { - &self.bindings - } - - fn bindings_mut(&mut self) -> &mut AllocVarDict { - &mut self.bindings - } - - fn take_bindings(self) -> AllocVarDict { - self.bindings - } - fn reset_at_head(&mut self, args: &Vec) { self.reset_arg(args.len()); self.arity = args.len(); for (idx, arg) in args.iter().enumerate() { if let &Term::Var(_, ref var) = arg { - let r = self.get(var.clone()); + let var_num = var.to_var_num().unwrap(); + let r = self.get_binding(var_num); if !r.is_perm() && r.reg_num() == 0 { self.in_use.insert(idx + 1); - self.contents.insert(idx + 1, var.clone()); - self.record_register(var.clone(), temp_v!(idx + 1)); + self.shallow_temp_mappings.insert(idx + 1, var_num); + self.var_data.records[var_num].allocation.set_register(idx + 1); } } } diff --git a/src/fixtures.rs b/src/fixtures.rs deleted file mode 100644 index 66734320..00000000 --- a/src/fixtures.rs +++ /dev/null @@ -1,342 +0,0 @@ -use crate::forms::*; -use crate::instructions::*; -use crate::machine::disjuncts::ClassifyInfo; -use crate::parser::ast::*; - -use bit_set::*; -use indexmap::{IndexMap, IndexSet}; - -pub(crate) type OccurrenceSet = IndexSet<(GenContext, usize)>; - -#[derive(Debug)] -pub(crate) struct TempVarData { - pub(crate) last_term_arity: usize, - pub(crate) use_set: OccurrenceSet, - pub(crate) no_use_set: BitSet, - pub(crate) conflict_set: BitSet, -} - -#[derive(Debug)] -pub(crate) struct TempVarStatus { - chunk_num: usize, - temp_var_data: TempVarData, -} - -// Perm: 0 initially, a stack register once processed. -// Temp: labeled with chunk_num and temp offset (unassigned if 0). -#[derive(Debug)] -pub(crate) enum VarAlloc { - Perm(usize), - Temp(usize, usize, TempVarData), -} - -impl VarAlloc { - pub(crate) fn as_reg_type(&self) -> RegType { - match self { - &VarAlloc::Temp(_, r, _) => RegType::Temp(r), - &VarAlloc::Perm(r) => RegType::Perm(r), - } - } -} - -impl TempVarData { - pub(crate) fn new(last_term_arity: usize) -> Self { - TempVarData { - last_term_arity: last_term_arity, - use_set: BitSet::::new(), - no_use_set: BitSet::new(), - conflict_set: BitSet::new(), - } - } - - pub(crate) fn uses_reg(&self, reg: usize) -> bool { - for &(_, nreg) in self.use_set.iter() { - if reg == nreg { - return true; - } - } - - return false; - } - - pub(crate) fn populate_conflict_set(&mut self) { - if self.last_term_arity > 0 { - let arity = self.last_term_arity; - let mut conflict_set: BitSet = (1..arity).collect(); - - for &(_, reg) in self.use_set.iter() { - conflict_set.remove(reg); - } - - self.conflict_set = conflict_set; - } - } -} - -#[derive(Debug)] -pub(crate) struct VariableFixtures { - temp_vars: IndexMap, -} - -impl VariableFixtures { - pub(crate) fn new() -> Self { - VariableFixtures { - temp_vars: IndexMap::new(), - } - } - - // computes no_use and conflict sets for all temp vars. - pub(crate) fn populate_restricting_sets(&mut self) { - // three stages: - // 1. move the use sets of each variable to a local IndexMap, use_set - // (iterate mutably, swap mutable refs). - // 2. drain use_set. For each use set of U, add into the - // no-use sets of appropriate variables T =/= U. - // 3. Move the use sets back to their original locations in the fixture. - // Compute the conflict set of u. - - // 1. - let mut use_sets: IndexMap = IndexMap::new(); - - for (var_gen_index, ref mut var_status) in self.temp_vars.iter_mut() { - let TempVarStatus { ref mut temp_var_data, .. } = var_status; - let mut use_set = OccurrenceSet::new(); - - std::mem::swap(&mut temp_var_data.use_set, &mut use_set); - use_sets.insert(var_gen_index, use_set); - } - - for (u, use_set) in use_sets.drain(..) { - // 2. - for &(term_loc, reg) in use_set.iter() { - if let GenContext::Last(cn_u) = term_loc { - for (var_gen_index, ref mut var_status) in self.terms_vars.iter_mut() { - let TempVarStatus { chunk_num, ref mut temp_var_data } = var_status; - - if cn_u == chunk_num && u != var_gen_index { - if !temp_var_data.uses_reg(reg) { - temp_var_data.no_use_set.insert(reg); - } - } - } - } - } - - // 3. - let TempVarStatus { ref mut temp_var_data, ..} = self.temp_vars.get_mut(u).unwrap(); - - temp_var_data.use_set = use_set; - temp_var_data.populate_conflict_set(); - } - } - - fn record_temp_info(&mut self, tvd: &mut TempVarData, arg_c: usize, term_loc: GenContext) { - match term_loc { - GenContext::Head | GenContext::Last(_) => { - tvd.use_set.insert((term_loc, arg_c)); - } - _ => {} - }; - } - - pub(crate) fn mark_temp_var(&mut self, var_info: &VarInfo) { - let chunk_num = term_loc.chunk_num(); - let var = Var::from(var_info.var_ptr); - - let mut status = self.temp_vars.swap_remove(&var).unwrap_or_else(|| { - TempVarStatus { - chunk_num, - temp_var_data: TempVarData::new(var_info.classify_info.arity), - } - }); - - if let Level::Shallow = var_info.lvl { - self.record_temp_info(&mut status, var_info.classify_info.arg_c, term_loc); - } - - self.temp_vars.insert(var, status); - } -} - -#[derive(Debug)] -pub(crate) struct UnsafeVarMarker { - pub(crate) unsafe_perm_vars: IndexMap, - pub(crate) unsafe_temp_vars: IndexSet, - pub(crate) safe_perm_vars: IndexSet, - pub(crate) safe_temp_vars: IndexSet, - pub(crate) temp_vars_to_perm_vars: IndexMap, -} - -impl UnsafeVarMarker { - pub(crate) fn new() -> Self { - UnsafeVarMarker { - unsafe_perm_vars: IndexMap::new(), - unsafe_temp_vars: IndexSet::new(), - safe_perm_vars: IndexSet::new(), - safe_temp_vars: IndexSet::new(), - temp_vars_to_perm_vars: IndexMap::new(), - } - } - - pub(crate) fn from_fact_vars(safe_vars: IndexSet) -> Self { - let mut unsafe_var_marker = Self::new(); - - for r in safe_vars { - unsafe_var_marker.mark_var_as_safe(r); - } - - unsafe_var_marker - } - - fn mark_var_as_safe(&mut self, r: RegType) { - match r { - RegType::Temp(t) => { - self.safe_temp_vars.insert(t); - } - RegType::Perm(p) => { - self.safe_perm_vars.insert(p); - } - }; - } - - fn mark_var_as_unsafe(&mut self, r: RegType, phase: usize) { - match r { - RegType::Temp(t) => { - self.unsafe_temp_vars.insert(t); - } - RegType::Perm(p) => { - self.unsafe_perm_vars.insert(p, phase); - } - } - } - - // returns true if the instruction at *query_instr cannot be - // changed by mark_unsafe_vars. - fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool { - match query_instr { - &Instruction::PutVariable(r @ RegType::Temp(_), _) | - &Instruction::SetVariable(r) => { - self.mark_var_as_safe(r); - true - } - &Instruction::PutVariable(RegType::Perm(p), t) => { - self.temp_vars_to_perm_vars.insert(t, p); - true - } - &Instruction::CallIs(RegType::Temp(t), ..) => { - if let Some(p) = self.temp_vars_to_perm_vars.get(&t) { - self.mark_var_as_safe(RegType::Perm(*p)); - } - - true - } - _ => false, - } - } - - fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) { - match query_instr { - &Instruction::PutValue(r @ RegType::Perm(_), _) | - &Instruction::SetValue(r) => { - self.mark_var_as_unsafe(r, phase); - } - _ => {} - } - } - - fn mark_unsafe_perm_vars(&mut self, query_instr: &mut Instruction, phase: usize) { - match query_instr { - &mut Instruction::PutValue(RegType::Perm(p), arg) - if !self.safe_perm_vars.contains(&p) => { - if let Some(ph) = self.unsafe_perm_vars.swap_remove(&p) { - if ph == phase { - *query_instr = Instruction::PutUnsafeValue(p, arg); - self.safe_perm_vars.insert(p); - } else { - self.unsafe_perm_vars.insert(p, ph); - } - } - } - &mut Instruction::SetValue(r @ RegType::Perm(p)) - if !self.safe_perm_vars.contains(&p) => { - *query_instr = Instruction::SetLocalValue(r); - - self.safe_perm_vars.insert(p); - self.unsafe_perm_vars.remove(&p); - } - _ => {} - } - } - - fn mark_unsafe_temp_vars(&mut self, query_instr: &mut Instruction) { - match query_instr { - &mut Instruction::SetValue(r @ RegType::Temp(t)) - if !self.safe_temp_vars.contains(&t) => { - *query_instr = Instruction::SetLocalValue(r); - - self.safe_temp_vars.insert(t); - self.unsafe_temp_vars.remove(&t); - } - _ => { - } - } - } - - fn clear_temp_vars(&mut self) { - self.safe_temp_vars.clear(); - self.unsafe_temp_vars.clear(); - self.temp_vars_to_perm_vars.clear(); - } - - pub(crate) fn mark_unsafe_instrs(&mut self, code: &mut Code) { - if code.is_empty() { - return; - } - - let mut code_index = 0; - - for phase in 0.. { - while code[code_index].is_query_instr() { - let query_instr = &mut code[code_index]; - - if !self.mark_safe_vars(query_instr) { - self.mark_phase(query_instr, phase); - self.mark_unsafe_temp_vars(query_instr); - } - - code_index += 1; - } - - while code_index < code.len() && !code[code_index].is_query_instr() { - self.mark_safe_vars(&code[code_index]); - code_index += 1; - } - - self.clear_temp_vars(); - - if code_index >= code.len() { - break; - } - } - - code_index = 0; - - for phase in 0.. { - while code[code_index].is_query_instr() { - let query_instr = &mut code[code_index]; - self.mark_unsafe_perm_vars(query_instr, phase); - code_index += 1; - } - - // ensure phase->instruction assignments match those of - // the previous for loop. - while code_index < code.len() && !code[code_index].is_query_instr() { - code_index += 1; - } - - if code_index >= code.len() { - break; - } - } - } -} diff --git a/src/forms.rs b/src/forms.rs index 3ed83866..627fb4b2 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -20,25 +20,23 @@ use std::cell::Cell; use std::collections::VecDeque; use std::convert::TryFrom; use std::fmt; -use std::ops::AddAssign; +use std::ops::{AddAssign, Deref, DerefMut}; use std::path::PathBuf; use crate::{is_infix, is_postfix}; pub type PredicateKey = (Atom, usize); // name, arity. -pub type Predicate = Vec; - +/* // vars of predicate, toplevel offset. Vec is always a vector // of vars (we get their adjoining cells this way). pub type JumpStub = Vec; +*/ -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum TopLevel { - Fact(Fact), // Term, line_num, col_num - Predicate(Predicate), - Query(Vec), - Rule(Rule), // Rule, line_num, col_num + Fact(Fact, VarData), // Term, line_num, col_num + Rule(Rule, VarData), // Rule, line_num, col_num } #[derive(Debug, Clone, Copy)] @@ -79,13 +77,30 @@ pub enum CallPolicy { Counted, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ChunkType { Head, Mid, Last, } +#[derive(Debug)] +pub enum RootIterationPolicy { + Iterated, + NotIterated, +} + +impl RootIterationPolicy { + #[inline(always)] + pub fn iterable(&self) -> bool { + if let RootIterationPolicy::Iterated = self { + true + } else { + false + } + } +} + impl ChunkType { #[inline(always)] pub fn to_gen_context(self, chunk_num: usize) -> GenContext { @@ -102,47 +117,104 @@ impl ChunkType { } } +#[derive(Debug)] +pub enum ChunkedTerms { + Branch(Vec>), + Chunk(VecDeque), +} + +#[derive(Debug)] +pub struct ChunkedTermVec { + pub chunk_vec: VecDeque, +} + +impl Deref for ChunkedTermVec { + type Target = VecDeque; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.chunk_vec + } +} + +impl DerefMut for ChunkedTermVec { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.chunk_vec + } +} + +impl ChunkedTermVec { + #[inline] + pub fn new() -> Self { + Self { chunk_vec: VecDeque::new() } + } + + pub fn reserve_branch(&mut self, capacity: usize) { + self.chunk_vec.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity))); + } + + pub fn push_branch_arm(&mut self, branch: VecDeque) { + match self.chunk_vec.back_mut().unwrap() { + ChunkedTerms::Branch(branches) => { + branches.push(branch); + } + ChunkedTerms::Chunk(_) => { + self.chunk_vec.push_back(ChunkedTerms::Branch(vec![branch])); + } + } + } + + #[inline] + pub fn add_chunk(&mut self) { + self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![]))); + } + + pub fn push_chunk_term(&mut self, term: QueryTerm) { + match self.chunk_vec.back_mut() { + Some(ChunkedTerms::Branch(_)) => { + self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term]))); + } + Some(ChunkedTerms::Chunk(chunk)) => { + chunk.push_back(term); + } + None => { + self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term]))); + } + } + } +} + #[derive(Debug)] pub enum QueryTerm { // register, clause type, subterms, clause call policy. Clause(Cell, ClauseType, Vec, CallPolicy), Fail, - GlobalCut, - GetCutPoint(usize), - LocalCut(usize), - Branch(Vec>), - ChunkTypeBoundary(ChunkType), + LocalCut(usize), // var_num + GlobalCut(usize), // var_num + GetCutPoint { var_num: usize, prev_b: bool }, + GetLevel(usize), // var_num } impl QueryTerm { - pub(crate) fn set_call_policy(&mut self, cp: CallPolicy) { - match self { - &mut QueryTerm::Clause(_, _, _, ref mut clause_cp) => *clause_cp = cp, - _ => {} - } - } - pub(crate) fn arity(&self) -> usize { match self { &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), - &QueryTerm::Cut | &QueryTerm::Branch(_) => 0, - &QueryTerm::IfThen(..) => 2, - &QueryTerm::Not(_) => 1, + &QueryTerm::GetLevel(_) | &QueryTerm::GetCutPoint { .. } => 1, + _ => 0, } } } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Fact { pub(crate) head: Term, - pub(crate) var_data: VarData, } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Rule { - pub(crate) head: (Atom, Vec, QueryTerm), - pub(crate) clauses: Vec, - pub(crate) var_data: VarData, + pub(crate) head: (Atom, Vec), + pub(crate) clauses: ChunkedTermVec, } #[derive(Clone, Debug, Hash)] @@ -233,29 +305,29 @@ impl ClauseInfo for Rule { impl ClauseInfo for PredicateClause { fn name(&self) -> Option { match self { - &PredicateClause::Fact(ref term, ..) => term.name(), + &PredicateClause::Fact(ref term, ..) => term.head.name(), &PredicateClause::Rule(ref rule, ..) => rule.name(), } } fn arity(&self) -> usize { match self { - &PredicateClause::Fact(ref term, ..) => term.arity(), + &PredicateClause::Fact(ref term, ..) => term.head.arity(), &PredicateClause::Rule(ref rule, ..) => rule.arity(), } } } -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum PredicateClause { - Fact(Fact), - Rule(Rule), + Fact(Fact, VarData), + Rule(Rule, VarData), } impl PredicateClause { pub(crate) fn args(&self) -> Option<&[Term]> { match self { - PredicateClause::Fact(term, ..) => match term { + PredicateClause::Fact(term, ..) => match &term.head { Term::Clause(_, _, args) => Some(&args), _ => None, }, diff --git a/src/heap_iter.rs b/src/heap_iter.rs index 9760be9e..d7f1f2e4 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -424,7 +424,6 @@ mod tests { use super::*; use crate::machine::mock_wam::*; - #[test] fn heap_stackless_iter_tests() { let mut wam = MockWAM::new(); diff --git a/src/heap_print.rs b/src/heap_print.rs index d09211d1..aa93ad29 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -472,7 +472,7 @@ pub struct HCPrinter<'a, Outputter> { state_stack: Vec, toplevel_spec: Option, last_item_idx: usize, - pub var_names: IndexMap, + pub var_names: IndexMap, pub numbervars_offset: Integer, pub numbervars: bool, pub quoted: bool, @@ -803,7 +803,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { if let Some(var) = self.var_names.get(&addr) { read_heap_cell!(addr, (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { - return Some(var.to_string()); + return Some(var.borrow().to_string()); } _ => { self.iter.push_stack(h); @@ -847,7 +847,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { // short-circuits handle_heap_term. // self.iter.pop_stack(); - let var_str = var.to_string(); + let var_str = var.borrow().to_string(); push_space_if_amb!(self, &var_str, { append_str!(self, &var_str); @@ -862,7 +862,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { Some(var) => { // If the term is bound to a named variable, // print the variable's name to output. - let var_str = var.to_string(); + let var_str = var.borrow().to_string(); push_space_if_amb!(self, &var_str, { append_str!(self, &var_str); diff --git a/src/iterators.rs b/src/iterators.rs index 529c453c..adec2e4c 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -5,100 +5,40 @@ use crate::parser::ast::*; use std::cell::Cell; use std::collections::VecDeque; -use std::fmt; -use std::fmt::Debug; -use std::hash::{Hash}; use std::iter::*; use std::vec::Vec; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub(crate) enum VarPtr { - ToVar(std::ptr::NonNull), - InSitu(usize), -} - -impl From<&Var> for VarPtr { - #[inline] - fn from(value: &Var) -> VarPtr { - unsafe { - VarPtr { ptr: std::ptr::NonNull::new_unchecked(value as *const _ as *mut _) } - } - } -} - -impl From for Var { - #[inline(always)] - fn from(value: VarPtr) -> Var { - match value { - VarPtr::ToPtr(ptr) => unsafe { - (*ptr.ptr.as_ptr()).clone() - }, - VarPtr::InSitu(var_num) => { - Var::Generated(var_num) - } - } - } -} - -impl VarPtr { - pub(crate) fn set(&mut self, value: Var) { - match self { - VarPtr::ToVar(ref mut ptr) => - unsafe { *ptr.as_mut() = value }, - VarPtr::InSitu(_) => { - } - } - } -} - #[derive(Debug, Clone)] pub(crate) enum TermRef<'a> { AnonVar(Level), - Cut(Level), - GetLevel(Level), Cons(Level, &'a Cell, &'a Term, &'a Term), - Fail(Level), Literal(Level, &'a Cell, &'a Literal), Clause(Level, &'a Cell, Atom, &'a Vec), PartialString(Level, &'a Cell, &'a String, &'a Box), CompleteString(Level, &'a Cell, Atom), - Var(Level, &'a Cell, Var), - InitialBranch(Level), - MiddleBranch(Level), - FinalBranch(Level), + Var(Level, &'a Cell, VarPtr), } +/* impl<'a> TermRef<'a> { - pub(crate) fn level(self) -> Level { + pub(crate) fn level(&self) -> Level { match self { TermRef::AnonVar(lvl) | TermRef::Cons(lvl, ..) | - TermRef::Cut(lvl) | - TermRef::GetLevel(lvl) | TermRef::Literal(lvl, ..) | TermRef::Var(lvl, ..) | TermRef::Clause(lvl, ..) | TermRef::CompleteString(lvl, ..) | - TermRef::PartialString(lvl, ..) | - TermRef::InitialBranch(lvl) | - TermRef::MiddleBranch(lvl) | - TermRef::FinalBranch(lvl) | - TermRef::Fail(lvl) => lvl, + TermRef::PartialString(lvl, ..) => *lvl, } } } +*/ #[derive(Debug)] pub(crate) enum TermIterState<'a> { AnonVar(Level), Clause(Level, usize, &'a Cell, Atom, &'a Vec), - Cut(Level), - Fail(Level), - GetLevel(Level), - InitialBranch(Level, &'a Vec), - MiddleBranch(Level, &'a Vec), - FinalBranch(Level, &'a Vec), - Sequence(Level, &'a Vec), Literal(Level, &'a Cell, &'a Literal), InitialCons(Level, &'a Cell, &'a Term, &'a Term), FinalCons(Level, &'a Cell, &'a Term, &'a Term), @@ -125,7 +65,7 @@ impl<'a> TermIterState<'a> { Term::CompleteString(cell, atom) => { TermIterState::CompleteString(lvl, cell, *atom) } - Term::Var(cell, var) => TermIterState::Var(lvl, cell, VarPtr::from(var)), + Term::Var(cell, var_ptr) => TermIterState::Var(lvl, cell, var_ptr.clone()), } } } @@ -140,6 +80,7 @@ impl<'a> QueryIterator<'a> { self.state_stack.push(TermIterState::subterm_to_state(lvl, term)); } + /* fn from_rule_head_clause(terms: &'a Vec) -> Self { let state_stack = terms .iter() @@ -149,6 +90,7 @@ impl<'a> QueryIterator<'a> { QueryIterator { state_stack } } + */ fn from_term(term: &'a Term) -> Self { let state = match term { @@ -165,7 +107,7 @@ impl<'a> QueryIterator<'a> { *name, terms, ), - Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, VarPtr::from(var)), + Term::Var(cell, var_ptr) => TermIterState::Var(Level::Root, cell, var_ptr.clone()), }; QueryIterator { @@ -181,36 +123,12 @@ impl<'a> QueryIterator<'a> { &QueryTerm::Clause(ref cell, ref ct, ref terms, _) => { self.state_stack.push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms)); } - &QueryTerm::Cut => { - self.state_stack.push(TermIterState::Cut(lvl)); - } - &QueryTerm::Not(ref terms) => { - self.state_stack.push(TermIterState::Fail(lvl)); - self.state_stack.push(TermIterState::Cut(lvl)); - self.state_stack.push(TermIterState::Sequence(lvl, terms)); - } - &QueryTerm::IfThen(ref if_terms, ref then_terms) => { - self.state_stack.push(TermIterState::Sequence(lvl, then_terms)); - self.state_stack.push(TermIterState::Cut(lvl)); - self.state_stack.push(TermIterState::Sequence(lvl, if_terms)); - self.state_stack.push(TermIterState::GetLevel(lvl)); - } - &QueryTerm::Branch(ref branches) => { - let len = branches.len(); - self.state_stack.push(TermIterState::FinalBranch(lvl, &branches[len - 1])); - - self.state_stack.extend(branches[1 .. len - 1] - .iter() - .rev() - .map(|t| TermIterState::MiddleBranch(lvl, t)), - ); - - self.state_stack.push(TermIterState::InitialBranch(lvl, &branches[0])); + _ => { } } } - fn new(term: &'a QueryTerm) -> Self { + pub fn new(term: &'a QueryTerm) -> Self { let mut iter = QueryIterator { state_stack: vec![] }; iter.extend_state(Level::Root, term); iter @@ -273,34 +191,8 @@ impl<'a> Iterator for QueryIterator<'a> { TermIterState::Literal(lvl, cell, constant) => { return Some(TermRef::Literal(lvl, cell, constant)); } - TermIterState::Var(lvl, cell, var) => { - return Some(TermRef::Var(lvl, cell, Var::from(var))); - } - TermIterState::Cut(lvl) => { - return Some(TermRef::Cut(lvl)); - } - TermIterState::GetLevel(lvl) => { - return Some(TermRef::GetLevel(lvl)); - } - TermIterState::InitialBranch(lvl, ref branch) => { - self.state_stack.push(TermIterState::Sequence(lvl, branch)); - return Some(TermRef::InitialBranch(lvl)); - } - TermIterState::MiddleBranch(lvl, ref branch) => { - self.state_stack.push(TermIterState::Sequence(lvl, branch)); - return Some(TermRef::MiddleBranch(lvl)); - } - TermIterState::FinalBranch(lvl, ref branch) => { - self.state_stack.push(TermIterState::Sequence(lvl, branch)); - return Some(TermRef::FinalBranch(lvl)); - } - TermIterState::Sequence(lvl, ref terms) => { - for term in branch.iter().rev() { - self.extend_state(lvl, term); - } - } - TermIterState::Fail(lvl) => { - return Some(TermRef::Fail(lvl)); + TermIterState::Var(lvl, cell, var_ptr) => { + return Some(TermRef::Var(lvl, cell, var_ptr)); } }; } @@ -312,7 +204,7 @@ impl<'a> Iterator for QueryIterator<'a> { #[derive(Debug)] pub(crate) struct FactIterator<'a> { state_queue: VecDeque>, - iterable_root: bool, + iterable_root: RootIterationPolicy, } impl<'a> FactIterator<'a> { @@ -329,11 +221,11 @@ impl<'a> FactIterator<'a> { FactIterator { state_queue, - iterable_root: false, + iterable_root: RootIterationPolicy::NotIterated, } } - fn new(term: &'a Term, iterable_root: bool) -> Self { + fn new(term: &'a Term, iterable_root: RootIterationPolicy) -> Self { let states = match term { Term::AnonVar => { vec![TermIterState::AnonVar(Level::Root)] @@ -365,8 +257,8 @@ impl<'a> FactIterator<'a> { Term::Literal(cell, constant) => { vec![TermIterState::Literal(Level::Root, cell, constant)] } - Term::Var(cell, var) => { - vec![TermIterState::Var(Level::Root, cell, VarPtr::from(var))] + Term::Var(cell, var_ptr) => { + vec![TermIterState::Var(Level::Root, cell, var_ptr.clone())] } }; @@ -392,7 +284,7 @@ impl<'a> Iterator for FactIterator<'a> { } match lvl { - Level::Root if !self.iterable_root => continue, + Level::Root if !self.iterable_root.iterable() => continue, _ => return Some(TermRef::Clause(lvl, cell, name, child_terms)), }; } @@ -412,8 +304,8 @@ impl<'a> Iterator for FactIterator<'a> { TermIterState::Literal(lvl, cell, constant) => { return Some(TermRef::Literal(lvl, cell, constant)) } - TermIterState::Var(lvl, cell, var) => { - return Some(TermRef::Var(lvl, cell, Var::from(var))); + TermIterState::Var(lvl, cell, var_ptr) => { + return Some(TermRef::Var(lvl, cell, var_ptr)); } _ => {} } @@ -427,143 +319,130 @@ pub(crate) fn post_order_iter<'a>(term: &'a Term) -> QueryIterator<'a> { QueryIterator::from_term(term) } -pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: bool) -> FactIterator<'a> { +pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: RootIterationPolicy) -> FactIterator<'a> { FactIterator::new(term, iterable_root) } -/* +#[derive(Debug, Copy, Clone)] +enum ClauseIteratorState<'a> { + RemainingChunks(&'a VecDeque, usize), + RemainingBranches(&'a Vec>, usize), +} + +#[derive(Debug, Clone)] +pub(crate) enum ClauseItem<'a> { + FirstBranch(usize), + NextBranch, + BranchEnd(usize), + Chunk(&'a VecDeque), +} + #[derive(Debug)] -pub(crate) enum ChunkedTerm<'a> { - HeadClause(Atom, &'a Vec), - BodyTerm(&'a QueryTerm), +pub(crate) struct ClauseIterator<'a> { + state_stack: Vec>, + remaining_chunks_on_stack: usize, } -pub(crate) fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> { - QueryIterator::new(query_term) -} - -impl<'a> ChunkedTerm<'a> { - pub(crate) fn post_order_iter(&self) -> QueryIterator<'a> { - match self { - &ChunkedTerm::BodyTerm(qt) => QueryIterator::new(qt), - &ChunkedTerm::HeadClause(_, terms) => QueryIterator::from_rule_head_clause(terms), +fn state_from_chunked_terms<'a>(chunk_vec: &'a VecDeque) -> ClauseIteratorState<'a> { + if chunk_vec.len() == 1 { + if let Some(ChunkedTerms::Branch(ref branches)) = chunk_vec.front() { + return ClauseIteratorState::RemainingBranches(branches, 0); } } + + ClauseIteratorState::RemainingChunks(chunk_vec, 0) } -pub(crate) struct ChunkedIterator<'a> { - pub(crate) chunk_num: usize, - iter: Box> + 'a>, -} - -impl<'a> fmt::Debug for ChunkedIterator<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("ChunkedIterator") - .field("chunk_num", &self.chunk_num) - // Hacky solution. - .field("iter", &"Box> + 'a>") - .finish() - } -} - -type ChunkedIteratorItem<'a> = (usize, usize, Vec>); -type RuleBodyIteratorItem<'a> = (usize, usize, Vec<&'a QueryTerm>); - -impl<'a> ChunkedIterator<'a> { - pub(crate) fn rule_body_iter(self) -> Box> + 'a> { - Box::new(self.filter_map(|(cn, lt_arity, terms)| { - let filtered_terms: Vec<_> = terms - .into_iter() - .filter_map(|ct| match ct { - ChunkedTerm::BodyTerm(qt) => Some(qt), - _ => None, - }) - .collect(); - - if filtered_terms.is_empty() { - None - } else { - Some((cn, lt_arity, filtered_terms)) +impl<'a> ClauseIterator<'a> { + pub fn new(clauses: &'a ChunkedTermVec) -> Self { + match state_from_chunked_terms(&clauses.chunk_vec) { + state @ ClauseIteratorState::RemainingBranches(..) => { + Self { + state_stack: vec![state], + remaining_chunks_on_stack: 0, + } + } + state @ ClauseIteratorState::RemainingChunks(..) => { + Self { + state_stack: vec![state], + remaining_chunks_on_stack: 1, + } } - })) - } - - pub(crate) fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec) -> Self { - let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); - let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))); - - ChunkedIterator { - chunk_num: 0, - iter: Box::new(iter), } } - pub(crate) fn from_rule(rule: &'a Rule) -> Self { - let &Rule { - head: (ref name, ref args, ref p1), - ref clauses, - .. - } = rule; - - let iter = once(ChunkedTerm::HeadClause(name.clone(), args)); - let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); - let iter = iter.chain(inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)))); - - ChunkedIterator { - chunk_num: 0, - iter: Box::new(iter), - } + #[inline(always)] + pub fn in_tail_position(&self) -> bool { + self.remaining_chunks_on_stack == 0 } - fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec>) { - let mut arity = 0; - let mut item = Some(term); - let mut result = Vec::new(); + fn branch_end_depth(&mut self) -> usize { + let mut depth = 1; - while let Some(term) = item { - match term { - ChunkedTerm::HeadClause(_, terms) => { - result.push(term); + while let Some(state) = self.state_stack.pop() { + match state { + ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => { + depth += 1; } - ChunkedTerm::BodyTerm(&QueryTerm::Cut) => { - result.push(term); - } - ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => { - result.push(term); - } - ChunkedTerm::BodyTerm(&QueryTerm::Clause( - _, - ClauseType::CallN(_), - ref subterms, - _, - )) => { - result.push(term); - arity = subterms.len() + 1; + _ => { + self.state_stack.push(state); break; } - ChunkedTerm::BodyTerm(qt) => { - result.push(term); - arity = qt.arity(); - break; - } - }; - - item = self.iter.next(); + } } - let chunk_num = self.chunk_num; - self.chunk_num += 1; - - (chunk_num, arity, result) + depth } } -impl<'a> Iterator for ChunkedIterator<'a> { - // the chunk number, last term arity, and vector of references. - type Item = ChunkedIteratorItem<'a>; +impl<'a> Iterator for ClauseIterator<'a> { + type Item = ClauseItem<'a>; fn next(&mut self) -> Option { - self.iter.next().map(|term| self.take_chunk(term)) + while let Some(state) = self.state_stack.pop() { + match state { + ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => { + if focus + 1 < chunks.len() { + self.state_stack.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1)); + } else { + self.remaining_chunks_on_stack -= 1; + } + + match &chunks[focus] { + ChunkedTerms::Branch(branches) => { + self.state_stack.push(ClauseIteratorState::RemainingBranches(branches, 0)); + } + ChunkedTerms::Chunk(chunk) => { + return Some(ClauseItem::Chunk(chunk)); + } + } + } + ClauseIteratorState::RemainingChunks(chunks, focus) => { + debug_assert_eq!(chunks.len(), focus); + } + ClauseIteratorState::RemainingBranches(branches, focus) if focus < branches.len() => { + self.state_stack.push(ClauseIteratorState::RemainingBranches(&branches, focus + 1)); + let state = state_from_chunked_terms(&branches[focus]); + + if let ClauseIteratorState::RemainingChunks(..) = &state { + self.remaining_chunks_on_stack += 1; + } + + self.state_stack.push(state); + + return if focus == 0 { + Some(ClauseItem::FirstBranch(branches.len())) + } else { + Some(ClauseItem::NextBranch) + }; + } + ClauseIteratorState::RemainingBranches(branches, focus) => { + debug_assert_eq!(branches.len(), focus); + return Some(ClauseItem::BranchEnd(self.branch_end_depth())); + } + } + } + + None } } -*/ diff --git a/src/lib.rs b/src/lib.rs index 45dc2385..36f7a45b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ mod arithmetic; pub mod codegen; mod debray_allocator; mod ffi; -mod fixtures; +mod variable_records; mod forms; mod heap_iter; pub mod heap_print; diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 0005d395..1c183a0c 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -218,13 +218,13 @@ fail :- '$fail'. %% \+(Goal) % % True iff Goal fails -\+ G :- call(G), !, false. +\+ G :- call(G), !, '$fail'. \+ _. %% \=(?X, ?Y) % % True iff X and Y can't be unified -X \= X :- !, false. +X \= X :- !, '$fail'. _ \= _. diff --git a/src/lib/format.pl b/src/lib/format.pl index 32ad2ff9..be1cd532 100644 --- a/src/lib/format.pl +++ b/src/lib/format.pl @@ -513,10 +513,12 @@ portray_clause(Stream, Term) :- phrase_to_stream(portray_clause_(Term), Stream), flush_output(Stream). +% called once. portray_clause_(Term) --> { unique_variable_names(Term, VNs) }, portray_(Term, VNs), ".\n". +% mysteriously called twice, the second time with the truncated B3. unique_variable_names(Term, VNs) :- term_variables(Term, Vs), foldl(var_name, Vs, VNs, 0, _). diff --git a/src/loader.pl b/src/loader.pl index 896d6bff..5c35822e 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -541,6 +541,7 @@ open_file(Path, Stream) :- ) ). + use_module(Module, Exports, Evacuable) :- ( var(Module) -> instantiation_error(load/1) @@ -562,12 +563,11 @@ use_module(Module, Exports, Evacuable) :- stream_property(Stream, file_name(PathFileName)), file_load(Stream, PathFileName, Subevacuable), '$use_module'(Evacuable, Subevacuable, Exports) - ; type_error(atom, Library, load/1) + ; type_error(atom, Module, load/1) ) ). - check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :- '$meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm). check_predicate_property(built_in, _, Name, Arity, built_in) :- diff --git a/src/machine/code_walker.rs b/src/machine/code_walker.rs index fcda8710..1244eb20 100644 --- a/src/machine/code_walker.rs +++ b/src/machine/code_walker.rs @@ -23,13 +23,9 @@ fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec) -> b { stack.push(index + offset); } - &Instruction::JmpByCall(_, offset, _) => { + &Instruction::JmpByCall(offset) => { stack.push(index + offset); } - &Instruction::JmpByExecute(_, offset, _) => { - stack.push(index + offset); - return true; - } &Instruction::Proceed => { return true; } diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 428e2952..0faf34c3 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -44,62 +44,6 @@ pub(super) fn bootstrapping_compile( Ok(()) } -// throw errors if declaration or query found. -pub(super) fn compile_relation( - cg: &mut CodeGenerator, - tl: &TopLevel, -) -> Result { - match tl { - &TopLevel::Query(_) => Err(CompilationError::ExpectedRel), - &TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses), - &TopLevel::Fact(ref fact, ..) => cg.compile_fact(fact), - &TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule), - } -} - -/* -pub(super) fn compile_appendix( - code: &mut Code, - mut queue: VecDeque, - jmp_by_locs: Vec, - non_counted_bt: bool, - atom_tbl: &mut AtomTable, -) -> Result<(), CompilationError> { - let mut jmp_by_locs = VecDeque::from(jmp_by_locs); - - while let Some(jmp_by_offset) = jmp_by_locs.pop_front() { - let code_len = code.len(); - - match &mut code[jmp_by_offset] { - &mut Instruction::JmpByCall(_, ref mut offset, ..) | - &mut Instruction::JmpByExecute(_, ref mut offset, ..) => { - *offset = code_len - jmp_by_offset; - } - _ => { - unreachable!() - } - } - - // false because the inner predicate is a one-off, hence not extensible. - let settings = CodeGenSettings { - global_clock_tick: None, - is_extensible: false, - non_counted_bt, - }; - - let mut cg = CodeGenerator::new(atom_tbl, settings); - - let tl = queue.pop_front().unwrap(); - let decl_code = compile_relation(&mut cg, &tl)?; - - jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len())); - code.extend(decl_code.into_iter()); - } - - Ok(()) -} -*/ - fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize { if target_pos == 0 { return 0; @@ -1351,17 +1295,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { settings, ); - let mut clause_code = cg.compile_predicate(&vec![clause])?; - - /* - compile_appendix( - &mut clause_code, - queue, - cg.jmp_by_locs, - settings.non_counted_bt, - cg.atom_tbl, - )?; - */ + let clause_code = cg.compile_predicate(vec![clause])?; Ok(StandaloneCompileResult { clause_code, @@ -1389,24 +1323,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { clauses.push(self.try_term_to_tl(term, &mut preprocessor)?); } - // let queue = preprocessor.parse_queue(self)?; - let mut cg = CodeGenerator::new( &mut LS::machine_st(&mut self.payload).atom_tbl, settings, ); - let mut code = cg.compile_predicate(&clauses)?; - - /* - compile_appendix( - &mut code, - queue, - cg.jmp_by_locs, - settings.non_counted_bt, - cg.atom_tbl, - )?; - */ + let mut code = cg.compile_predicate(clauses)?; if settings.is_extensible { let mut clause_clause_locs = VecDeque::new(); diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 98875bc8..1b65ef9e 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -1,4 +1,3 @@ - /* ================================================================================ @@ -9,7 +8,6 @@ paper "Compiling Large Disjunctions" to Scryer Prolog. */ use crate::atom_table::*; -use crate::fixtures::VariableFixtures; use crate::forms::*; use crate::instructions::*; use crate::iterators::*; @@ -18,16 +16,18 @@ use crate::machine::machine_errors::CompilationError; use crate::machine::preprocessor::*; use crate::parser::ast::*; use crate::parser::rug::Rational; +use crate::variable_records::*; use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::cmp::Ordering; +use std::collections::VecDeque; use std::hash::{Hash, Hasher}; use std::ops::{Deref, DerefMut}; -#[derive(Debug, Clone)] -struct BranchNumber { +#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)] +pub struct BranchNumber { branch_num: Rational, delta: Rational, } @@ -35,7 +35,7 @@ struct BranchNumber { impl Default for BranchNumber { fn default() -> Self { Self { - branch_num: Rational::from(1 << 63), + branch_num: Rational::from(1usize << 63), delta: Rational::from(1), } } @@ -87,9 +87,10 @@ impl BranchNumber { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct VarInfo { var_ptr: VarPtr, + chunk_type: ChunkType, classify_info: ClassifyInfo, lvl: Level, } @@ -102,6 +103,11 @@ pub struct ChunkInfo { vars: Vec, } +#[derive(Debug)] +pub struct BranchArm { + pub arm_terms: Vec, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BranchInfo { branch_num: BranchNumber, @@ -114,7 +120,7 @@ impl BranchInfo { } } -type BranchMapInt = IndexMap>; +type BranchMapInt = IndexMap>; #[derive(Debug, Clone)] pub struct BranchMap(BranchMapInt); @@ -145,82 +151,77 @@ pub struct ClassifyInfo { enum TraversalState { // construct a QueryTerm::Branch with number of disjuncts, reset - // the chunk type to that of the chunk preceding the disjunct. - BuildDisjunct(ChunkType, usize), + // the chunk type to that of the chunk preceding the disjunct and the chunk_num. + BuildDisjunct(usize), // add the last disjunct to a QueryTerm::Branch, continuing from // where it leaves off. BuildFinalDisjunct(usize), Fail, - GetCutPoint(usize), - LocalCut(usize), + GetCutPoint{ var_num: usize, prev_b: bool }, + Cut { var_num: usize, is_global: bool }, ResetCallPolicy(CallPolicy), Term(Term), - AddBranchNum(BranchNumber), // set current_branch_number, add it to the root set - RemoveBranchNum, // remove latest branch number from the root set - RepBranchNum(BranchNumber), // replace current_branch_number and the latest in the root set - IncrChunkNum, // increment self.current_chunk_number - SetLastChunkType, // consider remaining terms as belonging to a last chunk -} - -impl Term { - #[inline] - fn is_var(&self) -> bool { - if let Term::Var(..) = self { - true - } else { - false - } - } - - #[inline] - fn is_compound(&self) -> bool { - match self { - Term::Clause(..) | Term::Cons(..) => true, - _ => false, - } - } + RemoveBranchNum, // pop the current_branch_num and from the root set. + AddBranchNum(BranchNumber), // set current_branch_num, add it to the root set + RepBranchNum(BranchNumber), // replace current_branch_num and the latest in the root set + // SetChunkType(ChunkType), // consider remaining terms as belonging to a last chunk } +#[derive(Debug)] pub struct VariableClassifier { call_policy: CallPolicy, current_branch_num: BranchNumber, current_chunk_num: usize, + current_chunk_type: ChunkType, branch_map: BranchMap, var_num: usize, root_set: RootSet, + global_cut_var_num: Option, } -#[derive(Debug)] -pub enum VarClassification { - Void, - Temp, - Perm, +#[derive(Debug, Default)] +pub struct VarData { + pub records: VariableRecords, + pub global_cut_var_num: Option, + pub allocates: bool, } -#[derive(Clone, Debug)] -pub struct VarRecord { - pub classification: VarClassification, - pub chunk_occurrences: Vec, - pub num_occurrences: usize, -} +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::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => { + Some(global_cut_var_num) + } + _ => None + } + } else { + None + }; -impl Default for VarRecord { - fn default() -> Self { - VarRecord { - classification: VarClassification::Void, - chunk_occurrences: vec![], - num_occurrences: 0, + 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); + + match build_stack.front_mut() { + Some(ChunkedTerms::Branch(_)) => { + build_stack.push_front(ChunkedTerms::Chunk(VecDeque::from(vec![term]))); + } + Some(ChunkedTerms::Chunk(chunk)) => { + chunk.push_front(term); + } + None => { + unreachable!() + } + } } } } -pub struct VarData { - pub records: Vec, - pub fixtures: VariableFixtures, -} - pub type ClassifyFactResult = (Term, VarData); -pub type ClassifyRuleResult = (Term, Vec, VarData); +pub type ClassifyRuleResult = (Term, ChunkedTermVec, VarData); fn merge_branch_seq>(branches: Iter) -> BranchInfo { let mut branch_info = BranchInfo::new(BranchNumber::default()); @@ -228,6 +229,7 @@ fn merge_branch_seq>(branches: Iter) -> Branch for mut branch in branches { branch_info.branch_num = branch.branch_num; + /* if let Some(last_chunk) = branch_info.chunks.last_mut() { if let Some(first_moved_chunk) = branch.chunks.first_mut() { if last_chunk.chunk_num == first_moved_chunk.chunk_num { @@ -238,6 +240,7 @@ fn merge_branch_seq>(branches: Iter) -> Branch } } } + */ branch_info.chunks.extend(branch.chunks.drain(..)); } @@ -248,82 +251,37 @@ fn merge_branch_seq>(branches: Iter) -> Branch branch_info } -fn flatten_into_disjunct(build_stack: &mut Vec, preceding_len: usize) { - let iter = build_stack.drain(preceding_len + 1 ..); +fn flatten_into_disjunct(build_stack: &mut ChunkedTermVec, preceding_len: usize) { + let branch_vec = build_stack.drain(preceding_len + 1 ..).collect(); - if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { - disjuncts.push(iter.collect()); + if let ChunkedTerms::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { + disjuncts.push(branch_vec); } else { unreachable!(); } } -fn term_in_other_chunk(term: &Term) -> Option { - match term { - Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(*name, terms.len())), - Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => Some(false), - Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(*name, 0)), - Term::Var(..) => Some(true), - _ => None, - } -} - -// returns true if SetLastChunkType was pushed. -// expects that iter iterates over a conjunct of Terms in reverse order. -fn insert_set_last_chunk_type( - state_stack: &mut Vec, - mut iter: impl Iterator, -) -> bool { - let beg = state_stack.len(); - - let mut will_break = false; - let mut last_chunk_delim = beg; - - while let Some(traversal_st) = iter.next() { - match traversal_st { - TraversalState::Term(term) => { - will_break = false; - - match term_in_other_chunk(&term) { - Some(true) if last_chunk_delim > beg => will_break = true, - Some(_) => last_chunk_delim += 1, - None => will_break = true, - } - - if will_break { - // recall that iter iterates in reverse order. - // therefore this is the correct push order. - state_stack.push(TraversalState::SetLastChunkType); - state_stack.push(traversal_st); - - break; - } - } - _ => { - state_stack.push(traversal_st); - } - } - } - - state_stack.extend(iter); - will_break -} - impl VariableClassifier { pub fn new(call_policy: CallPolicy) -> Self { Self { call_policy, current_branch_num: BranchNumber::default(), current_chunk_num: 0, + current_chunk_type: ChunkType::Head, branch_map: BranchMap(BranchMapInt::new()), root_set: RootSet::new(), var_num: 0, + global_cut_var_num: None, } } pub fn classify_fact(mut self, term: Term) -> Result { self.classify_head_variables(&term)?; - Ok((term, self.branch_map.separate_and_classify_variables(self.var_num))) + Ok((term, 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>>( @@ -333,9 +291,21 @@ impl VariableClassifier { body: Term, ) -> Result { self.classify_head_variables(&head)?; - let query_terms = self.classify_body_variables(loader, body)?; + self.root_set.insert(self.current_branch_num.clone()); - Ok((head, query_terms, self.branch_map.separate_and_classify_variables(self.var_num))) + let mut query_terms = self.classify_body_variables(loader, body)?; + + self.merge_branches(); + + let mut var_data = self.branch_map.separate_and_classify_variables( + self.var_num, + self.global_cut_var_num, + self.current_chunk_num, + ); + + var_data.emit_initial_get_level(&mut query_terms); + + Ok((head, query_terms, var_data)) } fn merge_branches(&mut self) { @@ -359,24 +329,49 @@ impl VariableClassifier { } } - fn probe_body_term(&mut self, term: &Term, term_loc: GenContext) { - let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() }; + fn try_set_chunk_at_inlined_boundary(&mut self) -> bool { + if self.current_chunk_type.is_last() { + self.current_chunk_type = ChunkType::Mid; + self.current_chunk_num += 1; + true + } else { + false + } + } + + fn try_set_chunk_at_call_boundary(&mut self) -> bool { + if self.current_chunk_type.is_last() { + self.current_chunk_num += 1; + true + } else { + self.current_chunk_type = ChunkType::Last; + false + } + } + + fn probe_body_term(&mut self, arg_c: usize, arity: usize, term: &Term) { + let classify_info = ClassifyInfo { arg_c, arity }; // second arg is true to iterate the root, which may be a variable - for term_ref in breadth_first_iter(term, true) { - if let TermRef::Var(lvl, _, var_name) = term_ref { - let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), lvl, classify_info }; - self.probe_body_var(var_name, term_loc, var_info); - } - - if let Level::Shallow = term_ref.level() { - classify_info.arg_c += 1; + 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, + }); } } } - fn probe_body_var(&mut self, var_name: Var, term_loc: GenContext, var_info: VarInfo) { - let branch_info_v = self.branch_map.entry(var_name) + fn probe_body_var(&mut self, var_info: VarInfo) { + let term_loc = self.current_chunk_type.to_gen_context(self.current_chunk_num); + + let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone()) .or_insert_with(|| vec![]); let needs_new_branch = if let Some(last_bi) = branch_info_v.last() { @@ -409,18 +404,17 @@ impl VariableClassifier { chunk_info.vars.push(var_info); } - fn probe_in_situ_var(&mut self, chunk_type: ChunkType, var_num: usize) { - let classify_info = ClassifyInfo { arg_c: 0, arity: 0 }; + fn probe_in_situ_var(&mut self, var_num: usize) { + let classify_info = ClassifyInfo { arg_c: 1, arity: 1 }; let var_info = VarInfo { - var_ptr: VarPtr::InSitu(var_num), + var_ptr: VarPtr::from(Var::InSitu(var_num)), classify_info, + chunk_type: self.current_chunk_type, lvl: Level::Shallow, }; - let term_loc = chunk_type.to_gen_context(self.current_chunk_num); - - self.probe_body_var(Var::Generated(var_num), term_loc, var_info); + self.probe_body_var(var_info); } fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> { @@ -430,43 +424,55 @@ impl VariableClassifier { _ => return Err(CompilationError::InvalidRuleHead), } - let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() }; + let mut classify_info = ClassifyInfo { arg_c: 1, arity: term.arity() }; - // false argument to breadth_first_iter because the root is not iterable. - for term_ref in breadth_first_iter(term, false) { - if let TermRef::Var(lvl, _, var_name) = term_ref { - // 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::from(var_name)) - .or_insert_with(|| vec![]); + match term { + Term::Clause(_, _, terms) => { + for term in terms.into_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(); - let needs_new_branch = branch_info_v.is_empty(); + // 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_insert_with(|| vec![]); - if needs_new_branch { - branch_info_v.push(BranchInfo::new(self.current_branch_num.clone())); + let needs_new_branch = branch_info_v.is_empty(); + + 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(); + + 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; } - - let branch_info = branch_info_v.last_mut().unwrap(); - let needs_new_chunk = branch_info.chunks.is_empty(); - - 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: VarPtr::from(&var_name), classify_info, lvl }; - - chunk_info.vars.push(var_info); - } - - if let Level::Shallow = term_ref.level() { - classify_info.arg_c += 1; } + _ => {} } Ok(()) @@ -476,10 +482,11 @@ impl VariableClassifier { &mut self, loader: &mut Loader<'a, LS>, term: Term, - ) -> Result, CompilationError> { + ) -> Result { let mut state_stack = vec![TraversalState::Term(term)]; - let mut build_stack = vec![]; - let mut chunk_type = ChunkType::Head; + let mut build_stack = ChunkedTermVec::new(); + + self.current_chunk_type = ChunkType::Mid; while let Some(traversal_st) = state_stack.pop() { match traversal_st { @@ -495,64 +502,78 @@ impl VariableClassifier { self.root_set.insert(branch_num.clone()); self.current_branch_num = branch_num; } - TraversalState::IncrChunkNum => { - self.current_chunk_num += 1; - chunk_type = ChunkType::Mid; - build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type)); - } TraversalState::ResetCallPolicy(call_policy) => { self.call_policy = call_policy; } - TraversalState::SetLastChunkType => { - chunk_type = ChunkType::Last; - build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type)); - } - TraversalState::BuildDisjunct(reset_chunk_type, preceding_len) => { - chunk_type = reset_chunk_type; - build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type)); + TraversalState::BuildDisjunct(preceding_len) => { flatten_into_disjunct(&mut build_stack, preceding_len); + + // self.current_chunk_type = ChunkType::Last; + self.current_chunk_type = ChunkType::Mid; + self.current_chunk_num += 1; } TraversalState::BuildFinalDisjunct(preceding_len) => { flatten_into_disjunct(&mut build_stack, preceding_len); - } - TraversalState::GetCutPoint(var_num) => { - let term_loc = chunk_type.to_gen_context(self.current_chunk_num); - self.probe_in_situ_var(term_loc, var_num); - build_stack.push(QueryTerm::GetCutPoint(var_num)); + self.current_chunk_type = ChunkType::Mid; + self.current_chunk_num += 1; } - TraversalState::LocalCut(var_num) => { - let term_loc = chunk_type.to_gen_context(self.current_chunk_num); + TraversalState::GetCutPoint { var_num, prev_b } => { + if self.try_set_chunk_at_inlined_boundary() { + build_stack.add_chunk(); + } - self.probe_in_situ_var(term_loc, var_num); - build_stack.push(QueryTerm::LocalCut(var_num)); + self.probe_in_situ_var(var_num); + build_stack.push_chunk_term(QueryTerm::GetCutPoint { var_num, prev_b }); + } + TraversalState::Cut { var_num, is_global } => { + if self.try_set_chunk_at_inlined_boundary() { + build_stack.add_chunk(); + } + + self.probe_in_situ_var(var_num); + + build_stack.push_chunk_term( + if is_global { + QueryTerm::GlobalCut(var_num) + } else { + QueryTerm::LocalCut(var_num) + } + ); } TraversalState::Fail => { - build_stack.push(QueryTerm::Fail); + build_stack.push_chunk_term(QueryTerm::Fail); } TraversalState::Term(term) => { + // 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) { + classifier.try_set_chunk_at_inlined_boundary() + } else { + classifier.try_set_chunk_at_call_boundary() + } + }; + match term { - Term::Clause(_, atom!(","), terms) if terms.len() == 2 => { - let iter = unfold_by_str(terms[1], atom!(",")) + 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(terms[0])) + .chain(std::iter::once(head)) .map(TraversalState::Term); - if ChunkType::Mid != chunk_type { - if insert_set_last_chunk_type(&mut state_stack, iter) { - if chunk_type.is_last() { - chunk_type = ChunkType::Mid; - } - } - } else { - state_stack.extend(iter); - } + state_stack.extend(iter); } - Term::Clause(_, atom!(";"), terms) if terms.len() == 2 => { + 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(terms[0]) - .chain(unfold_by_str(terms[1], atom!(";")).into_iter()) + let branches: Vec<_> = std::iter::once(head) + .chain(unfold_by_str(tail, atom!(";")).into_iter()) .collect(); let mut branch_numbers = vec![first_branch_num]; @@ -568,7 +589,7 @@ impl VariableClassifier { } let build_stack_len = build_stack.len(); - build_stack.push(QueryTerm::Branch(Vec::with_capacity(branches.len()))); + build_stack.reserve_branch(branches.len()); state_stack.push(TraversalState::RepBranchNum( self.current_branch_num.halve_delta(), @@ -578,47 +599,52 @@ impl VariableClassifier { let final_disjunct_loc = state_stack.len(); for (term, branch_num) in iter.rev() { - state_stack.push(TraversalState::BuildDisjunct(chunk_type, build_stack_len)); - + 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)); } - state_stack[final_disjunct_loc] = - TraversalState::BuildFinalDisjunct(build_stack_len); + if let TraversalState::BuildDisjunct(build_stack_len) = state_stack[final_disjunct_loc] { + state_stack[final_disjunct_loc] = TraversalState::BuildFinalDisjunct(build_stack_len); + } } Term::Clause(_, atom!("->"), mut terms) if terms.len() == 2 => { let then_term = terms.pop().unwrap(); let if_term = terms.pop().unwrap(); - let iter = vec![TraversalState::Term(then_term), - TraversalState::LocalCut(self.var_num), - TraversalState::Term(if_term), - TraversalState::GetCutPoint(self.var_num)] - .into_iter(); + 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. + matches!(state_stack.iter().rev().nth(1), Some(TraversalState::BuildDisjunct(..))) + } 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; - - if ChunkType::Mid != chunk_type { - if insert_set_last_chunk_type(&mut state_stack, iter) { - if chunk_type.is_last() { - chunk_type = ChunkType::Mid; - } - } - } } - Term::Clause(_, atom!("\\+"), terms) if terms.len() == 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::LocalCut(self.var_num)); - state_stack.push(TraversalState::Term(terms[0])); - state_stack.push(TraversalState::GetCutPoint(self.var_num)); + state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false }); + state_stack.push(TraversalState::Term(not_term)); + state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b: true }); self.var_num += 1; } Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => { - let term_loc = chunk_type.to_gen_context(self.current_chunk_num); - let predicate_name = terms.pop().unwrap(); let module_name = terms.pop().unwrap(); @@ -627,11 +653,11 @@ impl VariableClassifier { Term::Literal(_, Literal::Atom(module_name)), Term::Literal(_, Literal::Atom(predicate_name)), ) => { - if !ClauseType::is_inbuilt(predicate_name, 0) { - state_stack.push(TraversalState::IncrChunkNum); + if update_chunk_data(self, predicate_name, 0) { + build_stack.add_chunk(); } - build_stack.push( + build_stack.push_chunk_term( qualified_clause_to_query_term( loader, module_name, @@ -645,15 +671,15 @@ impl VariableClassifier { Term::Literal(_, Literal::Atom(module_name)), Term::Clause(_, name, terms), ) => { - if !ClauseType::is_inbuilt(name, terms.len()) { - state_stack.push(TraversalState::IncrChunkNum); + if update_chunk_data(self, name, terms.len()) { + build_stack.add_chunk(); } - for term in terms.iter() { - self.probe_body_term(term, term_loc); + for (arg_c, term) in terms.iter().enumerate() { + self.probe_body_term(arg_c + 1, terms.len(), term); } - build_stack.push( + build_stack.push_chunk_term( qualified_clause_to_query_term( loader, module_name, @@ -664,15 +690,17 @@ impl VariableClassifier { ); } (module_name, predicate_name) => { - state_stack.push(TraversalState::IncrChunkNum); + if update_chunk_data(self, atom!("call"), 2) { + build_stack.add_chunk(); + } - self.probe_body_term(&module_name, term_loc); - self.probe_body_term(&predicate_name, 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); - build_stack.push( + build_stack.push_chunk_term( clause_to_query_term( loader, atom!("call"), @@ -683,30 +711,22 @@ impl VariableClassifier { } } } - Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 1 => { - let term_loc = chunk_type.to_gen_context(self.current_chunk_num); - - for term in terms.iter() { - self.probe_body_term(term, term_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[0])); + state_stack.push(TraversalState::Term(terms.pop().unwrap())); self.call_policy = CallPolicy::Counted; } - Term::Clause(cell, name, terms) => { - if !ClauseType::is_inbuilt(name, terms.len()) { - state_stack.push(TraversalState::IncrChunkNum); + Term::Clause(_, name, terms) => { + if update_chunk_data(self, name, terms.len()) { + build_stack.add_chunk(); } - let term_loc = chunk_type.to_gen_context(self.current_chunk_num); - - for term in terms.iter() { - self.probe_body_term(term, term_loc); + for (arg_c, term) in terms.iter().enumerate() { + self.probe_body_term(arg_c + 1, terms.len(), term); } - build_stack.push( + build_stack.push_chunk_term( clause_to_query_term( loader, name, @@ -716,14 +736,24 @@ impl VariableClassifier { ); } Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => { - build_stack.push(QueryTerm::GlobalCut); - } - Term::Literal(cell, Literal::Atom(name)) => { - if !ClauseType::is_inbuilt(name, 0) { - state_stack.push(TraversalState::IncrChunkNum); + if self.global_cut_var_num.is_none() { + self.global_cut_var_num = Some(self.var_num); + self.var_num += 1; } - build_stack.push( + self.probe_in_situ_var(self.global_cut_var_num.unwrap()); + + state_stack.push(TraversalState::Cut { + var_num: self.global_cut_var_num.unwrap(), + is_global: true, + }); + } + Term::Literal(_, Literal::Atom(name)) => { + if update_chunk_data(self, name, 0) { + build_stack.add_chunk(); + } + + build_stack.push_chunk_term( clause_to_query_term( loader, name, @@ -732,7 +762,6 @@ impl VariableClassifier { ), ); } - _ => { return Err(CompilationError::InadmissibleQueryTerm); } @@ -746,61 +775,76 @@ impl VariableClassifier { } impl BranchMap { - pub fn separate_and_classify_variables(&mut self, mut var_num: usize) -> VarData { + pub fn separate_and_classify_variables( + &mut self, + var_num: usize, + global_cut_var_num: Option, + current_chunk_num: usize, + ) -> VarData { let mut var_data = VarData { - records: vec![VarRecord::default(); self.len()], - fixtures: VariableFixtures::new(), + records: VariableRecords::new(var_num), + global_cut_var_num, + allocates: current_chunk_num > 0, }; for (var, branches) in self.iter_mut() { - for branch in branches.iter_mut() { - let mut num_occurrences = 0; - - let idx = if let Var::Generated(var_num) = var { - *var_num + let (mut var_num, var_num_incr) = + if let Var::InSitu(var_num) = *var.borrow() { + (var_num, false) } else { - var_num += 1; - var_num - 1 + (var_data.records.len(), true) }; - var_data.records[idx].classification = - if branch.chunks.len() > 1 { - VarClassification::Perm - } else { - branch.chunks - .first() - .map(|chunk| if chunk.vars.len() > 1 { - VarClassification::Temp - } else { - VarClassification::Void - }) - .unwrap_or(VarClassification::Void) - }; + for branch in branches.iter_mut() { + if var_num_incr { + var_num = var_data.records.len(); + var_data.records.push(VariableRecord::default()); + } - var_data.records[idx].chunk_occurrences.reserve(branch.chunks.len()); + if branch.chunks.len() <= 1 { // true iff var is a temporary variable. + debug_assert_eq!(branch.chunks.len(), 1); - for chunk in branch.chunks.iter_mut() { - var_data.records[idx].num_occurrences += chunk.vars.len(); + let chunk = &mut branch.chunks[0]; + let mut temp_var_data = TempVarData::new(); - if let VarClassification::Temp = classification { - for var_info in chunk.vars.iter_mut() { - var_info.var_ptr.set(Var::Generated(var_num)); - var_data.fixtures.mark_temp_var(&var_info); - } - } else { - for var_info in chunk.vars.iter_mut() { - var_info.var_ptr.set(Var::Generated(var_num)); + for var_info in chunk.vars.iter_mut() { + if var_info.lvl == Level::Shallow { + let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num); + temp_var_data.use_set.insert((term_loc, var_info.classify_info.arg_c)); } } - var_data.records[idx].chunk_occurrences.push(chunk.chunk_num); + var_data.records[var_num].allocation = VarAlloc::Temp { + term_loc: chunk.term_loc, + temp_reg: 0, + temp_var_data, + safety: VarSafetyStatus::Needed, + to_perm_var_num: None, + }; + } // else VarAlloc is already a Perm variant, as it's the default. + + for chunk in branch.chunks.iter_mut() { + 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)); + } } } } - debug_assert_eq!(var_data.records.len(), var_num); + // debug_assert_eq!(var_data.records.len(), var_num); - var_data.fixtures.populate_restricting_sets(); + var_data.records.populate_restricting_sets(); var_data } } + +#[cfg(test)] +mod tests { + #[test] + fn disjunct_compilation() { + let mut wam = MachineState::new(); + let mut op_dir = default_op_dir(); + } +} diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 92eca80f..1d310bcd 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -1152,6 +1152,16 @@ impl Machine { self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(b0 as i64)); self.machine_st.p += 1; } + &Instruction::GetPrevLevel(r) => { + let prev_b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b; + + self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(prev_b as i64)); + self.machine_st.p += 1; + } + &Instruction::GetCutPoint(r) => { + self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(self.machine_st.b as i64)); + self.machine_st.p += 1; + } &Instruction::Cut(r) => { let value = self.machine_st[r]; self.machine_st.cut_body(value); @@ -1170,7 +1180,7 @@ impl Machine { &Instruction::Allocate(num_cells) => { self.machine_st.allocate(num_cells); } - &Instruction::DefaultCallAcyclicTerm(_) => { + &Instruction::DefaultCallAcyclicTerm => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { @@ -1179,7 +1189,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::DefaultExecuteAcyclicTerm(_) => { + &Instruction::DefaultExecuteAcyclicTerm => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { @@ -1188,23 +1198,23 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallArg(_) => { + &Instruction::DefaultCallArg => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteArg(_) => { + &Instruction::DefaultExecuteArg => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::DefaultCallCompare(_) => { + &Instruction::DefaultCallCompare => { try_or_throw!(self.machine_st, self.machine_st.compare()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteCompare(_) => { + &Instruction::DefaultExecuteCompare => { try_or_throw!(self.machine_st, self.machine_st.compare()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::DefaultCallTermGreaterThan(_) => { + &Instruction::DefaultCallTermGreaterThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1214,7 +1224,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::DefaultExecuteTermGreaterThan(_) => { + &Instruction::DefaultExecuteTermGreaterThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1224,7 +1234,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::DefaultCallTermLessThan(_) => { + &Instruction::DefaultCallTermLessThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1234,7 +1244,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::DefaultExecuteTermLessThan(_) => { + &Instruction::DefaultExecuteTermLessThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1244,7 +1254,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::DefaultCallTermGreaterThanOrEqual(_) => { + &Instruction::DefaultCallTermGreaterThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1257,7 +1267,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteTermGreaterThanOrEqual(_) => { + &Instruction::DefaultExecuteTermGreaterThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1270,7 +1280,7 @@ impl Machine { } } } - &Instruction::DefaultCallTermLessThanOrEqual(_) => { + &Instruction::DefaultCallTermLessThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1283,7 +1293,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteTermLessThanOrEqual(_) => { + &Instruction::DefaultExecuteTermLessThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1296,11 +1306,11 @@ impl Machine { } } } - &Instruction::DefaultCallRead(_) => { + &Instruction::DefaultCallRead => { try_or_throw!(self.machine_st, self.read()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteRead(_) => { + &Instruction::DefaultExecuteRead => { try_or_throw!(self.machine_st, self.read()); if self.machine_st.fail { @@ -1309,11 +1319,11 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallCopyTerm(_) => { + &Instruction::DefaultCallCopyTerm => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteCopyTerm(_) => { + &Instruction::DefaultExecuteCopyTerm => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); if self.machine_st.fail { @@ -1322,7 +1332,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallTermEqual(_) => { + &Instruction::DefaultCallTermEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1332,7 +1342,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::DefaultExecuteTermEqual(_) => { + &Instruction::DefaultExecuteTermEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1342,26 +1352,26 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallGround(_) => { + &Instruction::DefaultCallGround => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { self.machine_st.p += 1; } } - &Instruction::DefaultExecuteGround(_) => { + &Instruction::DefaultExecuteGround => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallFunctor(_) => { + &Instruction::DefaultCallFunctor => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteFunctor(_) => { + &Instruction::DefaultExecuteFunctor => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); if self.machine_st.fail { @@ -1370,7 +1380,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallTermNotEqual(_) => { + &Instruction::DefaultCallTermNotEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1380,7 +1390,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::DefaultExecuteTermNotEqual(_) => { + &Instruction::DefaultExecuteTermNotEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1390,19 +1400,19 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallSort(_) => { + &Instruction::DefaultCallSort => { try_or_throw!(self.machine_st, self.machine_st.sort()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteSort(_) => { + &Instruction::DefaultExecuteSort => { try_or_throw!(self.machine_st, self.machine_st.sort()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::DefaultCallKeySort(_) => { + &Instruction::DefaultCallKeySort => { try_or_throw!(self.machine_st, self.machine_st.keysort()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteKeySort(_) => { + &Instruction::DefaultExecuteKeySort => { try_or_throw!(self.machine_st, self.machine_st.keysort()); if self.machine_st.fail { @@ -1411,15 +1421,15 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::DefaultCallIs(r, at, _) => { + &Instruction::DefaultCallIs(r, at) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::DefaultExecuteIs(r, at, _) => { + &Instruction::DefaultExecuteIs(r, at) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallAcyclicTerm(_) => { + &Instruction::CallAcyclicTerm => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { @@ -1433,7 +1443,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteAcyclicTerm(_) => { + &Instruction::ExecuteAcyclicTerm => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { @@ -1447,7 +1457,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallArg(_) => { + &Instruction::CallArg => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); if self.machine_st.fail { @@ -1461,7 +1471,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteArg(_) => { + &Instruction::ExecuteArg => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); if self.machine_st.fail { @@ -1475,7 +1485,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallCompare(_) => { + &Instruction::CallCompare => { try_or_throw!(self.machine_st, self.machine_st.compare()); if self.machine_st.fail { @@ -1489,7 +1499,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteCompare(_) => { + &Instruction::ExecuteCompare => { try_or_throw!(self.machine_st, self.machine_st.compare()); if self.machine_st.fail { @@ -1503,7 +1513,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallTermGreaterThan(_) => { + &Instruction::CallTermGreaterThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1518,7 +1528,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::ExecuteTermGreaterThan(_) => { + &Instruction::ExecuteTermGreaterThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1533,7 +1543,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::CallTermLessThan(_) => { + &Instruction::CallTermLessThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1548,7 +1558,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::ExecuteTermLessThan(_) => { + &Instruction::ExecuteTermLessThan => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1563,7 +1573,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::CallTermGreaterThanOrEqual(_) => { + &Instruction::CallTermGreaterThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1581,7 +1591,7 @@ impl Machine { } } } - &Instruction::ExecuteTermGreaterThanOrEqual(_) => { + &Instruction::ExecuteTermGreaterThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1599,7 +1609,7 @@ impl Machine { } } } - &Instruction::CallTermLessThanOrEqual(_) => { + &Instruction::CallTermLessThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1617,7 +1627,7 @@ impl Machine { } } } - &Instruction::ExecuteTermLessThanOrEqual(_) => { + &Instruction::ExecuteTermLessThanOrEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1635,7 +1645,7 @@ impl Machine { } } } - &Instruction::CallRead(_) => { + &Instruction::CallRead => { try_or_throw!(self.machine_st, self.read()); if self.machine_st.fail { @@ -1649,7 +1659,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteRead(_) => { + &Instruction::ExecuteRead => { try_or_throw!(self.machine_st, self.read()); if self.machine_st.fail { @@ -1663,7 +1673,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallCopyTerm(_) => { + &Instruction::CallCopyTerm => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); if self.machine_st.fail { @@ -1677,7 +1687,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteCopyTerm(_) => { + &Instruction::ExecuteCopyTerm => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); if self.machine_st.fail { @@ -1691,7 +1701,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallTermEqual(_) => { + &Instruction::CallTermEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1706,7 +1716,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteTermEqual(_) => { + &Instruction::ExecuteTermEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1721,7 +1731,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallGround(_) => { + &Instruction::CallGround => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { @@ -1733,7 +1743,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteGround(_) => { + &Instruction::ExecuteGround => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { @@ -1745,7 +1755,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallFunctor(_) => { + &Instruction::CallFunctor => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); if self.machine_st.fail { @@ -1759,7 +1769,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteFunctor(_) => { + &Instruction::ExecuteFunctor => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); if self.machine_st.fail { @@ -1773,7 +1783,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallTermNotEqual(_) => { + &Instruction::CallTermNotEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1788,7 +1798,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteTermNotEqual(_) => { + &Instruction::ExecuteTermNotEqual => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; @@ -1803,7 +1813,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallSort(_) => { + &Instruction::CallSort => { try_or_throw!(self.machine_st, self.machine_st.sort()); if self.machine_st.fail { @@ -1817,7 +1827,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteSort(_) => { + &Instruction::ExecuteSort => { try_or_throw!(self.machine_st, self.machine_st.sort()); if self.machine_st.fail { @@ -1831,7 +1841,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallKeySort(_) => { + &Instruction::CallKeySort => { try_or_throw!(self.machine_st, self.machine_st.keysort()); if self.machine_st.fail { @@ -1845,7 +1855,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteKeySort(_) => { + &Instruction::ExecuteKeySort => { try_or_throw!(self.machine_st, self.machine_st.keysort()); if self.machine_st.fail { @@ -1859,7 +1869,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallIs(r, at, _) => { + &Instruction::CallIs(r, at) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); if self.machine_st.fail { @@ -1873,7 +1883,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteIs(r, at, _) => { + &Instruction::ExecuteIs(r, at) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); if self.machine_st.fail { @@ -1887,7 +1897,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallN(arity, _) => { + &Instruction::CallN(arity) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { @@ -1910,7 +1920,7 @@ impl Machine { ); } } - &Instruction::ExecuteN(arity, _) => { + &Instruction::ExecuteN(arity) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { @@ -1933,7 +1943,7 @@ impl Machine { ); } } - &Instruction::DefaultCallN(arity, _) => { + &Instruction::DefaultCallN(arity) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { @@ -1951,7 +1961,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::DefaultExecuteN(arity, _) => { + &Instruction::DefaultExecuteN(arity) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { @@ -1969,7 +1979,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::CallNumberLessThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::CallNumberLessThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -1987,7 +1997,7 @@ impl Machine { } } } - &Instruction::ExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::ExecuteNumberLessThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2005,7 +2015,7 @@ impl Machine { } } } - &Instruction::CallNumberEqual(ref at_1, ref at_2, _) => { + &Instruction::CallNumberEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2023,7 +2033,7 @@ impl Machine { } } } - &Instruction::ExecuteNumberEqual(ref at_1, ref at_2, _) => { + &Instruction::ExecuteNumberEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2041,7 +2051,7 @@ impl Machine { } } } - &Instruction::CallNumberNotEqual(ref at_1, ref at_2, _) => { + &Instruction::CallNumberNotEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2059,7 +2069,7 @@ impl Machine { } } } - &Instruction::ExecuteNumberNotEqual(ref at_1, ref at_2, _) => { + &Instruction::ExecuteNumberNotEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2077,7 +2087,7 @@ impl Machine { } } } - &Instruction::CallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::CallNumberGreaterThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2095,7 +2105,7 @@ impl Machine { } } } - &Instruction::ExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::ExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2113,7 +2123,7 @@ impl Machine { } } } - &Instruction::CallNumberGreaterThan(ref at_1, ref at_2, _) => { + &Instruction::CallNumberGreaterThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2131,7 +2141,7 @@ impl Machine { } } } - &Instruction::ExecuteNumberGreaterThan(ref at_1, ref at_2, _) => { + &Instruction::ExecuteNumberGreaterThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2149,7 +2159,7 @@ impl Machine { } } } - &Instruction::CallNumberLessThan(ref at_1, ref at_2, _) => { + &Instruction::CallNumberLessThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2167,7 +2177,7 @@ impl Machine { } } } - &Instruction::ExecuteNumberLessThan(ref at_1, ref at_2, _) => { + &Instruction::ExecuteNumberLessThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2185,7 +2195,7 @@ impl Machine { } } } - &Instruction::DefaultCallNumberLessThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultCallNumberLessThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2198,7 +2208,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultExecuteNumberLessThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2211,7 +2221,7 @@ impl Machine { } } } - &Instruction::DefaultCallNumberNotEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultCallNumberNotEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2224,7 +2234,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteNumberNotEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultExecuteNumberNotEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2237,7 +2247,7 @@ impl Machine { } } } - &Instruction::DefaultCallNumberEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultCallNumberEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2250,7 +2260,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteNumberEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultExecuteNumberEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2263,7 +2273,7 @@ impl Machine { } } } - &Instruction::DefaultCallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultCallNumberGreaterThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2276,7 +2286,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { + &Instruction::DefaultExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2289,7 +2299,7 @@ impl Machine { } } } - &Instruction::DefaultCallNumberGreaterThan(ref at_1, ref at_2, _) => { + &Instruction::DefaultCallNumberGreaterThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2302,7 +2312,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteNumberGreaterThan(ref at_1, ref at_2, _) => { + &Instruction::DefaultExecuteNumberGreaterThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2315,7 +2325,7 @@ impl Machine { } } } - &Instruction::DefaultCallNumberLessThan(ref at_1, ref at_2, _) => { + &Instruction::DefaultCallNumberLessThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2328,7 +2338,7 @@ impl Machine { } } } - &Instruction::DefaultExecuteNumberLessThan(ref at_1, ref at_2, _) => { + &Instruction::DefaultExecuteNumberLessThan(ref at_1, ref at_2) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); @@ -2342,7 +2352,7 @@ impl Machine { } } // - &Instruction::CallIsAtom(r, _) => { + &Instruction::CallIsAtom(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2371,7 +2381,7 @@ impl Machine { } ); } - &Instruction::ExecuteIsAtom(r, _) => { + &Instruction::ExecuteIsAtom(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2400,7 +2410,7 @@ impl Machine { } ); } - &Instruction::CallIsAtomic(r, _) => { + &Instruction::CallIsAtomic(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2430,7 +2440,7 @@ impl Machine { } ); } - &Instruction::ExecuteIsAtomic(r, _) => { + &Instruction::ExecuteIsAtomic(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2460,7 +2470,7 @@ impl Machine { } ); } - &Instruction::CallIsCompound(r, _) => { + &Instruction::CallIsCompound(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2491,7 +2501,7 @@ impl Machine { } ); } - &Instruction::ExecuteIsCompound(r, _) => { + &Instruction::ExecuteIsCompound(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2522,7 +2532,7 @@ impl Machine { } ); } - &Instruction::CallIsInteger(r, _) => { + &Instruction::CallIsInteger(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { @@ -2541,7 +2551,7 @@ impl Machine { } } } - &Instruction::ExecuteIsInteger(r, _) => { + &Instruction::ExecuteIsInteger(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { @@ -2560,7 +2570,7 @@ impl Machine { } } } - &Instruction::CallIsNumber(r, _) => { + &Instruction::CallIsNumber(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { @@ -2572,7 +2582,7 @@ impl Machine { } } } - &Instruction::ExecuteIsNumber(r, _) => { + &Instruction::ExecuteIsNumber(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { @@ -2584,7 +2594,7 @@ impl Machine { } } } - &Instruction::CallIsRational(r, _) => { + &Instruction::CallIsRational(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2603,7 +2613,7 @@ impl Machine { } ); } - &Instruction::ExecuteIsRational(r, _) => { + &Instruction::ExecuteIsRational(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, @@ -2622,7 +2632,7 @@ impl Machine { } ); } - &Instruction::CallIsFloat(r, _) => { + &Instruction::CallIsFloat(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { @@ -2634,7 +2644,7 @@ impl Machine { } } } - &Instruction::ExecuteIsFloat(r, _) => { + &Instruction::ExecuteIsFloat(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { @@ -2646,7 +2656,7 @@ impl Machine { } } } - &Instruction::CallIsNonVar(r, _) => { + &Instruction::CallIsNonVar(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { @@ -2660,7 +2670,7 @@ impl Machine { } } } - &Instruction::ExecuteIsNonVar(r, _) => { + &Instruction::ExecuteIsNonVar(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { @@ -2674,7 +2684,7 @@ impl Machine { } } } - &Instruction::CallIsVar(r, _) => { + &Instruction::CallIsVar(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { @@ -2688,7 +2698,7 @@ impl Machine { } } } - &Instruction::ExecuteIsVar(r, _) => { + &Instruction::ExecuteIsVar(r) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { @@ -2702,7 +2712,7 @@ impl Machine { } } } - &Instruction::CallNamed(arity, name, ref idx, _) => { + &Instruction::CallNamed(arity, name, ref idx) => { let idx = idx.get(); try_or_throw!( @@ -2719,7 +2729,7 @@ impl Machine { ); } } - &Instruction::ExecuteNamed(arity, name, ref idx, _) => { + &Instruction::ExecuteNamed(arity, name, ref idx) => { let idx = idx.get(); try_or_throw!( @@ -2736,7 +2746,7 @@ impl Machine { ); } } - &Instruction::DefaultCallNamed(arity, name, ref idx, _) => { + &Instruction::DefaultCallNamed(arity, name, ref idx) => { let idx = idx.get(); try_or_throw!( @@ -2748,7 +2758,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::DefaultExecuteNamed(arity, name, ref idx, _) => { + &Instruction::DefaultExecuteNamed(arity, name, ref idx) => { let idx = idx.get(); try_or_throw!( @@ -2763,15 +2773,7 @@ impl Machine { &Instruction::Deallocate => { self.machine_st.deallocate() } - &Instruction::JmpByCall(arity, offset, _) => { - self.machine_st.num_of_args = arity; - self.machine_st.b0 = self.machine_st.b; - self.machine_st.cp = self.machine_st.p + 1; - self.machine_st.p += offset; - } - &Instruction::JmpByExecute(arity, offset, _) => { - self.machine_st.num_of_args = arity; - self.machine_st.b0 = self.machine_st.b; + &Instruction::JmpByCall(offset) => { self.machine_st.p += offset; } &Instruction::RevJmpBy(offset) => { @@ -3219,8 +3221,8 @@ impl Machine { self.machine_st.p += 1; } - &Instruction::PutUnsafeValue(n, arg) => { - let s = stack_loc!(AndFrame, self.machine_st.e, n); + &Instruction::PutUnsafeValue(perm_slot, arg) => { + let s = stack_loc!(AndFrame, self.machine_st.e, perm_slot); let addr = self.machine_st.store(self.machine_st.deref(stack_loc_as_cell!(s))); if addr.is_protected(self.machine_st.e) { @@ -3298,11 +3300,11 @@ impl Machine { self.machine_st.p += 1; } // - &Instruction::CallAtomChars(_) => { + &Instruction::CallAtomChars => { self.atom_chars(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteAtomChars(_) => { + &Instruction::ExecuteAtomChars => { self.atom_chars(); if self.machine_st.fail { @@ -3311,7 +3313,7 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallAtomCodes(_) => { + &Instruction::CallAtomCodes => { try_or_throw!(self.machine_st, self.atom_codes()); if self.machine_st.fail { @@ -3320,7 +3322,7 @@ impl Machine { self.machine_st.p += 1; } } - &Instruction::ExecuteAtomCodes(_) => { + &Instruction::ExecuteAtomCodes => { try_or_throw!(self.machine_st, self.atom_codes()); if self.machine_st.fail { @@ -3329,237 +3331,237 @@ impl Machine { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallAtomLength(_) => { + &Instruction::CallAtomLength => { self.atom_length(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteAtomLength(_) => { + &Instruction::ExecuteAtomLength => { self.atom_length(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallBindFromRegister(_) => { + &Instruction::CallBindFromRegister => { self.bind_from_register(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteBindFromRegister(_) => { + &Instruction::ExecuteBindFromRegister => { self.bind_from_register(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallContinuation(_) => { + &Instruction::CallContinuation => { try_or_throw!(self.machine_st, self.call_continuation(false)); } - &Instruction::ExecuteContinuation(_) => { + &Instruction::ExecuteContinuation => { try_or_throw!(self.machine_st, self.call_continuation(true)); } - &Instruction::CallCharCode(_) => { + &Instruction::CallCharCode => { try_or_throw!(self.machine_st, self.char_code()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCharCode(_) => { + &Instruction::ExecuteCharCode => { try_or_throw!(self.machine_st, self.char_code()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCharType(_) => { + &Instruction::CallCharType => { self.char_type(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCharType(_) => { + &Instruction::ExecuteCharType => { self.char_type(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCharsToNumber(_) => { + &Instruction::CallCharsToNumber => { try_or_throw!(self.machine_st, self.chars_to_number()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCharsToNumber(_) => { + &Instruction::ExecuteCharsToNumber => { try_or_throw!(self.machine_st, self.chars_to_number()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCodesToNumber(_) => { + &Instruction::CallCodesToNumber => { try_or_throw!(self.machine_st, self.codes_to_number()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCodesToNumber(_) => { + &Instruction::ExecuteCodesToNumber => { try_or_throw!(self.machine_st, self.codes_to_number()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCopyTermWithoutAttrVars(_) => { + &Instruction::CallCopyTermWithoutAttrVars => { self.copy_term_without_attr_vars(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCopyTermWithoutAttrVars(_) => { + &Instruction::ExecuteCopyTermWithoutAttrVars => { self.copy_term_without_attr_vars(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCheckCutPoint(_) => { + &Instruction::CallCheckCutPoint => { self.check_cut_point(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCheckCutPoint(_) => { + &Instruction::ExecuteCheckCutPoint => { self.check_cut_point(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallClose(_) => { + &Instruction::CallClose => { try_or_throw!(self.machine_st, self.close()); self.machine_st.p += 1; } - &Instruction::ExecuteClose(_) => { + &Instruction::ExecuteClose => { try_or_throw!(self.machine_st, self.close()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallCopyToLiftedHeap(_) => { + &Instruction::CallCopyToLiftedHeap => { self.copy_to_lifted_heap(); self.machine_st.p += 1; } - &Instruction::ExecuteCopyToLiftedHeap(_) => { + &Instruction::ExecuteCopyToLiftedHeap => { self.copy_to_lifted_heap(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallCreatePartialString(_) => { + &Instruction::CallCreatePartialString => { self.create_partial_string(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCreatePartialString(_) => { + &Instruction::ExecuteCreatePartialString => { self.create_partial_string(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCurrentHostname(_) => { + &Instruction::CallCurrentHostname => { self.current_hostname(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCurrentHostname(_) => { + &Instruction::ExecuteCurrentHostname => { self.current_hostname(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCurrentInput(_) => { + &Instruction::CallCurrentInput => { try_or_throw!(self.machine_st, self.current_input()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCurrentInput(_) => { + &Instruction::ExecuteCurrentInput => { try_or_throw!(self.machine_st, self.current_input()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCurrentOutput(_) => { + &Instruction::CallCurrentOutput => { try_or_throw!(self.machine_st, self.current_output()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCurrentOutput(_) => { + &Instruction::ExecuteCurrentOutput => { try_or_throw!(self.machine_st, self.current_output()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDirectoryFiles(_) => { + &Instruction::CallDirectoryFiles => { try_or_throw!(self.machine_st, self.directory_files()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDirectoryFiles(_) => { + &Instruction::ExecuteDirectoryFiles => { try_or_throw!(self.machine_st, self.directory_files()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFileSize(_) => { + &Instruction::CallFileSize => { self.file_size(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFileSize(_) => { + &Instruction::ExecuteFileSize => { self.file_size(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFileExists(_) => { + &Instruction::CallFileExists => { self.file_exists(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFileExists(_) => { + &Instruction::ExecuteFileExists => { self.file_exists(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDirectoryExists(_) => { + &Instruction::CallDirectoryExists => { self.directory_exists(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDirectoryExists(_) => { + &Instruction::ExecuteDirectoryExists => { self.directory_exists(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDirectorySeparator(_) => { + &Instruction::CallDirectorySeparator => { self.directory_separator(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDirectorySeparator(_) => { + &Instruction::ExecuteDirectorySeparator => { self.directory_separator(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallMakeDirectory(_) => { + &Instruction::CallMakeDirectory => { self.make_directory(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteMakeDirectory(_) => { + &Instruction::ExecuteMakeDirectory => { self.make_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallMakeDirectoryPath(_) => { + &Instruction::CallMakeDirectoryPath => { self.make_directory_path(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteMakeDirectoryPath(_) => { + &Instruction::ExecuteMakeDirectoryPath => { self.make_directory_path(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDeleteFile(_) => { + &Instruction::CallDeleteFile => { self.delete_file(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDeleteFile(_) => { + &Instruction::ExecuteDeleteFile => { self.delete_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallRenameFile(_) => { + &Instruction::CallRenameFile => { self.rename_file(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteRenameFile(_) => { + &Instruction::ExecuteRenameFile => { self.rename_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFileCopy(_) => { + &Instruction::CallFileCopy => { self.file_copy(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFileCopy(_) => { + &Instruction::ExecuteFileCopy => { self.file_copy(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallWorkingDirectory(_) => { + &Instruction::CallWorkingDirectory => { try_or_throw!(self.machine_st, self.working_directory()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteWorkingDirectory(_) => { + &Instruction::ExecuteWorkingDirectory => { try_or_throw!(self.machine_st, self.working_directory()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDeleteDirectory(_) => { + &Instruction::CallDeleteDirectory => { self.delete_directory(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDeleteDirectory(_) => { + &Instruction::ExecuteDeleteDirectory => { self.delete_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPathCanonical(_) => { + &Instruction::CallPathCanonical => { try_or_throw!(self.machine_st, self.path_canonical()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePathCanonical(_) => { + &Instruction::ExecutePathCanonical => { try_or_throw!(self.machine_st, self.path_canonical()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFileTime(_) => { + &Instruction::CallFileTime => { self.file_time(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFileTime(_) => { + &Instruction::ExecuteFileTime => { self.file_time(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDynamicModuleResolution(arity, _) => { + &Instruction::CallDynamicModuleResolution(arity) => { let (module_name, key) = try_or_throw!( self.machine_st, self.dynamic_module_resolution(arity - 2) @@ -3574,7 +3576,7 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::ExecuteDynamicModuleResolution(arity, _) => { + &Instruction::ExecuteDynamicModuleResolution(arity) => { let (module_name, key) = try_or_throw!( self.machine_st, self.dynamic_module_resolution(arity - 2) @@ -3589,428 +3591,428 @@ impl Machine { self.machine_st.backtrack(); } } - &Instruction::CallFetchGlobalVar(_) => { + &Instruction::CallFetchGlobalVar => { self.fetch_global_var(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFetchGlobalVar(_) => { + &Instruction::ExecuteFetchGlobalVar => { self.fetch_global_var(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFirstStream(_) => { + &Instruction::CallFirstStream => { self.first_stream(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFirstStream(_) => { + &Instruction::ExecuteFirstStream => { self.first_stream(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFlushOutput(_) => { + &Instruction::CallFlushOutput => { try_or_throw!(self.machine_st, self.flush_output()); self.machine_st.p += 1; } - &Instruction::ExecuteFlushOutput(_) => { + &Instruction::ExecuteFlushOutput => { try_or_throw!(self.machine_st, self.flush_output()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallGetByte(_) => { + &Instruction::CallGetByte => { try_or_throw!(self.machine_st, self.get_byte()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetByte(_) => { + &Instruction::ExecuteGetByte => { try_or_throw!(self.machine_st, self.get_byte()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetChar(_) => { + &Instruction::CallGetChar => { try_or_throw!(self.machine_st, self.get_char()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetChar(_) => { + &Instruction::ExecuteGetChar => { try_or_throw!(self.machine_st, self.get_char()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetNChars(_) => { + &Instruction::CallGetNChars => { try_or_throw!(self.machine_st, self.get_n_chars()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetNChars(_) => { + &Instruction::ExecuteGetNChars => { try_or_throw!(self.machine_st, self.get_n_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetCode(_) => { + &Instruction::CallGetCode => { try_or_throw!(self.machine_st, self.get_code()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetCode(_) => { + &Instruction::ExecuteGetCode => { try_or_throw!(self.machine_st, self.get_code()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetSingleChar(_) => { + &Instruction::CallGetSingleChar => { try_or_throw!(self.machine_st, self.get_single_char()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetSingleChar(_) => { + &Instruction::ExecuteGetSingleChar => { try_or_throw!(self.machine_st, self.get_single_char()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff(_) => { + &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff => { self.truncate_if_no_lifted_heap_growth_diff(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) => { + &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff => { self.truncate_if_no_lifted_heap_growth_diff(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) => { + &Instruction::CallTruncateIfNoLiftedHeapGrowth => { self.truncate_if_no_lifted_heap_growth(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) => { + &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth => { self.truncate_if_no_lifted_heap_growth(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetAttributedVariableList(_) => { + &Instruction::CallGetAttributedVariableList => { self.get_attributed_variable_list(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetAttributedVariableList(_) => { + &Instruction::ExecuteGetAttributedVariableList => { self.get_attributed_variable_list(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetAttrVarQueueDelimiter(_) => { + &Instruction::CallGetAttrVarQueueDelimiter => { self.get_attr_var_queue_delimiter(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetAttrVarQueueDelimiter(_) => { + &Instruction::ExecuteGetAttrVarQueueDelimiter => { self.get_attr_var_queue_delimiter(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetAttrVarQueueBeyond(_) => { + &Instruction::CallGetAttrVarQueueBeyond => { self.get_attr_var_queue_beyond(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetAttrVarQueueBeyond(_) => { + &Instruction::ExecuteGetAttrVarQueueBeyond => { self.get_attr_var_queue_beyond(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetBValue(_) => { + &Instruction::CallGetBValue => { self.get_b_value(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetBValue(_) => { + &Instruction::ExecuteGetBValue => { self.get_b_value(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetContinuationChunk(_) => { + &Instruction::CallGetContinuationChunk => { self.get_continuation_chunk(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetContinuationChunk(_) => { + &Instruction::ExecuteGetContinuationChunk => { self.get_continuation_chunk(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLookupDBRef(_) => { + &Instruction::CallLookupDBRef => { self.lookup_db_ref(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLookupDBRef(_) => { + &Instruction::ExecuteLookupDBRef => { self.lookup_db_ref(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetNextOpDBRef(_) => { + &Instruction::CallGetNextOpDBRef => { self.get_next_op_db_ref(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetNextOpDBRef(_) => { + &Instruction::ExecuteGetNextOpDBRef => { self.get_next_op_db_ref(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallIsPartialString(_) => { + &Instruction::CallIsPartialString => { self.is_partial_string(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteIsPartialString(_) => { + &Instruction::ExecuteIsPartialString => { self.is_partial_string(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallHalt(_) => { + &Instruction::CallHalt => { self.halt(); self.machine_st.p += 1; } - &Instruction::ExecuteHalt(_) => { + &Instruction::ExecuteHalt => { self.halt(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallGetLiftedHeapFromOffset(_) => { + &Instruction::CallGetLiftedHeapFromOffset => { self.get_lifted_heap_from_offset(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetLiftedHeapFromOffset(_) => { + &Instruction::ExecuteGetLiftedHeapFromOffset => { self.get_lifted_heap_from_offset(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetLiftedHeapFromOffsetDiff(_) => { + &Instruction::CallGetLiftedHeapFromOffsetDiff => { self.get_lifted_heap_from_offset_diff(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetLiftedHeapFromOffsetDiff(_) => { + &Instruction::ExecuteGetLiftedHeapFromOffsetDiff => { self.get_lifted_heap_from_offset_diff(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetSCCCleaner(_) => { + &Instruction::CallGetSCCCleaner => { self.get_scc_cleaner(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetSCCCleaner(_) => { + &Instruction::ExecuteGetSCCCleaner => { self.get_scc_cleaner(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallHeadIsDynamic(_) => { + &Instruction::CallHeadIsDynamic => { self.head_is_dynamic(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteHeadIsDynamic(_) => { + &Instruction::ExecuteHeadIsDynamic => { self.head_is_dynamic(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInstallSCCCleaner(_) => { + &Instruction::CallInstallSCCCleaner => { self.install_scc_cleaner(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteInstallSCCCleaner(_) => { + &Instruction::ExecuteInstallSCCCleaner => { self.install_scc_cleaner(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInstallInferenceCounter(_) => { + &Instruction::CallInstallInferenceCounter => { try_or_throw!(self.machine_st, self.install_inference_counter()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteInstallInferenceCounter(_) => { + &Instruction::ExecuteInstallInferenceCounter => { try_or_throw!(self.machine_st, self.install_inference_counter()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLiftedHeapLength(_) => { + &Instruction::CallLiftedHeapLength => { self.lifted_heap_length(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLiftedHeapLength(_) => { + &Instruction::ExecuteLiftedHeapLength => { self.lifted_heap_length(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadLibraryAsStream(_) => { + &Instruction::CallLoadLibraryAsStream => { try_or_throw!(self.machine_st, self.load_library_as_stream()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadLibraryAsStream(_) => { + &Instruction::ExecuteLoadLibraryAsStream => { try_or_throw!(self.machine_st, self.load_library_as_stream()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallModuleExists(_) => { + &Instruction::CallModuleExists => { self.module_exists(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteModuleExists(_) => { + &Instruction::ExecuteModuleExists => { self.module_exists(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallNextEP(_) => { + &Instruction::CallNextEP => { self.next_ep(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteNextEP(_) => { + &Instruction::ExecuteNextEP => { self.next_ep(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallNoSuchPredicate(_) => { + &Instruction::CallNoSuchPredicate => { try_or_throw!(self.machine_st, self.no_such_predicate()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteNoSuchPredicate(_) => { + &Instruction::ExecuteNoSuchPredicate => { try_or_throw!(self.machine_st, self.no_such_predicate()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallNumberToChars(_) => { + &Instruction::CallNumberToChars => { self.number_to_chars(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteNumberToChars(_) => { + &Instruction::ExecuteNumberToChars => { self.number_to_chars(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallNumberToCodes(_) => { + &Instruction::CallNumberToCodes => { self.number_to_codes(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteNumberToCodes(_) => { + &Instruction::ExecuteNumberToCodes => { self.number_to_codes(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallOpDeclaration(_) => { + &Instruction::CallOpDeclaration => { try_or_throw!(self.machine_st, self.op_declaration()); self.machine_st.p += 1; } - &Instruction::ExecuteOpDeclaration(_) => { + &Instruction::ExecuteOpDeclaration => { try_or_throw!(self.machine_st, self.op_declaration()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallOpen(_) => { + &Instruction::CallOpen => { try_or_throw!(self.machine_st, self.open()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteOpen(_) => { + &Instruction::ExecuteOpen => { try_or_throw!(self.machine_st, self.open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSetStreamOptions(_) => { + &Instruction::CallSetStreamOptions => { try_or_throw!(self.machine_st, self.set_stream_options()); self.machine_st.p += 1; } - &Instruction::ExecuteSetStreamOptions(_) => { + &Instruction::ExecuteSetStreamOptions => { try_or_throw!(self.machine_st, self.set_stream_options()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallNextStream(_) => { + &Instruction::CallNextStream => { self.next_stream(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteNextStream(_) => { + &Instruction::ExecuteNextStream => { self.next_stream(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPartialStringTail(_) => { + &Instruction::CallPartialStringTail => { self.partial_string_tail(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePartialStringTail(_) => { + &Instruction::ExecutePartialStringTail => { self.partial_string_tail(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPeekByte(_) => { + &Instruction::CallPeekByte => { try_or_throw!(self.machine_st, self.peek_byte()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePeekByte(_) => { + &Instruction::ExecutePeekByte => { try_or_throw!(self.machine_st, self.peek_byte()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPeekChar(_) => { + &Instruction::CallPeekChar => { try_or_throw!(self.machine_st, self.peek_char()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePeekChar(_) => { + &Instruction::ExecutePeekChar => { try_or_throw!(self.machine_st, self.peek_char()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPeekCode(_) => { + &Instruction::CallPeekCode => { try_or_throw!(self.machine_st, self.peek_code()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePeekCode(_) => { + &Instruction::ExecutePeekCode => { try_or_throw!(self.machine_st, self.peek_code()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPointsToContinuationResetMarker(_) => { + &Instruction::CallPointsToContinuationResetMarker => { self.points_to_continuation_reset_marker(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePointsToContinuationResetMarker(_) => { + &Instruction::ExecutePointsToContinuationResetMarker => { self.points_to_continuation_reset_marker(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPutByte(_) => { + &Instruction::CallPutByte => { try_or_throw!(self.machine_st, self.put_byte()); self.machine_st.p += 1; } - &Instruction::ExecutePutByte(_) => { + &Instruction::ExecutePutByte => { try_or_throw!(self.machine_st, self.put_byte()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPutChar(_) => { + &Instruction::CallPutChar => { try_or_throw!(self.machine_st, self.put_char()); self.machine_st.p += 1; } - &Instruction::ExecutePutChar(_) => { + &Instruction::ExecutePutChar => { try_or_throw!(self.machine_st, self.put_char()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPutChars(_) => { + &Instruction::CallPutChars => { try_or_throw!(self.machine_st, self.put_chars()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePutChars(_) => { + &Instruction::ExecutePutChars => { try_or_throw!(self.machine_st, self.put_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPutCode(_) => { + &Instruction::CallPutCode => { try_or_throw!(self.machine_st, self.put_code()); self.machine_st.p += 1; } - &Instruction::ExecutePutCode(_) => { + &Instruction::ExecutePutCode => { try_or_throw!(self.machine_st, self.put_code()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallReadQueryTerm(_) => { + &Instruction::CallReadQueryTerm => { try_or_throw!(self.machine_st, self.read_query_term()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteReadQueryTerm(_) => { + &Instruction::ExecuteReadQueryTerm => { try_or_throw!(self.machine_st, self.read_query_term()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallReadTerm(_) => { + &Instruction::CallReadTerm => { try_or_throw!(self.machine_st, self.read_term()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteReadTerm(_) => { + &Instruction::ExecuteReadTerm => { try_or_throw!(self.machine_st, self.read_term()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallRedoAttrVarBinding(_) => { + &Instruction::CallRedoAttrVarBinding => { self.redo_attr_var_binding(); self.machine_st.p += 1; } - &Instruction::ExecuteRedoAttrVarBinding(_) => { + &Instruction::ExecuteRedoAttrVarBinding => { self.redo_attr_var_binding(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallRemoveCallPolicyCheck(_) => { + &Instruction::CallRemoveCallPolicyCheck => { self.remove_call_policy_check(); self.machine_st.p += 1; } - &Instruction::ExecuteRemoveCallPolicyCheck(_) => { + &Instruction::ExecuteRemoveCallPolicyCheck => { self.remove_call_policy_check(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallRemoveInferenceCounter(_) => { + &Instruction::CallRemoveInferenceCounter => { self.remove_inference_counter(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteRemoveInferenceCounter(_) => { + &Instruction::ExecuteRemoveInferenceCounter => { self.remove_inference_counter(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallResetContinuationMarker(_) => { + &Instruction::CallResetContinuationMarker => { self.reset_continuation_marker(); self.machine_st.p += 1; } - &Instruction::ExecuteResetContinuationMarker(_) => { + &Instruction::ExecuteResetContinuationMarker => { self.reset_continuation_marker(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallRestoreCutPolicy(_) => { + &Instruction::CallRestoreCutPolicy => { self.restore_cut_policy(); self.machine_st.p += 1; } - &Instruction::ExecuteRestoreCutPolicy(_) => { + &Instruction::ExecuteRestoreCutPolicy => { self.restore_cut_policy(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallSetCutPoint(r, _) => { + &Instruction::CallSetCutPoint(r) => { if !self.set_cut_point(r) { step_or_fail!(self, self.machine_st.p += 1); } } - &Instruction::ExecuteSetCutPoint(r, _) => { + &Instruction::ExecuteSetCutPoint(r) => { let cp = self.machine_st.cp; if !self.set_cut_point(r) { @@ -4023,962 +4025,962 @@ impl Machine { self.machine_st.cp = cp; } } - &Instruction::CallSetInput(_) => { + &Instruction::CallSetInput => { try_or_throw!(self.machine_st, self.set_input()); self.machine_st.p += 1; } - &Instruction::ExecuteSetInput(_) => { + &Instruction::ExecuteSetInput => { try_or_throw!(self.machine_st, self.set_input()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallSetOutput(_) => { + &Instruction::CallSetOutput => { try_or_throw!(self.machine_st, self.set_output()); self.machine_st.p += 1; } - &Instruction::ExecuteSetOutput(_) => { + &Instruction::ExecuteSetOutput => { try_or_throw!(self.machine_st, self.set_output()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallStoreBacktrackableGlobalVar(_) => { + &Instruction::CallStoreBacktrackableGlobalVar => { self.store_backtrackable_global_var(); self.machine_st.p += 1; } - &Instruction::ExecuteStoreBacktrackableGlobalVar(_) => { + &Instruction::ExecuteStoreBacktrackableGlobalVar => { self.store_backtrackable_global_var(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallStoreGlobalVar(_) => { + &Instruction::CallStoreGlobalVar => { self.store_global_var(); self.machine_st.p += 1; } - &Instruction::ExecuteStoreGlobalVar(_) => { + &Instruction::ExecuteStoreGlobalVar => { self.store_global_var(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallStreamProperty(_) => { + &Instruction::CallStreamProperty => { try_or_throw!(self.machine_st, self.stream_property()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteStreamProperty(_) => { + &Instruction::ExecuteStreamProperty => { try_or_throw!(self.machine_st, self.stream_property()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSetStreamPosition(_) => { + &Instruction::CallSetStreamPosition => { try_or_throw!(self.machine_st, self.set_stream_position()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSetStreamPosition(_) => { + &Instruction::ExecuteSetStreamPosition => { try_or_throw!(self.machine_st, self.set_stream_position()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInferenceLevel(_) => { + &Instruction::CallInferenceLevel => { self.inference_level(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteInferenceLevel(_) => { + &Instruction::ExecuteInferenceLevel => { self.inference_level(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCleanUpBlock(_) => { + &Instruction::CallCleanUpBlock => { self.clean_up_block(); self.machine_st.p += 1; } - &Instruction::ExecuteCleanUpBlock(_) => { + &Instruction::ExecuteCleanUpBlock => { self.clean_up_block(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallFail(_) | &Instruction::ExecuteFail(_) => { + &Instruction::CallFail | &Instruction::ExecuteFail => { self.machine_st.backtrack(); } - &Instruction::CallGetBall(_) => { + &Instruction::CallGetBall => { self.get_ball(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetBall(_) => { + &Instruction::ExecuteGetBall => { self.get_ball(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetCurrentBlock(_) => { + &Instruction::CallGetCurrentBlock => { self.get_current_block(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetCurrentBlock(_) => { + &Instruction::ExecuteGetCurrentBlock => { self.get_current_block(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetCutPoint(_) => { + &Instruction::CallGetCutPoint => { self.get_cut_point(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetCutPoint(_) => { + &Instruction::ExecuteGetCutPoint => { self.get_cut_point(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetDoubleQuotes(_) => { + &Instruction::CallGetDoubleQuotes => { self.get_double_quotes(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetDoubleQuotes(_) => { + &Instruction::ExecuteGetDoubleQuotes => { self.get_double_quotes(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInstallNewBlock(_) => { + &Instruction::CallInstallNewBlock => { self.machine_st.install_new_block(self.machine_st.registers[1]); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteInstallNewBlock(_) => { + &Instruction::ExecuteInstallNewBlock => { self.machine_st.install_new_block(self.machine_st.registers[1]); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallMaybe(_) => { + &Instruction::CallMaybe => { self.maybe(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteMaybe(_) => { + &Instruction::ExecuteMaybe => { self.maybe(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCpuNow(_) => { + &Instruction::CallCpuNow => { self.cpu_now(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCpuNow(_) => { + &Instruction::ExecuteCpuNow => { self.cpu_now(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDeterministicLengthRundown(_) => { + &Instruction::CallDeterministicLengthRundown => { try_or_throw!(self.machine_st, self.det_length_rundown()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDeterministicLengthRundown(_) => { + &Instruction::ExecuteDeterministicLengthRundown => { try_or_throw!(self.machine_st, self.det_length_rundown()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallHttpOpen(_) => { + &Instruction::CallHttpOpen => { try_or_throw!(self.machine_st, self.http_open()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteHttpOpen(_) => { + &Instruction::ExecuteHttpOpen => { try_or_throw!(self.machine_st, self.http_open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallHttpListen(_) => { + &Instruction::CallHttpListen => { try_or_throw!(self.machine_st, self.http_listen()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteHttpListen(_) => { + &Instruction::ExecuteHttpListen => { try_or_throw!(self.machine_st, self.http_listen()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallHttpAccept(_) => { + &Instruction::CallHttpAccept => { try_or_throw!(self.machine_st, self.http_accept()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteHttpAccept(_) => { + &Instruction::ExecuteHttpAccept => { try_or_throw!(self.machine_st, self.http_accept()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallHttpAnswer(_) => { + &Instruction::CallHttpAnswer => { try_or_throw!(self.machine_st, self.http_answer()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteHttpAnswer(_) => { + &Instruction::ExecuteHttpAnswer => { try_or_throw!(self.machine_st, self.http_answer()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadForeignLib(_) => { + &Instruction::CallLoadForeignLib => { try_or_throw!(self.machine_st, self.load_foreign_lib()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadForeignLib(_) => { + &Instruction::ExecuteLoadForeignLib => { try_or_throw!(self.machine_st, self.load_foreign_lib()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallForeignCall(_) => { + &Instruction::CallForeignCall => { try_or_throw!(self.machine_st, self.foreign_call()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteForeignCall(_) => { + &Instruction::ExecuteForeignCall => { try_or_throw!(self.machine_st, self.foreign_call()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDefineForeignStruct(_) => { + &Instruction::CallDefineForeignStruct => { try_or_throw!(self.machine_st, self.define_foreign_struct()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDefineForeignStruct(_) => { + &Instruction::ExecuteDefineForeignStruct => { try_or_throw!(self.machine_st, self.define_foreign_struct()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCurrentTime(_) => { + &Instruction::CallCurrentTime => { self.current_time(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCurrentTime(_) => { + &Instruction::ExecuteCurrentTime => { self.current_time(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallQuotedToken(_) => { + &Instruction::CallQuotedToken => { self.quoted_token(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteQuotedToken(_) => { + &Instruction::ExecuteQuotedToken => { self.quoted_token(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallReadTermFromChars(_) => { + &Instruction::CallReadTermFromChars => { try_or_throw!(self.machine_st, self.read_term_from_chars()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteReadTermFromChars(_) => { + &Instruction::ExecuteReadTermFromChars => { try_or_throw!(self.machine_st, self.read_term_from_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallResetBlock(_) => { + &Instruction::CallResetBlock => { self.reset_block(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteResetBlock(_) => { + &Instruction::ExecuteResetBlock => { self.reset_block(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallReturnFromVerifyAttr(_) | - &Instruction::ExecuteReturnFromVerifyAttr(_) => { + &Instruction::CallReturnFromVerifyAttr | + &Instruction::ExecuteReturnFromVerifyAttr => { self.return_from_verify_attr(); } - &Instruction::CallSetBall(_) => { + &Instruction::CallSetBall => { self.set_ball(); self.machine_st.p += 1; } - &Instruction::ExecuteSetBall(_) => { + &Instruction::ExecuteSetBall => { self.set_ball(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPushBallStack(_) => { + &Instruction::CallPushBallStack => { self.push_ball_stack(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePushBallStack(_) => { + &Instruction::ExecutePushBallStack => { self.push_ball_stack(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPopBallStack(_) => { + &Instruction::CallPopBallStack => { self.pop_ball_stack(); self.machine_st.p += 1; } - &Instruction::ExecutePopBallStack(_) => { + &Instruction::ExecutePopBallStack => { self.pop_ball_stack(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPopFromBallStack(_) => { + &Instruction::CallPopFromBallStack => { self.pop_from_ball_stack(); self.machine_st.p += 1; } - &Instruction::ExecutePopFromBallStack(_) => { + &Instruction::ExecutePopFromBallStack => { self.pop_from_ball_stack(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallSetCutPointByDefault(r, _) => { + &Instruction::CallSetCutPointByDefault(r) => { self.set_cut_point_by_default(r); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSetCutPointByDefault(r, _) => { + &Instruction::ExecuteSetCutPointByDefault(r) => { self.set_cut_point_by_default(r); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSetDoubleQuotes(_) => { + &Instruction::CallSetDoubleQuotes => { self.set_double_quotes(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSetDoubleQuotes(_) => { + &Instruction::ExecuteSetDoubleQuotes => { self.set_double_quotes(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSetSeed(_) => { + &Instruction::CallSetSeed => { self.set_seed(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSetSeed(_) => { + &Instruction::ExecuteSetSeed => { self.set_seed(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSkipMaxList(_) => { + &Instruction::CallSkipMaxList => { try_or_throw!(self.machine_st, self.machine_st.skip_max_list()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSkipMaxList(_) => { + &Instruction::ExecuteSkipMaxList => { try_or_throw!(self.machine_st, self.machine_st.skip_max_list()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSleep(_) => { + &Instruction::CallSleep => { self.sleep(); self.machine_st.p += 1; } - &Instruction::ExecuteSleep(_) => { + &Instruction::ExecuteSleep => { self.sleep(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallSocketClientOpen(_) => { + &Instruction::CallSocketClientOpen => { try_or_throw!(self.machine_st, self.socket_client_open()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSocketClientOpen(_) => { + &Instruction::ExecuteSocketClientOpen => { try_or_throw!(self.machine_st, self.socket_client_open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSocketServerOpen(_) => { + &Instruction::CallSocketServerOpen => { try_or_throw!(self.machine_st, self.socket_server_open()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSocketServerOpen(_) => { + &Instruction::ExecuteSocketServerOpen => { try_or_throw!(self.machine_st, self.socket_server_open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSocketServerAccept(_) => { + &Instruction::CallSocketServerAccept => { try_or_throw!(self.machine_st, self.socket_server_accept()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteSocketServerAccept(_) => { + &Instruction::ExecuteSocketServerAccept => { try_or_throw!(self.machine_st, self.socket_server_accept()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSocketServerClose(_) => { + &Instruction::CallSocketServerClose => { try_or_throw!(self.machine_st, self.socket_server_close()); self.machine_st.p += 1; } - &Instruction::ExecuteSocketServerClose(_) => { + &Instruction::ExecuteSocketServerClose => { try_or_throw!(self.machine_st, self.socket_server_close()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallTLSAcceptClient(_) => { + &Instruction::CallTLSAcceptClient => { try_or_throw!(self.machine_st, self.tls_accept_client()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTLSAcceptClient(_) => { + &Instruction::ExecuteTLSAcceptClient => { try_or_throw!(self.machine_st, self.tls_accept_client()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallTLSClientConnect(_) => { + &Instruction::CallTLSClientConnect => { try_or_throw!(self.machine_st, self.tls_client_connect()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTLSClientConnect(_) => { + &Instruction::ExecuteTLSClientConnect => { try_or_throw!(self.machine_st, self.tls_client_connect()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSucceed(_) => { + &Instruction::CallSucceed => { self.machine_st.p += 1; } - &Instruction::ExecuteSucceed(_) => { + &Instruction::ExecuteSucceed => { self.machine_st.p = self.machine_st.cp; } - &Instruction::CallTermAttributedVariables(_) => { + &Instruction::CallTermAttributedVariables => { self.term_attributed_variables(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTermAttributedVariables(_) => { + &Instruction::ExecuteTermAttributedVariables => { self.term_attributed_variables(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallTermVariables(_) => { + &Instruction::CallTermVariables => { self.term_variables(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTermVariables(_) => { + &Instruction::ExecuteTermVariables => { self.term_variables(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallTermVariablesUnderMaxDepth(_) => { + &Instruction::CallTermVariablesUnderMaxDepth => { self.term_variables_under_max_depth(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteTermVariablesUnderMaxDepth(_) => { + &Instruction::ExecuteTermVariablesUnderMaxDepth => { self.term_variables_under_max_depth(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallTruncateLiftedHeapTo(_) => { + &Instruction::CallTruncateLiftedHeapTo => { self.truncate_lifted_heap_to(); self.machine_st.p += 1; } - &Instruction::ExecuteTruncateLiftedHeapTo(_) => { + &Instruction::ExecuteTruncateLiftedHeapTo => { self.truncate_lifted_heap_to(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallUnifyWithOccursCheck(_) => { + &Instruction::CallUnifyWithOccursCheck => { self.unify_with_occurs_check(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteUnifyWithOccursCheck(_) => { + &Instruction::ExecuteUnifyWithOccursCheck => { self.unify_with_occurs_check(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallUnwindEnvironments(_) => { + &Instruction::CallUnwindEnvironments => { if !self.unwind_environments() { self.machine_st.p += 1; } } - &Instruction::ExecuteUnwindEnvironments(_) => { + &Instruction::ExecuteUnwindEnvironments => { if !self.unwind_environments() { self.machine_st.p = self.machine_st.cp; } } - &Instruction::CallUnwindStack(_) | &Instruction::ExecuteUnwindStack(_) => { + &Instruction::CallUnwindStack | &Instruction::ExecuteUnwindStack => { self.machine_st.unwind_stack(); self.machine_st.backtrack(); } - &Instruction::CallWAMInstructions(_) => { + &Instruction::CallWAMInstructions => { try_or_throw!(self.machine_st, self.wam_instructions()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteWAMInstructions(_) => { + &Instruction::ExecuteWAMInstructions => { try_or_throw!(self.machine_st, self.wam_instructions()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInlinedInstructions(_) => { + &Instruction::CallInlinedInstructions => { self.inlined_instructions(); self.machine_st.p += 1; } - &Instruction::ExecuteInlinedInstructions(_) => { + &Instruction::ExecuteInlinedInstructions => { self.inlined_instructions(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallWriteTerm(_) => { + &Instruction::CallWriteTerm => { try_or_throw!(self.machine_st, self.write_term()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteWriteTerm(_) => { + &Instruction::ExecuteWriteTerm => { try_or_throw!(self.machine_st, self.write_term()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallWriteTermToChars(_) => { + &Instruction::CallWriteTermToChars => { try_or_throw!(self.machine_st, self.write_term_to_chars()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteWriteTermToChars(_) => { + &Instruction::ExecuteWriteTermToChars => { try_or_throw!(self.machine_st, self.write_term_to_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallScryerPrologVersion(_) => { + &Instruction::CallScryerPrologVersion => { self.scryer_prolog_version(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteScryerPrologVersion(_) => { + &Instruction::ExecuteScryerPrologVersion => { self.scryer_prolog_version(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoRandomByte(_) => { + &Instruction::CallCryptoRandomByte => { self.crypto_random_byte(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoRandomByte(_) => { + &Instruction::ExecuteCryptoRandomByte => { self.crypto_random_byte(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoDataHash(_) => { + &Instruction::CallCryptoDataHash => { self.crypto_data_hash(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoDataHash(_) => { + &Instruction::ExecuteCryptoDataHash => { self.crypto_data_hash(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoDataHKDF(_) => { + &Instruction::CallCryptoDataHKDF => { self.crypto_data_hkdf(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoDataHKDF(_) => { + &Instruction::ExecuteCryptoDataHKDF => { self.crypto_data_hkdf(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoPasswordHash(_) => { + &Instruction::CallCryptoPasswordHash => { self.crypto_password_hash(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoPasswordHash(_) => { + &Instruction::ExecuteCryptoPasswordHash => { self.crypto_password_hash(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoDataEncrypt(_) => { + &Instruction::CallCryptoDataEncrypt => { self.crypto_data_encrypt(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoDataEncrypt(_) => { + &Instruction::ExecuteCryptoDataEncrypt => { self.crypto_data_encrypt(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoDataDecrypt(_) => { + &Instruction::CallCryptoDataDecrypt => { self.crypto_data_decrypt(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoDataDecrypt(_) => { + &Instruction::ExecuteCryptoDataDecrypt => { self.crypto_data_decrypt(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCryptoCurveScalarMult(_) => { + &Instruction::CallCryptoCurveScalarMult => { self.crypto_curve_scalar_mult(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCryptoCurveScalarMult(_) => { + &Instruction::ExecuteCryptoCurveScalarMult => { self.crypto_curve_scalar_mult(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallEd25519Sign(_) => { + &Instruction::CallEd25519Sign => { self.ed25519_sign(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteEd25519Sign(_) => { + &Instruction::ExecuteEd25519Sign => { self.ed25519_sign(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallEd25519Verify(_) => { + &Instruction::CallEd25519Verify => { self.ed25519_verify(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteEd25519Verify(_) => { + &Instruction::ExecuteEd25519Verify => { self.ed25519_verify(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallEd25519NewKeyPair(_) => { + &Instruction::CallEd25519NewKeyPair => { self.ed25519_new_key_pair(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteEd25519NewKeyPair(_) => { + &Instruction::ExecuteEd25519NewKeyPair => { self.ed25519_new_key_pair(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallEd25519KeyPairPublicKey(_) => { + &Instruction::CallEd25519KeyPairPublicKey => { self.ed25519_key_pair_public_key(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteEd25519KeyPairPublicKey(_) => { + &Instruction::ExecuteEd25519KeyPairPublicKey => { self.ed25519_key_pair_public_key(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCurve25519ScalarMult(_) => { + &Instruction::CallCurve25519ScalarMult => { self.curve25519_scalar_mult(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCurve25519ScalarMult(_) => { + &Instruction::ExecuteCurve25519ScalarMult => { self.curve25519_scalar_mult(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallFirstNonOctet(_) => { + &Instruction::CallFirstNonOctet => { self.first_non_octet(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteFirstNonOctet(_) => { + &Instruction::ExecuteFirstNonOctet => { self.first_non_octet(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadHTML(_) => { + &Instruction::CallLoadHTML => { self.load_html(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadHTML(_) => { + &Instruction::ExecuteLoadHTML => { self.load_html(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadXML(_) => { + &Instruction::CallLoadXML => { self.load_xml(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadXML(_) => { + &Instruction::ExecuteLoadXML => { self.load_xml(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallGetEnv(_) => { + &Instruction::CallGetEnv => { self.get_env(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetEnv(_) => { + &Instruction::ExecuteGetEnv => { self.get_env(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSetEnv(_) => { + &Instruction::CallSetEnv => { self.set_env(); self.machine_st.p += 1; } - &Instruction::ExecuteSetEnv(_) => { + &Instruction::ExecuteSetEnv => { self.set_env(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallUnsetEnv(_) => { + &Instruction::CallUnsetEnv => { self.unset_env(); self.machine_st.p += 1; } - &Instruction::ExecuteUnsetEnv(_) => { + &Instruction::ExecuteUnsetEnv => { self.unset_env(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallShell(_) => { + &Instruction::CallShell => { self.shell(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteShell(_) => { + &Instruction::ExecuteShell => { self.shell(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPID(_) => { + &Instruction::CallPID => { self.pid(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePID(_) => { + &Instruction::ExecutePID => { self.pid(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCharsBase64(_) => { + &Instruction::CallCharsBase64 => { try_or_throw!(self.machine_st, self.chars_base64()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCharsBase64(_) => { + &Instruction::ExecuteCharsBase64 => { try_or_throw!(self.machine_st, self.chars_base64()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDevourWhitespace(_) => { + &Instruction::CallDevourWhitespace => { try_or_throw!(self.machine_st, self.devour_whitespace()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDevourWhitespace(_) => { + &Instruction::ExecuteDevourWhitespace => { try_or_throw!(self.machine_st, self.devour_whitespace()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallIsSTOEnabled(_) => { + &Instruction::CallIsSTOEnabled => { self.is_sto_enabled(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteIsSTOEnabled(_) => { + &Instruction::ExecuteIsSTOEnabled => { self.is_sto_enabled(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallSetSTOAsUnify(_) => { + &Instruction::CallSetSTOAsUnify => { self.set_sto_as_unify(); self.machine_st.p += 1; } - &Instruction::ExecuteSetSTOAsUnify(_) => { + &Instruction::ExecuteSetSTOAsUnify => { self.set_sto_as_unify(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallSetNSTOAsUnify(_) => { + &Instruction::CallSetNSTOAsUnify => { self.set_nsto_as_unify(); self.machine_st.p += 1; } - &Instruction::ExecuteSetNSTOAsUnify(_) => { + &Instruction::ExecuteSetNSTOAsUnify => { self.set_nsto_as_unify(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallSetSTOWithErrorAsUnify(_) => { + &Instruction::CallSetSTOWithErrorAsUnify => { self.set_sto_with_error_as_unify(); self.machine_st.p += 1; } - &Instruction::ExecuteSetSTOWithErrorAsUnify(_) => { + &Instruction::ExecuteSetSTOWithErrorAsUnify => { self.set_sto_with_error_as_unify(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallHomeDirectory(_) => { + &Instruction::CallHomeDirectory => { self.home_directory(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteHomeDirectory(_) => { + &Instruction::ExecuteHomeDirectory => { self.home_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDebugHook(_) => { + &Instruction::CallDebugHook => { self.debug_hook(); self.machine_st.p += 1; } - &Instruction::ExecuteDebugHook(_) => { + &Instruction::ExecuteDebugHook => { self.debug_hook(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPopCount(_) => { + &Instruction::CallPopCount => { self.pop_count(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePopCount(_) => { + &Instruction::ExecutePopCount => { self.pop_count(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallAddDiscontiguousPredicate(_) => { + &Instruction::CallAddDiscontiguousPredicate => { try_or_throw!(self.machine_st, self.add_discontiguous_predicate()); self.machine_st.p += 1; } - &Instruction::ExecuteAddDiscontiguousPredicate(_) => { + &Instruction::ExecuteAddDiscontiguousPredicate => { try_or_throw!(self.machine_st, self.add_discontiguous_predicate()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAddDynamicPredicate(_) => { + &Instruction::CallAddDynamicPredicate => { try_or_throw!(self.machine_st, self.add_dynamic_predicate()); self.machine_st.p += 1; } - &Instruction::ExecuteAddDynamicPredicate(_) => { + &Instruction::ExecuteAddDynamicPredicate => { try_or_throw!(self.machine_st, self.add_dynamic_predicate()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAddMultifilePredicate(_) => { + &Instruction::CallAddMultifilePredicate => { try_or_throw!(self.machine_st, self.add_multifile_predicate()); self.machine_st.p += 1; } - &Instruction::ExecuteAddMultifilePredicate(_) => { + &Instruction::ExecuteAddMultifilePredicate => { try_or_throw!(self.machine_st, self.add_multifile_predicate()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAddGoalExpansionClause(_) => { + &Instruction::CallAddGoalExpansionClause => { try_or_throw!(self.machine_st, self.add_goal_expansion_clause()); self.machine_st.p += 1; } - &Instruction::ExecuteAddGoalExpansionClause(_) => { + &Instruction::ExecuteAddGoalExpansionClause => { try_or_throw!(self.machine_st, self.add_goal_expansion_clause()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAddTermExpansionClause(_) => { + &Instruction::CallAddTermExpansionClause => { try_or_throw!(self.machine_st, self.add_term_expansion_clause()); self.machine_st.p += 1; } - &Instruction::ExecuteAddTermExpansionClause(_) => { + &Instruction::ExecuteAddTermExpansionClause => { try_or_throw!(self.machine_st, self.add_term_expansion_clause()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAddInSituFilenameModule(_) => { + &Instruction::CallAddInSituFilenameModule => { try_or_throw!(self.machine_st, self.add_in_situ_filename_module()); self.machine_st.p += 1; } - &Instruction::ExecuteAddInSituFilenameModule(_) => { + &Instruction::ExecuteAddInSituFilenameModule => { try_or_throw!(self.machine_st, self.add_in_situ_filename_module()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallClauseToEvacuable(_) => { + &Instruction::CallClauseToEvacuable => { try_or_throw!(self.machine_st, self.clause_to_evacuable()); self.machine_st.p += 1; } - &Instruction::ExecuteClauseToEvacuable(_) => { + &Instruction::ExecuteClauseToEvacuable => { try_or_throw!(self.machine_st, self.clause_to_evacuable()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallScopedClauseToEvacuable(_) => { + &Instruction::CallScopedClauseToEvacuable => { try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable()); self.machine_st.p += 1; } - &Instruction::ExecuteScopedClauseToEvacuable(_) => { + &Instruction::ExecuteScopedClauseToEvacuable => { try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallConcludeLoad(_) => { + &Instruction::CallConcludeLoad => { try_or_throw!(self.machine_st, self.conclude_load()); self.machine_st.p += 1; } - &Instruction::ExecuteConcludeLoad(_) => { + &Instruction::ExecuteConcludeLoad => { try_or_throw!(self.machine_st, self.conclude_load()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallDeclareModule(_) => { + &Instruction::CallDeclareModule => { try_or_throw!(self.machine_st, self.declare_module()); self.machine_st.p += 1; } - &Instruction::ExecuteDeclareModule(_) => { + &Instruction::ExecuteDeclareModule => { try_or_throw!(self.machine_st, self.declare_module()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallLoadCompiledLibrary(_) => { + &Instruction::CallLoadCompiledLibrary => { try_or_throw!(self.machine_st, self.load_compiled_library()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadCompiledLibrary(_) => { + &Instruction::ExecuteLoadCompiledLibrary => { try_or_throw!(self.machine_st, self.load_compiled_library()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadContextSource(_) => { + &Instruction::CallLoadContextSource => { self.load_context_source(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadContextSource(_) => { + &Instruction::ExecuteLoadContextSource => { self.load_context_source(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadContextFile(_) => { + &Instruction::CallLoadContextFile => { self.load_context_file(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadContextFile(_) => { + &Instruction::ExecuteLoadContextFile => { self.load_context_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadContextDirectory(_) => { + &Instruction::CallLoadContextDirectory => { self.load_context_directory(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadContextDirectory(_) => { + &Instruction::ExecuteLoadContextDirectory => { self.load_context_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadContextModule(_) => { + &Instruction::CallLoadContextModule => { self.load_context_module(self.machine_st.registers[1]); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadContextModule(_) => { + &Instruction::ExecuteLoadContextModule => { self.load_context_module(self.machine_st.registers[1]); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallLoadContextStream(_) => { + &Instruction::CallLoadContextStream => { self.load_context_stream(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteLoadContextStream(_) => { + &Instruction::ExecuteLoadContextStream => { self.load_context_stream(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPopLoadContext(_) => { + &Instruction::CallPopLoadContext => { self.pop_load_context(); self.machine_st.p += 1; } - &Instruction::ExecutePopLoadContext(_) => { + &Instruction::ExecutePopLoadContext => { self.pop_load_context(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPopLoadStatePayload(_) => { + &Instruction::CallPopLoadStatePayload => { self.pop_load_state_payload(); self.machine_st.p += 1; } - &Instruction::ExecutePopLoadStatePayload(_) => { + &Instruction::ExecutePopLoadStatePayload => { self.pop_load_state_payload(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPushLoadContext(_) => { + &Instruction::CallPushLoadContext => { try_or_throw!(self.machine_st, self.push_load_context()); self.machine_st.p += 1; } - &Instruction::ExecutePushLoadContext(_) => { + &Instruction::ExecutePushLoadContext => { try_or_throw!(self.machine_st, self.push_load_context()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPushLoadStatePayload(_) => { + &Instruction::CallPushLoadStatePayload => { self.push_load_state_payload(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePushLoadStatePayload(_) => { + &Instruction::ExecutePushLoadStatePayload => { self.push_load_state_payload(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallUseModule(_) => { + &Instruction::CallUseModule => { try_or_throw!(self.machine_st, self.use_module()); self.machine_st.p += 1; } - &Instruction::ExecuteUseModule(_) => { + &Instruction::ExecuteUseModule => { try_or_throw!(self.machine_st, self.use_module()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallBuiltInProperty(_) => { + &Instruction::CallBuiltInProperty => { self.builtin_property(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteBuiltInProperty(_) => { + &Instruction::ExecuteBuiltInProperty => { self.builtin_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallMetaPredicateProperty(_) => { + &Instruction::CallMetaPredicateProperty => { self.meta_predicate_property(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteMetaPredicateProperty(_) => { + &Instruction::ExecuteMetaPredicateProperty => { self.meta_predicate_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallMultifileProperty(_) => { + &Instruction::CallMultifileProperty => { self.multifile_property(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteMultifileProperty(_) => { + &Instruction::ExecuteMultifileProperty => { self.multifile_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDiscontiguousProperty(_) => { + &Instruction::CallDiscontiguousProperty => { self.discontiguous_property(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDiscontiguousProperty(_) => { + &Instruction::ExecuteDiscontiguousProperty => { self.discontiguous_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDynamicProperty(_) => { + &Instruction::CallDynamicProperty => { self.dynamic_property(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDynamicProperty(_) => { + &Instruction::ExecuteDynamicProperty => { self.dynamic_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallAbolishClause(_) => { + &Instruction::CallAbolishClause => { try_or_throw!(self.machine_st, self.abolish_clause()); self.machine_st.p += 1; } - &Instruction::ExecuteAbolishClause(_) => { + &Instruction::ExecuteAbolishClause => { try_or_throw!(self.machine_st, self.abolish_clause()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAsserta(_) => { + &Instruction::CallAsserta => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend)); self.machine_st.p += 1; } - &Instruction::ExecuteAsserta(_) => { + &Instruction::ExecuteAsserta => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend)); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAssertz(_) => { + &Instruction::CallAssertz => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append)); self.machine_st.p += 1; } - &Instruction::ExecuteAssertz(_) => { + &Instruction::ExecuteAssertz => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append)); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallRetract(_) => { + &Instruction::CallRetract => { try_or_throw!(self.machine_st, self.retract_clause()); self.machine_st.p += 1; } - &Instruction::ExecuteRetract(_) => { + &Instruction::ExecuteRetract => { try_or_throw!(self.machine_st, self.retract_clause()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallIsConsistentWithTermQueue(_) => { + &Instruction::CallIsConsistentWithTermQueue => { try_or_throw!(self.machine_st, self.is_consistent_with_term_queue()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteIsConsistentWithTermQueue(_) => { + &Instruction::ExecuteIsConsistentWithTermQueue => { try_or_throw!(self.machine_st, self.is_consistent_with_term_queue()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::CallFlushTermQueue(_) => { + &Instruction::CallFlushTermQueue => { try_or_throw!(self.machine_st, self.flush_term_queue()); self.machine_st.p += 1; } - &Instruction::ExecuteFlushTermQueue(_) => { + &Instruction::ExecuteFlushTermQueue => { try_or_throw!(self.machine_st, self.flush_term_queue()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallRemoveModuleExports(_) => { + &Instruction::CallRemoveModuleExports => { try_or_throw!(self.machine_st, self.remove_module_exports()); self.machine_st.p += 1; } - &Instruction::ExecuteRemoveModuleExports(_) => { + &Instruction::ExecuteRemoveModuleExports => { try_or_throw!(self.machine_st, self.remove_module_exports()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallAddNonCountedBacktracking(_) => { + &Instruction::CallAddNonCountedBacktracking => { try_or_throw!(self.machine_st, self.add_non_counted_backtracking()); self.machine_st.p += 1; } - &Instruction::ExecuteAddNonCountedBacktracking(_) => { + &Instruction::ExecuteAddNonCountedBacktracking => { try_or_throw!(self.machine_st, self.add_non_counted_backtracking()); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallPredicateDefined(_) => { + &Instruction::CallPredicateDefined => { self.machine_st.fail = !self.predicate_defined(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePredicateDefined(_) => { + &Instruction::ExecutePredicateDefined => { self.machine_st.fail = !self.predicate_defined(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallStripModule(_) => { + &Instruction::CallStripModule => { let (module_loc, qualified_goal) = self.machine_st.strip_module( self.machine_st.registers[1], self.machine_st.registers[2], @@ -5002,7 +5004,7 @@ impl Machine { step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteStripModule(_) => { + &Instruction::ExecuteStripModule => { let (module_loc, qualified_goal) = self.machine_st.strip_module( self.machine_st.registers[1], self.machine_st.registers[2], @@ -5026,31 +5028,31 @@ impl Machine { step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPrepareCallClause(arity, _) => { + &Instruction::CallPrepareCallClause(arity) => { try_or_throw!(self.machine_st, self.prepare_call_clause(arity)); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePrepareCallClause(arity, _) => { + &Instruction::ExecutePrepareCallClause(arity) => { try_or_throw!(self.machine_st, self.prepare_call_clause(arity)); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallCompileInlineOrExpandedGoal(_) => { + &Instruction::CallCompileInlineOrExpandedGoal => { try_or_throw!(self.machine_st, self.compile_inline_or_expanded_goal()); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteCompileInlineOrExpandedGoal(_) => { + &Instruction::ExecuteCompileInlineOrExpandedGoal => { try_or_throw!(self.machine_st, self.compile_inline_or_expanded_goal()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallIsExpandedOrInlined(_) => { + &Instruction::CallIsExpandedOrInlined => { self.machine_st.fail = !self.is_expanded_or_inlined(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteIsExpandedOrInlined(_) => { + &Instruction::ExecuteIsExpandedOrInlined => { self.machine_st.fail = !self.is_expanded_or_inlined(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInlineCallN(arity, _) => { + &Instruction::CallInlineCallN(arity) => { let call_at_index = |wam: &mut Machine, name, arity, ptr| { wam.try_call(name, arity, ptr) }; @@ -5066,7 +5068,7 @@ impl Machine { ); } } - &Instruction::ExecuteInlineCallN(arity, _) => { + &Instruction::ExecuteInlineCallN(arity) => { let call_at_index = |wam: &mut Machine, name, arity, ptr| { wam.try_execute(name, arity, ptr) }; @@ -5082,7 +5084,7 @@ impl Machine { ); } } - &Instruction::CallGetClauseP(_) => { + &Instruction::CallGetClauseP => { let module_name = cell_as_atom!(self.deref_register(3)); let (n, p) = self.get_clause_p(module_name); @@ -5098,7 +5100,7 @@ impl Machine { step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetClauseP(_) => { + &Instruction::ExecuteGetClauseP => { let module_name = cell_as_atom!(self.deref_register(3)); let (n, p) = self.get_clause_p(module_name); @@ -5114,7 +5116,7 @@ impl Machine { step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInvokeClauseAtP(_) => { + &Instruction::CallInvokeClauseAtP => { let key_cell = self.machine_st.registers[1]; let key = self.machine_st.name_and_arity_from_heap(key_cell).unwrap(); @@ -5159,7 +5161,7 @@ impl Machine { self.machine_st.call_at_index(2, p); } - &Instruction::ExecuteInvokeClauseAtP(_) => { + &Instruction::ExecuteInvokeClauseAtP => { let key_cell = self.machine_st.registers[1]; let key = self.machine_st.name_and_arity_from_heap(key_cell).unwrap(); @@ -5204,51 +5206,51 @@ impl Machine { self.machine_st.execute_at_index(2, p); } - &Instruction::CallGetFromAttributedVarList(_) => { + &Instruction::CallGetFromAttributedVarList => { self.get_from_attributed_variable_list(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetFromAttributedVarList(_) => { + &Instruction::ExecuteGetFromAttributedVarList => { self.get_from_attributed_variable_list(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallPutToAttributedVarList(_) => { + &Instruction::CallPutToAttributedVarList => { self.put_to_attributed_variable_list(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecutePutToAttributedVarList(_) => { + &Instruction::ExecutePutToAttributedVarList => { self.put_to_attributed_variable_list(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDeleteFromAttributedVarList(_) => { + &Instruction::CallDeleteFromAttributedVarList => { self.delete_from_attributed_variable_list(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteDeleteFromAttributedVarList(_) => { + &Instruction::ExecuteDeleteFromAttributedVarList => { self.delete_from_attributed_variable_list(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallDeleteAllAttributesFromVar(_) => { + &Instruction::CallDeleteAllAttributesFromVar => { self.delete_all_attributes_from_var(); self.machine_st.p += 1; } - &Instruction::ExecuteDeleteAllAttributesFromVar(_) => { + &Instruction::ExecuteDeleteAllAttributesFromVar => { self.delete_all_attributes_from_var(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallUnattributedVar(_) => { + &Instruction::CallUnattributedVar => { self.machine_st.unattributed_var(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteUnattributedVar(_) => { + &Instruction::ExecuteUnattributedVar => { self.machine_st.unattributed_var(); self.machine_st.p = self.machine_st.cp; } - &Instruction::CallGetDBRefs(_) => { + &Instruction::CallGetDBRefs => { self.get_db_refs(); step_or_fail!(self, self.machine_st.p += 1); } - &Instruction::ExecuteGetDBRefs(_) => { + &Instruction::ExecuteGetDBRefs => { self.get_db_refs(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 3d0a638a..56aa88eb 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -444,10 +444,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let tl = preprocessor.try_term_to_tl(self, term)?; Ok(match tl { - TopLevel::Fact(fact) => PredicateClause::Fact(fact), - TopLevel::Rule(rule) => PredicateClause::Rule(rule), - TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact), - _ => unreachable!(), + TopLevel::Fact(fact, var_data) => PredicateClause::Fact(fact, var_data), + TopLevel::Rule(rule, var_data) => PredicateClause::Rule(rule, var_data), }) } diff --git a/src/machine/loader.rs b/src/machine/loader.rs index bb093a0e..51815c7e 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1428,7 +1428,7 @@ impl MachineState { } } (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => { - term_stack.push(Term::Var(Cell::default(), Var::Generated(h))); + term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h)))); } (HeapCellValueTag::Cons | HeapCellValueTag::CStr | HeapCellValueTag::Fixnum | HeapCellValueTag::Char | HeapCellValueTag::F64) => { diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index afa2bea2..fdc60e0b 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -2,7 +2,6 @@ use crate::parser::ast::*; use crate::arena::*; use crate::atom_table::*; -use crate::fixtures::*; use crate::forms::*; use crate::machine::loader::*; use crate::machine::machine_state::*; @@ -227,8 +226,8 @@ impl CodeIndex { } } -pub(crate) type HeapVarDict = IndexMap; -pub(crate) type AllocVarDict = IndexMap; +pub(crate) type HeapVarDict = IndexMap; +// pub(crate) type AllocVarDict = IndexMap; pub(crate) type GlobalVarDir = IndexMap), FxBuildHasher>; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 6d0de7d9..26d0309b 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -500,13 +500,13 @@ impl MachineState { pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult { fn push_var_eq_functors<'a>( heap: &mut Heap, - iter: impl Iterator, + iter: impl Iterator, atom_tbl: &mut AtomTable, ) -> Vec { let mut list_of_var_eqs = vec![]; for (var, binding) in iter { - let var_atom = atom_tbl.build_with(&var.to_string()); + let var_atom = atom_tbl.build_with(&var.borrow().to_string()); let h = heap.len(); heap.push(atom_as_cell!(atom!("="), 2)); @@ -672,7 +672,7 @@ impl MachineState { let printer = match self.try_from_list(self.registers[6], stub_gen) { Ok(addrs) => { - let mut var_names: IndexMap = IndexMap::new(); + let mut var_names: IndexMap = IndexMap::new(); for addr in addrs { read_heap_cell!(addr, @@ -690,18 +690,18 @@ impl MachineState { read_heap_cell!(atom, (HeapCellValueTag::Char, c) => { - var_names.insert(var, Var::from(c.to_string())); + var_names.insert(var, VarPtr::from(c.to_string())); } (HeapCellValueTag::Atom, (name, _arity)) => { debug_assert_eq!(_arity, 0); - var_names.insert(var, Var::from(name.as_str())); + var_names.insert(var, VarPtr::from(name.as_str())); } (HeapCellValueTag::Str, s) => { let (name, arity) = cell_as_atom_cell!(self.heap[s]) .get_name_and_arity(); debug_assert_eq!(arity, 0); - var_names.insert(var, Var::from(name.as_str())); + var_names.insert(var, VarPtr::from(name.as_str())); } _ => { unreachable!(); diff --git a/src/machine/mod.rs b/src/machine/mod.rs index dab4c54c..ddf64d34 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -68,7 +68,7 @@ pub struct Machine { pub(super) user_error: Stream, pub(super) load_contexts: Vec, pub(super) runtime: Runtime, - pub(super) foreign_function_table: ForeignFunctionTable, + pub(super) foreign_function_table: ForeignFunctionTable, } #[derive(Debug)] @@ -365,46 +365,46 @@ impl Machine { Instruction::BreakFromDispatchLoop, Instruction::InstallVerifyAttr, Instruction::VerifyAttrInterrupt, - Instruction::ExecuteTermGreaterThan(0), - Instruction::ExecuteTermLessThan(0), - Instruction::ExecuteTermGreaterThanOrEqual(0), - Instruction::ExecuteTermLessThanOrEqual(0), - Instruction::ExecuteTermEqual(0), - Instruction::ExecuteTermNotEqual(0), - Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2)), 0), - Instruction::ExecuteAcyclicTerm(0), - Instruction::ExecuteArg(0), - Instruction::ExecuteCompare(0), - Instruction::ExecuteCopyTerm(0), - Instruction::ExecuteFunctor(0), - Instruction::ExecuteGround(0), - Instruction::ExecuteKeySort(0), - Instruction::ExecuteRead(0), - Instruction::ExecuteSort(0), - Instruction::ExecuteN(1, 0), - Instruction::ExecuteN(2, 0), - Instruction::ExecuteN(3, 0), - Instruction::ExecuteN(4, 0), - Instruction::ExecuteN(5, 0), - Instruction::ExecuteN(6, 0), - Instruction::ExecuteN(7, 0), - Instruction::ExecuteN(8, 0), - Instruction::ExecuteN(9, 0), - Instruction::ExecuteIsAtom(temp_v!(1), 0), - Instruction::ExecuteIsAtomic(temp_v!(1), 0), - Instruction::ExecuteIsCompound(temp_v!(1), 0), - Instruction::ExecuteIsInteger(temp_v!(1), 0), - Instruction::ExecuteIsNumber(temp_v!(1), 0), - Instruction::ExecuteIsRational(temp_v!(1), 0), - Instruction::ExecuteIsFloat(temp_v!(1), 0), - Instruction::ExecuteIsNonVar(temp_v!(1), 0), - Instruction::ExecuteIsVar(temp_v!(1), 0) + Instruction::ExecuteTermGreaterThan, + Instruction::ExecuteTermLessThan, + Instruction::ExecuteTermGreaterThanOrEqual, + Instruction::ExecuteTermLessThanOrEqual, + Instruction::ExecuteTermEqual, + Instruction::ExecuteTermNotEqual, + Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), + Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), + Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), + Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), + Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), + Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), + Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2))), + Instruction::ExecuteAcyclicTerm, + Instruction::ExecuteArg, + Instruction::ExecuteCompare, + Instruction::ExecuteCopyTerm, + Instruction::ExecuteFunctor, + Instruction::ExecuteGround, + Instruction::ExecuteKeySort, + Instruction::ExecuteRead, + Instruction::ExecuteSort, + Instruction::ExecuteN(1), + Instruction::ExecuteN(2), + Instruction::ExecuteN(3), + Instruction::ExecuteN(4), + Instruction::ExecuteN(5), + Instruction::ExecuteN(6), + Instruction::ExecuteN(7), + Instruction::ExecuteN(8), + Instruction::ExecuteN(9), + Instruction::ExecuteIsAtom(temp_v!(1)), + Instruction::ExecuteIsAtomic(temp_v!(1)), + Instruction::ExecuteIsCompound(temp_v!(1)), + Instruction::ExecuteIsInteger(temp_v!(1)), + Instruction::ExecuteIsNumber(temp_v!(1)), + Instruction::ExecuteIsRational(temp_v!(1)), + Instruction::ExecuteIsFloat(temp_v!(1)), + Instruction::ExecuteIsNonVar(temp_v!(1)), + Instruction::ExecuteIsVar(temp_v!(1)) ].into_iter()); for (p, instr) in self.code[impls_offset ..].iter().enumerate() { @@ -690,6 +690,8 @@ impl Machine { fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult { let compiled_tl_index = idx.p() as usize; + // println!("calling {}/{}", name.as_str(), arity); + match idx.tag() { IndexPtrTag::DynamicUndefined => { self.machine_st.fail = true; @@ -713,6 +715,8 @@ impl Machine { fn try_execute(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult { let compiled_tl_index = idx.p() as usize; + // println!("executing {}/{}", name.as_str(), arity); + match idx.tag() { IndexPtrTag::DynamicUndefined => { self.machine_st.fail = true; diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 02e0e29f..a0cab869 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -10,20 +10,8 @@ use crate::parser::ast::*; use indexmap::IndexSet; use std::cell::Cell; -use std::collections::VecDeque; use std::convert::TryFrom; -pub(crate) fn fold_by_str(terms: I, mut term: Term, sym: Atom) -> Term -where - I: DoubleEndedIterator, -{ - for prec in terms.rev() { - term = Term::Clause(Cell::default(), sym, vec![prec, term]); - } - - term -} - pub(crate) fn to_op_decl( prec: u16, spec: Atom, @@ -546,16 +534,15 @@ impl Preprocessor { } } - fn setup_fact(&mut self, term: Term) -> Result { + fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> { match term { Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => { - let mut classifier = VariableClassifier::new( + let classifier = VariableClassifier::new( self.settings.default_call_policy(), ); let (head, var_data) = classifier.classify_fact(term)?; - - Ok(Fact { head, var_data }) + Ok((Fact { head }, var_data)) } _ => Err(CompilationError::InadmissibleFact), } @@ -566,28 +553,22 @@ impl Preprocessor { loader: &mut Loader<'a, LS>, head: Term, body: Term, - ) -> Result { - let mut classifier = VariableClassifier::new( + ) -> Result<(Rule, VarData), CompilationError> { + let classifier = VariableClassifier::new( self.settings.default_call_policy(), ); - let (head, mut query_terms, var_data) = - classifier.classify_rule(loader, head, body)?; - - let clauses = query_terms.drain(1..).collect(); - let qt = query_terms.pop().unwrap(); + let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?; match head { - Term::Clause(_, name, terms) => Ok(Rule { - head: (name, terms, qt), + Term::Clause(_, name, terms) => Ok((Rule { + head: (name, terms), clauses, - var_data, - }), - Term::Literal(_, Literal::Atom(name)) => Ok(Rule { - head: (name, vec![], qt), + }, var_data)), + Term::Literal(_, Literal::Atom(name)) => Ok((Rule { + head: (name, vec![]), clauses, - var_data, - }), + }, var_data)), _ => Err(CompilationError::InvalidRuleHead), } } @@ -613,20 +594,29 @@ impl Preprocessor { term: Term, ) -> Result { match term { - Term::Clause(r, name, terms) => { + Term::Clause(r, name, mut terms) => { let is_rule = name == atom!(":-") && terms.len() == 2; if is_rule { - Ok(TopLevel::Rule(self.setup_rule(loader, terms[0], terms[1])?)) + let tail = terms.pop().unwrap(); + let head = terms.pop().unwrap(); + + let (rule, var_data) = self.setup_rule(loader, head, tail)?; + Ok(TopLevel::Rule(rule, var_data)) } else { let term = Term::Clause(r, name, terms); - Ok(TopLevel::Fact(self.setup_fact(term)?)) + let (fact, var_data) = self.setup_fact(term)?; + Ok(TopLevel::Fact(fact, var_data)) } } - term => Ok(TopLevel::Fact(self.setup_fact(term)?)), + term => { + let (fact, var_data) = self.setup_fact(term)?; + Ok(TopLevel::Fact(fact, var_data)) + } } } + /* fn try_terms_to_tls<'a, I: IntoIterator, LS: LoadState<'a>>( &mut self, loader: &mut Loader<'a, LS>, @@ -640,4 +630,5 @@ impl Preprocessor { Ok(results) } + */ } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index d26468da..7985f5fe 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1409,7 +1409,7 @@ impl Machine { let vars: Vec<_> = vars .union(&result.supp_vars) // difference + union does not cancel. - .map(|v| Term::Var(Cell::default(), Var::Generated(v.get_value()))) + .map(|v| Term::Var(Cell::default(), VarPtr::from(format!("_{}", v.get_value())))) .collect(); let helper_clause_loc = self.code.len(); @@ -1571,8 +1571,8 @@ impl Machine { #[inline(always)] pub(crate) fn is_reset_cont_marker(&self, p: usize) -> bool { match &self.code[p] { - &Instruction::CallResetContinuationMarker(_) | - &Instruction::ExecuteResetContinuationMarker(_) => true, + &Instruction::CallResetContinuationMarker | + &Instruction::ExecuteResetContinuationMarker => true, _ => false } } @@ -4911,9 +4911,7 @@ impl Machine { let p_functor = self.deref_register(2); - let p = to_local_code_ptr(&self.machine_st.heap, p_functor).unwrap(); - - let num_cells = *self.code[p].perm_vars_mut().unwrap(); + let num_cells = self.machine_st.stack.index_and_frame(e).prelude.num_cells; let mut addrs = vec![]; for idx in 1..num_cells + 1 { diff --git a/src/macros.rs b/src/macros.rs index 85e2e086..c1f1552f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -540,23 +540,7 @@ macro_rules! functor_term { macro_rules! compare_number_instr { ($cmp: expr, $at_1: expr, $at_2: expr) => {{ $cmp.set_terms($at_1, $at_2); - call_clause!(ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)), 0) - }}; -} - -macro_rules! call_clause { - ($clause_type:expr, $pvs:expr) => {{ - let mut instr = $clause_type.to_instr(); - instr.perm_vars_mut().map(|pvs| *pvs = $pvs); - instr - }}; -} - -macro_rules! call_clause_by_default { - ($clause_type:expr, $pvs:expr) => {{ - let mut instr = $clause_type.to_instr().to_default(); - instr.perm_vars_mut().map(|pvs| *pvs = $pvs); - instr + ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)).to_instr() }}; } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 73c91c6a..283a9dc0 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -4,11 +4,11 @@ use crate::machine::machine_indices::*; use crate::parser::char_reader::*; use crate::types::HeapCellValueTag; -use std::cell::Cell; +use std::cell::{Cell, Ref, RefCell, RefMut}; use std::fmt; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::io::{Error as IOError}; -use std::ops::Neg; +use std::ops::{Deref, Neg}; use std::rc::Rc; use std::vec::Vec; @@ -572,23 +572,89 @@ impl Literal { } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct VarPtr(Rc>); + +impl Hash for VarPtr { + #[inline(always)] + fn hash(&self, hasher: &mut H) { + self.borrow().hash(hasher) + } +} + +impl Deref for VarPtr { + type Target = RefCell; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + self.0.deref() + } +} + +impl VarPtr { + #[inline(always)] + pub(crate) fn borrow(&self) -> Ref<'_, Var> { + self.0.borrow() + } + + #[inline(always)] + pub(crate) fn borrow_mut(&self) -> RefMut<'_, Var> { + self.0.borrow_mut() + } + + pub(crate) fn to_var_num(&self) -> Option { + match *self.borrow() { + Var::Generated(var_num) => Some(var_num), + _ => None, + } + } + + pub(crate) fn set(&self, var: Var) { + let mut var_ref = self.borrow_mut(); + *var_ref = var; + } +} + +impl From for VarPtr { + #[inline(always)] + fn from(value: Var) -> VarPtr { + VarPtr(Rc::new(RefCell::new(value))) + } +} + +impl From for VarPtr { + #[inline(always)] + fn from(value: String) -> VarPtr { + VarPtr::from(Var::from(value)) + } +} + +impl From<&str> for VarPtr { + #[inline(always)] + fn from(value: &str) -> VarPtr { + VarPtr::from(value.to_owned()) + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Var { Generated(usize), - Named(Rc), + InSitu(usize), + Named(String), } impl From for Var { #[inline(always)] fn from(value: String) -> Var { - Var::Named(Rc::new(value)) + Var::Named(value) } } impl From<&str> for Var { #[inline(always)] fn from(value: &str) -> Var { - Var::Named(Rc::new(value.to_owned())) + Var::Named(value.to_owned()) } } @@ -596,16 +662,16 @@ impl Var { #[inline(always)] pub fn as_str(&self) -> Option<&str> { match self { - Var::Generated(_) => None, Var::Named(value) => Some(&value), + _ => None, } } #[inline(always)] pub fn to_string(&self) -> String { match self { - Var::Generated(n) => format!("_{}", n), - Var::Named(value) => value.to_string(), + Var::InSitu(n) | Var::Generated(n) => format!("_{}", n), + Var::Named(value) => value.to_owned(), } } } @@ -620,7 +686,7 @@ pub enum Term { // other PartialString variants in as_partial_string. PartialString(Cell, String, Box), CompleteString(Cell, Atom), - Var(Cell, Var), + Var(Cell, VarPtr), } impl Term { diff --git a/src/parser/parser.rs b/src/parser/parser.rs index ce633b94..021147ea 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -426,7 +426,7 @@ impl<'a, R: CharRead> Parser<'a, R> { if v.trim() == "_" { self.terms.push(Term::AnonVar); } else { - self.terms.push(Term::Var(Cell::default(), Var::from(v))); + self.terms.push(Term::Var(Cell::default(), VarPtr::from(v))); } TokenType::Term diff --git a/src/read.rs b/src/read.rs index c8743c2f..8f70eeec 100644 --- a/src/read.rs +++ b/src/read.rs @@ -317,7 +317,7 @@ impl<'a, 'b> TermWriter<'a, 'b> { fn write_term_to_heap(mut self, term: &'a Term) -> Result { let heap_loc = self.heap.len(); - for term in breadth_first_iter(term, true) { + for term in breadth_first_iter(term, RootIterationPolicy::Iterated) { let h = self.heap.len(); match &term { @@ -372,9 +372,9 @@ impl<'a, 'b> TermWriter<'a, 'b> { let addr = self.term_as_addr(&term, h); self.heap.push(addr); } - &TermRef::Var(Level::Root, _, ref var) => { + &TermRef::Var(Level::Root, _, ref var_ptr) => { let addr = self.term_as_addr(&term, h); - self.var_dict.insert(var.clone(), heap_loc_as_cell!(h)); + self.var_dict.insert(var_ptr.clone(), heap_loc_as_cell!(h)); self.heap.push(addr); } &TermRef::AnonVar(_) => { diff --git a/src/targets.rs b/src/targets.rs index cbb469f9..56a4c127 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -29,11 +29,13 @@ pub(crate) trait CompilationTarget<'a> { fn argument_to_variable(r: RegType, r: usize) -> Instruction; fn argument_to_value(r: RegType, val: usize) -> Instruction; + fn unsafe_argument_to_value(r: RegType, val: usize) -> Instruction; fn move_to_register(r: RegType, val: usize) -> Instruction; fn subterm_to_variable(r: RegType) -> Instruction; fn subterm_to_value(r: RegType) -> Instruction; + fn unsafe_subterm_to_value(r: RegType) -> Instruction; fn clause_arg_to_instr(r: RegType) -> Instruction; } @@ -42,7 +44,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction { type Iterator = FactIterator<'a>; fn iter(term: &'a Term) -> Self::Iterator { - breadth_first_iter(term, false) // do not iterate over the root clause if one exists. + breadth_first_iter(term, RootIterationPolicy::NotIterated) } fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction { @@ -95,6 +97,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction { Instruction::GetValue(arg, val) } + fn unsafe_argument_to_value(arg: RegType, val: usize) -> Instruction { + Instruction::GetValue(arg, val) + } + fn subterm_to_variable(val: RegType) -> Instruction { Instruction::UnifyVariable(val) } @@ -103,6 +109,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction { Instruction::UnifyValue(val) } + fn unsafe_subterm_to_value(val: RegType) -> Instruction { + Instruction::UnifyLocalValue(val) + } + fn clause_arg_to_instr(val: RegType) -> Instruction { Instruction::UnifyVariable(val) } @@ -165,6 +175,13 @@ impl<'a> CompilationTarget<'a> for QueryInstruction { Instruction::PutValue(arg, val) } + fn unsafe_argument_to_value(arg: RegType, val: usize) -> Instruction { + match arg { + RegType::Perm(p) => Instruction::PutUnsafeValue(p, val), + RegType::Temp(_) => Instruction::PutValue(arg, val), + } + } + fn subterm_to_variable(val: RegType) -> Instruction { Instruction::SetVariable(val) } @@ -173,6 +190,10 @@ impl<'a> CompilationTarget<'a> for QueryInstruction { Instruction::SetValue(val) } + fn unsafe_subterm_to_value(val: RegType) -> Instruction { + Instruction::SetLocalValue(val) + } + fn clause_arg_to_instr(val: RegType) -> Instruction { Instruction::SetValue(val) } From 9ea6cb4cab4409e0f5cee917d37c3ff9ac0b0fc1 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 22 Jun 2023 18:28:10 -0600 Subject: [PATCH 14/40] backtrack on emission of unsafe register instructions on internal branches --- src/codegen.rs | 20 +-------------- src/debray_allocator.rs | 54 ++++++++++++++++++++++++++++------------ src/machine/disjuncts.rs | 9 ------- 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 794ec65b..000c0e65 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -103,25 +103,15 @@ impl BranchCodeStack { for (inner_idx, code) in self.stack[idx].iter_mut().enumerate() { if inner_idx + 1 == inner_len { - jump_span -= code.len() + 1; // = jump_span.saturating_sub(code.len() + 1); + jump_span -= code.len() + 1; } else { jump_span -= code.len() + 1; code.push_back(instr!("jmp_by_call", jump_span as usize)); - // saturate at 0 if underflow happens, which only - // happens when jump_span is no longer needed - // anyway. still, we don't want to panic at - // underflow. jump_span -= 1; } } } - - // eliminate terminating jump instruction in last arm of last - // branch. - // self.stack.last_mut() - // .and_then(|branch| branch.last_mut()) - // .map(|code| code.pop_back()); } fn pop_branch(&mut self, depth: usize, settings: CodeGenSettings) -> CodeDeque { @@ -1242,14 +1232,6 @@ impl<'b> CodeGenerator<'b> { code.extend(code_segment.into_iter()); } - /* - for line in &code { - println!("{:?}", line); - } - - println!(""); - */ - Ok(code) } } diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 2f8d442e..2cd853c7 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -75,7 +75,17 @@ impl DebrayAllocator { self.branch_stack.push(BranchOccurrences::new(num_branches)); } + pub(crate) fn current_branch_designator(&self) -> BranchDesignator { + let num_branches = self.branch_stack.len(); + let current_branch = self.branch_stack.last() + .map(|occurrences| occurrences.current_branch) + .unwrap_or(0); + + BranchDesignator((num_branches, current_branch)) + } + pub(crate) fn add_branch(&mut self) { + let branch_designator = self.current_branch_designator(); let branch_occurrences = self.branch_stack.last_mut().unwrap(); for var_num in branch_occurrences.subsumed_hits.drain(..) { @@ -83,11 +93,11 @@ impl DebrayAllocator { VarAlloc::Perm(_, ref mut allocation) => { match allocation { PermVarAllocation::Done { shallow_safety, deep_safety, .. } => { - if !shallow_safety.unneeded() { + if !shallow_safety.is_unneeded(branch_designator) { branch_occurrences.shallow_safety.insert(var_num); } - if !deep_safety.unneeded() { + if !deep_safety.is_unneeded(branch_designator) { branch_occurrences.deep_safety.insert(var_num); } } @@ -128,6 +138,8 @@ impl DebrayAllocator { (deep_safety, shallow_safety) }); + let branch_designator = self.current_branch_designator(); + let (deep_safety, shallow_safety) = match self.branch_stack.last_mut() { Some(latest_branch) => { latest_branch.deep_safety.union_with(&deep_safety); @@ -143,10 +155,12 @@ impl DebrayAllocator { VarAlloc::Perm(_, ref mut allocation) => { let shallow_safety = VarSafetyStatus::needed_if( shallow_safety.contains(var_num), + branch_designator, ); let deep_safety = VarSafetyStatus::needed_if( deep_safety.contains(var_num), + branch_designator, ); *allocation = PermVarAllocation::Done { shallow_safety, deep_safety }; @@ -415,10 +429,12 @@ impl DebrayAllocator { pub(crate) fn mark_temp_to_safe_perm(&mut self, var_num: usize) { match &self.var_data.records[var_num].allocation { &VarAlloc::Temp { to_perm_var_num: Some(perm_var_num), .. } => { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[perm_var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { - *deep_safety = VarSafetyStatus::Unneeded; - *shallow_safety = VarSafetyStatus::Unneeded; + *deep_safety = VarSafetyStatus::unneeded(branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); } _ => unreachable!() } @@ -429,14 +445,16 @@ impl DebrayAllocator { } fn mark_safe_var(&mut self, var_num: usize, lvl: Level, term_loc: GenContext) { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { // GetVariable in head chunk is considered safe. if lvl == Level::Deep { - *deep_safety = VarSafetyStatus::Unneeded; - *shallow_safety = VarSafetyStatus::Unneeded; + *deep_safety = VarSafetyStatus::unneeded(branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); } else if term_loc == GenContext::Head { - *shallow_safety = VarSafetyStatus::Unneeded; + *shallow_safety = VarSafetyStatus::GloballyUnneeded; } else { if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() { match &mut self.var_data.records[temp_var_num].allocation { @@ -449,7 +467,7 @@ impl DebrayAllocator { } } VarAlloc::Temp { ref mut safety, .. } => { - *safety = VarSafetyStatus::Unneeded; + *safety = VarSafetyStatus::GloballyUnneeded; } _ => { unreachable!() @@ -463,20 +481,22 @@ impl DebrayAllocator { r: RegType, arg_c: usize, ) -> Instruction { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => { - if !self.in_tail_position || shallow_safety.unneeded() { + if !self.in_tail_position || shallow_safety.is_unneeded(branch_designator) { Target::argument_to_value(r, arg_c) } else { - *shallow_safety = VarSafetyStatus::Unneeded; + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); Target::unsafe_argument_to_value(r, arg_c) } } VarAlloc::Temp { ref mut safety, .. } => { - if safety.unneeded() { + if safety.is_unneeded(branch_designator) { Target::argument_to_value(r, arg_c) } else { - *safety = VarSafetyStatus::Unneeded; + *safety = VarSafetyStatus::GloballyUnneeded; Target::unsafe_argument_to_value(r, arg_c) } } @@ -491,20 +511,22 @@ impl DebrayAllocator { var_num: usize, r: RegType, ) -> Instruction { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => { - if deep_safety.unneeded() { + if deep_safety.is_unneeded(branch_designator) { Target::subterm_to_value(r) } else { - *deep_safety = VarSafetyStatus::Unneeded; + *deep_safety = VarSafetyStatus::unneeded(branch_designator); Target::unsafe_subterm_to_value(r) } } VarAlloc::Temp { ref mut safety, .. } => { - if safety.unneeded() { + if safety.is_unneeded(branch_designator) { Target::subterm_to_value(r) } else { - *safety = VarSafetyStatus::Unneeded; + *safety = VarSafetyStatus::unneeded(branch_designator); Target::unsafe_subterm_to_value(r) } } diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 1b65ef9e..a701dba3 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -839,12 +839,3 @@ impl BranchMap { var_data } } - -#[cfg(test)] -mod tests { - #[test] - fn disjunct_compilation() { - let mut wam = MachineState::new(); - let mut op_dir = default_op_dir(); - } -} From 33f65210eeb6bd573a694aa4ffa8c252140403be Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 22 Jun 2023 18:50:20 -0600 Subject: [PATCH 15/40] make tests compatible --- src/heap_print.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index aa93ad29..2a2149d2 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1717,7 +1717,7 @@ mod tests { heap_loc_as_cell!(0) ); - printer.var_names.insert(list_loc_as_cell!(1), Var::from("L")); + printer.var_names.insert(list_loc_as_cell!(1), VarPtr::from("L")); let output = printer.print(); @@ -1778,7 +1778,7 @@ mod tests { heap_loc_as_cell!(0) ); - printer.var_names.insert(list_loc_as_cell!(1), Var::from("L")); + printer.var_names.insert(list_loc_as_cell!(1), VarPtr::from("L")); let output = printer.print(); From 47d4e6d2f99de18df627a6dcbd52fc7d851b845b Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Wed, 3 May 2023 23:23:53 +0200 Subject: [PATCH 16/40] FIXED: consistent read/write of further control characters, and non-breaking space Example: ?- X = '\xa0\'. X = '\xa0\'. This addresses #1768. --- src/heap_print.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index 2a2149d2..df22113c 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -172,7 +172,9 @@ fn char_to_string(is_quoted: bool, c: char) -> String { '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => { c.to_string() } - '\u{0}'..='\u{1f}' => format!("\\x{:x}\\", c as u32), // print all other control characters in hex. + '\u{0}'..='\u{1f}' | '\u{7f}' ..= '\u{a0}' + // print all other control characters, and also non-breaking space, in hex. + => format!("\\x{:x}\\", c as u32), _ => c.to_string(), } } From 5e124ccf44a5b3ef0cdbbe62c12bc1d7e76cda56 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Wed, 3 May 2023 21:56:04 +0200 Subject: [PATCH 17/40] ENHANCED: allow Roman numerals in strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example: ?- X = "ↁ". X = "ↁ". This addresses #1790. --- src/parser/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/macros.rs b/src/parser/macros.rs index 27b106fc..3e6826c9 100644 --- a/src/parser/macros.rs +++ b/src/parser/macros.rs @@ -20,7 +20,7 @@ macro_rules! alpha_char { #[macro_export] macro_rules! alpha_numeric_char { ($c: expr) => { - $crate::alpha_char!($c) || $crate::decimal_digit_char!($c) + $crate::alpha_char!($c) || $c.is_numeric() }; } From 86beb222ae092baf7a0316eecb82810058fac65b Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 4 May 2023 00:50:27 +0200 Subject: [PATCH 18/40] rely on first instantiated argument indexing in the definitions of foldl/N This allows shorter and more natural definitions. --- src/lib/lists.pl | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/lib/lists.pl b/src/lib/lists.pl index 92bc202d..815e2b2a 100644 --- a/src/lib/lists.pl +++ b/src/lib/lists.pl @@ -295,25 +295,19 @@ same_length([_|As], [_|Bs]) :- % sum_list(Ls, S) :- foldl(sum_, Ls, 0, S). % ``` -foldl(Goal_3, Ls, A0, A) :- - foldl_(Ls, Goal_3, A0, A). - -foldl_([], _, A, A). -foldl_([L|Ls], G_3, A0, A) :- +foldl(_, [], A, A). +foldl(G_3, [L|Ls], A0, A) :- call(G_3, L, A0, A1), - foldl_(Ls, G_3, A1, A). + foldl(G_3, Ls, A1, A). %% foldl(+Predicate, ?Ls0, ?Ls1, +A0, ?A). % % Same as `foldl/4` but with an extra list -foldl(Goal_4, Xs, Ys, A0, A) :- - foldl_(Xs, Ys, Goal_4, A0, A). - -foldl_([], [], _, A, A). -foldl_([X|Xs], [Y|Ys], G_4, A0, A) :- +foldl(_, [], [], A, A). +foldl(G_4, [X|Xs], [Y|Ys], A0, A) :- call(G_4, X, Y, A0, A1), - foldl_(Xs, Ys, G_4, A1, A). + foldl(G_4, Xs, Ys, A1, A). %% transpose(?Ls, ?Ts). % From 8e4465315f8ec3e4e91b52b460ac4f1ac994817b Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 10 May 2023 00:04:35 -0600 Subject: [PATCH 19/40] use same logic to print Chars and Atoms (#1804) --- src/heap_print.rs | 123 ++++++++++++++++++++--------------- src/machine/machine_state.rs | 1 + src/machine/mock_wam.rs | 1 + 3 files changed, 73 insertions(+), 52 deletions(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index df22113c..c861a26c 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -470,6 +470,7 @@ pub fn fmt_float(mut fl: f64) -> String { pub struct HCPrinter<'a, Outputter> { outputter: Outputter, iter: StackfulPreOrderHeapIter<'a>, + atom_tbl: &'a mut AtomTable, op_dir: &'a OpDir, state_stack: Vec, toplevel_spec: Option, @@ -534,6 +535,7 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn new( heap: &'a mut Heap, + atom_tbl: &'a mut AtomTable, op_dir: &'a OpDir, output: Outputter, cell: HeapCellValue, @@ -541,6 +543,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { HCPrinter { outputter: output, iter: stackful_preorder_iter(heap, cell), + atom_tbl, op_dir, state_stack: vec![], toplevel_spec: None, @@ -890,7 +893,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - fn print_atom(&mut self, atom: Atom) { + fn print_impromptu_atom(&mut self, atom: Atom) { let result = self.print_op_addendum(atom.as_str()); push_space_if_amb!(self, result.as_str(), { @@ -1406,7 +1409,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn print_stream(&mut self, stream: Stream, max_depth: usize) { if let Some(alias) = stream.options().get_alias() { - self.print_atom(alias); + self.print_impromptu_atom(alias); } else { let stream_atom = atom!("$stream"); @@ -1442,53 +1445,62 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { None => return, }; - read_heap_cell!(addr, - (HeapCellValueTag::Atom, (name, arity)) => { - if name == atom!("[]") && arity == 0 { - if !self.at_cdr("") { - append_str!(self, "[]"); - } - } else if arity > 0 { - if let Some(spec) = fetch_op_spec(name, arity, self.op_dir) { - self.handle_op_as_struct( - name, - arity, - &op, - is_functor_redirect, - spec, - negated_operand, - max_depth, - ); - } else { - push_space_if_amb!(self, name.as_str(), { - self.format_clause(max_depth, arity, name, None); - }); - } - } else if fetch_op_spec(name, arity, self.op_dir).is_some() { - let mut result = String::new(); - - if let Some(ref op) = op { - if self.outputter.ends_with(&format!(" {}", op.as_atom().as_str())) { - result.push(' '); - } - - result.push('('); - } - - result += &self.print_op_addendum(name.as_str()); - - if op.is_some() { - result.push(')'); - } - - push_space_if_amb!(self, &result, { - append_str!(self, &result); - }); + let print_atom = |printer: &mut Self, name: Atom, arity: usize| { + if name == atom!("[]") && arity == 0 { + if !printer.at_cdr("") { + append_str!(printer, "[]"); + } + } else if arity > 0 { + if let Some(spec) = fetch_op_spec(name, arity, printer.op_dir) { + printer.handle_op_as_struct( + name, + arity, + &op, + is_functor_redirect, + spec, + negated_operand, + max_depth, + ); } else { - push_space_if_amb!(self, name.as_str(), { - self.print_atom(name); + push_space_if_amb!(printer, name.as_str(), { + printer.format_clause(max_depth, arity, name, None); }); } + } else if fetch_op_spec(name, arity, printer.op_dir).is_some() { + let mut result = String::new(); + + if let Some(ref op) = op { + if printer.outputter.ends_with(&format!(" {}", op.as_atom().as_str())) { + result.push(' '); + } + + result.push('('); + } + + result += &printer.print_op_addendum(name.as_str()); + + if op.is_some() { + result.push(')'); + } + + push_space_if_amb!(printer, &result, { + append_str!(printer, &result); + }); + } else { + push_space_if_amb!(printer, name.as_str(), { + printer.print_impromptu_atom(name); + }); + } + }; + + read_heap_cell!(addr, + (HeapCellValueTag::Atom, (name, arity)) => { + print_atom(self, name, arity); + } + (HeapCellValueTag::Char, c) => { + let name = self.atom_tbl.build_with(&String::from(c)); + print_atom(self, name, 0); + // print_char!(self, self.quoted, c); } (HeapCellValueTag::Str, s) => { let (name, arity) = cell_as_atom_cell!(self.iter.heap[s]) @@ -1536,9 +1548,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }) } } - (HeapCellValueTag::Char, c) => { - print_char!(self, self.quoted, c); - } (HeapCellValueTag::Cons, c) => { match_untyped_arena_ptr!(c, (ArenaHeaderTag::Integer, n) => { @@ -1551,10 +1560,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.print_stream(stream, max_depth); } (ArenaHeaderTag::OssifiedOpDir, _op_dir) => { - self.print_atom(atom!("$ossified_op_dir")); + self.print_impromptu_atom(atom!("$ossified_op_dir")); } (ArenaHeaderTag::Dropped, _value) => { - self.print_atom(atom!("$dropped_value")); + self.print_impromptu_atom(atom!("$dropped_value")); } (ArenaHeaderTag::IndexPtr, index_ptr) => { self.print_index_ptr(*index_ptr, max_depth); @@ -1588,7 +1597,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { while let Some(loc_data) = self.state_stack.pop() { match loc_data { - TokenOrRedirect::Atom(atom) => self.print_atom(atom), + TokenOrRedirect::Atom(atom) => self.print_impromptu_atom(atom), TokenOrRedirect::BarAsOp => append_str!(self, " | "), TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c), TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()), @@ -1654,6 +1663,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1681,6 +1691,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1703,6 +1714,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1714,6 +1726,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1743,6 +1756,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1760,6 +1774,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1775,6 +1790,7 @@ mod tests { { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1803,6 +1819,7 @@ mod tests { { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1824,6 +1841,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), pstr_loc_as_cell!(0) @@ -1850,6 +1868,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.atom_tbl, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 26d0309b..7d0f6c77 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -764,6 +764,7 @@ impl MachineState { let mut printer = HCPrinter::new( &mut self.heap, + &mut self.atom_tbl, op_dir, PrinterOutputter::new(), term_to_be_printed, diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index 761590fb..2ddde129 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -61,6 +61,7 @@ impl MockWAM { let mut printer = HCPrinter::new( &mut self.machine_st.heap, + &mut self.machine_st.atom_tbl, &self.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(term_write_result.heap_loc), From c2f26234718ed285f7f28d96cdb3782707e76aec Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Sun, 14 May 2023 09:14:10 +0200 Subject: [PATCH 20/40] extend logic to all control and whitespace characters This addresses #1802. --- src/heap_print.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index c861a26c..dfb2efde 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -169,13 +169,16 @@ fn char_to_string(is_quoted: bool, c: char) -> String { '\u{08}' if is_quoted => "\\b".to_string(), // UTF-8 backspace '\u{07}' if is_quoted => "\\a".to_string(), // UTF-8 alert '\\' if is_quoted => "\\\\".to_string(), - '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => { + ' ' | '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => { c.to_string() } - '\u{0}'..='\u{1f}' | '\u{7f}' ..= '\u{a0}' - // print all other control characters, and also non-breaking space, in hex. - => format!("\\x{:x}\\", c as u32), - _ => c.to_string(), + _ => + if c.is_whitespace() || c.is_control() { + // print all other control and whitespace characters in hex. + format!("\\x{:x}\\", c as u32) + } else { + c.to_string() + } } } From 43df2e2649ad6d11f4a8e0dca9774f9c338d9d9f Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Tue, 16 May 2023 22:41:20 +0200 Subject: [PATCH 21/40] shorten gensym/2 --- src/lib/gensym.pl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib/gensym.pl b/src/lib/gensym.pl index 92cd4d1f..86e7ad5b 100644 --- a/src/lib/gensym.pl +++ b/src/lib/gensym.pl @@ -19,13 +19,12 @@ gensym(Base, Unique) :- must_be(var, Unique), atom_si(Base), gensym_key(Base, BaseKey), - ( bb_get(BaseKey, UniqueID0) -> - UniqueID is UniqueID0 + 1, - bb_put(BaseKey, UniqueID), - append_id(Base, UniqueID, Unique) - ; bb_put(BaseKey, 1), - append_id(Base, 1, Unique) - ). + ( bb_get(BaseKey, UniqueID0) -> true + ; UniqueID0 = 0 + ), + UniqueID is UniqueID0 + 1, + append_id(Base, UniqueID, Unique), + bb_put(BaseKey, UniqueID). reset_gensym(Base) :- atom_si(Base), From 97bd77874571954bda1c93f14ba41a42c50386e1 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Tue, 16 May 2023 22:42:10 +0200 Subject: [PATCH 22/40] FIXED: correctly reset counter in reset_gensym/2 (#1807) Many thanks to @infradig for detecting this issue and suggesting this correction! --- src/lib/gensym.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/gensym.pl b/src/lib/gensym.pl index 86e7ad5b..272e68bd 100644 --- a/src/lib/gensym.pl +++ b/src/lib/gensym.pl @@ -28,4 +28,5 @@ gensym(Base, Unique) :- reset_gensym(Base) :- atom_si(Base), - bb_put(Base, 0). + gensym_key(Base, BaseKey), + bb_put(BaseKey, 0). From 5850125d97b1b8e7a013f92091525c49908dc47e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Wed, 17 May 2023 18:19:19 +0200 Subject: [PATCH 23/40] Update select crate to 0.6.0 and remove warning --- Cargo.lock | 477 ++++++++++++++++------------------------------------- Cargo.toml | 2 +- 2 files changed, 142 insertions(+), 337 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b4fc8a9..76c1c10c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,15 +31,6 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -215,15 +206,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -301,7 +283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2db40892a506901e4e8281f00e42687df82d1d3448cb0289ae9183a60cb42ec1" dependencies = [ "blake2 0.10.4", - "rand_core 0.6.4", + "rand_core", "sha2", ] @@ -356,10 +338,10 @@ dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "scratch", - "syn 1.0.103", + "syn", ] [[package]] @@ -374,9 +356,9 @@ version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -385,9 +367,9 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcdbcee2d9941369faba772587a565f4f534e42cb8d17e5295871de730163b2b" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -542,18 +524,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futf" version = "0.1.5" @@ -618,9 +588,9 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -709,9 +679,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -780,16 +750,16 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.23.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce65ac8028cf5a287a7dbf6c4e0a6cf2dcf022ed5b167a81bae66ebf599a8b7" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ "log", "mac", "markup5ever", - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -893,7 +863,7 @@ version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ - "autocfg 1.1.0", + "autocfg", "hashbrown", ] @@ -1043,7 +1013,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ - "autocfg 1.1.0", + "autocfg", "scopeguard", ] @@ -1064,21 +1034,30 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "markup5ever" -version = "0.8.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1af46a727284117e09780d05038b1ce6fc9c76cc6df183c3dae5a8955a25e21" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ "log", - "phf 0.7.24", + "phf 0.10.1", "phf_codegen", - "serde", - "serde_derive", - "serde_json", "string_cache", "string_cache_codegen", "tendril", ] +[[package]] +name = "markup5ever_rcdom" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9521dd6750f8e80ee6c53d65e2e4656d7de37064f3a7a5d2d11d05df93839c2" +dependencies = [ + "html5ever", + "markup5ever", + "tendril", + "xml5ever", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -1097,7 +1076,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1148,9 +1127,9 @@ name = "modular-bitfield-impl" version = "0.11.2" source = "git+https://github.com/mthom/modular-bitfield#213535c684af277563678179d8496f11b84a283f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1205,7 +1184,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" dependencies = [ - "autocfg 1.1.0", + "autocfg", "bitflags", "cfg-if", "libc", @@ -1226,7 +1205,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-traits", ] @@ -1236,7 +1215,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1282,9 +1261,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1299,7 +1278,7 @@ version = "0.9.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cc", "libc", "pkg-config", @@ -1363,15 +1342,6 @@ dependencies = [ "windows-sys 0.42.0", ] -[[package]] -name = "phf" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -dependencies = [ - "phf_shared 0.7.24", -] - [[package]] name = "phf" version = "0.9.0" @@ -1384,23 +1354,22 @@ dependencies = [ ] [[package]] -name = "phf_codegen" -version = "0.7.24" +name = "phf" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "phf_generator 0.7.24", - "phf_shared 0.7.24", + "phf_shared 0.10.0", ] [[package]] -name = "phf_generator" -version = "0.7.24" +name = "phf_codegen" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" dependencies = [ - "phf_shared 0.7.24", - "rand 0.6.5", + "phf_generator 0.10.0", + "phf_shared 0.10.0", ] [[package]] @@ -1410,7 +1379,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d43f3220d96e0080cc9ea234978ccd80d904eafb17be31bb0f76daaea6493082" dependencies = [ "phf_shared 0.9.0", - "rand 0.8.5", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", ] [[package]] @@ -1422,18 +1401,9 @@ dependencies = [ "phf_generator 0.9.1", "phf_shared 0.9.0", "proc-macro-hack", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -dependencies = [ - "siphasher 0.2.3", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1442,7 +1412,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a68318426de33640f02be62b4ae8eb1261be2efbc337b60c54d845bf4484e0d9" dependencies = [ - "siphasher 0.3.10", + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", ] [[package]] @@ -1508,15 +1487,6 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid", -] - [[package]] name = "proc-macro2" version = "1.0.47" @@ -1526,22 +1496,13 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - [[package]] name = "quote" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 1.0.47", + "proc-macro2", ] [[package]] @@ -1560,25 +1521,6 @@ dependencies = [ "nibble_vec", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -1586,18 +1528,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -1607,24 +1539,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -1634,77 +1551,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -1907,8 +1753,8 @@ dependencies = [ "ordered-float", "phf 0.9.0", "predicates-core", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "ref_thread_local", "ring", "ripemd160", @@ -1924,7 +1770,7 @@ dependencies = [ "static_assertions", "strum", "strum_macros", - "syn 1.0.103", + "syn", "to-syn-value", "to-syn-value_derive", "tokio", @@ -1956,12 +1802,13 @@ dependencies = [ [[package]] name = "select" -version = "0.4.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac645958c62108d11f90f8d34e4dc2799c838fc995ed4c2075867a2a8d5be76b" +checksum = "6f9da09dc3f4dfdb6374cbffff7a2cffcec316874d4429899eefdc97b3b94dcd" dependencies = [ "bit-set", "html5ever", + "markup5ever_rcdom", ] [[package]] @@ -1970,28 +1817,6 @@ version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" -[[package]] -name = "serde_derive" -version = "1.0.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "serde_json" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" -dependencies = [ - "itoa", - "ryu", - "serde", -] - [[package]] name = "serial_test" version = "0.5.1" @@ -2009,9 +1834,9 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2074,12 +1899,6 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" - [[package]] name = "siphasher" version = "0.3.10" @@ -2092,7 +1911,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -2143,38 +1962,30 @@ checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" [[package]] name = "string_cache" -version = "0.7.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c058a82f9fd69b1becf8c274f412281038877c553182f1d02eb027045a2d67" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ - "lazy_static", "new_debug_unreachable", - "phf_shared 0.7.24", + "once_cell", + "parking_lot 0.12.1", + "phf_shared 0.10.0", "precomputed-hash", "serde", - "string_cache_codegen", - "string_cache_shared", ] [[package]] name = "string_cache_codegen" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "phf_generator 0.7.24", - "phf_shared 0.7.24", - "proc-macro2 1.0.47", - "quote 1.0.21", - "string_cache_shared", + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", ] -[[package]] -name = "string_cache_shared" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" - [[package]] name = "strum" version = "0.23.0" @@ -2188,10 +1999,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" dependencies = [ "heck", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "rustversion", - "syn 1.0.103", + "syn", ] [[package]] @@ -2206,25 +2017,14 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid", -] - [[package]] name = "syn" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "unicode-ident", ] @@ -2289,9 +2089,9 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2311,7 +2111,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45dcb7b4108a4793bdd74aa3714296c6eaf43663edf73fa8625d0d7621e68447" dependencies = [ - "syn 1.0.103", + "syn", "to-syn-value_derive", ] @@ -2321,9 +2121,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd4fdec6de01b568c1d3721c9d46a352623c536cd55a8a5acfefb63d1fccccbc" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2332,7 +2132,7 @@ version = "1.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" dependencies = [ - "autocfg 1.1.0", + "autocfg", "bytes", "libc", "memchr", @@ -2352,9 +2152,9 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2437,12 +2237,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "untrusted" version = "0.7.1" @@ -2534,9 +2328,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-shared", ] @@ -2546,7 +2340,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.21", + "quote", "wasm-bindgen-macro-support", ] @@ -2556,9 +2350,9 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2719,6 +2513,17 @@ dependencies = [ "tap", ] +[[package]] +name = "xml5ever" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650" +dependencies = [ + "log", + "mac", + "markup5ever", +] + [[package]] name = "xmlparser" version = "0.13.5" diff --git a/Cargo.toml b/Cargo.toml index 1f4fa7aa..99218c71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,7 @@ blake2 = "0.8.1" crrl = "0.2.0" native-tls = "0.2.4" chrono = "0.4.11" -select = "0.4.3" +select = "0.6.0" roxmltree = "0.11.0" base64 = "0.12.3" smallvec = "1.8.0" From dae34b60099cdd000d8dc16513d9d6311c9d2251 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 24 May 2023 13:43:52 -0600 Subject: [PATCH 24/40] affirm integers as rational/1 (#1810) --- src/machine/dispatch.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 1d310bcd..a6e7963a 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -2600,7 +2600,7 @@ impl Machine { read_heap_cell!(d, (HeapCellValueTag::Cons, ptr) => { match_untyped_arena_ptr!(ptr, - (ArenaHeaderTag::Rational, _r) => { + (ArenaHeaderTag::Rational | ArenaHeaderTag::Integer, _r) => { self.machine_st.p += 1; } _ => { @@ -2608,6 +2608,9 @@ impl Machine { } ); } + (HeapCellValueTag::Fixnum) => { + self.machine_st.p += 1; + } _ => { self.machine_st.backtrack(); } @@ -2619,7 +2622,7 @@ impl Machine { read_heap_cell!(d, (HeapCellValueTag::Cons, ptr) => { match_untyped_arena_ptr!(ptr, - (ArenaHeaderTag::Rational, _r) => { + (ArenaHeaderTag::Rational | ArenaHeaderTag::Integer, _r) => { self.machine_st.p = self.machine_st.cp; } _ => { @@ -2627,6 +2630,9 @@ impl Machine { } ); } + (HeapCellValueTag::Fixnum) => { + self.machine_st.p = self.machine_st.cp; + } _ => { self.machine_st.backtrack(); } From e0f49e8f43e30c20fe3c646a44f32407e097d1d0 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 26 May 2023 15:19:07 -0600 Subject: [PATCH 25/40] optionally read from machine stack in stackful pre-order iterator (#1812) --- Cargo.lock | 6 + src/heap_iter.rs | 425 +++++++++++++++++++++++++---------- src/heap_print.rs | 93 ++++---- src/machine/loader.rs | 2 +- src/machine/machine_state.rs | 1 + src/machine/mock_wam.rs | 1 + 6 files changed, 374 insertions(+), 154 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76c1c10c..364b4891 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -524,6 +524,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" diff --git a/src/heap_iter.rs b/src/heap_iter.rs index d7f1f2e4..96aef41d 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -1,8 +1,9 @@ #[cfg(test)] pub(crate) use crate::machine::gc::{IteratorUMP, StacklessPreOrderHeapIter}; -use crate::machine::heap::*; use crate::atom_table::*; +use crate::machine::heap::*; +use crate::machine::stack::*; use crate::types::*; use modular_bitfield::prelude::*; @@ -18,28 +19,45 @@ enum IterStackLocTag { PendingMark, } +#[derive(BitfieldSpecifier, Clone, Copy, Debug, PartialEq, Eq)] +#[bits = 1] +pub enum HeapOrStackTag { + Heap, + Stack, +} + #[bitfield] #[repr(u64)] #[derive(Clone, Copy, Debug)] pub struct IterStackLoc { - value: B62, + pub value: B61, tag: IterStackLocTag, + heap_or_stack: HeapOrStackTag, } impl IterStackLoc { #[inline] - pub fn iterable_heap_loc(h: usize) -> Self { - IterStackLoc::new().with_tag(IterStackLocTag::Iterable).with_value(h as u64) + pub fn iterable_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self { + IterStackLoc::new() + .with_tag(IterStackLocTag::Iterable) + .with_heap_or_stack(heap_or_stack) + .with_value(h as u64) } #[inline] - pub fn mark_heap_loc(h: usize) -> Self { - IterStackLoc::new().with_tag(IterStackLocTag::Marked).with_value(h as u64) + fn mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self { + IterStackLoc::new() + .with_tag(IterStackLocTag::Marked) + .with_heap_or_stack(heap_or_stack) + .with_value(h as u64) } #[inline] - pub fn pending_mark_heap_loc(h: usize) -> Self { - IterStackLoc::new().with_tag(IterStackLocTag::PendingMark).with_value(h as u64) + fn pending_mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self { + IterStackLoc::new() + .with_tag(IterStackLocTag::PendingMark) + .with_heap_or_stack(heap_or_stack) + .with_value(h as u64) } #[inline] @@ -51,38 +69,35 @@ impl IterStackLoc { pub fn is_pending_mark(self) -> bool { self.tag() == IterStackLocTag::PendingMark } -} -#[inline] -fn forward_if_referent_marked(heap: &mut [HeapCellValue], h: usize) { - read_heap_cell!(heap[h], - (HeapCellValueTag::Str - | HeapCellValueTag::Lis - | HeapCellValueTag::AttrVar - | HeapCellValueTag::Var - | HeapCellValueTag::PStrLoc, vh) => { - if heap[vh].get_mark_bit() { - heap[h].set_forwarding_bit(true); + #[inline] + pub fn as_ref(self) -> Ref { + match self.heap_or_stack() { + HeapOrStackTag::Heap => { + Ref::heap_cell(self.value() as usize) + } + HeapOrStackTag::Stack => { + Ref::stack_cell(self.value() as usize) } } - _ => {} - ) + } } #[derive(Debug)] pub struct StackfulPreOrderHeapIter<'a> { pub heap: &'a mut Vec, + pub machine_stack: &'a mut Stack, stack: Vec, - h: usize, + h: IterStackLoc, } impl<'a> Drop for StackfulPreOrderHeapIter<'a> { fn drop(&mut self) { while let Some(h) = self.stack.pop() { - let h = h.value() as usize; + let cell = self.read_cell_mut(h); - self.heap[h].set_forwarding_bit(false); - self.heap[h].set_mark_bit(false); + cell.set_forwarding_bit(false); + cell.set_mark_bit(false); } self.heap.pop(); @@ -90,48 +105,93 @@ impl<'a> Drop for StackfulPreOrderHeapIter<'a> { } pub trait FocusedHeapIter: Iterator { - fn focus(&self) -> usize; + fn focus(&self) -> IterStackLoc; } impl<'a> FocusedHeapIter for StackfulPreOrderHeapIter<'a> { #[inline] - fn focus(&self) -> usize { + fn focus(&self) -> IterStackLoc { self.h } } impl<'a> StackfulPreOrderHeapIter<'a> { #[inline] - fn new(heap: &'a mut Vec, cell: HeapCellValue) -> Self { - let h = heap.len(); + fn new(heap: &'a mut Vec, stack: &'a mut Stack, cell: HeapCellValue) -> Self { + let h = IterStackLoc::iterable_loc(heap.len(), HeapOrStackTag::Heap); heap.push(cell); Self { heap, h, - stack: vec![IterStackLoc::iterable_heap_loc(h)], + machine_stack: stack, + stack: vec![h], } } #[inline] - pub fn push_stack(&mut self, h: usize) { - self.stack.push(IterStackLoc::iterable_heap_loc(h)); + fn forward_if_referent_marked(&mut self, loc: IterStackLoc) { + read_heap_cell!(self.read_cell(loc), + (HeapCellValueTag::Str | + HeapCellValueTag::Lis | + HeapCellValueTag::AttrVar | + HeapCellValueTag::Var | + HeapCellValueTag::PStrLoc, vh) => { + if self.heap[vh].get_mark_bit() { + self.read_cell_mut(loc).set_forwarding_bit(true); + } + } + (HeapCellValueTag::StackVar, vs) => { + if self.machine_stack[vs].get_mark_bit() { + self.read_cell_mut(loc).set_forwarding_bit(true); + } + } + _ => {} + ); } #[inline] - pub fn stack_last(&self) -> Option { + pub fn push_stack(&mut self, h: IterStackLoc) { + self.stack.push(h); + } + + #[inline] + pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue { + match loc.heap_or_stack() { + HeapOrStackTag::Heap => { + &mut self.heap[loc.value() as usize] + } + HeapOrStackTag::Stack => { + &mut self.machine_stack[loc.value() as usize] + } + } + } + + #[inline] + pub fn read_cell(&self, loc: IterStackLoc) -> HeapCellValue { + match loc.heap_or_stack() { + HeapOrStackTag::Heap => { + self.heap[loc.value() as usize] + } + HeapOrStackTag::Stack => { + self.machine_stack[loc.value() as usize] + } + } + } + + #[inline] + pub fn stack_last(&self) -> Option { for h in self.stack.iter().rev() { let is_readable_marked = h.is_marked(); - let h = h.value() as usize; - let cell = self.heap[h]; + let cell = self.read_cell(*h); if cell.get_forwarding_bit() { - return Some(h); + return Some(*h); } else if cell.get_mark_bit() && !is_readable_marked { continue; } - return Some(h); + return Some(*h); } None @@ -141,10 +201,9 @@ impl<'a> StackfulPreOrderHeapIter<'a> { pub fn pop_stack(&mut self) -> Option { while let Some(h) = self.stack.pop() { let is_readable_marked = h.is_marked(); - let h = h.value() as usize; - self.h = h; - let cell = &mut self.heap[h]; + self.h = h; + let cell = self.read_cell_mut(h); if cell.get_forwarding_bit() { cell.set_forwarding_bit(false); @@ -159,30 +218,29 @@ impl<'a> StackfulPreOrderHeapIter<'a> { None } - fn push_if_unmarked(&mut self, h: usize) { - if !self.heap[h].get_mark_bit() { - self.heap[h].set_mark_bit(true); - self.stack.push(IterStackLoc::iterable_heap_loc(h)); + fn push_if_unmarked(&mut self, loc: IterStackLoc) { + let cell = self.read_cell_mut(loc); + + if !cell.get_mark_bit() { + cell.set_mark_bit(true); + self.stack.push(IterStackLoc::iterable_loc(loc.value() as usize, loc.heap_or_stack())); } } fn follow(&mut self) -> Option { while let Some(h) = self.stack.pop() { if h.is_pending_mark() { - let h = h.value() as usize; - self.push_if_unmarked(h); - self.stack.push(IterStackLoc::mark_heap_loc(h)); + self.stack.push(IterStackLoc::mark_loc(h.value() as usize, h.heap_or_stack())); - forward_if_referent_marked(&mut self.heap, h); + self.forward_if_referent_marked(h); continue; } - let is_readable_marked = h.is_marked(); - let h = h.value() as usize; - self.h = h; - let cell = &mut self.heap[h]; + + let is_readable_marked = h.is_marked(); + let cell = self.read_cell_mut(h); if cell.get_forwarding_bit() { let copy = *cell; @@ -195,50 +253,68 @@ impl<'a> StackfulPreOrderHeapIter<'a> { read_heap_cell!(*cell, (HeapCellValueTag::Str | HeapCellValueTag::PStrLoc, vh) => { - self.push_if_unmarked(vh); - self.stack.push(IterStackLoc::mark_heap_loc(vh)); + let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap); + + self.push_if_unmarked(loc); + self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap)); } (HeapCellValueTag::Lis, vh) => { - self.push_if_unmarked(vh); + let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap); - self.stack.push(IterStackLoc::pending_mark_heap_loc(vh + 1)); - self.stack.push(IterStackLoc::mark_heap_loc(vh)); + self.push_if_unmarked(loc); - forward_if_referent_marked(&mut self.heap, vh); + self.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap)); - return Some(self.heap[h]); + self.forward_if_referent_marked(loc); + + return Some(self.read_cell(h)); } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, vh) => { - self.push_if_unmarked(vh); - self.stack.push(IterStackLoc::mark_heap_loc(vh)); - forward_if_referent_marked(&mut self.heap, vh); + let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap); + + self.push_if_unmarked(loc); + self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap)); + self.forward_if_referent_marked(loc); + } + (HeapCellValueTag::StackVar, vs) => { + let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack); + + self.push_if_unmarked(loc); + self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack)); + self.forward_if_referent_marked(loc); } (HeapCellValueTag::PStrOffset, offset) => { - self.push_if_unmarked(offset); - self.stack.push(IterStackLoc::iterable_heap_loc(h+1)); + self.push_if_unmarked(IterStackLoc::iterable_loc(offset, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap)); - return Some(self.heap[h]); + return Some(self.read_cell(h)); } (HeapCellValueTag::PStr) => { - self.push_if_unmarked(h); + let tail_loc = IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap); - self.stack.push(IterStackLoc::iterable_heap_loc(h+1)); - forward_if_referent_marked(&mut self.heap, h+1); + self.push_if_unmarked(IterStackLoc::iterable_loc(h.value() as usize, HeapOrStackTag::Heap)); + self.stack.push(tail_loc); + self.forward_if_referent_marked(tail_loc); - return Some(self.heap[h]); + return Some(self.read_cell(h)); } (HeapCellValueTag::Atom, (_name, arity)) => { - for h in (h + 2 .. h + arity + 1).rev() { - self.stack.push(IterStackLoc::pending_mark_heap_loc(h)); + let l = h.value() as usize; + + for l in (l + 2 .. l + arity + 1).rev() { + self.stack.push(IterStackLoc::pending_mark_loc(l, HeapOrStackTag::Heap)); } if arity > 0 { - self.push_if_unmarked(h+1); - self.stack.push(IterStackLoc::mark_heap_loc(h+1)); - forward_if_referent_marked(&mut self.heap, h+1); + let first_arg_loc = IterStackLoc::iterable_loc(l+1, HeapOrStackTag::Heap); + + self.push_if_unmarked(first_arg_loc); + self.stack.push(IterStackLoc::mark_loc(l+1, HeapOrStackTag::Heap)); + self.forward_if_referent_marked(first_arg_loc); } - return Some(self.heap[h]); + return Some(self.read_cell(h)); } _ => { return Some(*cell); @@ -269,19 +345,20 @@ pub(crate) fn stackless_preorder_iter( } #[inline(always)] -pub(crate) fn stackful_preorder_iter( - heap: &mut Vec, +pub(crate) fn stackful_preorder_iter<'a>( + heap: &'a mut Vec, + stack: &'a mut Stack, cell: HeapCellValue, -) -> StackfulPreOrderHeapIter { - StackfulPreOrderHeapIter::new(heap, cell) +) -> StackfulPreOrderHeapIter<'a> { + StackfulPreOrderHeapIter::new(heap, stack, cell) } #[derive(Debug)] pub(crate) struct PostOrderIterator { - focus: usize, + focus: IterStackLoc, base_iter: Iter, base_iter_valid: bool, - parent_stack: Vec<(usize, HeapCellValue, usize)>, // number of children, parent node, focus. + parent_stack: Vec<(usize, HeapCellValue, IterStackLoc)>, // number of children, parent node, focus. } impl Deref for PostOrderIterator { @@ -295,7 +372,7 @@ impl Deref for PostOrderIterator { impl PostOrderIterator { pub(crate) fn new(base_iter: Iter) -> Self { PostOrderIterator { - focus: 0, + focus: IterStackLoc::iterable_loc(0, HeapOrStackTag::Heap), base_iter, base_iter_valid: true, parent_stack: vec![], @@ -352,7 +429,7 @@ impl Iterator for PostOrderIterator { impl FocusedHeapIter for PostOrderIterator { #[inline(always)] - fn focus(&self) -> usize { + fn focus(&self) -> IterStackLoc { self.focus } } @@ -368,7 +445,8 @@ impl PostOrderIterator { if let Some((_child_count, item, focus)) = self.parent_stack.last() { read_heap_cell!(item, (HeapCellValueTag::Atom, (_name, arity)) => { - return focus + arity >= idx_loc && *focus < idx_loc; + let focus = focus.value() as usize; + return focus + arity >= idx_loc && focus < idx_loc; } _ => {} ); @@ -401,9 +479,10 @@ impl<'a> LeftistPostOrderHeapIter<'a> { #[inline] pub(crate) fn stackful_post_order_iter<'a>( heap: &'a mut Heap, + stack: &'a mut Stack, cell: HeapCellValue, ) -> LeftistPostOrderHeapIter<'a> { - PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, cell)) + PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, cell)) } #[cfg(test)] @@ -424,6 +503,7 @@ mod tests { use super::*; use crate::machine::mock_wam::*; + #[test] fn heap_stackless_iter_tests() { let mut wam = MockWAM::new(); @@ -1381,7 +1461,11 @@ mod tests { .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1412,7 +1496,11 @@ mod tests { )); for _ in 0..20 { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1440,7 +1528,12 @@ mod tests { { wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); + let mut var = heap_loc_as_cell!(0); // self-referencing variables are copied with their forwarding @@ -1462,7 +1555,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1482,7 +1579,11 @@ mod tests { wam.machine_st.heap.push(empty_list_as_cell!()); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1514,7 +1615,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(0)); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); // the cycle will be iterated twice before being detected. assert_eq!( @@ -1542,7 +1647,11 @@ mod tests { } { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); // cut the iteration short to check that all cells are // unmarked and unforwarded by the Drop instance of @@ -1576,7 +1685,11 @@ mod tests { let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!( @@ -1596,7 +1709,11 @@ mod tests { let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); @@ -1615,7 +1732,12 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); + let pstr_offset_cell = pstr_offset_as_cell!(0); // pstr_offset_cell.set_forwarding_bit(true); @@ -1640,7 +1762,12 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); + let pstr_offset_cell = pstr_offset_as_cell!(0); // pstr_offset_cell.set_forwarding_bit(true); @@ -1653,7 +1780,7 @@ mod tests { let h = iter.focus(); - assert_eq!(h, 5); + assert_eq!(h.value(), 5); assert_eq!(unmark_cell_bits!(iter.heap[4]), pstr_offset_as_cell!(0)); assert_eq!(unmark_cell_bits!(iter.heap[5]), fixnum_as_cell!(Fixnum::build_with(1i64))); @@ -1673,7 +1800,11 @@ mod tests { wam.machine_st.heap.extend(functor); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1732,7 +1863,11 @@ mod tests { wam.machine_st.heap[4] = list_loc_as_cell!(1); { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1799,6 +1934,7 @@ mod tests { { let mut iter = StackfulPreOrderHeapIter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -1830,6 +1966,7 @@ mod tests { { let mut iter = stackful_preorder_iter( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -1864,6 +2001,7 @@ mod tests { { let mut iter = stackful_preorder_iter( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -1898,7 +2036,11 @@ mod tests { .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1929,7 +2071,11 @@ mod tests { )); for _ in 0..20 { // 0000 { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1959,7 +2105,12 @@ mod tests { { wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); + let mut var = heap_loc_as_cell!(0); // self-referencing variables are copied with their forwarding @@ -1981,7 +2132,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2001,7 +2156,11 @@ mod tests { wam.machine_st.heap.push(empty_list_as_cell!()); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2033,7 +2192,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(0)); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); // the cycle will be iterated twice before being detected. assert_eq!( @@ -2063,6 +2226,7 @@ mod tests { { let mut iter = stackful_post_order_iter( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -2098,7 +2262,11 @@ mod tests { let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2117,7 +2285,11 @@ mod tests { let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2136,7 +2308,11 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64))); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); @@ -2151,7 +2327,11 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1i64))); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); @@ -2175,7 +2355,11 @@ mod tests { wam.machine_st.heap.extend(functor); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2235,7 +2419,11 @@ mod tests { wam.machine_st.heap[4] = list_loc_as_cell!(1); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2342,7 +2530,10 @@ mod tests { )); for _ in 0..20 { - let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = stackless_post_order_iter( + &mut wam.machine_st.heap, + str_loc_as_cell!(0), + ); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0)); @@ -2372,7 +2563,10 @@ mod tests { { wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackless_post_order_iter( + &mut wam.machine_st.heap, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2388,7 +2582,10 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackless_post_order_iter( + &mut wam.machine_st.heap, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), diff --git a/src/heap_print.rs b/src/heap_print.rs index dfb2efde..26f3f5d2 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -14,6 +14,7 @@ use crate::machine::heap::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::pstr_loc_and_offset; use crate::machine::partial_string::*; +use crate::machine::stack::*; use crate::machine::streams::*; use crate::types::*; @@ -474,6 +475,7 @@ pub struct HCPrinter<'a, Outputter> { outputter: Outputter, iter: StackfulPreOrderHeapIter<'a>, atom_tbl: &'a mut AtomTable, + stack: &'a Stack, op_dir: &'a OpDir, state_stack: Vec, toplevel_spec: Option, @@ -539,6 +541,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn new( heap: &'a mut Heap, atom_tbl: &'a mut AtomTable, + stack: &'a Stack, op_dir: &'a OpDir, output: Outputter, cell: HeapCellValue, @@ -547,6 +550,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { outputter: output, iter: stackful_preorder_iter(heap, cell), atom_tbl, + stack, op_dir, state_stack: vec![], toplevel_spec: None, @@ -1443,12 +1447,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { ) { let negated_operand = negated_op_needs_bracketing(&self.iter, self.op_dir, &op); - let addr = match self.check_for_seen() { - Some(addr) => addr, - None => return, - }; - - let print_atom = |printer: &mut Self, name: Atom, arity: usize| { + let print_struct = |printer: &mut Self, name: Atom, arity: usize| { if name == atom!("[]") && arity == 0 { if !printer.at_cdr("") { append_str!(printer, "[]"); @@ -1496,29 +1495,33 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } }; + let addr = match self.check_for_seen() { + Some(addr) => addr, + None => return, + }; + read_heap_cell!(addr, (HeapCellValueTag::Atom, (name, arity)) => { - print_atom(self, name, arity); + print_struct(self, name, arity); } (HeapCellValueTag::Char, c) => { let name = self.atom_tbl.build_with(&String::from(c)); - print_atom(self, name, 0); - // print_char!(self, self.quoted, c); + print_struct(self, name, 0); } (HeapCellValueTag::Str, s) => { let (name, arity) = cell_as_atom_cell!(self.iter.heap[s]) .get_name_and_arity(); if let Some(spec) = fetch_op_spec(name, arity, self.op_dir) { - self.handle_op_as_struct( - name, - arity, - &op, - is_functor_redirect, - spec, - negated_operand, - max_depth, - ); + self.handle_op_as_struct( + name, + arity, + &op, + is_functor_redirect, + spec, + negated_operand, + max_depth, + ); } else { push_space_if_amb!(self, name.as_str(), { self.format_clause(max_depth, arity, name, None); @@ -1553,27 +1556,27 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } (HeapCellValueTag::Cons, c) => { match_untyped_arena_ptr!(c, - (ArenaHeaderTag::Integer, n) => { - self.print_number(max_depth, NumberFocus::Unfocused(Number::Integer(n)), &op); - } - (ArenaHeaderTag::Rational, r) => { - self.print_number(max_depth, NumberFocus::Unfocused(Number::Rational(r)), &op); - } - (ArenaHeaderTag::Stream, stream) => { - self.print_stream(stream, max_depth); - } - (ArenaHeaderTag::OssifiedOpDir, _op_dir) => { - self.print_impromptu_atom(atom!("$ossified_op_dir")); - } - (ArenaHeaderTag::Dropped, _value) => { - self.print_impromptu_atom(atom!("$dropped_value")); - } - (ArenaHeaderTag::IndexPtr, index_ptr) => { - self.print_index_ptr(*index_ptr, max_depth); - } - _ => { - } - ); + (ArenaHeaderTag::Integer, n) => { + self.print_number(max_depth, NumberFocus::Unfocused(Number::Integer(n)), &op); + } + (ArenaHeaderTag::Rational, r) => { + self.print_number(max_depth, NumberFocus::Unfocused(Number::Rational(r)), &op); + } + (ArenaHeaderTag::Stream, stream) => { + self.print_stream(stream, max_depth); + } + (ArenaHeaderTag::OssifiedOpDir, _op_dir) => { + self.print_impromptu_atom(atom!("$ossified_op_dir")); + } + (ArenaHeaderTag::Dropped, _value) => { + self.print_impromptu_atom(atom!("$dropped_value")); + } + (ArenaHeaderTag::IndexPtr, index_ptr) => { + self.print_index_ptr(*index_ptr, max_depth); + } + _ => { + } + ); } _ => { unreachable!() @@ -1596,6 +1599,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn print(mut self) -> Outputter { let spec = self.toplevel_spec.take(); + + self.iter.iterate_over_machine_stack(self.stack); self.handle_heap_term(spec, false, self.max_depth); while let Some(loc_data) = self.state_stack.pop() { @@ -1667,6 +1672,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1695,6 +1701,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1718,6 +1725,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1730,6 +1738,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1760,6 +1769,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1778,6 +1788,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1794,6 +1805,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1823,6 +1835,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1845,6 +1858,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), pstr_loc_as_cell!(0) @@ -1872,6 +1886,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, + &wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 51815c7e..6c98024c 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1404,7 +1404,7 @@ impl MachineState { let term_addr = self[r]; let mut term_stack = vec![]; - let mut iter = stackful_post_order_iter(&mut self.heap, term_addr); + let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term_addr); while let Some(addr) = iter.next() { let addr = unmark_cell_bits!(addr); diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 7d0f6c77..0203f62f 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -765,6 +765,7 @@ impl MachineState { let mut printer = HCPrinter::new( &mut self.heap, &mut self.atom_tbl, + &mut self.stack, op_dir, PrinterOutputter::new(), term_to_be_printed, diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index 2ddde129..f71f32e3 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -62,6 +62,7 @@ impl MockWAM { let mut printer = HCPrinter::new( &mut self.machine_st.heap, &mut self.machine_st.atom_tbl, + &mut self.machine_st.stack, &self.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(term_write_result.heap_loc), From 73ca37eccad4393d7f1b088295cfd693fe6adad1 Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 27 May 2023 13:08:25 +0200 Subject: [PATCH 26/40] Remove and move comments --- src/lib/clpz.pl | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index b6ad08b3..43b8f26e 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -4990,7 +4990,6 @@ run_propagator(ptzdiv(X,Y,Z), MState) --> run_propagator(pmod(X,Y,Z), MState) --> ( Y == 0 -> { false } ; Y == Z -> { false } - % ; nonvar(Y), Z == X -> true ; X == Y -> kill(MState), queue_goal(Z = 0) ; true ), @@ -5008,7 +5007,7 @@ run_propagator(pmod(X,Y,Z), MState) --> ), { fd_get(X, XD0, XPs), domain_remove_smaller_than(XD0, XMin, XD2) }, - fd_put(X, XD2, XPs) + fd_put(X, XD2, XPs) % queue_goal(X #>= XMin) ; true ), @@ -5016,7 +5015,7 @@ run_propagator(pmod(X,Y,Z), MState) --> XMax is Z + Y * ((XU - Z) div Y), { fd_get(X, XD1, XPs), domain_remove_greater_than(XD1, XMax, XD3) }, - fd_put(X, XD3, XPs) + fd_put(X, XD3, XPs) % queue_goal(X #=< XMax) ; true ) @@ -5041,13 +5040,13 @@ run_propagator(pmod(X,Y,Z), MState) --> { fd_get(Y, YD, YPs), YMin is Z + 1, domain_remove_smaller_than(YD, YMin, YD1) }, - fd_put(Y, YD1, YPs) + fd_put(Y, YD1, YPs) % queue_goal(Y #> Z) ; Z < 0 -> { fd_get(Y, YD, YPs), YMax is Z - 1, domain_remove_greater_than(YD, YMax, YD1) }, - fd_put(Y, YD1, YPs) + fd_put(Y, YD1, YPs) % queue_goal(Y #< Z) ; true ) @@ -5067,7 +5066,7 @@ run_propagator(pmodz(X,Y,Z), MState) --> queue_goal(Z = X) ; { fd_get(Z, ZD0, ZPs), domain_remove_greater_than(ZD0, X, ZD2) }, - fd_put(Z, ZD2, ZPs) + fd_put(Z, ZD2, ZPs) % queue_goal(Z #=< X) ) ; X < 0 -> @@ -5076,7 +5075,7 @@ run_propagator(pmodz(X,Y,Z), MState) --> queue_goal(Z = X) ; { fd_get(Z, ZD0, ZPs), domain_remove_smaller_than(ZD0, X, ZD2) }, - fd_put(Z, ZD2, ZPs) + fd_put(Z, ZD2, ZPs) % queue_goal(Z #>= X) ) ), @@ -5085,14 +5084,14 @@ run_propagator(pmodz(X,Y,Z), MState) --> { fd_get(Z, ZD1, ZPs), domain_remove_smaller_than(ZD1, 0, ZD3), domain_remove_greater_than(ZD3, ZMax, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in 0..ZMax) ; { fd_get(Y, _, n(YL), n(YU), _), YU < 0 } -> ZMin is YL + 1, { fd_get(Z, ZD1, ZPs), domain_remove_greater_than(ZD1, 0, ZD3), domain_remove_smaller_than(ZD3, ZMin, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in ZMin..0) ; true ) @@ -5107,7 +5106,7 @@ run_propagator(pmodz(X,Y,Z), MState) --> { fd_get(Z, ZD1, ZPs), domain_remove_greater_than(ZD1, 0, ZD3), domain_remove_smaller_than(ZD3, ZMin, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in ZMin..0) ) ; Y > 0 -> @@ -5118,7 +5117,7 @@ run_propagator(pmodz(X,Y,Z), MState) --> { fd_get(Z, ZD1, ZPs), domain_remove_smaller_than(ZD1, 0, ZD3), domain_remove_greater_than(ZD3, ZMax, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in 0..ZMax) ) ) @@ -5133,12 +5132,12 @@ run_propagator(pmodz(X,Y,Z), MState) --> ; ( { fd_get(X, _, n(XL), n(XU), _), XL >= 0 } -> { fd_get(Z, ZD0, ZPs), domain_remove_greater_than(ZD0, XU, ZD2) }, - fd_put(Z, ZD2, ZPs) + fd_put(Z, ZD2, ZPs) % queue_goal(Z #=< XU) ; { fd_get(X, _, n(XL), n(XU), _), XU =< 0 } -> { fd_get(Z, ZD0, ZPs), domain_remove_smaller_than(ZD0, XL, ZD2) }, - fd_put(Z, ZD2, ZPs) + fd_put(Z, ZD2, ZPs) % queue_goal(Z #>= XL) ; true ), @@ -5147,14 +5146,14 @@ run_propagator(pmodz(X,Y,Z), MState) --> { fd_get(Z, ZD1, ZPs), domain_remove_smaller_than(ZD1, 0, ZD3), domain_remove_greater_than(ZD3, ZMax, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in 0..ZMax) ; { fd_get(Y, _, n(YL), n(YU), _), YU < 0 } -> ZMin is YL + 1, { fd_get(Z, ZD1, ZPs), domain_remove_greater_than(ZD1, 0, ZD3), domain_remove_smaller_than(ZD3, ZMin, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in ZMin..0) ; { fd_get(Y, _, n(YL), n(YU), _) } -> ZMin is YL + 1, @@ -5162,19 +5161,19 @@ run_propagator(pmodz(X,Y,Z), MState) --> { fd_get(Z, ZD1, ZPs), domain_remove_greater_than(ZD1, ZMax, ZD3), domain_remove_smaller_than(ZD3, ZMin, ZD5) }, - fd_put(Z, ZD5, ZPs) + fd_put(Z, ZD5, ZPs) % queue_goal(Z in ZMin..ZMax) ; { fd_get(Y, _, _, n(YU), _), YU > 0 } -> { fd_get(Z, ZD1, ZPs), ZMax is YU - 1, domain_remove_greater_than(ZD1, ZMax, ZD3) }, - fd_put(Z, ZD3, ZPs) + fd_put(Z, ZD3, ZPs) % queue_goal(Z #< YU) ; { fd_get(Y, _, n(YL), _, _), YL < 0 } -> { fd_get(Z, ZD1, ZPs), ZMin is YL + 1, domain_remove_smaller_than(ZD1, ZMin, ZD3) }, - fd_put(Z, ZD3, ZPs) + fd_put(Z, ZD3, ZPs) % queue_goal(Z #> YL) ; true ) @@ -5185,29 +5184,31 @@ run_propagator(pmody(X,Y,Z), MState) --> ( nonvar(Y) -> true % Nothing to do. % ; nonvar(X) -> true ; nonvar(Z) -> - ( Z > 0 -> % queue_goal(Y #> Z) + ( Z > 0 -> { fd_get(Y, YD, YPs), YMin is Z + 1, domain_remove_smaller_than(YD, YMin, YD1) }, - fd_put(Y, YD1, YPs) - ; Z < 0 -> % queue_goal(Y #< Z) + fd_put(Y, YD1, YPs) + % queue_goal(Y #> Z) + ; Z < 0 -> { fd_get(Y, YD, YPs), YMax is Z - 1, domain_remove_greater_than(YD, YMax, YD1) }, - fd_put(Y, YD1, YPs) + fd_put(Y, YD1, YPs) + % queue_goal(Y #< Z) ; Z =:= 0 -> kill(MState), queue_goal(X / Y #= _) ) ; ( { fd_get(Z, _, n(ZL), _, _), ZL > 0 } -> { fd_get(Y, YD, YPs), YMin is ZL + 1, domain_remove_smaller_than(YD, YMin, YD1) }, - fd_put(Y, YD1, YPs) + fd_put(Y, YD1, YPs) % queue_goal(Y #> ZL) ; { fd_get(Z, _, _, n(ZU), _), ZU < 0 } -> { fd_get(Y, YD, YPs), YMax is ZU - 1, domain_remove_greater_than(YD, YMax, YD1) }, - fd_put(Y, YD1, YPs) + fd_put(Y, YD1, YPs) % queue_goal(Y #< ZU) ; true ) From 770a682d8bb6b660f31f1b1c8b6426b609b13489 Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 27 May 2023 13:19:19 +0200 Subject: [PATCH 27/40] Don't add variable ?- Z #= 0, Z #= X mod Y. Z = 0, clpz:(_A*Y#=X), clpz:(Y in inf.. -1\/1..sup) % Unexpected. The expected result: Z = 0, clpz:(X mod Y#=0), clpz:(Y in inf.. -1\/1..sup). --- src/lib/clpz.pl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index 43b8f26e..4cdcdc9a 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -5019,8 +5019,6 @@ run_propagator(pmod(X,Y,Z), MState) --> % queue_goal(X #=< XMax) ; true ) - % kill(MState), - % queue_goal(X #= Z + Y * _) % Add a variable to be efficient. ; nonvar(Z), nonvar(X) -> ( Z > 0 -> ( X < 0 -> true @@ -5180,7 +5178,7 @@ run_propagator(pmodz(X,Y,Z), MState) --> ) ). -run_propagator(pmody(X,Y,Z), MState) --> +run_propagator(pmody(_X,Y,Z), _MState) --> ( nonvar(Y) -> true % Nothing to do. % ; nonvar(X) -> true ; nonvar(Z) -> @@ -5196,7 +5194,7 @@ run_propagator(pmody(X,Y,Z), MState) --> domain_remove_greater_than(YD, YMax, YD1) }, fd_put(Y, YD1, YPs) % queue_goal(Y #< Z) - ; Z =:= 0 -> kill(MState), queue_goal(X / Y #= _) + ; Z =:= 0 % Multiple solutions so do nothing special. ) ; ( { fd_get(Z, _, n(ZL), _, _), ZL > 0 } -> { fd_get(Y, YD, YPs), From 911c49c43f5e1005baf5fb4fef5829629addc923 Mon Sep 17 00:00:00 2001 From: notoria Date: Sat, 27 May 2023 13:47:14 +0200 Subject: [PATCH 28/40] Compute correctly the domain of the remainder --- src/lib/clpz.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index 4cdcdc9a..8f9c6bf8 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -5153,7 +5153,7 @@ run_propagator(pmodz(X,Y,Z), MState) --> domain_remove_smaller_than(ZD3, ZMin, ZD5) }, fd_put(Z, ZD5, ZPs) % queue_goal(Z in ZMin..0) - ; { fd_get(Y, _, n(YL), n(YU), _) } -> + ; { fd_get(Y, _, n(YL), n(YU), _), YL < 0, YU > 0 } -> ZMin is YL + 1, ZMax is YU - 1, { fd_get(Z, ZD1, ZPs), From 749dedf47773be2b36fadf990aa4ebced1564064 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 26 May 2023 15:19:07 -0600 Subject: [PATCH 29/40] read from machine stack in stackful pre-order iterator (#1812) --- src/heap_print.rs | 80 ++++++++++++++--------------- src/machine/arithmetic_ops.rs | 2 +- src/machine/attributed_variables.rs | 6 +-- src/machine/gc.rs | 6 +-- src/machine/machine_state.rs | 6 +-- src/machine/machine_state_impl.rs | 4 +- src/machine/system_calls.rs | 4 +- src/machine/unify.rs | 8 +-- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index 26f3f5d2..d4b74378 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -116,7 +116,9 @@ impl<'a> StackfulPreOrderHeapIter<'a> { let mut parent_spec = DirectedOp::Left(atom!("-"), OpDesc::build_with(200, FY as u8)); loop { - read_heap_cell!(self.heap[h], + let cell = self.read_cell(h); + + read_heap_cell!(cell, (HeapCellValueTag::Str, s) => { read_heap_cell!(self.heap[s], (HeapCellValueTag::Atom, (name, _arity)) => { @@ -125,7 +127,7 @@ impl<'a> StackfulPreOrderHeapIter<'a> { if needs_bracketing(spec, &parent_spec) { return false; } else { - h = s + 1; + h = IterStackLoc::iterable_loc(s + 1, HeapOrStackTag::Heap); parent_spec = DirectedOp::Right(name, spec); continue; } @@ -140,7 +142,7 @@ impl<'a> StackfulPreOrderHeapIter<'a> { ) } _ => { - return property_check(self.heap[h]); + return property_check(cell); } ) } @@ -150,12 +152,12 @@ impl<'a> StackfulPreOrderHeapIter<'a> { where P: Fn(HeapCellValue) -> bool, { - let addr = match self.stack_last() { - Some(h) => self.heap[h], + let cell = match self.stack_last() { + Some(h) => self.read_cell(h), None => return false, }; - property_check(addr) + property_check(cell) } } @@ -475,7 +477,6 @@ pub struct HCPrinter<'a, Outputter> { outputter: Outputter, iter: StackfulPreOrderHeapIter<'a>, atom_tbl: &'a mut AtomTable, - stack: &'a Stack, op_dir: &'a OpDir, state_stack: Vec, toplevel_spec: Option, @@ -541,16 +542,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn new( heap: &'a mut Heap, atom_tbl: &'a mut AtomTable, - stack: &'a Stack, + stack: &'a mut Stack, op_dir: &'a OpDir, output: Outputter, cell: HeapCellValue, ) -> Self { HCPrinter { outputter: output, - iter: stackful_preorder_iter(heap, cell), + iter: stackful_preorder_iter(heap, stack, cell), atom_tbl, - stack, op_dir, state_stack: vec![], toplevel_spec: None, @@ -758,14 +758,14 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn format_numbered_vars(&mut self) -> bool { let h = self.iter.stack_last().unwrap(); - let addr = self.iter.heap[h]; - let addr = heap_bound_store( + let cell = self.iter.read_cell(h); + let cell = heap_bound_store( &self.iter.heap, - heap_bound_deref(&self.iter.heap, addr), + heap_bound_deref(&self.iter.heap, cell), ); // 7.10.4 - if let Some(var) = numbervar(&self.numbervars_offset, addr) { + if let Some(var) = numbervar(&self.numbervars_offset, cell) { self.iter.pop_stack(); self.state_stack.push(TokenOrRedirect::NumberedVar(var)); return true; @@ -809,11 +809,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }; } - fn offset_as_string(&mut self, h: usize) -> Option { - let addr = self.iter.heap[h]; + fn offset_as_string(&mut self, h: IterStackLoc) -> Option { + let cell = self.iter.read_cell(h); - if let Some(var) = self.var_names.get(&addr) { - read_heap_cell!(addr, + if let Some(var) = self.var_names.get(&cell) { + read_heap_cell!(cell, (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { return Some(var.borrow().to_string()); } @@ -824,7 +824,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { ); } - read_heap_cell!(addr, + read_heap_cell!(cell, (HeapCellValueTag::Lis | HeapCellValueTag::Str, h) => { Some(format!("{}", h)) } @@ -1169,7 +1169,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn print_list_like(&mut self, mut max_depth: usize) { let focus = self.iter.focus(); - let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus); + let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus.value() as usize); if heap_pstr_iter.next().is_some() { while let Some(_) = heap_pstr_iter.next() {} @@ -1181,7 +1181,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let end_cell = heap_pstr_iter.focus; if self.check_max_depth(&mut max_depth) { - self.remove_list_children(focus); + self.remove_list_children(focus.value() as usize); self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); return; } @@ -1189,26 +1189,26 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let at_cdr = self.outputter.ends_with("|"); if !at_cdr && !self.ignore_ops && end_cell.is_string_terminator(&self.iter.heap) { - self.remove_list_children(focus); - return self.print_proper_string(focus, max_depth); + self.remove_list_children(focus.value() as usize); + return self.print_proper_string(focus.value() as usize, max_depth); } if self.ignore_ops { self.at_cdr(","); - self.remove_list_children(focus); + self.remove_list_children(focus.value() as usize); - if !self.print_string_as_functor(focus, max_depth) { + if !self.print_string_as_functor(focus.value() as usize, max_depth) { if end_cell == empty_list_as_cell!() { append_str!(self, "[]"); } else { self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); - self.iter.push_stack(end_h); + self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap)); } } } else { let value = heap_bound_store( self.iter.heap, - heap_bound_deref(self.iter.heap, self.iter.heap[focus]), + heap_bound_deref(self.iter.heap, self.iter.read_cell(focus)), ); read_heap_cell!(value, @@ -1219,7 +1219,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let switch = Rc::new(Cell::new((!at_cdr, 0))); self.state_stack.push(TokenOrRedirect::CloseList(switch.clone())); - let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus); + let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus.value() as usize); let pstr = cell_as_string!(self.iter.heap[h]); let pstr = pstr.as_str_from(offset.get_num() as usize); @@ -1241,7 +1241,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.state_stack.push(TokenOrRedirect::HeadTailSeparator); } else if end_cell != empty_list_as_cell!() { if tag == HeapCellValueTag::PStrOffset { - self.iter.push_stack(end_h); + self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap)); } self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); @@ -1599,8 +1599,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn print(mut self) -> Outputter { let spec = self.toplevel_spec.take(); - - self.iter.iterate_over_machine_stack(self.stack); self.handle_heap_term(spec, false, self.max_depth); while let Some(loc_data) = self.state_stack.pop() { @@ -1672,7 +1670,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1701,7 +1699,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1725,7 +1723,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1738,7 +1736,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1769,7 +1767,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1788,7 +1786,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1805,7 +1803,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1835,7 +1833,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1858,7 +1856,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), pstr_loc_as_cell!(0) @@ -1886,7 +1884,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 774b848f..f5aa982f 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1106,7 +1106,7 @@ impl MachineState { pub(crate) fn arith_eval_by_metacall(&mut self, value: HeapCellValue) -> Result { let stub_gen = || functor_stub(atom!("is"), 2); - let mut iter = stackful_post_order_iter(&mut self.heap, value); + let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { if value.get_forwarding_bit() { diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index 57ea1c22..633378a0 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -136,7 +136,7 @@ impl MachineState { let mut seen_set = IndexSet::new(); let mut seen_vars = vec![]; - let mut iter = stackful_preorder_iter(&mut self.heap, cell); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, cell); while let Some(value) = iter.next() { read_heap_cell!(value, @@ -147,7 +147,7 @@ impl MachineState { let value = unmark_cell_bits!(value); - if h != iter.focus() { + if h != iter.focus().value() as usize { let deref_value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value)); if deref_value.is_compound(iter.heap) { @@ -167,7 +167,7 @@ impl MachineState { loop { read_heap_cell!(iter.heap[l], (HeapCellValueTag::Lis) => { - iter.push_stack(l); + iter.push_stack(IterStackLoc::iterable_loc(l, HeapOrStackTag::Heap)); // l = elem + 1; break; } diff --git a/src/machine/gc.rs b/src/machine/gc.rs index 8a884950..1de28ffe 100644 --- a/src/machine/gc.rs +++ b/src/machine/gc.rs @@ -3,7 +3,7 @@ use crate::machine::heap::*; use crate::types::*; #[cfg(test)] -use crate::heap_iter::FocusedHeapIter; +use crate::heap_iter::{IterStackLoc, FocusedHeapIter, HeapOrStackTag}; use core::marker::PhantomData; @@ -75,8 +75,8 @@ pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> { #[cfg(test)] impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> { #[inline] - fn focus(&self) -> usize { - self.current + fn focus(&self) -> IterStackLoc { + IterStackLoc::iterable_loc(self.current, HeapOrStackTag::Heap) } } diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 0203f62f..de034374 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -557,10 +557,10 @@ impl MachineState { let mut singleton_var_set: IndexMap = IndexMap::new(); - for addr in stackful_preorder_iter(&mut self.heap, term) { - let addr = unmark_cell_bits!(addr); + for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, term) { + let cell = unmark_cell_bits!(cell); - if let Some(var) = addr.as_var() { + if let Some(var) = cell.as_var() { if !singleton_var_set.contains_key(&var) { singleton_var_set.insert(var, true); } else { diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index b457ecae..b4dc3fea 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1125,7 +1125,7 @@ impl MachineState { return false; } - let mut iter = stackful_preorder_iter(&mut self.heap, value); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { if value.get_forwarding_bit() { @@ -1626,7 +1626,7 @@ impl MachineState { return true; } - let mut iter = stackful_preorder_iter(&mut self.heap, value); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { let value = unmark_cell_bits!(value); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 7985f5fe..a871750a 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -531,7 +531,7 @@ impl MachineState { seen_set: &mut IndexSet, value: HeapCellValue, ) { - let mut iter = stackful_preorder_iter(&mut self.heap, value); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { let value = unmark_cell_bits!(value); @@ -721,7 +721,7 @@ impl MachineState { let mut seen_set = IndexSet::new(); { - let mut iter = stackful_post_order_iter(&mut self.heap, term); + let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term); while let Some(value) = iter.next() { if iter.parent_stack_len() >= max_depth { diff --git a/src/machine/unify.rs b/src/machine/unify.rs index 19445fe4..d6401b92 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -651,10 +651,12 @@ fn bind_with_occurs_check(unifier: &mut U, r: Ref, value: HeapCellVa let mut occurs_triggered = false; if !value.is_constant() { - for addr in stackful_preorder_iter(&mut unifier.heap, value) { - let addr = unmark_cell_bits!(addr); + let machine_st: &mut MachineState = unifier.deref_mut(); - if let Some(inner_r) = addr.as_var() { + for cell in stackful_preorder_iter(&mut machine_st.heap, &mut machine_st.stack, value) { + let cell = unmark_cell_bits!(cell); + + if let Some(inner_r) = cell.as_var() { if r == inner_r { occurs_triggered = true; break; From c5c83d724a920bebd54397d3999f303c31acf982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Mon, 29 May 2023 00:29:53 +0200 Subject: [PATCH 30/40] Rename INDEX.md to INDEX.dj and add banner about Scryer Prolog Meetup --- INDEX.md => INDEX.dj | 7 +++++++ 1 file changed, 7 insertions(+) rename INDEX.md => INDEX.dj (87%) diff --git a/INDEX.md b/INDEX.dj similarity index 87% rename from INDEX.md rename to INDEX.dj index 907d1e9c..c7cf6a11 100644 --- a/INDEX.md +++ b/INDEX.dj @@ -5,6 +5,13 @@ X = "Scryer Prolog!". ``` +``` =html +
+

Scryer Prolog Meetup 2023

+

The first annual Scryer Prolog meetup is going to happen in Düsseldorf (Germany) on the 9th and 10th of November 2023. Join us to discover the present and future of Scryer Prolog! Participation is free, registration not required. More details here.

+
+``` + ![scryer](scryer.png){width=128 style=float:right;} [Scryer Prolog](https://github.com/mthom/scryer-prolog) is a free software ISO Prolog system intended to be an industrial strength production environment *and* a testbed for bleeding edge research in logic and constraint programming. From 2716381e7b20fae2b0fb8e8e80f26d4582b345f9 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 29 May 2023 11:12:00 +0200 Subject: [PATCH 31/40] FIXED: correct dereferencing in atom_codes/2 and number_codes/2. This addresses #1818. Test case: run :- length(Ls, L), portray_clause(L), maplist(=(X), Ls), X = Y, Y = 12, atom_codes(_, Ls), false. --- src/machine/system_calls.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index a871750a..5fc5d451 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1010,6 +1010,8 @@ impl MachineState { let mut string = String::new(); for addr in addrs { + let addr = self.store(self.deref(addr)); + match Number::try_from(addr) { Ok(Number::Fixnum(n)) => { match u32::try_from(n.get_num()) { From 5ed1802f0fb5ce6202af79fac23a988d8bc445a1 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 29 May 2023 20:49:54 -0600 Subject: [PATCH 32/40] read set_value args from temp regs of put_unsafe_value (#1812) --- src/fixtures.rs | 439 ++++++++++++++++++++++++++++++++++++++++++++++ src/heap_print.rs | 20 +-- 2 files changed, 449 insertions(+), 10 deletions(-) create mode 100644 src/fixtures.rs diff --git a/src/fixtures.rs b/src/fixtures.rs new file mode 100644 index 00000000..01a5e385 --- /dev/null +++ b/src/fixtures.rs @@ -0,0 +1,439 @@ +use crate::parser::ast::*; + +use crate::forms::*; +use crate::instructions::*; +use crate::iterators::*; + +use indexmap::{IndexMap, IndexSet}; + +use std::cell::Cell; +use std::collections::BTreeSet; +use std::mem::swap; +use std::rc::Rc; +use std::vec::Vec; + +// labeled with chunk numbers. +#[derive(Debug)] +pub(crate) enum VarStatus { + Perm(usize), + Temp(usize, TempVarData), // Perm(chunk_num) | Temp(chunk_num, _) +} + +pub(crate) type OccurrenceSet = BTreeSet<(GenContext, usize)>; + +// Perm: 0 initially, a stack register once processed. +// Temp: labeled with chunk_num and temp offset (unassigned if 0). +#[derive(Debug)] +pub(crate) enum VarData { + Perm(usize), + Temp(usize, usize, TempVarData), +} + +impl VarData { + pub(crate) fn as_reg_type(&self) -> RegType { + match self { + &VarData::Temp(_, r, _) => RegType::Temp(r), + &VarData::Perm(r) => RegType::Perm(r), + } + } +} + +#[derive(Debug)] +pub(crate) struct TempVarData { + pub(crate) last_term_arity: usize, + pub(crate) use_set: OccurrenceSet, + pub(crate) no_use_set: BTreeSet, + pub(crate) conflict_set: BTreeSet, +} + +impl TempVarData { + pub(crate) fn new(last_term_arity: usize) -> Self { + TempVarData { + last_term_arity: last_term_arity, + use_set: BTreeSet::new(), + no_use_set: BTreeSet::new(), + conflict_set: BTreeSet::new(), + } + } + + pub(crate) fn uses_reg(&self, reg: usize) -> bool { + for &(_, nreg) in self.use_set.iter() { + if reg == nreg { + return true; + } + } + + return false; + } + + pub(crate) fn populate_conflict_set(&mut self) { + if self.last_term_arity > 0 { + let arity = self.last_term_arity; + let mut conflict_set: BTreeSet = (1..arity).collect(); + + for &(_, reg) in self.use_set.iter() { + conflict_set.remove(®); + } + + self.conflict_set = conflict_set; + } + } +} + +type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); + +#[derive(Debug)] +pub(crate) struct VariableFixtures<'a> { + perm_vars: IndexMap, VariableFixture<'a>>, + last_chunk_temp_vars: IndexSet>, +} + +impl<'a> VariableFixtures<'a> { + pub(crate) fn new() -> Self { + VariableFixtures { + perm_vars: IndexMap::new(), + last_chunk_temp_vars: IndexSet::new(), + } + } + + pub(crate) fn insert(&mut self, var: Rc, vs: VariableFixture<'a>) { + self.perm_vars.insert(var, vs); + } + + pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Rc) { + self.last_chunk_temp_vars.insert(var); + } + + // computes no_use and conflict sets for all temp vars. + pub(crate) fn populate_restricting_sets(&mut self) { + // three stages: + // 1. move the use sets of each variable to a local IndexMap, use_set + // (iterate mutably, swap mutable refs). + // 2. drain use_set. For each use set of U, add into the + // no-use sets of appropriate variables T =/= U. + // 3. Move the use sets back to their original locations in the fixture. + // Compute the conflict set of u. + + // 1. + let mut use_sets: IndexMap, OccurrenceSet> = IndexMap::new(); + + for (var, &mut (ref mut var_status, _)) in self.iter_mut() { + if let &mut VarStatus::Temp(_, ref mut var_data) = var_status { + let mut use_set = OccurrenceSet::new(); + + swap(&mut var_data.use_set, &mut use_set); + use_sets.insert((*var).clone(), use_set); + } + } + + for (u, use_set) in use_sets.drain(..) { + // 2. + for &(term_loc, reg) in use_set.iter() { + if let GenContext::Last(cn_u) = term_loc { + for (ref t, &mut (ref mut var_status, _)) in self.iter_mut() { + if let &mut VarStatus::Temp(cn_t, ref mut t_data) = var_status { + if cn_u == cn_t && *u != ***t { + if !t_data.uses_reg(reg) { + t_data.no_use_set.insert(reg); + } + } + } + } + } + } + + // 3. + match self.get_mut(u).unwrap() { + &mut (VarStatus::Temp(_, ref mut u_data), _) => { + u_data.use_set = use_set; + u_data.populate_conflict_set(); + } + _ => {} + }; + } + } + + fn get_mut(&mut self, u: Rc) -> Option<&mut VariableFixture<'a>> { + self.perm_vars.get_mut(&u) + } + + fn iter_mut(&mut self) -> indexmap::map::IterMut, VariableFixture<'a>> { + self.perm_vars.iter_mut() + } + + fn record_temp_info(&mut self, tvd: &mut TempVarData, arg_c: usize, term_loc: GenContext) { + match term_loc { + GenContext::Head | GenContext::Last(_) => { + tvd.use_set.insert((term_loc, arg_c)); + } + _ => {} + }; + } + + pub(crate) fn vars_above_threshold(&self, index: usize) -> usize { + let mut var_count = 0; + + for &(ref var_status, _) in self.values() { + if let &VarStatus::Perm(i) = var_status { + if i > index { + var_count += 1; + } + } + } + + var_count + } + + pub(crate) fn mark_vars_in_chunk(&mut self, iter: I, lt_arity: usize, term_loc: GenContext) + where + I: Iterator>, + { + let chunk_num = term_loc.chunk_num(); + let mut arg_c = 1; + + for term_ref in iter { + if let &TermRef::Var(lvl, cell, ref var) = &term_ref { + let mut status = self.perm_vars.swap_remove(var).unwrap_or(( + VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), + Vec::new(), + )); + + status.1.push(cell); + + match status.0 { + VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => { + if let Level::Shallow = lvl { + self.record_temp_info(tvd, arg_c, term_loc); + } + } + _ => status.0 = VarStatus::Perm(chunk_num), + }; + + self.perm_vars.insert(var.clone(), status); + } + + if let Level::Shallow = term_ref.level() { + arg_c += 1; + } + } + } + + pub(crate) fn into_iter(self) -> indexmap::map::IntoIter, VariableFixture<'a>> { + self.perm_vars.into_iter() + } + + fn values(&self) -> indexmap::map::Values, VariableFixture<'a>> { + self.perm_vars.values() + } + + pub(crate) fn size(&self) -> usize { + self.perm_vars.len() + } + + pub(crate) fn set_perm_vals(&self, has_deep_cuts: bool) { + let mut values_vec: Vec<_> = self + .values() + .filter_map(|ref v| match &v.0 { + &VarStatus::Perm(i) => Some((i, &v.1)), + _ => None, + }) + .collect(); + + values_vec.sort_by_key(|ref v| v.0); + + let offset = has_deep_cuts as usize; + + for (i, (_, cells)) in values_vec.into_iter().rev().enumerate() { + for cell in cells { + cell.set(VarReg::Norm(RegType::Perm(i + 1 + offset))); + } + } + } +} + +#[derive(Debug)] +pub(crate) struct UnsafeVarMarker { + pub(crate) unsafe_perm_vars: IndexMap, + pub(crate) unsafe_temp_vars: IndexSet, + pub(crate) safe_perm_vars: IndexSet, + pub(crate) safe_temp_vars: IndexSet, + pub(crate) temp_vars_to_perm_vars: IndexMap, + pub(crate) perm_vars_to_temp_vars: IndexMap, +} + +impl UnsafeVarMarker { + pub(crate) fn new() -> Self { + UnsafeVarMarker { + unsafe_perm_vars: IndexMap::new(), + unsafe_temp_vars: IndexSet::new(), + safe_perm_vars: IndexSet::new(), + safe_temp_vars: IndexSet::new(), + temp_vars_to_perm_vars: IndexMap::new(), + perm_vars_to_temp_vars: IndexMap::new(), + } + } + + pub(crate) fn from_fact_vars(safe_vars: IndexSet) -> Self { + let mut unsafe_var_marker = Self::new(); + + for r in safe_vars { + unsafe_var_marker.mark_var_as_safe(r); + } + + unsafe_var_marker + } + + fn mark_var_as_safe(&mut self, r: RegType) { + match r { + RegType::Temp(t) => { + self.safe_temp_vars.insert(t); + } + RegType::Perm(p) => { + self.safe_perm_vars.insert(p); + } + }; + } + + fn mark_var_as_unsafe(&mut self, r: RegType, phase: usize) { + match r { + RegType::Temp(t) => { + self.unsafe_temp_vars.insert(t); + } + RegType::Perm(p) => { + self.unsafe_perm_vars.insert(p, phase); + } + } + } + + // returns true if the instruction at *query_instr cannot be + // changed by mark_unsafe_vars. + fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool { + match query_instr { + &Instruction::PutVariable(r @ RegType::Temp(_), _) | + &Instruction::SetVariable(r) => { + self.mark_var_as_safe(r); + true + } + &Instruction::PutVariable(RegType::Perm(p), t) => { + self.temp_vars_to_perm_vars.insert(t, p); + true + } + &Instruction::CallIs(RegType::Temp(t), ..) => { + if let Some(p) = self.temp_vars_to_perm_vars.get(&t) { + self.mark_var_as_safe(RegType::Perm(*p)); + } + + true + } + _ => false, + } + } + + fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) { + match query_instr { + &Instruction::PutValue(r @ RegType::Perm(_), _) | + &Instruction::SetValue(r) => { + self.mark_var_as_unsafe(r, phase); + } + _ => {} + } + } + + fn mark_unsafe_perm_vars(&mut self, query_instr: &mut Instruction, phase: usize) { + match query_instr { + &mut Instruction::PutValue(RegType::Perm(p), arg) + if !self.safe_perm_vars.contains(&p) => { + if let Some(ph) = self.unsafe_perm_vars.swap_remove(&p) { + if ph == phase { + *query_instr = Instruction::PutUnsafeValue(p, arg); + self.perm_vars_to_temp_vars.insert(p, arg); + } else { + self.unsafe_perm_vars.insert(p, ph); + } + } + } + &mut Instruction::SetValue(r @ RegType::Perm(p)) => + if let Some(t) = self.perm_vars_to_temp_vars.get(&p) { + *query_instr = Instruction::SetValue(RegType::Temp(*t)); + } else { + *query_instr = Instruction::SetLocalValue(r); + + self.safe_perm_vars.insert(p); + self.unsafe_perm_vars.remove(&p); + } + _ => {} + } + } + + fn mark_unsafe_temp_vars(&mut self, query_instr: &mut Instruction) { + match query_instr { + &mut Instruction::SetValue(r @ RegType::Temp(t)) + if !self.safe_temp_vars.contains(&t) => { + *query_instr = Instruction::SetLocalValue(r); + + self.safe_temp_vars.insert(t); + self.unsafe_temp_vars.remove(&t); + } + _ => { + } + } + } + + fn clear_temp_vars(&mut self) { + self.safe_temp_vars.clear(); + self.unsafe_temp_vars.clear(); + self.temp_vars_to_perm_vars.clear(); + } + + pub(crate) fn mark_unsafe_instrs(&mut self, code: &mut Code) { + if code.is_empty() { + return; + } + + let mut code_index = 0; + + for phase in 0.. { + while code[code_index].is_query_instr() { + let query_instr = &mut code[code_index]; + + if !self.mark_safe_vars(query_instr) { + self.mark_phase(query_instr, phase); + self.mark_unsafe_temp_vars(query_instr); + } + + code_index += 1; + } + + while code_index < code.len() && !code[code_index].is_query_instr() { + self.mark_safe_vars(&code[code_index]); + code_index += 1; + } + + self.clear_temp_vars(); + + if code_index >= code.len() { + break; + } + } + + code_index = 0; + + for phase in 0.. { + while code[code_index].is_query_instr() { + let query_instr = &mut code[code_index]; + self.mark_unsafe_perm_vars(query_instr, phase); + code_index += 1; + } + + // ensure phase->instruction assignments match those of + // the previous for loop. + while code_index < code.len() && !code[code_index].is_query_instr() { + code_index += 1; + } + + if code_index >= code.len() { + break; + } + } + } +} diff --git a/src/heap_print.rs b/src/heap_print.rs index d4b74378..5b0b40b4 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -841,19 +841,19 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } fn check_for_seen(&mut self) -> Option { - if let Some(addr) = self.iter.next() { - let is_cyclic = addr.get_forwarding_bit(); + if let Some(cell) = self.iter.next() { + let is_cyclic = cell.get_forwarding_bit(); - let addr = heap_bound_store( + let cell = heap_bound_store( self.iter.heap, - heap_bound_deref(self.iter.heap, addr), + heap_bound_deref(self.iter.heap, cell), ); - let addr = unmark_cell_bits!(addr); + let cell = unmark_cell_bits!(cell); - match self.var_names.get(&addr).cloned() { - Some(var) if addr.is_var() => { - // If addr is an unbound variable and maps to + match self.var_names.get(&cell).cloned() { + Some(var) if cell.is_var() => { + // If cell is an unbound variable and maps to // a name via heap_locs, append the name to // the current output, and return None. None // short-circuits handle_heap_term. @@ -868,7 +868,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { None } var_opt => { - if is_cyclic && addr.is_compound(self.iter.heap) { + if is_cyclic && cell.is_compound(self.iter.heap) { // self-referential variables are marked "cyclic". match var_opt { Some(var) => { @@ -891,7 +891,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { return None; } - Some(addr) + Some(cell) } } } else { From 4d982d22c140bea42e350ba4b423d15ad27f9b34 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 6 Jun 2023 00:58:44 -0600 Subject: [PATCH 33/40] set_local_value does not make values safe (#1812) --- src/fixtures.rs | 3 --- src/heap_print.rs | 1 - 2 files changed, 4 deletions(-) diff --git a/src/fixtures.rs b/src/fixtures.rs index 01a5e385..1f812e2c 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -357,9 +357,6 @@ impl UnsafeVarMarker { *query_instr = Instruction::SetValue(RegType::Temp(*t)); } else { *query_instr = Instruction::SetLocalValue(r); - - self.safe_perm_vars.insert(p); - self.unsafe_perm_vars.remove(&p); } _ => {} } diff --git a/src/heap_print.rs b/src/heap_print.rs index 5b0b40b4..f846dea1 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -848,7 +848,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.iter.heap, heap_bound_deref(self.iter.heap, cell), ); - let cell = unmark_cell_bits!(cell); match self.var_names.get(&cell).cloned() { From d7f56757272f83139e91c2ddeb489c581e8a0c5f Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 10 Jun 2023 01:25:47 -0600 Subject: [PATCH 34/40] improve call/N implementation (#1829) --- build/instructions_template.rs | 12 +- src/loader.pl | 1225 +++++++++++--------------------- src/machine/dispatch.rs | 8 +- src/machine/loader.rs | 15 + src/machine/machine_indices.rs | 10 +- src/machine/system_calls.rs | 273 +++---- src/macros.rs | 1 + src/toplevel.pl | 3 +- 8 files changed, 596 insertions(+), 951 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 25036607..7687d4e0 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -560,8 +560,8 @@ enum SystemClauseType { StripModule, #[strum_discriminants(strum(props(Arity = "4", Name = "$compile_inline_or_expanded_goal")))] CompileInlineOrExpandedGoal, - #[strum_discriminants(strum(props(Arity = "arity", Name = "$call_inline")))] - InlineCallN(usize), + #[strum_discriminants(strum(props(Arity = "arity", Name = "$fast_call")))] + FastCallN(usize), #[strum_discriminants(strum(props(Arity = "1", Name = "$is_expanded_or_inlined")))] IsExpandedOrInlined, #[strum_discriminants(strum(props(Arity = "3", Name = "$get_clause_p")))] @@ -1472,11 +1472,11 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::DefaultExecuteN(arity) => { functor!(atom!("execute_default_n"), [fixnum(arity)]) } - &Instruction::CallInlineCallN(arity) => { - functor!(atom!("call_n_inline"), [fixnum(arity)]) + &Instruction::CallFastCallN(arity) => { + functor!(atom!("call_fast_call_n"), [fixnum(arity)]) } - &Instruction::ExecuteInlineCallN(arity) => { - functor!(atom!("call_n_inline"), [fixnum(arity)]) + &Instruction::ExecuteFastCallN(arity) => { + functor!(atom!("execute_fast_call_n"), [fixnum(arity)]) } &Instruction::CallTermGreaterThan | &Instruction::CallTermLessThan | diff --git a/src/loader.pl b/src/loader.pl index 5c35822e..f809cd1a 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -758,7 +758,6 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals) :- UnexpandedGoals = ExpandedGoals), !. - :- non_counted_backtracking expand_goal/4. expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- @@ -779,7 +778,6 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- ) ). - /* * private predicate for use in call/N. it doesn't specially consider * control predicates as expand_goal does with expand_goal_cases. @@ -790,27 +788,20 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- expand_call_goal(UnexpandedGoals, Module, ExpandedGoals) :- % if a goal isn't callable, defer to call/N to report the error. - catch(loader:expand_call_goal_(UnexpandedGoals, Module, ExpandedGoals), + catch('$call'(loader:expand_call_goal_(UnexpandedGoals, Module, ExpandedGoals)), error(type_error(callable, _), _), - UnexpandedGoals = ExpandedGoals), + '$call'(UnexpandedGoals = ExpandedGoals)), !. - :- non_counted_backtracking expand_call_goal_/3. expand_call_goal_(UnexpandedGoals, Module, ExpandedGoals) :- ( var(UnexpandedGoals) -> - expand_module_names(call(UnexpandedGoals), [0], Module, ExpandedGoals, []) + UnexpandedGoals = ExpandedGoals ; goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1), ( Module \== user -> - goal_expansion(UnexpandedGoals1, user, Goals) - ; Goals = UnexpandedGoals1 - ), - ( predicate_property(Module:Goals, meta_predicate(MetaSpecs0)), - MetaSpecs0 =.. [_ | MetaSpecs] -> - expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, []) - ; thread_goals(Goals, ExpandedGoals, (',')) - ; Goals = ExpandedGoals + goal_expansion(UnexpandedGoals1, user, ExpandedGoals) + ; ExpandedGoals = UnexpandedGoals1 ) ). @@ -838,7 +829,6 @@ expand_goal_cases((Module:Goals0), _, ExpandedGoals, HeadVars) :- expand_goal(Goals0, Module, Goals1, HeadVars), ExpandedGoals = (Module:Goals1). - :- non_counted_backtracking thread_goals/3. thread_goals(Goals0, Goals1, Functor) :- @@ -853,7 +843,6 @@ thread_goals(Goals0, Goals1, Functor) :- ; Goals1 = Goals0 ). - :- non_counted_backtracking thread_goals/4. thread_goals(Goals0, Goals1, Hole, Functor) :- @@ -872,8 +861,6 @@ thread_goals(Goals0, Goals1, Hole, Functor) :- % % call/{1-64} with dynamic goal expansion. % -% The program used to generate the call/N predicates: -% % :- use_module(library(between)). % :- use_module(library(error)). % :- use_module(library(lists)). @@ -884,22 +871,18 @@ thread_goals(Goals0, Goals1, Hole, Functor) :- % Head =.. [call, G | Args], % CallNHead =.. [call, '$call'(G) | Args], % N1 is N + 1, -% InlineCall =.. ['$call_inline', G0 | Args], -% CallClause =.. ['$prepare_call_clause', G1, M1, G | Args], -% ModuleCallClause0 =.. ['$module_call', M1, G1], -% ModuleCallClause1 =.. ['$module_call', M2, G3], +% StripModule =.. ['$strip_module', G, M1, G1], +% FastCall =.. ['$fast_call', G | Args], +% PrepareCallClause =.. [ '$prepare_call_clause', G2, G1 | Args], +% ModuleCall =.. ['$module_call', M2, G4], % Clauses = [(Head :- var(G), % instantiation_error(call/N1)), -% (Head :- '$strip_module'(G, _, G0), InlineCall), -% (CallNHead :- !, -% CallClause, -% '$call_with_inference_counting'(ModuleCallClause0)), -% (Head :- CallClause, -% ( '$call_inline'(G1) -% ; expand_call_goal(G1, M1, G2), -% strip_subst_module(G2, M1, M2, G3), -% '$call_with_inference_counting'(ModuleCallClause1) -% ))]. +% (Head :- FastCall), +% (Head :- StripModule, +% PrepareCallClause, +% expand_call_goal(G2, M1, G3), +% strip_subst_module(G3, M1, M2, G4), +% '$call_with_inference_counting'(ModuleCall))]. % % generate_call_forms :- % between(1, 64, N), @@ -915,1237 +898,847 @@ thread_goals(Goals0, Goals1, Hole, Functor) :- % The '$call' functor is an escape hatch from goal expansion. So far, % it is used only to avoid infinite recursion into expand_call_goal/3. -:-non_counted_backtracking call/1. +:- non_counted_backtracking call/1. + call(G) :- - var(G), - instantiation_error(call/1). + var(G), + instantiation_error(call/1). call(G) :- - '$strip_module'(G, _, G0), - '$call_inline'(G0). -call('$call'(G0)) :- - !, - '$prepare_call_clause'(G,M,G0), - '$call_with_inference_counting'('$module_call'(M, G)). -call(G) :- - '$prepare_call_clause'(G0,M1,G), - ( '$call_inline'(G0) %% '$call_inline' cuts (only) after succeeding. - ; expand_call_goal(G0, M1, G1), - strip_subst_module(G1, M1, M2, G2), - '$call_with_inference_counting'('$module_call'(M2, G2)) - ). + '$fast_call'(G). +call(G0) :- + '$strip_module'(G0, M0, G1), + expand_call_goal(G1, M0, G2), + strip_subst_module(G2, M0, M1, G3), + '$call_with_inference_counting'('$module_call'(M1, G3)). :-non_counted_backtracking call/2. call(A,B) :- var(A), instantiation_error(call/2). call(A,B) :- - '$strip_module'(A,C,D), - '$call_inline'(D,B). -call('$call'(A),B) :- - !, - '$prepare_call_clause'(C,D,A,B), - '$call_with_inference_counting'('$module_call'(D,C)). + '$fast_call'(A,B). call(A,B) :- - '$prepare_call_clause'(C,D,A,B), - ( '$call_inline'(C) - ; expand_call_goal(C,D,E), - strip_subst_module(E,D,F,G), - '$call_with_inference_counting'('$module_call'(F,G)) - ). + '$strip_module'(A,C,D), + '$prepare_call_clause'(E,D,B), + expand_call_goal(E,C,F), + strip_subst_module(F,C,G,H), + '$call_with_inference_counting'('$module_call'(G,H)). :-non_counted_backtracking call/3. call(A,B,C) :- var(A), instantiation_error(call/3). call(A,B,C) :- - '$strip_module'(A,D,E), - '$call_inline'(E,B,C). -call('$call'(A),B,C) :- - !, - '$prepare_call_clause'(D,E,A,B,C), - '$call_with_inference_counting'('$module_call'(E,D)). + '$fast_call'(A,B,C). call(A,B,C) :- - '$prepare_call_clause'(D,E,A,B,C), - ( '$call_inline'(D) - ; expand_call_goal(D,E,F), - strip_subst_module(F,E,G,H), - '$call_with_inference_counting'('$module_call'(G,H)) - ). + '$strip_module'(A,D,E), + '$prepare_call_clause'(F,E,B,C), + expand_call_goal(F,D,G), + strip_subst_module(G,D,H,I), + '$call_with_inference_counting'('$module_call'(H,I)). :-non_counted_backtracking call/4. call(A,B,C,D) :- var(A), instantiation_error(call/4). call(A,B,C,D) :- - '$strip_module'(A,E,F), - '$call_inline'(F,B,C,D). -call('$call'(A),B,C,D) :- - !, - '$prepare_call_clause'(E,F,A,B,C,D), - '$call_with_inference_counting'('$module_call'(F,E)). + '$fast_call'(A,B,C,D). call(A,B,C,D) :- - '$prepare_call_clause'(E,F,A,B,C,D), - ( '$call_inline'(E) - ; expand_call_goal(E,F,G), - strip_subst_module(G,F,H,I), - '$call_with_inference_counting'('$module_call'(H,I)) - ). + '$strip_module'(A,E,F), + '$prepare_call_clause'(G,F,B,C,D), + expand_call_goal(G,E,H), + strip_subst_module(H,E,I,J), + '$call_with_inference_counting'('$module_call'(I,J)). :-non_counted_backtracking call/5. call(A,B,C,D,E) :- var(A), instantiation_error(call/5). call(A,B,C,D,E) :- - '$strip_module'(A,F,G), - '$call_inline'(G,B,C,D,E). -call('$call'(A),B,C,D,E) :- - !, - '$prepare_call_clause'(F,G,A,B,C,D,E), - '$call_with_inference_counting'('$module_call'(G,F)). + '$fast_call'(A,B,C,D,E). call(A,B,C,D,E) :- - '$prepare_call_clause'(F,G,A,B,C,D,E), - ( '$call_inline'(F) - ; expand_call_goal(F,G,H), - strip_subst_module(H,G,I,J), - '$call_with_inference_counting'('$module_call'(I,J)) - ). + '$strip_module'(A,F,G), + '$prepare_call_clause'(H,G,B,C,D,E), + expand_call_goal(H,F,I), + strip_subst_module(I,F,J,K), + '$call_with_inference_counting'('$module_call'(J,K)). :-non_counted_backtracking call/6. call(A,B,C,D,E,F) :- var(A), instantiation_error(call/6). call(A,B,C,D,E,F) :- - '$strip_module'(A,G,H), - '$call_inline'(H,B,C,D,E,F). -call('$call'(A),B,C,D,E,F) :- - !, - '$prepare_call_clause'(G,H,A,B,C,D,E,F), - '$call_with_inference_counting'('$module_call'(H,G)). + '$fast_call'(A,B,C,D,E,F). call(A,B,C,D,E,F) :- - '$prepare_call_clause'(G,H,A,B,C,D,E,F), - ( '$call_inline'(G) - ; expand_call_goal(G,H,I), - strip_subst_module(I,H,J,K), - '$call_with_inference_counting'('$module_call'(J,K)) - ). + '$strip_module'(A,G,H), + '$prepare_call_clause'(I,H,B,C,D,E,F), + expand_call_goal(I,G,J), + strip_subst_module(J,G,K,L), + '$call_with_inference_counting'('$module_call'(K,L)). :-non_counted_backtracking call/7. call(A,B,C,D,E,F,G) :- var(A), instantiation_error(call/7). call(A,B,C,D,E,F,G) :- - '$strip_module'(A,H,I), - '$call_inline'(I,B,C,D,E,F,G). -call('$call'(A),B,C,D,E,F,G) :- - !, - '$prepare_call_clause'(H,I,A,B,C,D,E,F,G), - '$call_with_inference_counting'('$module_call'(I,H)). + '$fast_call'(A,B,C,D,E,F,G). call(A,B,C,D,E,F,G) :- - '$prepare_call_clause'(H,I,A,B,C,D,E,F,G), - ( '$call_inline'(H) - ; expand_call_goal(H,I,J), - strip_subst_module(J,I,K,L), - '$call_with_inference_counting'('$module_call'(K,L)) - ). + '$strip_module'(A,H,I), + '$prepare_call_clause'(J,I,B,C,D,E,F,G), + expand_call_goal(J,H,K), + strip_subst_module(K,H,L,M), + '$call_with_inference_counting'('$module_call'(L,M)). :-non_counted_backtracking call/8. call(A,B,C,D,E,F,G,H) :- var(A), instantiation_error(call/8). call(A,B,C,D,E,F,G,H) :- - '$strip_module'(A,I,J), - '$call_inline'(J,B,C,D,E,F,G,H). -call('$call'(A),B,C,D,E,F,G,H) :- - !, - '$prepare_call_clause'(I,J,A,B,C,D,E,F,G,H), - '$call_with_inference_counting'('$module_call'(J,I)). + '$fast_call'(A,B,C,D,E,F,G,H). call(A,B,C,D,E,F,G,H) :- - '$prepare_call_clause'(I,J,A,B,C,D,E,F,G,H), - ( '$call_inline'(I) - ; expand_call_goal(I,J,K), - strip_subst_module(K,J,L,M), - '$call_with_inference_counting'('$module_call'(L,M)) - ). + '$strip_module'(A,I,J), + '$prepare_call_clause'(K,J,B,C,D,E,F,G,H), + expand_call_goal(K,I,L), + strip_subst_module(L,I,M,N), + '$call_with_inference_counting'('$module_call'(M,N)). :-non_counted_backtracking call/9. call(A,B,C,D,E,F,G,H,I) :- var(A), instantiation_error(call/9). call(A,B,C,D,E,F,G,H,I) :- - '$strip_module'(A,J,K), - '$call_inline'(K,B,C,D,E,F,G,H,I). -call('$call'(A),B,C,D,E,F,G,H,I) :- - !, - '$prepare_call_clause'(J,K,A,B,C,D,E,F,G,H,I), - '$call_with_inference_counting'('$module_call'(K,J)). + '$fast_call'(A,B,C,D,E,F,G,H,I). call(A,B,C,D,E,F,G,H,I) :- - '$prepare_call_clause'(J,K,A,B,C,D,E,F,G,H,I), - ( '$call_inline'(J) - ; expand_call_goal(J,K,L), - strip_subst_module(L,K,M,N), - '$call_with_inference_counting'('$module_call'(M,N)) - ). + '$strip_module'(A,J,K), + '$prepare_call_clause'(L,K,B,C,D,E,F,G,H,I), + expand_call_goal(L,J,M), + strip_subst_module(M,J,N,O), + '$call_with_inference_counting'('$module_call'(N,O)). :-non_counted_backtracking call/10. call(A,B,C,D,E,F,G,H,I,J) :- var(A), instantiation_error(call/10). call(A,B,C,D,E,F,G,H,I,J) :- - '$strip_module'(A,K,L), - '$call_inline'(L,B,C,D,E,F,G,H,I,J). -call('$call'(A),B,C,D,E,F,G,H,I,J) :- - !, - '$prepare_call_clause'(K,L,A,B,C,D,E,F,G,H,I,J), - '$call_with_inference_counting'('$module_call'(L,K)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J). call(A,B,C,D,E,F,G,H,I,J) :- - '$prepare_call_clause'(K,L,A,B,C,D,E,F,G,H,I,J), - ( '$call_inline'(K) - ; expand_call_goal(K,L,M), - strip_subst_module(M,L,N,O), - '$call_with_inference_counting'('$module_call'(N,O)) - ). + '$strip_module'(A,K,L), + '$prepare_call_clause'(M,L,B,C,D,E,F,G,H,I,J), + expand_call_goal(M,K,N), + strip_subst_module(N,K,O,P), + '$call_with_inference_counting'('$module_call'(O,P)). :-non_counted_backtracking call/11. call(A,B,C,D,E,F,G,H,I,J,K) :- var(A), instantiation_error(call/11). call(A,B,C,D,E,F,G,H,I,J,K) :- - '$strip_module'(A,L,M), - '$call_inline'(M,B,C,D,E,F,G,H,I,J,K). -call('$call'(A),B,C,D,E,F,G,H,I,J,K) :- - !, - '$prepare_call_clause'(L,M,A,B,C,D,E,F,G,H,I,J,K), - '$call_with_inference_counting'('$module_call'(M,L)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K). call(A,B,C,D,E,F,G,H,I,J,K) :- - '$prepare_call_clause'(L,M,A,B,C,D,E,F,G,H,I,J,K), - ( '$call_inline'(L) - ; expand_call_goal(L,M,N), - strip_subst_module(N,M,O,P), - '$call_with_inference_counting'('$module_call'(O,P)) - ). + '$strip_module'(A,L,M), + '$prepare_call_clause'(N,M,B,C,D,E,F,G,H,I,J,K), + expand_call_goal(N,L,O), + strip_subst_module(O,L,P,Q), + '$call_with_inference_counting'('$module_call'(P,Q)). :-non_counted_backtracking call/12. call(A,B,C,D,E,F,G,H,I,J,K,L) :- var(A), instantiation_error(call/12). call(A,B,C,D,E,F,G,H,I,J,K,L) :- - '$strip_module'(A,M,N), - '$call_inline'(N,B,C,D,E,F,G,H,I,J,K,L). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L) :- - !, - '$prepare_call_clause'(M,N,A,B,C,D,E,F,G,H,I,J,K,L), - '$call_with_inference_counting'('$module_call'(N,M)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L). call(A,B,C,D,E,F,G,H,I,J,K,L) :- - '$prepare_call_clause'(M,N,A,B,C,D,E,F,G,H,I,J,K,L), - ( '$call_inline'(M) - ; expand_call_goal(M,N,O), - strip_subst_module(O,N,P,Q), - '$call_with_inference_counting'('$module_call'(P,Q)) - ). + '$strip_module'(A,M,N), + '$prepare_call_clause'(O,N,B,C,D,E,F,G,H,I,J,K,L), + expand_call_goal(O,M,P), + strip_subst_module(P,M,Q,R), + '$call_with_inference_counting'('$module_call'(Q,R)). :-non_counted_backtracking call/13. call(A,B,C,D,E,F,G,H,I,J,K,L,M) :- var(A), instantiation_error(call/13). call(A,B,C,D,E,F,G,H,I,J,K,L,M) :- - '$strip_module'(A,N,O), - '$call_inline'(O,B,C,D,E,F,G,H,I,J,K,L,M). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M) :- - !, - '$prepare_call_clause'(N,O,A,B,C,D,E,F,G,H,I,J,K,L,M), - '$call_with_inference_counting'('$module_call'(O,N)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M). call(A,B,C,D,E,F,G,H,I,J,K,L,M) :- - '$prepare_call_clause'(N,O,A,B,C,D,E,F,G,H,I,J,K,L,M), - ( '$call_inline'(N) - ; expand_call_goal(N,O,P), - strip_subst_module(P,O,Q,R), - '$call_with_inference_counting'('$module_call'(Q,R)) - ). + '$strip_module'(A,N,O), + '$prepare_call_clause'(P,O,B,C,D,E,F,G,H,I,J,K,L,M), + expand_call_goal(P,N,Q), + strip_subst_module(Q,N,R,S), + '$call_with_inference_counting'('$module_call'(R,S)). :-non_counted_backtracking call/14. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N) :- var(A), instantiation_error(call/14). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N) :- - '$strip_module'(A,O,P), - '$call_inline'(P,B,C,D,E,F,G,H,I,J,K,L,M,N). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N) :- - !, - '$prepare_call_clause'(O,P,A,B,C,D,E,F,G,H,I,J,K,L,M,N), - '$call_with_inference_counting'('$module_call'(P,O)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N) :- - '$prepare_call_clause'(O,P,A,B,C,D,E,F,G,H,I,J,K,L,M,N), - ( '$call_inline'(O) - ; expand_call_goal(O,P,Q), - strip_subst_module(Q,P,R,S), - '$call_with_inference_counting'('$module_call'(R,S)) - ). + '$strip_module'(A,O,P), + '$prepare_call_clause'(Q,P,B,C,D,E,F,G,H,I,J,K,L,M,N), + expand_call_goal(Q,O,R), + strip_subst_module(R,O,S,T), + '$call_with_inference_counting'('$module_call'(S,T)). :-non_counted_backtracking call/15. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) :- var(A), instantiation_error(call/15). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) :- - '$strip_module'(A,P,Q), - '$call_inline'(Q,B,C,D,E,F,G,H,I,J,K,L,M,N,O). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O) :- - !, - '$prepare_call_clause'(P,Q,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O), - '$call_with_inference_counting'('$module_call'(Q,P)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) :- - '$prepare_call_clause'(P,Q,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O), - ( '$call_inline'(P) - ; expand_call_goal(P,Q,R), - strip_subst_module(R,Q,S,T), - '$call_with_inference_counting'('$module_call'(S,T)) - ). + '$strip_module'(A,P,Q), + '$prepare_call_clause'(R,Q,B,C,D,E,F,G,H,I,J,K,L,M,N,O), + expand_call_goal(R,P,S), + strip_subst_module(S,P,T,U), + '$call_with_inference_counting'('$module_call'(T,U)). :-non_counted_backtracking call/16. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :- var(A), instantiation_error(call/16). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :- - '$strip_module'(A,Q,R), - '$call_inline'(R,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :- - !, - '$prepare_call_clause'(Q,R,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P), - '$call_with_inference_counting'('$module_call'(R,Q)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :- - '$prepare_call_clause'(Q,R,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P), - ( '$call_inline'(Q) - ; expand_call_goal(Q,R,S), - strip_subst_module(S,R,T,U), - '$call_with_inference_counting'('$module_call'(T,U)) - ). + '$strip_module'(A,Q,R), + '$prepare_call_clause'(S,R,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P), + expand_call_goal(S,Q,T), + strip_subst_module(T,Q,U,V), + '$call_with_inference_counting'('$module_call'(U,V)). :-non_counted_backtracking call/17. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :- var(A), instantiation_error(call/17). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :- - '$strip_module'(A,R,S), - '$call_inline'(S,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :- - !, - '$prepare_call_clause'(R,S,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q), - '$call_with_inference_counting'('$module_call'(S,R)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :- - '$prepare_call_clause'(R,S,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q), - ( '$call_inline'(R) - ; expand_call_goal(R,S,T), - strip_subst_module(T,S,U,V), - '$call_with_inference_counting'('$module_call'(U,V)) - ). + '$strip_module'(A,R,S), + '$prepare_call_clause'(T,S,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q), + expand_call_goal(T,R,U), + strip_subst_module(U,R,V,W), + '$call_with_inference_counting'('$module_call'(V,W)). :-non_counted_backtracking call/18. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :- var(A), instantiation_error(call/18). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :- - '$strip_module'(A,S,T), - '$call_inline'(T,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :- - !, - '$prepare_call_clause'(S,T,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R), - '$call_with_inference_counting'('$module_call'(T,S)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :- - '$prepare_call_clause'(S,T,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R), - ( '$call_inline'(S) - ; expand_call_goal(S,T,U), - strip_subst_module(U,T,V,W), - '$call_with_inference_counting'('$module_call'(V,W)) - ). + '$strip_module'(A,S,T), + '$prepare_call_clause'(U,T,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R), + expand_call_goal(U,S,V), + strip_subst_module(V,S,W,X), + '$call_with_inference_counting'('$module_call'(W,X)). :-non_counted_backtracking call/19. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :- var(A), instantiation_error(call/19). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :- - '$strip_module'(A,T,U), - '$call_inline'(U,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :- - !, - '$prepare_call_clause'(T,U,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S), - '$call_with_inference_counting'('$module_call'(U,T)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :- - '$prepare_call_clause'(T,U,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S), - ( '$call_inline'(T) - ; expand_call_goal(T,U,V), - strip_subst_module(V,U,W,X), - '$call_with_inference_counting'('$module_call'(W,X)) - ). + '$strip_module'(A,T,U), + '$prepare_call_clause'(V,U,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S), + expand_call_goal(V,T,W), + strip_subst_module(W,T,X,Y), + '$call_with_inference_counting'('$module_call'(X,Y)). :-non_counted_backtracking call/20. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :- var(A), instantiation_error(call/20). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :- - '$strip_module'(A,U,V), - '$call_inline'(V,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :- - !, - '$prepare_call_clause'(U,V,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T), - '$call_with_inference_counting'('$module_call'(V,U)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :- - '$prepare_call_clause'(U,V,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T), - ( '$call_inline'(U) - ; expand_call_goal(U,V,W), - strip_subst_module(W,V,X,Y), - '$call_with_inference_counting'('$module_call'(X,Y)) - ). + '$strip_module'(A,U,V), + '$prepare_call_clause'(W,V,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T), + expand_call_goal(W,U,X), + strip_subst_module(X,U,Y,Z), + '$call_with_inference_counting'('$module_call'(Y,Z)). :-non_counted_backtracking call/21. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :- var(A), instantiation_error(call/21). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :- - '$strip_module'(A,V,W), - '$call_inline'(W,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :- - !, - '$prepare_call_clause'(V,W,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U), - '$call_with_inference_counting'('$module_call'(W,V)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :- - '$prepare_call_clause'(V,W,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U), - ( '$call_inline'(V) - ; expand_call_goal(V,W,X), - strip_subst_module(X,W,Y,Z), - '$call_with_inference_counting'('$module_call'(Y,Z)) - ). + '$strip_module'(A,V,W), + '$prepare_call_clause'(X,W,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U), + expand_call_goal(X,V,Y), + strip_subst_module(Y,V,Z,A1), + '$call_with_inference_counting'('$module_call'(Z,A1)). :-non_counted_backtracking call/22. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :- var(A), instantiation_error(call/22). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :- - '$strip_module'(A,W,X), - '$call_inline'(X,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :- - !, - '$prepare_call_clause'(W,X,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V), - '$call_with_inference_counting'('$module_call'(X,W)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :- - '$prepare_call_clause'(W,X,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V), - ( '$call_inline'(W) - ; expand_call_goal(W,X,Y), - strip_subst_module(Y,X,Z,A1), - '$call_with_inference_counting'('$module_call'(Z,A1)) - ). + '$strip_module'(A,W,X), + '$prepare_call_clause'(Y,X,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V), + expand_call_goal(Y,W,Z), + strip_subst_module(Z,W,A1,B1), + '$call_with_inference_counting'('$module_call'(A1,B1)). :-non_counted_backtracking call/23. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :- var(A), instantiation_error(call/23). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :- - '$strip_module'(A,X,Y), - '$call_inline'(Y,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :- - !, - '$prepare_call_clause'(X,Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W), - '$call_with_inference_counting'('$module_call'(Y,X)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :- - '$prepare_call_clause'(X,Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W), - ( '$call_inline'(X) - ; expand_call_goal(X,Y,Z), - strip_subst_module(Z,Y,A1,B1), - '$call_with_inference_counting'('$module_call'(A1,B1)) - ). + '$strip_module'(A,X,Y), + '$prepare_call_clause'(Z,Y,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W), + expand_call_goal(Z,X,A1), + strip_subst_module(A1,X,B1,C1), + '$call_with_inference_counting'('$module_call'(B1,C1)). :-non_counted_backtracking call/24. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :- var(A), instantiation_error(call/24). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :- - '$strip_module'(A,Y,Z), - '$call_inline'(Z,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :- - !, - '$prepare_call_clause'(Y,Z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X), - '$call_with_inference_counting'('$module_call'(Z,Y)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :- - '$prepare_call_clause'(Y,Z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X), - ( '$call_inline'(Y) - ; expand_call_goal(Y,Z,A1), - strip_subst_module(A1,Z,B1,C1), - '$call_with_inference_counting'('$module_call'(B1,C1)) - ). + '$strip_module'(A,Y,Z), + '$prepare_call_clause'(A1,Z,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X), + expand_call_goal(A1,Y,B1), + strip_subst_module(B1,Y,C1,D1), + '$call_with_inference_counting'('$module_call'(C1,D1)). :-non_counted_backtracking call/25. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :- var(A), instantiation_error(call/25). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :- - '$strip_module'(A,Z,A1), - '$call_inline'(A1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :- - !, - '$prepare_call_clause'(Z,A1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y), - '$call_with_inference_counting'('$module_call'(A1,Z)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :- - '$prepare_call_clause'(Z,A1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y), - ( '$call_inline'(Z) - ; expand_call_goal(Z,A1,B1), - strip_subst_module(B1,A1,C1,D1), - '$call_with_inference_counting'('$module_call'(C1,D1)) - ). + '$strip_module'(A,Z,A1), + '$prepare_call_clause'(B1,A1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y), + expand_call_goal(B1,Z,C1), + strip_subst_module(C1,Z,D1,E1), + '$call_with_inference_counting'('$module_call'(D1,E1)). :-non_counted_backtracking call/26. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :- var(A), instantiation_error(call/26). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :- - '$strip_module'(A,A1,B1), - '$call_inline'(B1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :- - !, - '$prepare_call_clause'(A1,B1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z), - '$call_with_inference_counting'('$module_call'(B1,A1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :- - '$prepare_call_clause'(A1,B1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z), - ( '$call_inline'(A1) - ; expand_call_goal(A1,B1,C1), - strip_subst_module(C1,B1,D1,E1), - '$call_with_inference_counting'('$module_call'(D1,E1)) - ). + '$strip_module'(A,A1,B1), + '$prepare_call_clause'(C1,B1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z), + expand_call_goal(C1,A1,D1), + strip_subst_module(D1,A1,E1,F1), + '$call_with_inference_counting'('$module_call'(E1,F1)). :-non_counted_backtracking call/27. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :- var(A), instantiation_error(call/27). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :- - '$strip_module'(A,B1,C1), - '$call_inline'(C1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :- - !, - '$prepare_call_clause'(B1,C1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1), - '$call_with_inference_counting'('$module_call'(C1,B1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :- - '$prepare_call_clause'(B1,C1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1), - ( '$call_inline'(B1) - ; expand_call_goal(B1,C1,D1), - strip_subst_module(D1,C1,E1,F1), - '$call_with_inference_counting'('$module_call'(E1,F1)) - ). + '$strip_module'(A,B1,C1), + '$prepare_call_clause'(D1,C1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1), + expand_call_goal(D1,B1,E1), + strip_subst_module(E1,B1,F1,G1), + '$call_with_inference_counting'('$module_call'(F1,G1)). :-non_counted_backtracking call/28. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :- var(A), instantiation_error(call/28). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :- - '$strip_module'(A,C1,D1), - '$call_inline'(D1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :- - !, - '$prepare_call_clause'(C1,D1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1), - '$call_with_inference_counting'('$module_call'(D1,C1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :- - '$prepare_call_clause'(C1,D1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1), - ( '$call_inline'(C1) - ; expand_call_goal(C1,D1,E1), - strip_subst_module(E1,D1,F1,G1), - '$call_with_inference_counting'('$module_call'(F1,G1)) - ). + '$strip_module'(A,C1,D1), + '$prepare_call_clause'(E1,D1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1), + expand_call_goal(E1,C1,F1), + strip_subst_module(F1,C1,G1,H1), + '$call_with_inference_counting'('$module_call'(G1,H1)). :-non_counted_backtracking call/29. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :- var(A), instantiation_error(call/29). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :- - '$strip_module'(A,D1,E1), - '$call_inline'(E1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :- - !, - '$prepare_call_clause'(D1,E1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1), - '$call_with_inference_counting'('$module_call'(E1,D1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :- - '$prepare_call_clause'(D1,E1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1), - ( '$call_inline'(D1) - ; expand_call_goal(D1,E1,F1), - strip_subst_module(F1,E1,G1,H1), - '$call_with_inference_counting'('$module_call'(G1,H1)) - ). + '$strip_module'(A,D1,E1), + '$prepare_call_clause'(F1,E1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1), + expand_call_goal(F1,D1,G1), + strip_subst_module(G1,D1,H1,I1), + '$call_with_inference_counting'('$module_call'(H1,I1)). :-non_counted_backtracking call/30. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :- var(A), instantiation_error(call/30). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :- - '$strip_module'(A,E1,F1), - '$call_inline'(F1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :- - !, - '$prepare_call_clause'(E1,F1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1), - '$call_with_inference_counting'('$module_call'(F1,E1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :- - '$prepare_call_clause'(E1,F1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1), - ( '$call_inline'(E1) - ; expand_call_goal(E1,F1,G1), - strip_subst_module(G1,F1,H1,I1), - '$call_with_inference_counting'('$module_call'(H1,I1)) - ). + '$strip_module'(A,E1,F1), + '$prepare_call_clause'(G1,F1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1), + expand_call_goal(G1,E1,H1), + strip_subst_module(H1,E1,I1,J1), + '$call_with_inference_counting'('$module_call'(I1,J1)). :-non_counted_backtracking call/31. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :- var(A), instantiation_error(call/31). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :- - '$strip_module'(A,F1,G1), - '$call_inline'(G1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :- - !, - '$prepare_call_clause'(F1,G1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1), - '$call_with_inference_counting'('$module_call'(G1,F1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :- - '$prepare_call_clause'(F1,G1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1), - ( '$call_inline'(F1) - ; expand_call_goal(F1,G1,H1), - strip_subst_module(H1,G1,I1,J1), - '$call_with_inference_counting'('$module_call'(I1,J1)) - ). + '$strip_module'(A,F1,G1), + '$prepare_call_clause'(H1,G1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1), + expand_call_goal(H1,F1,I1), + strip_subst_module(I1,F1,J1,K1), + '$call_with_inference_counting'('$module_call'(J1,K1)). :-non_counted_backtracking call/32. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :- var(A), instantiation_error(call/32). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :- - '$strip_module'(A,G1,H1), - '$call_inline'(H1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :- - !, - '$prepare_call_clause'(G1,H1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1), - '$call_with_inference_counting'('$module_call'(H1,G1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :- - '$prepare_call_clause'(G1,H1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1), - ( '$call_inline'(G1) - ; expand_call_goal(G1,H1,I1), - strip_subst_module(I1,H1,J1,K1), - '$call_with_inference_counting'('$module_call'(J1,K1)) - ). + '$strip_module'(A,G1,H1), + '$prepare_call_clause'(I1,H1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1), + expand_call_goal(I1,G1,J1), + strip_subst_module(J1,G1,K1,L1), + '$call_with_inference_counting'('$module_call'(K1,L1)). :-non_counted_backtracking call/33. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :- var(A), instantiation_error(call/33). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :- - '$strip_module'(A,H1,I1), - '$call_inline'(I1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :- - !, - '$prepare_call_clause'(H1,I1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1), - '$call_with_inference_counting'('$module_call'(I1,H1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :- - '$prepare_call_clause'(H1,I1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1), - ( '$call_inline'(H1) - ; expand_call_goal(H1,I1,J1), - strip_subst_module(J1,I1,K1,L1), - '$call_with_inference_counting'('$module_call'(K1,L1)) - ). + '$strip_module'(A,H1,I1), + '$prepare_call_clause'(J1,I1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1), + expand_call_goal(J1,H1,K1), + strip_subst_module(K1,H1,L1,M1), + '$call_with_inference_counting'('$module_call'(L1,M1)). :-non_counted_backtracking call/34. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1) :- var(A), instantiation_error(call/34). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1) :- - '$strip_module'(A,I1,J1), - '$call_inline'(J1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1) :- - !, - '$prepare_call_clause'(I1,J1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1), - '$call_with_inference_counting'('$module_call'(J1,I1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1) :- - '$prepare_call_clause'(I1,J1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1), - ( '$call_inline'(I1) - ; expand_call_goal(I1,J1,K1), - strip_subst_module(K1,J1,L1,M1), - '$call_with_inference_counting'('$module_call'(L1,M1)) - ). + '$strip_module'(A,I1,J1), + '$prepare_call_clause'(K1,J1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1), + expand_call_goal(K1,I1,L1), + strip_subst_module(L1,I1,M1,N1), + '$call_with_inference_counting'('$module_call'(M1,N1)). :-non_counted_backtracking call/35. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1) :- var(A), instantiation_error(call/35). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1) :- - '$strip_module'(A,J1,K1), - '$call_inline'(K1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1) :- - !, - '$prepare_call_clause'(J1,K1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1), - '$call_with_inference_counting'('$module_call'(K1,J1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1) :- - '$prepare_call_clause'(J1,K1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1), - ( '$call_inline'(J1) - ; expand_call_goal(J1,K1,L1), - strip_subst_module(L1,K1,M1,N1), - '$call_with_inference_counting'('$module_call'(M1,N1)) - ). + '$strip_module'(A,J1,K1), + '$prepare_call_clause'(L1,K1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1), + expand_call_goal(L1,J1,M1), + strip_subst_module(M1,J1,N1,O1), + '$call_with_inference_counting'('$module_call'(N1,O1)). :-non_counted_backtracking call/36. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1) :- var(A), instantiation_error(call/36). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1) :- - '$strip_module'(A,K1,L1), - '$call_inline'(L1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1) :- - !, - '$prepare_call_clause'(K1,L1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1), - '$call_with_inference_counting'('$module_call'(L1,K1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1) :- - '$prepare_call_clause'(K1,L1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1), - ( '$call_inline'(K1) - ; expand_call_goal(K1,L1,M1), - strip_subst_module(M1,L1,N1,O1), - '$call_with_inference_counting'('$module_call'(N1,O1)) - ). + '$strip_module'(A,K1,L1), + '$prepare_call_clause'(M1,L1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1), + expand_call_goal(M1,K1,N1), + strip_subst_module(N1,K1,O1,P1), + '$call_with_inference_counting'('$module_call'(O1,P1)). :-non_counted_backtracking call/37. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1) :- var(A), instantiation_error(call/37). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1) :- - '$strip_module'(A,L1,M1), - '$call_inline'(M1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1) :- - !, - '$prepare_call_clause'(L1,M1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1), - '$call_with_inference_counting'('$module_call'(M1,L1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1) :- - '$prepare_call_clause'(L1,M1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1), - ( '$call_inline'(L1) - ; expand_call_goal(L1,M1,N1), - strip_subst_module(N1,M1,O1,P1), - '$call_with_inference_counting'('$module_call'(O1,P1)) - ). + '$strip_module'(A,L1,M1), + '$prepare_call_clause'(N1,M1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1), + expand_call_goal(N1,L1,O1), + strip_subst_module(O1,L1,P1,Q1), + '$call_with_inference_counting'('$module_call'(P1,Q1)). :-non_counted_backtracking call/38. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1) :- var(A), instantiation_error(call/38). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1) :- - '$strip_module'(A,M1,N1), - '$call_inline'(N1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1) :- - !, - '$prepare_call_clause'(M1,N1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1), - '$call_with_inference_counting'('$module_call'(N1,M1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1) :- - '$prepare_call_clause'(M1,N1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1), - ( '$call_inline'(M1) - ; expand_call_goal(M1,N1,O1), - strip_subst_module(O1,N1,P1,Q1), - '$call_with_inference_counting'('$module_call'(P1,Q1)) - ). + '$strip_module'(A,M1,N1), + '$prepare_call_clause'(O1,N1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1), + expand_call_goal(O1,M1,P1), + strip_subst_module(P1,M1,Q1,R1), + '$call_with_inference_counting'('$module_call'(Q1,R1)). :-non_counted_backtracking call/39. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1) :- var(A), instantiation_error(call/39). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1) :- - '$strip_module'(A,N1,O1), - '$call_inline'(O1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1) :- - !, - '$prepare_call_clause'(N1,O1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1), - '$call_with_inference_counting'('$module_call'(O1,N1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1) :- - '$prepare_call_clause'(N1,O1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1), - ( '$call_inline'(N1) - ; expand_call_goal(N1,O1,P1), - strip_subst_module(P1,O1,Q1,R1), - '$call_with_inference_counting'('$module_call'(Q1,R1)) - ). + '$strip_module'(A,N1,O1), + '$prepare_call_clause'(P1,O1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1), + expand_call_goal(P1,N1,Q1), + strip_subst_module(Q1,N1,R1,S1), + '$call_with_inference_counting'('$module_call'(R1,S1)). :-non_counted_backtracking call/40. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1) :- var(A), instantiation_error(call/40). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1) :- - '$strip_module'(A,O1,P1), - '$call_inline'(P1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1) :- - !, - '$prepare_call_clause'(O1,P1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1), - '$call_with_inference_counting'('$module_call'(P1,O1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1) :- - '$prepare_call_clause'(O1,P1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1), - ( '$call_inline'(O1) - ; expand_call_goal(O1,P1,Q1), - strip_subst_module(Q1,P1,R1,S1), - '$call_with_inference_counting'('$module_call'(R1,S1)) - ). + '$strip_module'(A,O1,P1), + '$prepare_call_clause'(Q1,P1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1), + expand_call_goal(Q1,O1,R1), + strip_subst_module(R1,O1,S1,T1), + '$call_with_inference_counting'('$module_call'(S1,T1)). :-non_counted_backtracking call/41. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1) :- var(A), instantiation_error(call/41). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1) :- - '$strip_module'(A,P1,Q1), - '$call_inline'(Q1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1) :- - !, - '$prepare_call_clause'(P1,Q1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1), - '$call_with_inference_counting'('$module_call'(Q1,P1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1) :- - '$prepare_call_clause'(P1,Q1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1), - ( '$call_inline'(P1) - ; expand_call_goal(P1,Q1,R1), - strip_subst_module(R1,Q1,S1,T1), - '$call_with_inference_counting'('$module_call'(S1,T1)) - ). + '$strip_module'(A,P1,Q1), + '$prepare_call_clause'(R1,Q1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1), + expand_call_goal(R1,P1,S1), + strip_subst_module(S1,P1,T1,U1), + '$call_with_inference_counting'('$module_call'(T1,U1)). :-non_counted_backtracking call/42. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1) :- var(A), instantiation_error(call/42). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1) :- - '$strip_module'(A,Q1,R1), - '$call_inline'(R1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1) :- - !, - '$prepare_call_clause'(Q1,R1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1), - '$call_with_inference_counting'('$module_call'(R1,Q1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1) :- - '$prepare_call_clause'(Q1,R1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1), - ( '$call_inline'(Q1) - ; expand_call_goal(Q1,R1,S1), - strip_subst_module(S1,R1,T1,U1), - '$call_with_inference_counting'('$module_call'(T1,U1)) - ). + '$strip_module'(A,Q1,R1), + '$prepare_call_clause'(S1,R1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1), + expand_call_goal(S1,Q1,T1), + strip_subst_module(T1,Q1,U1,V1), + '$call_with_inference_counting'('$module_call'(U1,V1)). :-non_counted_backtracking call/43. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1) :- var(A), instantiation_error(call/43). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1) :- - '$strip_module'(A,R1,S1), - '$call_inline'(S1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1) :- - !, - '$prepare_call_clause'(R1,S1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1), - '$call_with_inference_counting'('$module_call'(S1,R1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1) :- - '$prepare_call_clause'(R1,S1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1), - ( '$call_inline'(R1) - ; expand_call_goal(R1,S1,T1), - strip_subst_module(T1,S1,U1,V1), - '$call_with_inference_counting'('$module_call'(U1,V1)) - ). + '$strip_module'(A,R1,S1), + '$prepare_call_clause'(T1,S1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1), + expand_call_goal(T1,R1,U1), + strip_subst_module(U1,R1,V1,W1), + '$call_with_inference_counting'('$module_call'(V1,W1)). :-non_counted_backtracking call/44. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1) :- var(A), instantiation_error(call/44). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1) :- - '$strip_module'(A,S1,T1), - '$call_inline'(T1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1) :- - !, - '$prepare_call_clause'(S1,T1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1), - '$call_with_inference_counting'('$module_call'(T1,S1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1) :- - '$prepare_call_clause'(S1,T1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1), - ( '$call_inline'(S1) - ; expand_call_goal(S1,T1,U1), - strip_subst_module(U1,T1,V1,W1), - '$call_with_inference_counting'('$module_call'(V1,W1)) - ). + '$strip_module'(A,S1,T1), + '$prepare_call_clause'(U1,T1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1), + expand_call_goal(U1,S1,V1), + strip_subst_module(V1,S1,W1,X1), + '$call_with_inference_counting'('$module_call'(W1,X1)). :-non_counted_backtracking call/45. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1) :- var(A), instantiation_error(call/45). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1) :- - '$strip_module'(A,T1,U1), - '$call_inline'(U1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1) :- - !, - '$prepare_call_clause'(T1,U1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1), - '$call_with_inference_counting'('$module_call'(U1,T1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1) :- - '$prepare_call_clause'(T1,U1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1), - ( '$call_inline'(T1) - ; expand_call_goal(T1,U1,V1), - strip_subst_module(V1,U1,W1,X1), - '$call_with_inference_counting'('$module_call'(W1,X1)) - ). + '$strip_module'(A,T1,U1), + '$prepare_call_clause'(V1,U1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1), + expand_call_goal(V1,T1,W1), + strip_subst_module(W1,T1,X1,Y1), + '$call_with_inference_counting'('$module_call'(X1,Y1)). :-non_counted_backtracking call/46. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1) :- var(A), instantiation_error(call/46). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1) :- - '$strip_module'(A,U1,V1), - '$call_inline'(V1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1) :- - !, - '$prepare_call_clause'(U1,V1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1), - '$call_with_inference_counting'('$module_call'(V1,U1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1) :- - '$prepare_call_clause'(U1,V1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1), - ( '$call_inline'(U1) - ; expand_call_goal(U1,V1,W1), - strip_subst_module(W1,V1,X1,Y1), - '$call_with_inference_counting'('$module_call'(X1,Y1)) - ). + '$strip_module'(A,U1,V1), + '$prepare_call_clause'(W1,V1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1), + expand_call_goal(W1,U1,X1), + strip_subst_module(X1,U1,Y1,Z1), + '$call_with_inference_counting'('$module_call'(Y1,Z1)). :-non_counted_backtracking call/47. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1) :- var(A), instantiation_error(call/47). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1) :- - '$strip_module'(A,V1,W1), - '$call_inline'(W1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1) :- - !, - '$prepare_call_clause'(V1,W1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1), - '$call_with_inference_counting'('$module_call'(W1,V1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1) :- - '$prepare_call_clause'(V1,W1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1), - ( '$call_inline'(V1) - ; expand_call_goal(V1,W1,X1), - strip_subst_module(X1,W1,Y1,Z1), - '$call_with_inference_counting'('$module_call'(Y1,Z1)) - ). + '$strip_module'(A,V1,W1), + '$prepare_call_clause'(X1,W1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1), + expand_call_goal(X1,V1,Y1), + strip_subst_module(Y1,V1,Z1,A2), + '$call_with_inference_counting'('$module_call'(Z1,A2)). :-non_counted_backtracking call/48. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1) :- var(A), instantiation_error(call/48). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1) :- - '$strip_module'(A,W1,X1), - '$call_inline'(X1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1) :- - !, - '$prepare_call_clause'(W1,X1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1), - '$call_with_inference_counting'('$module_call'(X1,W1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1) :- - '$prepare_call_clause'(W1,X1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1), - ( '$call_inline'(W1) - ; expand_call_goal(W1,X1,Y1), - strip_subst_module(Y1,X1,Z1,A2), - '$call_with_inference_counting'('$module_call'(Z1,A2)) - ). + '$strip_module'(A,W1,X1), + '$prepare_call_clause'(Y1,X1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1), + expand_call_goal(Y1,W1,Z1), + strip_subst_module(Z1,W1,A2,B2), + '$call_with_inference_counting'('$module_call'(A2,B2)). :-non_counted_backtracking call/49. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1) :- var(A), instantiation_error(call/49). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1) :- - '$strip_module'(A,X1,Y1), - '$call_inline'(Y1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1) :- - !, - '$prepare_call_clause'(X1,Y1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1), - '$call_with_inference_counting'('$module_call'(Y1,X1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1) :- - '$prepare_call_clause'(X1,Y1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1), - ( '$call_inline'(X1) - ; expand_call_goal(X1,Y1,Z1), - strip_subst_module(Z1,Y1,A2,B2), - '$call_with_inference_counting'('$module_call'(A2,B2)) - ). + '$strip_module'(A,X1,Y1), + '$prepare_call_clause'(Z1,Y1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1), + expand_call_goal(Z1,X1,A2), + strip_subst_module(A2,X1,B2,C2), + '$call_with_inference_counting'('$module_call'(B2,C2)). :-non_counted_backtracking call/50. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1) :- var(A), instantiation_error(call/50). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1) :- - '$strip_module'(A,Y1,Z1), - '$call_inline'(Z1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1) :- - !, - '$prepare_call_clause'(Y1,Z1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1), - '$call_with_inference_counting'('$module_call'(Z1,Y1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1) :- - '$prepare_call_clause'(Y1,Z1,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1), - ( '$call_inline'(Y1) - ; expand_call_goal(Y1,Z1,A2), - strip_subst_module(A2,Z1,B2,C2), - '$call_with_inference_counting'('$module_call'(B2,C2)) - ). + '$strip_module'(A,Y1,Z1), + '$prepare_call_clause'(A2,Z1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1), + expand_call_goal(A2,Y1,B2), + strip_subst_module(B2,Y1,C2,D2), + '$call_with_inference_counting'('$module_call'(C2,D2)). :-non_counted_backtracking call/51. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1) :- var(A), instantiation_error(call/51). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1) :- - '$strip_module'(A,Z1,A2), - '$call_inline'(A2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1) :- - !, - '$prepare_call_clause'(Z1,A2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1), - '$call_with_inference_counting'('$module_call'(A2,Z1)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1) :- - '$prepare_call_clause'(Z1,A2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1), - ( '$call_inline'(Z1) - ; expand_call_goal(Z1,A2,B2), - strip_subst_module(B2,A2,C2,D2), - '$call_with_inference_counting'('$module_call'(C2,D2)) - ). + '$strip_module'(A,Z1,A2), + '$prepare_call_clause'(B2,A2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1), + expand_call_goal(B2,Z1,C2), + strip_subst_module(C2,Z1,D2,E2), + '$call_with_inference_counting'('$module_call'(D2,E2)). :-non_counted_backtracking call/52. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1) :- var(A), instantiation_error(call/52). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1) :- - '$strip_module'(A,A2,B2), - '$call_inline'(B2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1) :- - !, - '$prepare_call_clause'(A2,B2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1), - '$call_with_inference_counting'('$module_call'(B2,A2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1) :- - '$prepare_call_clause'(A2,B2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1), - ( '$call_inline'(A2) - ; expand_call_goal(A2,B2,C2), - strip_subst_module(C2,B2,D2,E2), - '$call_with_inference_counting'('$module_call'(D2,E2)) - ). + '$strip_module'(A,A2,B2), + '$prepare_call_clause'(C2,B2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1), + expand_call_goal(C2,A2,D2), + strip_subst_module(D2,A2,E2,F2), + '$call_with_inference_counting'('$module_call'(E2,F2)). :-non_counted_backtracking call/53. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2) :- var(A), instantiation_error(call/53). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2) :- - '$strip_module'(A,B2,C2), - '$call_inline'(C2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2) :- - !, - '$prepare_call_clause'(B2,C2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2), - '$call_with_inference_counting'('$module_call'(C2,B2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2) :- - '$prepare_call_clause'(B2,C2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2), - ( '$call_inline'(B2) - ; expand_call_goal(B2,C2,D2), - strip_subst_module(D2,C2,E2,F2), - '$call_with_inference_counting'('$module_call'(E2,F2)) - ). + '$strip_module'(A,B2,C2), + '$prepare_call_clause'(D2,C2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2), + expand_call_goal(D2,B2,E2), + strip_subst_module(E2,B2,F2,G2), + '$call_with_inference_counting'('$module_call'(F2,G2)). :-non_counted_backtracking call/54. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2) :- var(A), instantiation_error(call/54). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2) :- - '$strip_module'(A,C2,D2), - '$call_inline'(D2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2) :- - !, - '$prepare_call_clause'(C2,D2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2), - '$call_with_inference_counting'('$module_call'(D2,C2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2) :- - '$prepare_call_clause'(C2,D2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2), - ( '$call_inline'(C2) - ; expand_call_goal(C2,D2,E2), - strip_subst_module(E2,D2,F2,G2), - '$call_with_inference_counting'('$module_call'(F2,G2)) - ). + '$strip_module'(A,C2,D2), + '$prepare_call_clause'(E2,D2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2), + expand_call_goal(E2,C2,F2), + strip_subst_module(F2,C2,G2,H2), + '$call_with_inference_counting'('$module_call'(G2,H2)). :-non_counted_backtracking call/55. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2) :- var(A), instantiation_error(call/55). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2) :- - '$strip_module'(A,D2,E2), - '$call_inline'(E2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2) :- - !, - '$prepare_call_clause'(D2,E2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2), - '$call_with_inference_counting'('$module_call'(E2,D2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2) :- - '$prepare_call_clause'(D2,E2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2), - ( '$call_inline'(D2) - ; expand_call_goal(D2,E2,F2), - strip_subst_module(F2,E2,G2,H2), - '$call_with_inference_counting'('$module_call'(G2,H2)) - ). + '$strip_module'(A,D2,E2), + '$prepare_call_clause'(F2,E2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2), + expand_call_goal(F2,D2,G2), + strip_subst_module(G2,D2,H2,I2), + '$call_with_inference_counting'('$module_call'(H2,I2)). :-non_counted_backtracking call/56. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2) :- var(A), instantiation_error(call/56). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2) :- - '$strip_module'(A,E2,F2), - '$call_inline'(F2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2) :- - !, - '$prepare_call_clause'(E2,F2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2), - '$call_with_inference_counting'('$module_call'(F2,E2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2) :- - '$prepare_call_clause'(E2,F2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2), - ( '$call_inline'(E2) - ; expand_call_goal(E2,F2,G2), - strip_subst_module(G2,F2,H2,I2), - '$call_with_inference_counting'('$module_call'(H2,I2)) - ). + '$strip_module'(A,E2,F2), + '$prepare_call_clause'(G2,F2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2), + expand_call_goal(G2,E2,H2), + strip_subst_module(H2,E2,I2,J2), + '$call_with_inference_counting'('$module_call'(I2,J2)). :-non_counted_backtracking call/57. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2) :- var(A), instantiation_error(call/57). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2) :- - '$strip_module'(A,F2,G2), - '$call_inline'(G2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2) :- - !, - '$prepare_call_clause'(F2,G2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2), - '$call_with_inference_counting'('$module_call'(G2,F2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2) :- - '$prepare_call_clause'(F2,G2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2), - ( '$call_inline'(F2) - ; expand_call_goal(F2,G2,H2), - strip_subst_module(H2,G2,I2,J2), - '$call_with_inference_counting'('$module_call'(I2,J2)) - ). + '$strip_module'(A,F2,G2), + '$prepare_call_clause'(H2,G2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2), + expand_call_goal(H2,F2,I2), + strip_subst_module(I2,F2,J2,K2), + '$call_with_inference_counting'('$module_call'(J2,K2)). :-non_counted_backtracking call/58. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2) :- var(A), instantiation_error(call/58). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2) :- - '$strip_module'(A,G2,H2), - '$call_inline'(H2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2) :- - !, - '$prepare_call_clause'(G2,H2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2), - '$call_with_inference_counting'('$module_call'(H2,G2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2) :- - '$prepare_call_clause'(G2,H2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2), - ( '$call_inline'(G2) - ; expand_call_goal(G2,H2,I2), - strip_subst_module(I2,H2,J2,K2), - '$call_with_inference_counting'('$module_call'(J2,K2)) - ). + '$strip_module'(A,G2,H2), + '$prepare_call_clause'(I2,H2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2), + expand_call_goal(I2,G2,J2), + strip_subst_module(J2,G2,K2,L2), + '$call_with_inference_counting'('$module_call'(K2,L2)). :-non_counted_backtracking call/59. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2) :- var(A), instantiation_error(call/59). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2) :- - '$strip_module'(A,H2,I2), - '$call_inline'(I2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2) :- - !, - '$prepare_call_clause'(H2,I2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2), - '$call_with_inference_counting'('$module_call'(I2,H2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2) :- - '$prepare_call_clause'(H2,I2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2), - ( '$call_inline'(H2) - ; expand_call_goal(H2,I2,J2), - strip_subst_module(J2,I2,K2,L2), - '$call_with_inference_counting'('$module_call'(K2,L2)) - ). + '$strip_module'(A,H2,I2), + '$prepare_call_clause'(J2,I2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2), + expand_call_goal(J2,H2,K2), + strip_subst_module(K2,H2,L2,M2), + '$call_with_inference_counting'('$module_call'(L2,M2)). :-non_counted_backtracking call/60. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2) :- var(A), instantiation_error(call/60). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2) :- - '$strip_module'(A,I2,J2), - '$call_inline'(J2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2) :- - !, - '$prepare_call_clause'(I2,J2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2), - '$call_with_inference_counting'('$module_call'(J2,I2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2) :- - '$prepare_call_clause'(I2,J2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2), - ( '$call_inline'(I2) - ; expand_call_goal(I2,J2,K2), - strip_subst_module(K2,J2,L2,M2), - '$call_with_inference_counting'('$module_call'(L2,M2)) - ). + '$strip_module'(A,I2,J2), + '$prepare_call_clause'(K2,J2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2), + expand_call_goal(K2,I2,L2), + strip_subst_module(L2,I2,M2,N2), + '$call_with_inference_counting'('$module_call'(M2,N2)). :-non_counted_backtracking call/61. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2) :- var(A), instantiation_error(call/61). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2) :- - '$strip_module'(A,J2,K2), - '$call_inline'(K2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2) :- - !, - '$prepare_call_clause'(J2,K2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2), - '$call_with_inference_counting'('$module_call'(K2,J2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2) :- - '$prepare_call_clause'(J2,K2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2), - ( '$call_inline'(J2) - ; expand_call_goal(J2,K2,L2), - strip_subst_module(L2,K2,M2,N2), - '$call_with_inference_counting'('$module_call'(M2,N2)) - ). + '$strip_module'(A,J2,K2), + '$prepare_call_clause'(L2,K2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2), + expand_call_goal(L2,J2,M2), + strip_subst_module(M2,J2,N2,O2), + '$call_with_inference_counting'('$module_call'(N2,O2)). :-non_counted_backtracking call/62. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2) :- var(A), instantiation_error(call/62). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2) :- - '$strip_module'(A,K2,L2), - '$call_inline'(L2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2) :- - !, - '$prepare_call_clause'(K2,L2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2), - '$call_with_inference_counting'('$module_call'(L2,K2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2) :- - '$prepare_call_clause'(K2,L2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2), - ( '$call_inline'(K2) - ; expand_call_goal(K2,L2,M2), - strip_subst_module(M2,L2,N2,O2), - '$call_with_inference_counting'('$module_call'(N2,O2)) - ). + '$strip_module'(A,K2,L2), + '$prepare_call_clause'(M2,L2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2), + expand_call_goal(M2,K2,N2), + strip_subst_module(N2,K2,O2,P2), + '$call_with_inference_counting'('$module_call'(O2,P2)). :-non_counted_backtracking call/63. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2) :- var(A), instantiation_error(call/63). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2) :- - '$strip_module'(A,L2,M2), - '$call_inline'(M2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2) :- - !, - '$prepare_call_clause'(L2,M2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2), - '$call_with_inference_counting'('$module_call'(M2,L2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2) :- - '$prepare_call_clause'(L2,M2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2), - ( '$call_inline'(L2) - ; expand_call_goal(L2,M2,N2), - strip_subst_module(N2,M2,O2,P2), - '$call_with_inference_counting'('$module_call'(O2,P2)) - ). + '$strip_module'(A,L2,M2), + '$prepare_call_clause'(N2,M2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2), + expand_call_goal(N2,L2,O2), + strip_subst_module(O2,L2,P2,Q2), + '$call_with_inference_counting'('$module_call'(P2,Q2)). :-non_counted_backtracking call/64. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2) :- var(A), instantiation_error(call/64). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2) :- - '$strip_module'(A,M2,N2), - '$call_inline'(N2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2) :- - !, - '$prepare_call_clause'(M2,N2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2), - '$call_with_inference_counting'('$module_call'(N2,M2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2) :- - '$prepare_call_clause'(M2,N2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2), - ( '$call_inline'(M2) - ; expand_call_goal(M2,N2,O2), - strip_subst_module(O2,N2,P2,Q2), - '$call_with_inference_counting'('$module_call'(P2,Q2)) - ). + '$strip_module'(A,M2,N2), + '$prepare_call_clause'(O2,N2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2), + expand_call_goal(O2,M2,P2), + strip_subst_module(P2,M2,Q2,R2), + '$call_with_inference_counting'('$module_call'(Q2,R2)). :-non_counted_backtracking call/65. call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :- var(A), instantiation_error(call/65). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :- - '$strip_module'(A,N2,O2), - '$call_inline'(O2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2). -call('$call'(A),B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :- - !, - '$prepare_call_clause'(N2,O2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2), - '$call_with_inference_counting'('$module_call'(O2,N2)). + '$fast_call'(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2). call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :- - '$prepare_call_clause'(N2,O2,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2), - ( '$call_inline'(N2) - ; expand_call_goal(N2,O2,P2), - strip_subst_module(P2,O2,Q2,R2), - '$call_with_inference_counting'('$module_call'(Q2,R2)) - ). + '$strip_module'(A,N2,O2), + '$prepare_call_clause'(P2,O2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2), + expand_call_goal(P2,N2,Q2), + strip_subst_module(Q2,N2,R2,S2), + '$call_with_inference_counting'('$module_call'(R2,S2)). diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index a6e7963a..9c83272d 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -5058,12 +5058,12 @@ impl Machine { self.machine_st.fail = !self.is_expanded_or_inlined(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } - &Instruction::CallInlineCallN(arity) => { + &Instruction::CallFastCallN(arity) => { let call_at_index = |wam: &mut Machine, name, arity, ptr| { wam.try_call(name, arity, ptr) }; - try_or_throw!(self.machine_st, self.call_inline(arity, call_at_index)); + try_or_throw!(self.machine_st, self.fast_call(arity, call_at_index)); if self.machine_st.fail { self.machine_st.backtrack(); @@ -5074,12 +5074,12 @@ impl Machine { ); } } - &Instruction::ExecuteInlineCallN(arity) => { + &Instruction::ExecuteFastCallN(arity) => { let call_at_index = |wam: &mut Machine, name, arity, ptr| { wam.try_execute(name, arity, ptr) }; - try_or_throw!(self.machine_st, self.call_inline(arity, call_at_index)); + try_or_throw!(self.machine_st, self.fast_call(arity, call_at_index)); if self.machine_st.fail { self.machine_st.backtrack(); diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 6c98024c..3c838b8b 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1698,6 +1698,21 @@ impl Machine { let add_clause = || { let term = loader.read_term_from_heap(temp_v!(2))?; + let indexing_arg = match term.name() { + Some(atom!(":-")) => term.first_arg().and_then(Term::first_arg), + Some(_) => term.first_arg(), + None => None, + }; + + if let Some(indexing_term) = indexing_arg { + if let Some(indexing_name) = indexing_term.name() { + loader.wam_prelude + .indices + .goal_expansion_indices + .insert((indexing_name, indexing_term.arity())); + } + } + loader.incremental_compile_clause( (atom!("goal_expansion"), 2), term, diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index fdc60e0b..ca31e4bd 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -8,7 +8,7 @@ use crate::machine::machine_state::*; use crate::machine::streams::Stream; use fxhash::FxBuildHasher; -use indexmap::IndexMap; +use indexmap::{IndexMap, IndexSet}; use modular_bitfield::{BitfieldSpecifier, bitfield}; use modular_bitfield::specifiers::*; @@ -243,12 +243,15 @@ pub(crate) type LocalExtensiblePredicates = pub(crate) type CodeDir = IndexMap; +pub(crate) type GoalExpansionIndices = IndexSet; + #[derive(Debug)] pub struct IndexStore { pub(super) code_dir: CodeDir, pub(super) extensible_predicates: ExtensiblePredicates, pub(super) local_extensible_predicates: LocalExtensiblePredicates, pub(super) global_variables: GlobalVarDir, + pub(super) goal_expansion_indices: GoalExpansionIndices, pub(super) meta_predicates: MetaPredicateDir, pub(super) modules: ModuleDir, pub(super) op_dir: OpDir, @@ -257,6 +260,11 @@ pub struct IndexStore { } impl IndexStore { + #[inline(always)] + pub(crate) fn goal_expansion_defined(&self, key: PredicateKey) -> bool { + self.goal_expansion_indices.contains(&key) + } + pub(crate) fn get_predicate_skeleton_mut( &mut self, compilation_target: &CompilationTarget, diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 5fc5d451..94f166f2 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1202,29 +1202,29 @@ impl Machine { #[inline(always)] pub(crate) fn deref_register(&mut self, i: usize) -> HeapCellValue { - self.machine_st.store(self.machine_st.deref(self.machine_st.registers[i])) + self.machine_st.store(self.machine_st.deref(self.machine_st.registers[i])) } #[inline(always)] - pub(crate) fn call_inline( + pub(crate) fn fast_call( &mut self, arity: usize, call_at_index: impl Fn(&mut Machine, Atom, usize, IndexPtr) -> CallResult, ) -> CallResult { let arity = arity - 1; - let goal = self.deref_register(1); + let (mut module_name, mut goal) = self.machine_st.strip_module( + self.machine_st.registers[1], + heap_loc_as_cell!(0), + ); - let load_registers = |machine_st: &mut MachineState, goal: HeapCellValue| -> Option { + let load_registers = |machine_st: &mut MachineState, goal: HeapCellValue, goal_arity: usize| { read_heap_cell!(goal, - (HeapCellValueTag::Str, s) => { - let (name, goal_arity) = cell_as_atom_cell!(machine_st.heap[s]) - .get_name_and_arity(); - - if goal_arity > 0 { + (HeapCellValueTag::Str | HeapCellValueTag::Atom, s) => { + if goal_arity > 1 { for idx in (1 .. arity + 1).rev() { machine_st.registers[idx + goal_arity] = machine_st.registers[idx + 1]; } - } else { + } else if goal_arity == 0 { for idx in 1 .. arity + 1 { machine_st.registers[idx] = machine_st.registers[idx + 1]; } @@ -1233,8 +1233,6 @@ impl Machine { for idx in 1 .. goal_arity + 1 { machine_st.registers[idx] = machine_st.heap[s+idx]; } - - Some((name, goal_arity)) } _ => { unreachable!() @@ -1242,35 +1240,70 @@ impl Machine { ) }; - read_heap_cell!(goal, + let (mut name, mut goal_arity, index_cell_opt) = read_heap_cell!(goal, (HeapCellValueTag::Str, s) => { - let goal_arity = cell_as_atom_cell!(self.machine_st.heap[s]).get_arity(); + let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity(); - if self.machine_st.heap.len() > s + goal_arity + 1 { - let index_cell = self.machine_st.heap[s+goal_arity+1]; - - if let Some(code_index) = get_structure_index(index_cell) { - if code_index.is_undefined() { - self.machine_st.fail = true; - return Ok(()); - } - - match load_registers(&mut self.machine_st, goal) { - Some((name, goal_arity)) => { - let arity = goal_arity + arity; - self.machine_st.neck_cut(); - return call_at_index(self, name, arity, code_index.get()); - } - None => { - } - } - } - } + (name, arity, if self.machine_st.heap.len() > s + arity + 1 { + get_structure_index(self.machine_st.heap[s + arity + 1]) + } else { + None + }) + } + (HeapCellValueTag::Atom, (name, arity)) => { + debug_assert_eq!(arity, 0); + (name, arity, None) } _ => { + self.machine_st.fail = true; + return Ok(()); } ); + let mut arity = arity + goal_arity; + + let index_cell = index_cell_opt.or_else(|| { + let is_internal_call = name == atom!("$call") && goal_arity > 0; + + if !is_internal_call && self.indices.goal_expansion_defined((name, arity)) { + None + } else { + if is_internal_call { + debug_assert_eq!(goal.get_tag(), HeapCellValueTag::Str); + goal = self.machine_st.heap[goal.get_value()+1]; + (module_name, goal) = self.machine_st.strip_module(goal, module_name); + + if let Some((inner_name, inner_arity)) = self.machine_st.name_and_arity_from_heap(goal) { + arity -= goal_arity; + (name, goal_arity) = (inner_name, inner_arity); + arity += goal_arity; + } else { + return None; + } + } + + let module_name = if module_name.get_tag() != HeapCellValueTag::Atom { + if let Some(load_context) = self.load_contexts.last() { + load_context.module + } else { + atom!("user") + } + } else { + cell_as_atom!(module_name) + }; + + self.indices.get_predicate_code_index(name, arity, module_name) + } + }); + + if let Some(code_index) = index_cell { + if !code_index.is_undefined() { + load_registers(&mut self.machine_st, goal, goal_arity); + self.machine_st.neck_cut(); + return call_at_index(self, name, arity, code_index.get()); + } + } + self.machine_st.fail = true; Ok(()) } @@ -1489,35 +1522,12 @@ impl Machine { } #[inline(always)] - pub(crate) fn prepare_call_clause(&mut self, arity: usize) -> CallResult { + pub(crate) fn strip_module(&mut self) { let (module_loc, qualified_goal) = self.machine_st.strip_module( - self.machine_st.registers[3], + self.machine_st.registers[1], self.machine_st.registers[2], ); - // the first three arguments don't belong to the containing call/N. - let arity = arity - 3; - - let (name, narity, s) = self.machine_st.setup_call_n_init_goal_info( - qualified_goal, - arity, - )?; - - let module_loc = self.machine_st.store(self.machine_st.deref(module_loc)); - - if module_loc.is_var() { - self.load_context_module(module_loc); - - if self.machine_st.fail { - self.machine_st.fail = false; - self.machine_st.unify_atom(atom!("user"), module_loc); - - if self.machine_st.fail { - return Ok(()); - } - } - } - let target_module_loc = self.machine_st.registers[2]; unify_fn!( @@ -1526,9 +1536,26 @@ impl Machine { target_module_loc ); - if self.machine_st.fail { - return Ok(()); - } + let target_qualified_goal = self.machine_st.registers[3]; + + unify_fn!( + &mut self.machine_st, + qualified_goal, + target_qualified_goal + ); + } + + #[inline(always)] + pub(crate) fn prepare_call_clause(&mut self, arity: usize) -> CallResult { + let qualified_goal = self.deref_register(2); + + // the first two arguments don't belong to the containing call/N. + let arity = arity - 2; + + let (name, narity, s) = self.machine_st.setup_call_n_init_goal_info( + qualified_goal, + arity, + )?; // assemble goal from pre-loaded (narity) and supplementary // (arity) arguments. @@ -1544,15 +1571,10 @@ impl Machine { } for idx in 1 .. arity + 1 { - self.machine_st.heap.push(self.machine_st.registers[3 + idx]); + self.machine_st.heap.push(self.machine_st.registers[2 + idx]); } - let index_cell = self.machine_st.heap[s + narity + 1]; - - if get_structure_index(index_cell).is_some() { - self.machine_st.heap.push(index_cell); - str_loc_as_cell!(h) - } else if narity + arity > 0 { + if narity + arity > 0 { str_loc_as_cell!(h) } else { heap_loc_as_cell!(h) @@ -1570,6 +1592,65 @@ impl Machine { Ok(()) } + #[inline(always)] + pub(crate) fn dynamic_module_resolution( + &mut self, + narity: usize, + ) -> Result<(Atom, PredicateKey), MachineStub> { + let module_name = self.deref_register(1); + + let module_name = read_heap_cell!(module_name, + (HeapCellValueTag::Atom, (name, _arity)) => { + debug_assert_eq!(_arity, 0); + name + } + (HeapCellValueTag::Str, s) => { + let (module_name, _arity) = cell_as_atom_cell!(self.machine_st.heap[s]) + .get_name_and_arity(); + + debug_assert_eq!(_arity, 0); + module_name + } + _ if module_name.is_var() => { + if let Some(load_context) = self.load_contexts.last() { + load_context.module + } else { + atom!("user") + } + } + _ => { + unreachable!() + } + ); + + let goal = self.deref_register(2); + + let (name, arity, s) = self.machine_st.setup_call_n_init_goal_info(goal, narity)?; + + // TODO: think we just need the 'Greater' branch here. + match arity.cmp(&2) { + Ordering::Less => { + for i in arity + 1..arity + narity + 1 { + self.machine_st.registers[i] = self.machine_st.registers[i + 2 - arity]; + } + } + Ordering::Greater => { + for i in (arity + 1..arity + narity + 1).rev() { + self.machine_st.registers[i] = self.machine_st.registers[i + 2 - arity]; + } + } + Ordering::Equal => {} + } + + let key = (name, arity + narity); + + for i in 1..arity + 1 { + self.machine_st.registers[i] = self.machine_st.heap[s + i]; + } + + Ok((module_name, key)) + } + #[inline(always)] pub(crate) fn is_reset_cont_marker(&self, p: usize) -> bool { match &self.code[p] { @@ -3606,60 +3687,6 @@ impl Machine { } } - #[inline(always)] - pub(crate) fn dynamic_module_resolution( - &mut self, - narity: usize, - ) -> Result<(Atom, PredicateKey), MachineStub> { - let module_name = self.deref_register(1); - - let module_name = read_heap_cell!(module_name, - (HeapCellValueTag::Atom, (name, _arity)) => { - debug_assert_eq!(_arity, 0); - name - } - (HeapCellValueTag::Str, s) => { - let (module_name, _arity) = cell_as_atom_cell!(self.machine_st.heap[s]) - .get_name_and_arity(); - - debug_assert_eq!(_arity, 0); - module_name - } - _ if module_name.is_var() => { - atom!("user") - } - _ => { - unreachable!() - } - ); - - let goal = self.deref_register(2); - - let (name, arity, s) = self.machine_st.setup_call_n_init_goal_info(goal, narity)?; - - match arity.cmp(&2) { - Ordering::Less => { - for i in arity + 1..arity + narity + 1 { - self.machine_st.registers[i] = self.machine_st.registers[i + 2 - arity]; - } - } - Ordering::Greater => { - for i in (arity + 1..arity + narity + 1).rev() { - self.machine_st.registers[i] = self.machine_st.registers[i + 2 - arity]; - } - } - Ordering::Equal => {} - } - - let key = (name, arity + narity); - - for i in 1..arity + 1 { - self.machine_st.registers[i] = self.machine_st.heap[s + i]; - } - - Ok((module_name, key)) - } - #[inline(always)] pub(crate) fn lookup_db_ref(&mut self) { let name = cell_as_atom!(self.deref_register(1)); diff --git a/src/macros.rs b/src/macros.rs index c1f1552f..c0c929c8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -574,6 +574,7 @@ macro_rules! index_store { extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()), local_extensible_predicates: LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()), global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()), + goal_expansion_indices: GoalExpansionIndices::with_hasher(FxBuildHasher::default()), meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()), modules: $modules, op_dir: $op_dir, diff --git a/src/toplevel.pl b/src/toplevel.pl index 0bab4415..b554e52c 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -181,7 +181,8 @@ submit_query_and_print_results_(Term, VarList) :- '$get_b_value'(B), bb_put('$report_all', false), bb_put('$report_n_more', 0), - atts:call_residue_vars(user:Term, AttrVars), + expand_goal(Term, user, Term0), + atts:call_residue_vars(user:Term0, AttrVars), write_eqs_and_read_input(B, VarList, AttrVars), !. submit_query_and_print_results_(_, _) :- From 89ed1aa8de253c75c4ac2b145c18639281a8a41c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 22:54:36 +0000 Subject: [PATCH 35/40] Bump openssl from 0.10.48 to 0.10.55 Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.48 to 0.10.55. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.48...openssl-v0.10.55) --- updated-dependencies: - dependency-name: openssl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 364b4891..28421131 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1248,9 +1248,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openssl" -version = "0.10.48" +version = "0.10.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" dependencies = [ "bitflags", "cfg-if", @@ -1280,11 +1280,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.83" +version = "0.9.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", From 4ad113a6f8180fd3839b93eec09f49a4ff457702 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 23 Jun 2023 11:13:51 -0600 Subject: [PATCH 36/40] mark is/2 allocated permanent variables as safe, add CompareNumber terms to ClauseType::is_inlined --- build/instructions_template.rs | 6 ++++++ src/codegen.rs | 3 ++- src/debray_allocator.rs | 29 ++++++++++------------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 7687d4e0..8e61ad23 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -2311,6 +2311,12 @@ pub fn generate_instructions_rs() -> TokenStream { (atom!(#name), #arity) => true } ); + + is_inlined_arms.push( + quote! { + (atom!(#name), #arity) => true + } + ); } for (name, arity, variant) in instr_data.compare_term_variants { diff --git a/src/codegen.rs b/src/codegen.rs index 000c0e65..dca532ce 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -803,7 +803,6 @@ impl<'b> CodeGenerator<'b> { let at = match &terms[0] { &Term::Var(ref vr, ref name) => { let var_num = name.to_var_num().unwrap(); - self.marker.mark_temp_to_safe_perm(var_num); self.marker.mark_var::( var_num, @@ -813,6 +812,8 @@ impl<'b> CodeGenerator<'b> { code, ); + self.marker.mark_safe_var_unconditionally(var_num); + compile_expr!(self, &terms[1], term_loc, code) } &Term::Literal(_, c @ Literal::Integer(_) | diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 2cd853c7..6ad47cfc 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -414,8 +414,7 @@ impl DebrayAllocator { self.perm_free_list.pop_front(); match &mut self.var_data.records[var_num].allocation { - &mut VarAlloc::Perm(p, ref mut allocation) => { - *allocation = PermVarAllocation::Pending; + &mut VarAlloc::Perm(p, _) => { Some(p) } _ => unreachable!() @@ -426,21 +425,18 @@ impl DebrayAllocator { } } - pub(crate) fn mark_temp_to_safe_perm(&mut self, var_num: usize) { - match &self.var_data.records[var_num].allocation { - &VarAlloc::Temp { to_perm_var_num: Some(perm_var_num), .. } => { - let branch_designator = self.current_branch_designator(); + pub(crate) fn mark_safe_var_unconditionally(&mut self, var_num: usize) { + let branch_designator = self.current_branch_designator(); - match &mut self.var_data.records[perm_var_num].allocation { - VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { - *deep_safety = VarSafetyStatus::unneeded(branch_designator); - *shallow_safety = VarSafetyStatus::unneeded(branch_designator); - } - _ => unreachable!() - } + match &mut self.var_data.records[var_num].allocation { + VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { + *deep_safety = VarSafetyStatus::unneeded(branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); } - _ => { + VarAlloc::Temp { safety, .. } => { + *safety = VarSafetyStatus::unneeded(branch_designator); } + _ => unreachable!(), } } @@ -708,11 +704,6 @@ impl Allocator for DebrayAllocator { if record.running_count < record.num_occurrences { record.running_count += 1; } else if r.is_perm() { - match &mut self.var_data.records[var_num].allocation { - VarAlloc::Perm(_, allocation) => *allocation = PermVarAllocation::Pending, - _ => unreachable!(), - } - self.perm_free_list.push_back((term_loc.chunk_num(), var_num)); } From 92853a6a1276d746b27baa249f08c1a35cb2089e Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 23 Jun 2023 12:24:34 -0600 Subject: [PATCH 37/40] free local cut variables after cut --- src/codegen.rs | 8 ++++---- src/debray_allocator.rs | 43 ++++++++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index dca532ce..87345494 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -332,7 +332,7 @@ trait AddToFreeList<'a, Target: CompilationTarget<'a>> { impl<'a, 'b> AddToFreeList<'a, FactInstruction> for CodeGenerator<'b> { fn add_term_to_free_list(&mut self, r: RegType) { - self.marker.add_to_free_list(r); + self.marker.add_reg_to_free_list(r); } fn add_subterm_to_free_list(&mut self, _term: &Term) {} @@ -345,7 +345,7 @@ impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> { #[inline(always)] fn add_subterm_to_free_list(&mut self, term: &Term) { if let Some(cell) = structure_cell(term) { - self.marker.add_to_free_list(cell.get()); + self.marker.add_reg_to_free_list(cell.get()); } } } @@ -881,7 +881,6 @@ impl<'b> CodeGenerator<'b> { code.push_back(instr!("neck_cut")); } else { let r = self.marker.get_binding(var_num); - // let r = self.marker.mark_cut_var(var_num, chunk_num); code.push_back(instr!("cut", r)); } @@ -896,7 +895,6 @@ impl<'b> CodeGenerator<'b> { &QueryTerm::LocalCut(var_num) => { let code = branch_code_stack.code(code); let r = self.marker.get_binding(var_num); - // let r = self.marker.mark_cut_var(var_num, chunk_num); code.push_back(instr!("cut", r)); if self.marker.in_tail_position { @@ -905,6 +903,8 @@ impl<'b> CodeGenerator<'b> { } code.push_back(instr!("proceed")); + } else { + self.marker.free_cut_var(chunk_num, var_num); } } &QueryTerm::Clause( diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 6ad47cfc..6bfbfb5e 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -382,7 +382,7 @@ impl DebrayAllocator { p } - pub fn add_to_free_list(&mut self, r: RegType) { + pub(crate) fn add_reg_to_free_list(&mut self, r: RegType) { if let RegType::Temp(r) = r { self.in_use.remove(r); self.temp_free_list.push(r); @@ -406,22 +406,43 @@ impl DebrayAllocator { self.var_data.records[var_num].running_count += 1; } + fn add_perm_to_free_list(&mut self, chunk_num: usize, var_num: usize) { + match &self.var_data.records[var_num].allocation { + VarAlloc::Perm(..) => { + self.perm_free_list.push_back((chunk_num, var_num)); + } + _ => {} + } + } + fn pop_free_perm(&mut self, chunk_num: usize) -> Option { - if let Some((perm_chunk_num, var_num)) = self.perm_free_list.front().cloned() { - if chunk_num == perm_chunk_num { - None - } else { + while let Some((perm_chunk_num, var_num)) = self.perm_free_list.front().cloned() { + if chunk_num > perm_chunk_num { self.perm_free_list.pop_front(); match &mut self.var_data.records[var_num].allocation { - &mut VarAlloc::Perm(p, _) => { - Some(p) + VarAlloc::Perm(p, PermVarAllocation::Pending) if *p > 0 => { + return Some(std::mem::replace(p, 0)); + } + _ => { } - _ => unreachable!() } + } else { + return None; + } + } + + None + } + + pub(crate) fn free_cut_var(&mut self, chunk_num: usize, var_num: usize) { + 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); + } + _ => { } - } else { - None } } @@ -704,7 +725,7 @@ impl Allocator for DebrayAllocator { if record.running_count < record.num_occurrences { record.running_count += 1; } else if r.is_perm() { - self.perm_free_list.push_back((term_loc.chunk_num(), var_num)); + self.add_perm_to_free_list(term_loc.chunk_num(), var_num); } self.in_use.insert(o); From f4469397707ac75f29e17a05c1d309990fbc7f15 Mon Sep 17 00:00:00 2001 From: infogulch Date: Thu, 22 Jun 2023 22:14:44 -0500 Subject: [PATCH 38/40] Add steps to publish binaries when releases are tagged --- .github/workflows/ci.yml | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73296baf..87a3331b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,8 @@ on: pull_request: schedule: - cron: '0 0 * * 3' # At 12:00 AM, only on Wednesday + label: + types: [created, edited] jobs: build-test: @@ -53,12 +55,12 @@ jobs: if: "!matrix.extra" run: cargo test --all --verbose - # Extra steps + # Extra steps only run once to avoid duplication, when matrix.extra is true - name: Test and report if: matrix.extra run: | cargo install cargo2junit --force - cargo test --all -- -Z unstable-options --format json --report-time | cargo2junit > cargo_test_results.xml + RUSTC_BOOTSTRAP=1 cargo test --all -- -Z unstable-options --format json --report-time | cargo2junit > cargo_test_results.xml - name: Publish cargo test results artifact if: matrix.extra uses: actions/upload-artifact@v3 @@ -99,6 +101,7 @@ jobs: runs-on: ubuntu-20.04 needs: [build-test] steps: + # Download prebuilt ubuntu binary from build-test job, setup logtalk - uses: actions/download-artifact@v3 with: name: scryer-prolog_ubuntu-20.04 @@ -139,3 +142,23 @@ jobs: files: '${{ env.LOGTALKUSER }}/tests/prolog/**/*.xml' fail_on: nothing comment_mode: off + + # Publish binaries when building for a tag + release: + runs-on: ubuntu-20.04 + needs: [build-test] + if: startsWith(github.ref, 'refs/tags/v') + steps: + - uses: actions/download-artifact@v3 + - name: Zip binaries for release + run: | + zip scryer-prolog_macos-11.zip ./scryer-prolog_macos-11/scryer-prolog + zip scryer-prolog_ubuntu-20.04.zip ./scryer-prolog_ubuntu-20.04/scryer-prolog + zip scryer-prolog_windows-latest.zip ./scryer-prolog_windows-latest/scryer-prolog.exe + - name: Release + uses: softprops/action-gh-release@v1 + with: + files: | + scryer-prolog_macos-11.zip + scryer-prolog_ubuntu-20.04.zip + scryer-prolog_windows-latest.zip From fcae0d9fcfb77e564f0f5e122b261b20aa1bbaf7 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 23 Jun 2023 12:53:21 -0600 Subject: [PATCH 39/40] polish perm free list management --- src/codegen.rs | 2 +- src/debray_allocator.rs | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 87345494..33ac87d9 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -904,7 +904,7 @@ impl<'b> CodeGenerator<'b> { code.push_back(instr!("proceed")); } else { - self.marker.free_cut_var(chunk_num, var_num); + self.marker.free_var(chunk_num, var_num); } } &QueryTerm::Clause( diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 6bfbfb5e..c1f32c49 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -151,8 +151,11 @@ impl DebrayAllocator { }; for var_num in subsumed_hits.iter().cloned() { + let running_count = self.var_data.records[var_num].running_count; + let num_occurrences = self.var_data.records[var_num].num_occurrences; + match &mut self.var_data.records[var_num].allocation { - VarAlloc::Perm(_, ref mut allocation) => { + VarAlloc::Perm(_, allocation) => { let shallow_safety = VarSafetyStatus::needed_if( shallow_safety.contains(var_num), branch_designator, @@ -163,7 +166,9 @@ impl DebrayAllocator { branch_designator, ); - *allocation = PermVarAllocation::Done { shallow_safety, deep_safety }; + if running_count < num_occurrences { + *allocation = PermVarAllocation::Done { shallow_safety, deep_safety }; + } } _ => unreachable!() } @@ -435,7 +440,7 @@ impl DebrayAllocator { None } - pub(crate) fn free_cut_var(&mut self, chunk_num: usize, var_num: usize) { + pub(crate) fn free_var(&mut self, chunk_num: usize, var_num: usize) { match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, allocation) => { *allocation = PermVarAllocation::Pending; @@ -724,8 +729,8 @@ impl Allocator for DebrayAllocator { if record.running_count < record.num_occurrences { record.running_count += 1; - } else if r.is_perm() { - self.add_perm_to_free_list(term_loc.chunk_num(), var_num); + } else { + self.free_var(term_loc.chunk_num(), var_num); } self.in_use.insert(o); From 612861e010b53d8ede949a02bec261152e5e49b8 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 23 Jun 2023 14:13:40 -0600 Subject: [PATCH 40/40] correct reversions after rebase --- src/machine/dispatch.rs | 44 +------ src/machine/loader.rs | 2 +- src/variable_records.rs | 248 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 251 insertions(+), 43 deletions(-) create mode 100644 src/variable_records.rs diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 9c83272d..686ec71b 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -4987,51 +4987,11 @@ impl Machine { step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallStripModule => { - let (module_loc, qualified_goal) = self.machine_st.strip_module( - self.machine_st.registers[1], - self.machine_st.registers[2], - ); - - let target_module_loc = self.machine_st.registers[2]; - - unify_fn!( - &mut self.machine_st, - module_loc, - target_module_loc - ); - - let target_qualified_goal = self.machine_st.registers[3]; - - unify_fn!( - &mut self.machine_st, - qualified_goal, - target_qualified_goal - ); - + self.strip_module(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteStripModule => { - let (module_loc, qualified_goal) = self.machine_st.strip_module( - self.machine_st.registers[1], - self.machine_st.registers[2], - ); - - let target_module_loc = self.machine_st.registers[2]; - - unify_fn!( - &mut self.machine_st, - module_loc, - target_module_loc - ); - - let target_qualified_goal = self.machine_st.registers[3]; - - unify_fn!( - &mut self.machine_st, - qualified_goal, - target_qualified_goal - ); - + self.strip_module(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPrepareCallClause(arity) => { diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 3c838b8b..3e9ae50e 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1435,7 +1435,7 @@ impl MachineState { term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap())); } (HeapCellValueTag::Atom, (name, arity)) => { - let h = iter.focus(); + let h = iter.focus().value() as usize; let mut arity = arity; if iter.heap.len() > h + arity + 1 { diff --git a/src/variable_records.rs b/src/variable_records.rs new file mode 100644 index 00000000..f301d909 --- /dev/null +++ b/src/variable_records.rs @@ -0,0 +1,248 @@ +use crate::parser::ast::*; + +use bit_set::*; +use fxhash::FxBuildHasher; +use indexmap::{IndexMap, IndexSet}; +use std::ops::{Deref, DerefMut}; + +#[derive(Debug, Clone)] +pub struct TempVarData { + pub(crate) use_set: IndexSet<(GenContext, usize), FxBuildHasher>, + pub(crate) no_use_set: BitSet, + pub(crate) conflict_set: BitSet, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BranchDesignator(pub (usize, usize)); + +impl BranchDesignator { + #[inline] + pub fn is_subbranch(&self) -> bool { + (self.0).0 > 0 + } + + #[inline] + pub fn subsumes(&self, branch_designator: &Self) -> bool { + (self.0).0 < (branch_designator.0).0 || self == branch_designator + } +} + +#[derive(Debug, Clone, Copy)] +pub enum VarSafetyStatus { + Needed, + // which branch planted the last unsafe guarded instruction? It may still be needed. + LocallyUnneeded(BranchDesignator), + GloballyUnneeded, +} + +impl VarSafetyStatus { + pub(crate) fn unneeded(current_branch: BranchDesignator) -> Self { + if current_branch.is_subbranch() { + VarSafetyStatus::LocallyUnneeded(current_branch) + } else { + VarSafetyStatus::GloballyUnneeded + } + } + + #[inline] + pub(crate) fn is_unneeded(&self, current_branch: BranchDesignator) -> bool { + match self { + &VarSafetyStatus::Needed => false, + &VarSafetyStatus::LocallyUnneeded(planter_branch) => planter_branch.subsumes(¤t_branch), + &VarSafetyStatus::GloballyUnneeded => true, + } + } + + #[inline] + pub(crate) fn needed_if(needed: bool, branch_designator: BranchDesignator) -> Self { + if needed { + VarSafetyStatus::Needed + } else if (branch_designator.0).0 == 0 { + VarSafetyStatus::GloballyUnneeded + } else { + VarSafetyStatus::LocallyUnneeded(branch_designator) + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum PermVarAllocation { + Done { shallow_safety: VarSafetyStatus, + deep_safety: VarSafetyStatus }, + Pending, +} + +impl PermVarAllocation { + #[inline] + pub(crate) fn done() -> Self { + PermVarAllocation::Done { + shallow_safety: VarSafetyStatus::Needed, + deep_safety: VarSafetyStatus::Needed, + } + } + + #[inline] + pub(crate) fn pending(&self) -> bool { + match self { + &PermVarAllocation::Pending => true, + _ => false, + } + } +} + +#[derive(Debug, Clone)] +pub enum VarAlloc { + Temp { term_loc: GenContext, + temp_reg: usize, + temp_var_data: TempVarData, + safety: VarSafetyStatus, + to_perm_var_num: Option }, + Perm(usize, PermVarAllocation), // stack offset, allocation info +} + +impl VarAlloc { + #[inline] + pub(crate) fn as_reg_type(&self) -> RegType { + match self { + &VarAlloc::Temp { temp_reg, .. } => RegType::Temp(temp_reg), + &VarAlloc::Perm(r, _) => RegType::Perm(r), + } + } + + #[inline] + pub(crate) fn set_register(&mut self, reg_num: usize) { + match self { + VarAlloc::Perm(ref mut p, _) => *p = reg_num, + VarAlloc::Temp { ref mut temp_reg, .. } => *temp_reg = reg_num, + }; + } +} + +impl TempVarData { + pub(crate) fn new() -> Self { + TempVarData { + use_set: IndexSet::with_hasher(FxBuildHasher::default()), + no_use_set: BitSet::default(), + conflict_set: BitSet::default(), + } + } + + pub(crate) fn uses_reg(&self, reg: usize) -> bool { + for &(_, nreg) in self.use_set.iter() { + if reg == nreg { + return true; + } + } + + return false; + } + + pub(crate) fn populate_conflict_set(&mut self) { + let arity = self.use_set.len(); + let mut conflict_set: BitSet = (1..arity).collect(); + + for &(_, idx) in &self.use_set { + conflict_set.remove(idx); + } + + self.conflict_set = conflict_set; + } +} + +#[derive(Debug, Clone)] +pub struct VariableRecord { + pub allocation: VarAlloc, + pub num_occurrences: usize, + pub running_count: usize, +} + +impl Default for VariableRecord { + fn default() -> Self { + VariableRecord { + allocation: VarAlloc::Perm(0, PermVarAllocation::Pending), + num_occurrences: 0, + running_count: 0, + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct VariableRecords(Vec); + +impl Deref for VariableRecords { + type Target = Vec; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for VariableRecords { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl VariableRecords { + #[inline] + pub(crate) fn new(num_records: usize) -> Self { + Self(vec![VariableRecord::default(); num_records]) + } + + // computes no_use and conflict sets for all temp vars. + pub(crate) fn populate_restricting_sets(&mut self) { + // three stages: + // 1. move the use sets of each variable to a local IndexMap, use_set + // (iterate mutably, swap mutable refs). + // 2. drain use_set. For each use set of U, add into the + // no-use sets of appropriate variables T =/= U. + // 3. Move the use sets back to their original locations in the fixture. + // Compute the conflict set of u. + + // 1. + let mut use_sets: IndexMap> = IndexMap::new(); + + for (var_gen_index, record) in self.0.iter_mut().enumerate() { + match &mut record.allocation { + VarAlloc::Temp { temp_var_data, .. } => { + let use_set = std::mem::replace( + &mut temp_var_data.use_set, + IndexSet::with_hasher(FxBuildHasher::default()), + ); + + use_sets.insert(var_gen_index, use_set); + } + _ => { + } + } + } + + for (u, use_set) in use_sets.drain(..) { + // 2. + for &(term_loc, reg) in &use_set { + if let GenContext::Last(cn_u) = term_loc { + for (var_gen_index, record) in self.0.iter_mut().enumerate() { + match &mut record.allocation { + VarAlloc::Temp { term_loc, temp_var_data, .. } => { + if cn_u == term_loc.chunk_num() && u != var_gen_index { + if !temp_var_data.uses_reg(reg) { + temp_var_data.no_use_set.insert(reg); + } + } + } + _ => {} + } + } + } + } + + // 3. + if let VarAlloc::Temp{ temp_var_data, .. } = &mut self[u].allocation { + temp_var_data.use_set = use_set; + temp_var_data.populate_conflict_set(); + } + } + } +}