inline metacalls
This commit is contained in:
@@ -548,6 +548,12 @@ enum SystemClauseType {
|
|||||||
PredicateDefined,
|
PredicateDefined,
|
||||||
#[strum_discriminants(strum(props(Arity = "3", Name = "$strip_module")))]
|
#[strum_discriminants(strum(props(Arity = "3", Name = "$strip_module")))]
|
||||||
StripModule,
|
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 = "1", Name = "$is_expanded_or_inlined")))]
|
||||||
|
IsExpandedOrInlined,
|
||||||
REPL(REPLCodePtr),
|
REPL(REPLCodePtr),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1435,6 +1441,12 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::DefaultExecuteN(arity, _) => {
|
&Instruction::DefaultExecuteN(arity, _) => {
|
||||||
functor!(atom!("execute_default_n"), [fixnum(arity)])
|
functor!(atom!("execute_default_n"), [fixnum(arity)])
|
||||||
}
|
}
|
||||||
|
&Instruction::CallInlineCallN(arity, _) => {
|
||||||
|
functor!(atom!("call_n_inline"), [fixnum(arity)])
|
||||||
|
}
|
||||||
|
&Instruction::ExecuteInlineCallN(arity, _) => {
|
||||||
|
functor!(atom!("call_n_inline"), [fixnum(arity)])
|
||||||
|
}
|
||||||
&Instruction::CallTermGreaterThan(_) |
|
&Instruction::CallTermGreaterThan(_) |
|
||||||
&Instruction::CallTermLessThan(_) |
|
&Instruction::CallTermLessThan(_) |
|
||||||
&Instruction::CallTermGreaterThanOrEqual(_) |
|
&Instruction::CallTermGreaterThanOrEqual(_) |
|
||||||
@@ -1597,6 +1609,8 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::CallDeleteHeadAttribute(_) |
|
&Instruction::CallDeleteHeadAttribute(_) |
|
||||||
&Instruction::CallDynamicModuleResolution(..) |
|
&Instruction::CallDynamicModuleResolution(..) |
|
||||||
&Instruction::CallPrepareCallClause(..) |
|
&Instruction::CallPrepareCallClause(..) |
|
||||||
|
&Instruction::CallCompileInlineOrExpandedGoal(..) |
|
||||||
|
&Instruction::CallIsExpandedOrInlined(_) |
|
||||||
&Instruction::CallEnqueueAttributedVar(_) |
|
&Instruction::CallEnqueueAttributedVar(_) |
|
||||||
&Instruction::CallFetchGlobalVar(_) |
|
&Instruction::CallFetchGlobalVar(_) |
|
||||||
&Instruction::CallFirstStream(_) |
|
&Instruction::CallFirstStream(_) |
|
||||||
@@ -1804,6 +1818,8 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::ExecuteDeleteHeadAttribute(_) |
|
&Instruction::ExecuteDeleteHeadAttribute(_) |
|
||||||
&Instruction::ExecuteDynamicModuleResolution(..) |
|
&Instruction::ExecuteDynamicModuleResolution(..) |
|
||||||
&Instruction::ExecutePrepareCallClause(..) |
|
&Instruction::ExecutePrepareCallClause(..) |
|
||||||
|
&Instruction::ExecuteCompileInlineOrExpandedGoal(..) |
|
||||||
|
&Instruction::ExecuteIsExpandedOrInlined(_) |
|
||||||
&Instruction::ExecuteEnqueueAttributedVar(_) |
|
&Instruction::ExecuteEnqueueAttributedVar(_) |
|
||||||
&Instruction::ExecuteFetchGlobalVar(_) |
|
&Instruction::ExecuteFetchGlobalVar(_) |
|
||||||
&Instruction::ExecuteFirstStream(_) |
|
&Instruction::ExecuteFirstStream(_) |
|
||||||
@@ -2412,6 +2428,12 @@ pub fn generate_instructions_rs() -> TokenStream {
|
|||||||
SystemClauseType::#ident(temp_v!(1))
|
SystemClauseType::#ident(temp_v!(1))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else if ident.to_string() == "InlineCallN" {
|
||||||
|
quote! {
|
||||||
|
(atom!(#name), arity) => ClauseType::System(
|
||||||
|
SystemClauseType::#ident(arity)
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
(atom!(#name), #arity) => ClauseType::System(
|
(atom!(#name), #arity) => ClauseType::System(
|
||||||
@@ -2442,6 +2464,7 @@ pub fn generate_instructions_rs() -> TokenStream {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let ident = variant.ident;
|
let ident = variant.ident;
|
||||||
|
|
||||||
let instr_ident = if ident != "CallContinuation" {
|
let instr_ident = if ident != "CallContinuation" {
|
||||||
format_ident!("Call{}", ident)
|
format_ident!("Call{}", ident)
|
||||||
} else {
|
} else {
|
||||||
@@ -2537,7 +2560,7 @@ pub fn generate_instructions_rs() -> TokenStream {
|
|||||||
|
|
||||||
if ident == "Named" {
|
if ident == "Named" {
|
||||||
clause_type_from_name_and_arity_arms.push(quote! {
|
clause_type_from_name_and_arity_arms.push(quote! {
|
||||||
(name, arity) => ClauseType::Named(arity, name, CodeIndex::default())
|
(name, arity) => ClauseType::Named(arity, name, CodeIndex::default(arena))
|
||||||
});
|
});
|
||||||
|
|
||||||
clause_type_to_instr_arms.push(quote! {
|
clause_type_to_instr_arms.push(quote! {
|
||||||
@@ -2933,7 +2956,7 @@ pub fn generate_instructions_rs() -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ClauseType {
|
impl ClauseType {
|
||||||
pub fn from(name: Atom, arity: usize) -> ClauseType {
|
pub fn from(name: Atom, arity: usize, arena: &mut Arena) -> ClauseType {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
#(
|
#(
|
||||||
#clause_type_from_name_and_arity_arms,
|
#clause_type_from_name_and_arity_arms,
|
||||||
|
|||||||
111
src/arena.rs
111
src/arena.rs
@@ -4,7 +4,6 @@ use crate::machine::streams::*;
|
|||||||
use crate::raw_block::*;
|
use crate::raw_block::*;
|
||||||
use crate::read::*;
|
use crate::read::*;
|
||||||
|
|
||||||
use modular_bitfield::prelude::*;
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use crate::parser::rug::{Integer, Rational};
|
use crate::parser::rug::{Integer, Rational};
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ macro_rules! arena_alloc {
|
|||||||
($e:expr, $arena:expr) => {{
|
($e:expr, $arena:expr) => {{
|
||||||
let result = $e;
|
let result = $e;
|
||||||
#[allow(unused_unsafe)]
|
#[allow(unused_unsafe)]
|
||||||
unsafe { $arena.alloc(result) }
|
unsafe { ArenaAllocated::alloc($arena, result) }
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +148,10 @@ pub enum ArenaHeaderTag {
|
|||||||
NullStream = 0b111100,
|
NullStream = 0b111100,
|
||||||
TcpListener = 0b1000000,
|
TcpListener = 0b1000000,
|
||||||
Dropped = 0b1000100,
|
Dropped = 0b1000100,
|
||||||
|
IndexPtrDynamicUndefined = 0b1000101,
|
||||||
|
IndexPtrDynamicIndex = 0b1000110,
|
||||||
|
IndexPtrIndex = 0b1000111,
|
||||||
|
IndexPtrUndefined = 0b1001000,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bitfield]
|
#[bitfield]
|
||||||
@@ -234,7 +237,7 @@ impl<T: fmt::Display> fmt::Display for TypedArenaPtr<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> TypedArenaPtr<T> {
|
impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(data: *mut T) -> Self {
|
pub const fn new(data: *mut T) -> Self {
|
||||||
unsafe { TypedArenaPtr(ptr::NonNull::new_unchecked(data)) }
|
unsafe { TypedArenaPtr(ptr::NonNull::new_unchecked(data)) }
|
||||||
@@ -248,14 +251,14 @@ impl<T: ?Sized> TypedArenaPtr<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn header_ptr(&self) -> *const ArenaHeader {
|
pub fn header_ptr(&self) -> *const ArenaHeader {
|
||||||
let mut ptr = self.as_ptr() as *const u8 as usize;
|
let mut ptr = self.as_ptr() as *const u8 as usize;
|
||||||
ptr -= mem::size_of::<*const ArenaHeader>();
|
ptr -= T::header_offset_from_payload(); // mem::size_of::<*const ArenaHeader>();
|
||||||
ptr as *const ArenaHeader
|
ptr as *const ArenaHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn header_ptr_mut(&mut self) -> *mut ArenaHeader {
|
fn header_ptr_mut(&mut self) -> *mut ArenaHeader {
|
||||||
let mut ptr = self.as_ptr() as *const u8 as usize;
|
let mut ptr = self.as_ptr() as *const u8 as usize;
|
||||||
ptr -= mem::size_of::<*const ArenaHeader>();
|
ptr -= T::header_offset_from_payload(); // mem::size_of::<*const ArenaHeader>();
|
||||||
ptr as *mut ArenaHeader
|
ptr as *mut ArenaHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,14 +292,35 @@ impl<T: ?Sized> TypedArenaPtr<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ArenaAllocated {
|
pub trait ArenaAllocated: Sized {
|
||||||
type PtrToAllocated;
|
type PtrToAllocated;
|
||||||
|
|
||||||
fn tag() -> ArenaHeaderTag;
|
fn tag() -> ArenaHeaderTag;
|
||||||
fn size(&self) -> usize;
|
fn size(&self) -> usize;
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated
|
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated;
|
||||||
where
|
|
||||||
Self: Sized;
|
fn header_offset_from_payload() -> usize {
|
||||||
|
mem::size_of::<*const ArenaHeader>()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
|
||||||
|
let size = value.size() + mem::size_of::<AllocSlab>();
|
||||||
|
|
||||||
|
let align = mem::align_of::<AllocSlab>();
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(size, align);
|
||||||
|
|
||||||
|
let slab = alloc::alloc(layout) as *mut AllocSlab;
|
||||||
|
|
||||||
|
(*slab).next = arena.base;
|
||||||
|
(*slab).header = ArenaHeader::build_with(value.size() as u64, Self::tag());
|
||||||
|
|
||||||
|
let offset = (*slab).payload_offset();
|
||||||
|
let result = value.copy_to_arena(offset as *mut Self);
|
||||||
|
|
||||||
|
arena.base = slab;
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@@ -536,6 +560,49 @@ impl ArenaAllocated for TcpListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ArenaAllocated for IndexPtr {
|
||||||
|
type PtrToAllocated = TypedArenaPtr<IndexPtr>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn tag() -> ArenaHeaderTag {
|
||||||
|
ArenaHeaderTag::IndexPtrUndefined
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
mem::size_of::<Self>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
||||||
|
unsafe {
|
||||||
|
ptr::write(dst, self);
|
||||||
|
TypedArenaPtr::new(dst as *mut Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn header_offset_from_payload() -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
|
||||||
|
let size = mem::size_of::<AllocSlab>();
|
||||||
|
|
||||||
|
let align = mem::align_of::<AllocSlab>();
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(size, align);
|
||||||
|
|
||||||
|
let slab = alloc::alloc(layout) as *mut AllocSlab;
|
||||||
|
|
||||||
|
(*slab).next = arena.base;
|
||||||
|
|
||||||
|
let result = value.copy_to_arena(mem::transmute::<_, *mut IndexPtr>(&(*slab).header));
|
||||||
|
arena.base = slab;
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
struct AllocSlab {
|
struct AllocSlab {
|
||||||
next: *mut AllocSlab,
|
next: *mut AllocSlab,
|
||||||
@@ -556,25 +623,6 @@ impl Arena {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Arena { base: ptr::null_mut(), f64_tbl: F64Table::new() }
|
Arena { base: ptr::null_mut(), f64_tbl: F64Table::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn alloc<T: ArenaAllocated>(&mut self, value: T) -> T::PtrToAllocated {
|
|
||||||
let size = value.size() + mem::size_of::<AllocSlab>();
|
|
||||||
|
|
||||||
let align = mem::align_of::<AllocSlab>();
|
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(size, align);
|
|
||||||
|
|
||||||
let slab = alloc::alloc(layout) as *mut AllocSlab;
|
|
||||||
|
|
||||||
(*slab).next = self.base;
|
|
||||||
(*slab).header = ArenaHeader::build_with(value.size() as u64, T::tag());
|
|
||||||
|
|
||||||
let offset = (*slab).payload_offset();
|
|
||||||
let result = value.copy_to_arena(offset as *mut T);
|
|
||||||
|
|
||||||
self.base = slab;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
||||||
@@ -628,7 +676,9 @@ unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
|||||||
ArenaHeaderTag::StandardErrorStream => {
|
ArenaHeaderTag::StandardErrorStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<StandardErrorStream>>());
|
ptr::drop_in_place(value.payload_offset::<StreamLayout<StandardErrorStream>>());
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::NullStream => {
|
ArenaHeaderTag::NullStream | ArenaHeaderTag::IndexPtrUndefined |
|
||||||
|
ArenaHeaderTag::IndexPtrDynamicUndefined | ArenaHeaderTag::IndexPtrDynamicIndex |
|
||||||
|
ArenaHeaderTag::IndexPtrIndex => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -745,7 +795,8 @@ mod tests {
|
|||||||
// integer
|
// integer
|
||||||
|
|
||||||
let big_int: Integer = 2 * Integer::from(1u64 << 63);
|
let big_int: Integer = 2 * Integer::from(1u64 << 63);
|
||||||
let big_int_ptr: TypedArenaPtr<Integer> = arena_alloc!(big_int, wam.machine_st.arena);
|
let big_int_ptr: TypedArenaPtr<Integer> =
|
||||||
|
arena_alloc!(big_int, &mut wam.machine_st.arena);
|
||||||
|
|
||||||
assert!(!big_int_ptr.as_ptr().is_null());
|
assert!(!big_int_ptr.as_ptr().is_null());
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use crate::parser::rug::ops::PowAssign;
|
|||||||
use crate::parser::rug::{Assign, Integer, Rational};
|
use crate::parser::rug::{Assign, Integer, Rational};
|
||||||
|
|
||||||
use crate::machine::machine_errors::*;
|
use crate::machine::machine_errors::*;
|
||||||
use crate::machine::machine_indices::*;
|
|
||||||
|
|
||||||
use ordered_float::*;
|
use ordered_float::*;
|
||||||
|
|
||||||
@@ -65,19 +64,22 @@ impl<'a> ArithInstructionIterator<'a> {
|
|||||||
fn from(term: &'a Term) -> Result<Self, ArithmeticError> {
|
fn from(term: &'a Term) -> Result<Self, ArithmeticError> {
|
||||||
let state = match term {
|
let state = match term {
|
||||||
Term::AnonVar => return Err(ArithmeticError::UninstantiatedVar),
|
Term::AnonVar => return Err(ArithmeticError::UninstantiatedVar),
|
||||||
Term::Clause(cell, name, terms) => match ClauseType::from(*name, terms.len()) {
|
Term::Clause(cell, name, terms) => {
|
||||||
|
TermIterState::Clause(Level::Shallow, 0, cell, *name, terms)
|
||||||
|
}
|
||||||
|
/* match ClauseType::from(*name, terms.len()) {
|
||||||
ct @ ClauseType::Named(..) => {
|
ct @ ClauseType::Named(..) => {
|
||||||
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
|
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
|
||||||
}
|
}
|
||||||
ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => {
|
ct @ ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => {
|
||||||
let ct = ClauseType::Named(1, atom!("float"), CodeIndex::default());
|
// let ct = ClauseType::Named(1, atom!("float"), CodeIndex::default());
|
||||||
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
|
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
|
||||||
}
|
}
|
||||||
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
||||||
Literal::Atom(*name),
|
Literal::Atom(*name),
|
||||||
terms.len(),
|
terms.len(),
|
||||||
)),
|
)),
|
||||||
}?,
|
}?,*/
|
||||||
Term::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
|
Term::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
|
||||||
Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
|
Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
|
||||||
return Err(ArithmeticError::NonEvaluableFunctor(
|
return Err(ArithmeticError::NonEvaluableFunctor(
|
||||||
@@ -108,17 +110,17 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
while let Some(iter_state) = self.state_stack.pop() {
|
while let Some(iter_state) = self.state_stack.pop() {
|
||||||
match iter_state {
|
match iter_state {
|
||||||
TermIterState::AnonVar(_) => return Some(Err(ArithmeticError::UninstantiatedVar)),
|
TermIterState::AnonVar(_) => return Some(Err(ArithmeticError::UninstantiatedVar)),
|
||||||
TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
|
TermIterState::Clause(lvl, child_num, cell, name, subterms) => {
|
||||||
let arity = subterms.len();
|
let arity = subterms.len();
|
||||||
|
|
||||||
if child_num == arity {
|
if child_num == arity {
|
||||||
return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
|
return Some(Ok(ArithTermRef::Op(name, arity)));
|
||||||
} else {
|
} else {
|
||||||
self.state_stack.push(TermIterState::Clause(
|
self.state_stack.push(TermIterState::Clause(
|
||||||
lvl,
|
lvl,
|
||||||
child_num + 1,
|
child_num + 1,
|
||||||
cell,
|
cell,
|
||||||
ct,
|
name,
|
||||||
subterms,
|
subterms,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -369,9 +369,15 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
self.marker.mark_anon_var::<Target>(lvl, term_loc, &mut target);
|
self.marker.mark_anon_var::<Target>(lvl, term_loc, &mut target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermRef::Clause(lvl, cell, ct, terms) => {
|
TermRef::Clause(lvl, cell, name, terms) => {
|
||||||
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
|
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
|
||||||
target.push(Target::to_structure(ct.name(), terms.len(), cell.get()));
|
target.push(Target::to_structure(name, terms.len(), cell.get()));
|
||||||
|
|
||||||
|
if let Some(instr) = target.last_mut() {
|
||||||
|
if let Some(term) = terms.last() {
|
||||||
|
Target::trim_structure_by_last_arg(instr, term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for subterm in terms {
|
for subterm in terms {
|
||||||
self.subterm_to_instr::<Target>(subterm, term_loc, is_exposed, &mut target);
|
self.subterm_to_instr::<Target>(subterm, term_loc, is_exposed, &mut target);
|
||||||
@@ -1039,10 +1045,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
let iter = query_term_post_order_iter(term);
|
let iter = query_term_post_order_iter(term);
|
||||||
let query = self.compile_target::<QueryInstruction, _>(iter, term_loc, is_exposed);
|
let query = self.compile_target::<QueryInstruction, _>(iter, term_loc, is_exposed);
|
||||||
|
|
||||||
if !query.is_empty() {
|
|
||||||
code.extend(query.into_iter());
|
code.extend(query.into_iter());
|
||||||
}
|
|
||||||
|
|
||||||
self.add_conditional_call(code, term, num_perm_vars_left);
|
self.add_conditional_call(code, term, num_perm_vars_left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
src/forms.rs
11
src/forms.rs
@@ -154,24 +154,21 @@ impl ClauseInfo for PredicateKey {
|
|||||||
|
|
||||||
impl ClauseInfo for Term {
|
impl ClauseInfo for Term {
|
||||||
fn name(&self) -> Option<Atom> {
|
fn name(&self) -> Option<Atom> {
|
||||||
//, atom_tbl: &AtomTable) -> Option<StringBuffer> {
|
|
||||||
match self {
|
match self {
|
||||||
Term::Clause(_, name, terms) => {
|
Term::Clause(_, name, terms) => {
|
||||||
// let str_buf = StringBuffer::from(*name, atom_tbl);
|
|
||||||
|
|
||||||
match name.as_str() {
|
match name {
|
||||||
// str_buf.as_str() {
|
atom!(":-") => {
|
||||||
":-" => {
|
|
||||||
match terms.len() {
|
match terms.len() {
|
||||||
1 => None, // a declaration.
|
1 => None, // a declaration.
|
||||||
2 => terms[0].name(), //.map(|name| StringBuffer::from(name, atom_tbl)),
|
2 => terms[0].name(),
|
||||||
_ => Some(*name),
|
_ => Some(*name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Some(*name), //str_buf),
|
_ => Some(*name), //str_buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Term::Literal(_, Literal::Atom(name)) => Some(*name), //Some(StringBuffer::from(*name, atom_tbl)),
|
Term::Literal(_, Literal::Atom(name)) => Some(*name),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,17 @@ impl<'a> Drop for StackfulPreOrderHeapIter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FocusedHeapIter: Iterator<Item = HeapCellValue> {
|
||||||
|
fn focus(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FocusedHeapIter for StackfulPreOrderHeapIter<'a> {
|
||||||
|
#[inline]
|
||||||
|
fn focus(&self) -> usize {
|
||||||
|
self.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> StackfulPreOrderHeapIter<'a> {
|
impl<'a> StackfulPreOrderHeapIter<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(heap: &'a mut Vec<HeapCellValue>, cell: HeapCellValue) -> Self {
|
fn new(heap: &'a mut Vec<HeapCellValue>, cell: HeapCellValue) -> Self {
|
||||||
@@ -126,11 +137,6 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn focus(&self) -> usize {
|
|
||||||
self.h
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pop_stack(&mut self) -> Option<HeapCellValue> {
|
pub fn pop_stack(&mut self) -> Option<HeapCellValue> {
|
||||||
while let Some(h) = self.stack.pop() {
|
while let Some(h) = self.stack.pop() {
|
||||||
@@ -271,13 +277,14 @@ pub(crate) fn stackful_preorder_iter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct PostOrderIterator<Iter: Iterator<Item = HeapCellValue>> {
|
pub(crate) struct PostOrderIterator<Iter: FocusedHeapIter> {
|
||||||
|
focus: usize,
|
||||||
base_iter: Iter,
|
base_iter: Iter,
|
||||||
base_iter_valid: bool,
|
base_iter_valid: bool,
|
||||||
parent_stack: Vec<(usize, HeapCellValue)>, // number of children, parent node.
|
parent_stack: Vec<(usize, HeapCellValue, usize)>, // number of children, parent node, focus.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Iter: Iterator<Item = HeapCellValue>> Deref for PostOrderIterator<Iter> {
|
impl<Iter: FocusedHeapIter> Deref for PostOrderIterator<Iter> {
|
||||||
type Target = Iter;
|
type Target = Iter;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -285,9 +292,10 @@ impl<Iter: Iterator<Item = HeapCellValue>> Deref for PostOrderIterator<Iter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Iter: Iterator<Item = HeapCellValue>> PostOrderIterator<Iter> {
|
impl<Iter: FocusedHeapIter> PostOrderIterator<Iter> {
|
||||||
pub(crate) fn new(base_iter: Iter) -> Self {
|
pub(crate) fn new(base_iter: Iter) -> Self {
|
||||||
PostOrderIterator {
|
PostOrderIterator {
|
||||||
|
focus: 0,
|
||||||
base_iter,
|
base_iter,
|
||||||
base_iter_valid: true,
|
base_iter_valid: true,
|
||||||
parent_stack: vec![],
|
parent_stack: vec![],
|
||||||
@@ -295,32 +303,36 @@ impl<Iter: Iterator<Item = HeapCellValue>> PostOrderIterator<Iter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Iter: Iterator<Item = HeapCellValue>> Iterator for PostOrderIterator<Iter> {
|
impl<Iter: FocusedHeapIter> Iterator for PostOrderIterator<Iter> {
|
||||||
type Item = HeapCellValue;
|
type Item = HeapCellValue;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
if let Some((child_count, node)) = self.parent_stack.pop() {
|
if let Some((child_count, node, focus)) = self.parent_stack.pop() {
|
||||||
if child_count == 0 {
|
if child_count == 0 {
|
||||||
|
self.focus = focus;
|
||||||
return Some(node);
|
return Some(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.parent_stack.push((child_count - 1, node));
|
self.parent_stack.push((child_count - 1, node, focus));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.base_iter_valid {
|
if self.base_iter_valid {
|
||||||
if let Some(item) = self.base_iter.next() {
|
if let Some(item) = self.base_iter.next() {
|
||||||
|
let focus = self.base_iter.focus();
|
||||||
|
|
||||||
read_heap_cell!(item,
|
read_heap_cell!(item,
|
||||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||||
self.parent_stack.push((arity, item));
|
self.parent_stack.push((arity, item, focus));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Lis) => {
|
(HeapCellValueTag::Lis) => {
|
||||||
self.parent_stack.push((2, item));
|
self.parent_stack.push((2, item, focus));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
|
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
|
||||||
self.parent_stack.push((1, item));
|
self.parent_stack.push((1, item, focus));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
self.focus = focus;
|
||||||
return Some(item);
|
return Some(item);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -338,12 +350,19 @@ impl<Iter: Iterator<Item = HeapCellValue>> Iterator for PostOrderIterator<Iter>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Iter: FocusedHeapIter> FocusedHeapIter for PostOrderIterator<Iter> {
|
||||||
|
#[inline]
|
||||||
|
fn focus(&self) -> usize {
|
||||||
|
self.focus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) type LeftistPostOrderHeapIter<'a> = PostOrderIterator<StackfulPreOrderHeapIter<'a>>;
|
pub(crate) type LeftistPostOrderHeapIter<'a> = PostOrderIterator<StackfulPreOrderHeapIter<'a>>;
|
||||||
|
|
||||||
impl<'a> LeftistPostOrderHeapIter<'a> {
|
impl<'a> LeftistPostOrderHeapIter<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pop_stack(&mut self) {
|
pub fn pop_stack(&mut self) {
|
||||||
if let Some((child_count, _)) = self.parent_stack.last() {
|
if let Some((child_count, ..)) = self.parent_stack.last() {
|
||||||
for _ in 0 .. *child_count {
|
for _ in 0 .. *child_count {
|
||||||
self.base_iter.pop_stack();
|
self.base_iter.pop_stack();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::instructions::*;
|
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::parser::rug::{Integer, Rational};
|
use crate::parser::rug::{Integer, Rational};
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -377,9 +376,9 @@ impl HCValueOutputter for PrinterOutputter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
|
fn is_numbered_var(name: Atom, arity: usize) -> bool {
|
||||||
arity == 1 && ct.name() == atom!("$VAR")
|
arity == 1 && name == atom!("$VAR")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -469,7 +468,6 @@ pub fn fmt_float(mut fl: f64) -> String {
|
|||||||
pub struct HCPrinter<'a, Outputter> {
|
pub struct HCPrinter<'a, Outputter> {
|
||||||
outputter: Outputter,
|
outputter: Outputter,
|
||||||
iter: StackfulPreOrderHeapIter<'a>,
|
iter: StackfulPreOrderHeapIter<'a>,
|
||||||
arena: &'a mut Arena,
|
|
||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
state_stack: Vec<TokenOrRedirect>,
|
state_stack: Vec<TokenOrRedirect>,
|
||||||
toplevel_spec: Option<DirectedOp>,
|
toplevel_spec: Option<DirectedOp>,
|
||||||
@@ -534,7 +532,6 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option<String>
|
|||||||
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
heap: &'a mut Heap,
|
heap: &'a mut Heap,
|
||||||
arena: &'a mut Arena,
|
|
||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
output: Outputter,
|
output: Outputter,
|
||||||
cell: HeapCellValue,
|
cell: HeapCellValue,
|
||||||
@@ -542,7 +539,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
HCPrinter {
|
HCPrinter {
|
||||||
outputter: output,
|
outputter: output,
|
||||||
iter: stackful_preorder_iter(heap, cell),
|
iter: stackful_preorder_iter(heap, cell),
|
||||||
arena,
|
|
||||||
op_dir,
|
op_dir,
|
||||||
state_stack: vec![],
|
state_stack: vec![],
|
||||||
toplevel_spec: None,
|
toplevel_spec: None,
|
||||||
@@ -563,9 +559,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
requires_space(tail, atom)
|
requires_space(tail, atom)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_op(&mut self, mut max_depth: usize, ct: ClauseType, spec: OpDesc) {
|
fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc) {
|
||||||
let name = ct.name();
|
|
||||||
|
|
||||||
if is_postfix!(spec.get_spec()) {
|
if is_postfix!(spec.get_spec()) {
|
||||||
if self.check_max_depth(&mut max_depth) {
|
if self.check_max_depth(&mut max_depth) {
|
||||||
self.iter.pop_stack();
|
self.iter.pop_stack();
|
||||||
@@ -652,15 +646,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.iter.pop_stack();
|
self.iter.pop_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if arity > 0 {
|
||||||
self.state_stack.push(TokenOrRedirect::Close);
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
self.state_stack.push(TokenOrRedirect::Open);
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
}
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(name));
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if arity > 0 {
|
||||||
self.state_stack.push(TokenOrRedirect::Close);
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
|
|
||||||
for _ in 0..arity {
|
for _ in 0..arity {
|
||||||
@@ -671,6 +668,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.state_stack.pop();
|
self.state_stack.pop();
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Open);
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
}
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(name));
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -763,21 +762,21 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove ClauseType here?
|
||||||
fn format_clause(
|
fn format_clause(
|
||||||
&mut self,
|
&mut self,
|
||||||
max_depth: usize,
|
max_depth: usize,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
ct: ClauseType,
|
name: Atom,
|
||||||
op_desc: Option<OpDesc>,
|
op_desc: Option<OpDesc>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if self.numbervars && is_numbered_var(&ct, arity) {
|
if self.numbervars && is_numbered_var(name, arity) {
|
||||||
if self.format_numbered_vars() {
|
if self.format_numbered_vars() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dot_atom = atom!(".");
|
let dot_atom = atom!(".");
|
||||||
let name = ct.name();
|
|
||||||
|
|
||||||
if let Some(spec) = op_desc {
|
if let Some(spec) = op_desc {
|
||||||
if dot_atom == name && is_infix!(spec.get_spec()) {
|
if dot_atom == name && is_infix!(spec.get_spec()) {
|
||||||
@@ -788,7 +787,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.ignore_ops && spec.get_prec() > 0 {
|
if !self.ignore_ops && spec.get_prec() > 0 {
|
||||||
self.enqueue_op(max_depth, ct, spec);
|
self.enqueue_op(max_depth, name, spec);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -858,7 +857,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
var_opt => {
|
var_opt => {
|
||||||
if is_cyclic && addr.is_compound() {
|
if is_cyclic && addr.is_compound(self.iter.heap) {
|
||||||
// self-referential variables are marked "cyclic".
|
// self-referential variables are marked "cyclic".
|
||||||
match var_opt {
|
match var_opt {
|
||||||
Some(var) => {
|
Some(var) => {
|
||||||
@@ -1333,9 +1332,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.state_stack.push(TokenOrRedirect::Close);
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ct = ClauseType::from(name, arity);
|
if self.format_clause(max_depth, arity, name, Some(op_desc)) && add_brackets {
|
||||||
|
|
||||||
if self.format_clause(max_depth, arity, ct, Some(op_desc)) && add_brackets {
|
|
||||||
self.state_stack.push(TokenOrRedirect::Open);
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
|
||||||
if let Some(ref op) = &op {
|
if let Some(ref op) = &op {
|
||||||
@@ -1349,10 +1346,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn print_tcp_listener(&mut self, tcp_listener: &TcpListener, max_depth: usize) {
|
fn print_tcp_listener(&mut self, tcp_listener: &TcpListener, max_depth: usize) {
|
||||||
let (ip, port) = if let Some(addr) = tcp_listener.local_addr().ok() {
|
let (ip, port) = if let Some(addr) = tcp_listener.local_addr().ok() {
|
||||||
(
|
(addr.ip(), addr.port())
|
||||||
addr.ip(),
|
|
||||||
Number::arena_from(addr.port() as usize, self.arena),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let disconnected_atom = atom!("$disconnected_tcp_listener");
|
let disconnected_atom = atom!("$disconnected_tcp_listener");
|
||||||
self.state_stack
|
self.state_stack
|
||||||
@@ -1371,7 +1365,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::NumberFocus(
|
self.state_stack.push(TokenOrRedirect::NumberFocus(
|
||||||
max_depth,
|
max_depth,
|
||||||
NumberFocus::Unfocused(port),
|
NumberFocus::Unfocused(Number::Fixnum(Fixnum::build_with(port as i64))),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
self.state_stack.push(TokenOrRedirect::Comma);
|
self.state_stack.push(TokenOrRedirect::Comma);
|
||||||
@@ -1439,8 +1433,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
push_space_if_amb!(self, name.as_str(), {
|
push_space_if_amb!(self, name.as_str(), {
|
||||||
let ct = ClauseType::from(name, arity);
|
self.format_clause(max_depth, arity, name, None);
|
||||||
self.format_clause(max_depth, arity, ct, None);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if fetch_op_spec(name, arity, self.op_dir).is_some() {
|
} else if fetch_op_spec(name, arity, self.op_dir).is_some() {
|
||||||
@@ -1485,8 +1478,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
push_space_if_amb!(self, name.as_str(), {
|
push_space_if_amb!(self, name.as_str(), {
|
||||||
let ct = ClauseType::from(name, arity);
|
self.format_clause(max_depth, arity, name, None);
|
||||||
self.format_clause(max_depth, arity, ct, None);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1536,6 +1528,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
(ArenaHeaderTag::Dropped, _value) => {
|
(ArenaHeaderTag::Dropped, _value) => {
|
||||||
append_str!(self, "'$dropped_value'");
|
append_str!(self, "'$dropped_value'");
|
||||||
}
|
}
|
||||||
|
(ArenaHeaderTag::IndexPtr, _index_ptr) => {
|
||||||
|
append_str!(self, "'$index_ptr'");
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -1631,7 +1626,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0)
|
heap_loc_as_cell!(0)
|
||||||
@@ -1659,7 +1653,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0)
|
heap_loc_as_cell!(0)
|
||||||
@@ -1682,7 +1675,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0)
|
heap_loc_as_cell!(0)
|
||||||
@@ -1694,7 +1686,6 @@ mod tests {
|
|||||||
|
|
||||||
let mut printer = HCPrinter::new(
|
let mut printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0)
|
heap_loc_as_cell!(0)
|
||||||
@@ -1726,7 +1717,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1744,7 +1734,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1760,7 +1749,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let mut printer = HCPrinter::new(
|
let mut printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0)
|
heap_loc_as_cell!(0)
|
||||||
@@ -1791,7 +1779,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let mut printer = HCPrinter::new(
|
let mut printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0)
|
heap_loc_as_cell!(0)
|
||||||
@@ -1813,7 +1800,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
pstr_loc_as_cell!(0)
|
pstr_loc_as_cell!(0)
|
||||||
@@ -1840,7 +1826,6 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.arena,
|
|
||||||
&wam.op_dir,
|
&wam.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::machine_indices::*;
|
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
@@ -16,7 +15,7 @@ pub(crate) enum TermRef<'a> {
|
|||||||
AnonVar(Level),
|
AnonVar(Level),
|
||||||
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||||
Literal(Level, &'a Cell<RegType>, &'a Literal),
|
Literal(Level, &'a Cell<RegType>, &'a Literal),
|
||||||
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Term>),
|
Clause(Level, &'a Cell<RegType>, Atom, &'a Vec<Term>),
|
||||||
PartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
|
PartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
|
||||||
CompleteString(Level, &'a Cell<RegType>, Atom),
|
CompleteString(Level, &'a Cell<RegType>, Atom),
|
||||||
Var(Level, &'a Cell<VarReg>, Rc<String>),
|
Var(Level, &'a Cell<VarReg>, Rc<String>),
|
||||||
@@ -40,7 +39,7 @@ impl<'a> TermRef<'a> {
|
|||||||
pub(crate) enum TermIterState<'a> {
|
pub(crate) enum TermIterState<'a> {
|
||||||
AnonVar(Level),
|
AnonVar(Level),
|
||||||
Literal(Level, &'a Cell<RegType>, &'a Literal),
|
Literal(Level, &'a Cell<RegType>, &'a Literal),
|
||||||
Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Term>),
|
Clause(Level, usize, &'a Cell<RegType>, Atom, &'a Vec<Term>),
|
||||||
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||||
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||||
InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
|
InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
|
||||||
@@ -54,8 +53,7 @@ impl<'a> TermIterState<'a> {
|
|||||||
match term {
|
match term {
|
||||||
Term::AnonVar => TermIterState::AnonVar(lvl),
|
Term::AnonVar => TermIterState::AnonVar(lvl),
|
||||||
Term::Clause(cell, name, subterms) => {
|
Term::Clause(cell, name, subterms) => {
|
||||||
let ct = ClauseType::Named(subterms.len(), *name, CodeIndex::default());
|
TermIterState::Clause(lvl, 0, cell, *name, subterms)
|
||||||
TermIterState::Clause(lvl, 0, cell, ct, subterms)
|
|
||||||
}
|
}
|
||||||
Term::Cons(cell, head, tail) => {
|
Term::Cons(cell, head, tail) => {
|
||||||
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
|
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
|
||||||
@@ -105,7 +103,7 @@ impl<'a> QueryIterator<'a> {
|
|||||||
Level::Root,
|
Level::Root,
|
||||||
0,
|
0,
|
||||||
r,
|
r,
|
||||||
ClauseType::from(*name, terms.len()),
|
*name,
|
||||||
terms,
|
terms,
|
||||||
),
|
),
|
||||||
Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, var.clone()),
|
Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, var.clone()),
|
||||||
@@ -118,14 +116,14 @@ impl<'a> QueryIterator<'a> {
|
|||||||
|
|
||||||
fn new(term: &'a QueryTerm) -> Self {
|
fn new(term: &'a QueryTerm) -> Self {
|
||||||
match term {
|
match term {
|
||||||
&QueryTerm::Clause(ref cell, ClauseType::CallN(arity), ref terms, _) => {
|
&QueryTerm::Clause(ref cell, ClauseType::CallN(_), ref terms, _) => {
|
||||||
let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN(arity), terms);
|
let state = TermIterState::Clause(Level::Root, 1, cell, atom!("$call"), terms);
|
||||||
QueryIterator {
|
QueryIterator {
|
||||||
state_stack: vec![state],
|
state_stack: vec![state],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
|
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
|
||||||
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
|
let state = TermIterState::Clause(Level::Root, 0, cell, ct.name(), terms);
|
||||||
QueryIterator {
|
QueryIterator {
|
||||||
state_stack: vec![state],
|
state_stack: vec![state],
|
||||||
}
|
}
|
||||||
@@ -167,28 +165,25 @@ impl<'a> Iterator for QueryIterator<'a> {
|
|||||||
TermIterState::AnonVar(lvl) => {
|
TermIterState::AnonVar(lvl) => {
|
||||||
return Some(TermRef::AnonVar(lvl));
|
return Some(TermRef::AnonVar(lvl));
|
||||||
}
|
}
|
||||||
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
|
TermIterState::Clause(lvl, child_num, cell, name, child_terms) => {
|
||||||
if child_num == child_terms.len() {
|
if child_num == child_terms.len() {
|
||||||
match ct {
|
match name {
|
||||||
ClauseType::CallN(_) => {
|
atom!("$call") if lvl == Level::Root => {
|
||||||
self.push_subterm(Level::Shallow, &child_terms[0]);
|
self.push_subterm(Level::Shallow, &child_terms[0]);
|
||||||
}
|
}
|
||||||
ClauseType::Named(..) => {
|
_ => {
|
||||||
return match lvl {
|
return match lvl {
|
||||||
Level::Root => None,
|
Level::Root => None,
|
||||||
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)),
|
lvl => Some(TermRef::Clause(lvl, cell, name, child_terms)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
self.state_stack.push(TermIterState::Clause(
|
self.state_stack.push(TermIterState::Clause(
|
||||||
lvl,
|
lvl,
|
||||||
child_num + 1,
|
child_num + 1,
|
||||||
cell,
|
cell,
|
||||||
ct,
|
name,
|
||||||
child_terms,
|
child_terms,
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -257,8 +252,7 @@ impl<'a> FactIterator<'a> {
|
|||||||
vec![TermIterState::AnonVar(Level::Root)]
|
vec![TermIterState::AnonVar(Level::Root)]
|
||||||
}
|
}
|
||||||
Term::Clause(cell, name, terms) => {
|
Term::Clause(cell, name, terms) => {
|
||||||
let ct = ClauseType::from(*name, terms.len());
|
vec![TermIterState::Clause(Level::Root, 0, cell, *name, terms)]
|
||||||
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
|
|
||||||
}
|
}
|
||||||
Term::Cons(cell, head, tail) => vec![TermIterState::InitialCons(
|
Term::Cons(cell, head, tail) => vec![TermIterState::InitialCons(
|
||||||
Level::Root,
|
Level::Root,
|
||||||
@@ -305,14 +299,14 @@ impl<'a> Iterator for FactIterator<'a> {
|
|||||||
TermIterState::AnonVar(lvl) => {
|
TermIterState::AnonVar(lvl) => {
|
||||||
return Some(TermRef::AnonVar(lvl));
|
return Some(TermRef::AnonVar(lvl));
|
||||||
}
|
}
|
||||||
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
|
TermIterState::Clause(lvl, _, cell, name, child_terms) => {
|
||||||
for child_term in child_terms {
|
for child_term in child_terms {
|
||||||
self.push_subterm(lvl.child_level(), child_term);
|
self.push_subterm(lvl.child_level(), child_term);
|
||||||
}
|
}
|
||||||
|
|
||||||
match lvl {
|
match lvl {
|
||||||
Level::Root if !self.iterable_root => continue,
|
Level::Root if !self.iterable_root => continue,
|
||||||
_ => return Some(TermRef::Clause(lvl, cell, ct, child_terms)),
|
_ => return Some(TermRef::Clause(lvl, cell, name, child_terms)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
:- module(builtins, [(=)/2, (\=)/2, (\+)/1, !/0, (',')/2, (->)/2,
|
:- module(builtins, [(=)/2, (\=)/2, (\+)/1, !/0, (',')/2, (->)/2,
|
||||||
(;)/2, (=..)/2, (:)/2, (:)/3, (:)/4, (:)/5,
|
(;)/2, (=..)/2, /* (:)/2, (:)/3, (:)/4, (:)/5,
|
||||||
(:)/6, (:)/7, (:)/8, (:)/9, (:)/10, (:)/11,
|
(:)/6, (:)/7, (:)/8, (:)/9, (:)/10, (:)/11,
|
||||||
(:)/12, abolish/1, asserta/1, assertz/1,
|
(:)/12, */ abolish/1, asserta/1, assertz/1,
|
||||||
at_end_of_stream/0, at_end_of_stream/1,
|
at_end_of_stream/0, at_end_of_stream/1,
|
||||||
atom_chars/2, atom_codes/2, atom_concat/3,
|
atom_chars/2, atom_codes/2, atom_concat/3,
|
||||||
atom_length/2, bagof/3, call/1, call/2, call/3,
|
atom_length/2, bagof/3, call/1, call/2, call/3,
|
||||||
@@ -41,82 +41,87 @@ false :- '$fail'.
|
|||||||
% Once Scryer is bootstrapped, each is replaced with a version that
|
% Once Scryer is bootstrapped, each is replaced with a version that
|
||||||
% uses expand_goal to pass the expanded goal along to '$call'.
|
% uses expand_goal to pass the expanded goal along to '$call'.
|
||||||
|
|
||||||
call(G) :- '$call'(G).
|
call(_).
|
||||||
|
|
||||||
call(G, A) :- '$call'(G, A).
|
call(_, _).
|
||||||
|
|
||||||
call(G, A, B) :- '$call'(G, A, B).
|
call(_, _, _).
|
||||||
|
|
||||||
call(G, A, B, C) :- '$call'(G, A, B, C).
|
call(_, _, _, _).
|
||||||
|
|
||||||
call(G, A, B, C, D) :- '$call'(G, A, B, C, D).
|
call(_, _, _, _, _).
|
||||||
|
|
||||||
call(G, A, B, C, D, E) :- '$call'(G, A, B, C, D, E).
|
call(_, _, _, _, _, _).
|
||||||
|
|
||||||
call(G, A, B, C, D, E, F) :- '$call'(G, A, B, C, D, E, F).
|
call(_, _, _, _, _, _, _).
|
||||||
|
|
||||||
call(G, A, B, C, D, E, F, G) :- '$call'(G, A, B, C, D, E, F, G).
|
call(_, _, _, _, _, _, _, _).
|
||||||
|
|
||||||
call(G, A, B, C, D, E, F, G, H) :- '$call'(G, A, B, C, D, E, F, G, H).
|
call(_, _, _, _, _, _, _, _, _).
|
||||||
|
|
||||||
% dynamic module resolution.
|
% dynamic module resolution.
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
Module : Predicate :-
|
Module : Predicate :-
|
||||||
( atom(Module) -> '$module_call'(Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1) :-
|
:(Module, Predicate, A1) :-
|
||||||
( atom(Module) ->
|
( atom(Module) -> '$module_call'(Module, Predicate, A1)
|
||||||
'$module_call'(A1, Module, Predicate)
|
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2) :-
|
:(Module, Predicate, A1, A2) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3) :-
|
:(Module, Predicate, A1, A2, A3) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4) :-
|
:(Module, Predicate, A1, A2, A3, A4) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, Module, Predicate)
|
( atom(Module) -> '$module_call'(A4, Module, Predicate, A1, A2, A3)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4, A5) :-
|
:(Module, Predicate, A1, A2, A3, A4, A5) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3, A4, A5)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4, A5, A6) :-
|
:(Module, Predicate, A1, A2, A3, A4, A5, A6) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3, A4, A5, A6)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7) :-
|
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3, A4, A5, A6, A7)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8) :-
|
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, A8, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9) :-
|
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, A8, A9, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) :-
|
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) :-
|
||||||
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Module, Predicate)
|
( atom(Module) -> '$module_call'(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)
|
||||||
; throw(error(type_error(atom, Module), (:)/2))
|
; throw(error(type_error(atom, Module), (:)/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
:- meta_predicate catch(0, ?, 0).
|
||||||
|
|
||||||
% flags.
|
% flags.
|
||||||
|
|
||||||
current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 1023.
|
current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 1023.
|
||||||
@@ -185,7 +190,7 @@ fail :- '$fail'.
|
|||||||
|
|
||||||
:- meta_predicate \+(0).
|
:- meta_predicate \+(0).
|
||||||
|
|
||||||
\+ G :- '$call'(G), !, false.
|
\+ G :- call(G), !, false.
|
||||||
\+ _.
|
\+ _.
|
||||||
|
|
||||||
|
|
||||||
@@ -195,7 +200,7 @@ _ \= _.
|
|||||||
|
|
||||||
:- meta_predicate once(0).
|
:- meta_predicate once(0).
|
||||||
|
|
||||||
once(G) :- '$call'(G), !.
|
once(G) :- call(G), !.
|
||||||
|
|
||||||
|
|
||||||
repeat.
|
repeat.
|
||||||
@@ -216,17 +221,17 @@ G1 -> G2 :- control_entry_point((G1 -> G2)).
|
|||||||
|
|
||||||
staggered_if_then(G1, G2) :-
|
staggered_if_then(G1, G2) :-
|
||||||
'$get_staggered_cp'(B),
|
'$get_staggered_cp'(B),
|
||||||
'$call'(G1),
|
call(G1),
|
||||||
'$set_cp'(B),
|
'$set_cp'(B),
|
||||||
'$call'(G2).
|
call(G2).
|
||||||
|
|
||||||
G1 ; G2 :- control_entry_point((G1 ; G2)).
|
G1 ; G2 :- control_entry_point((G1 ; G2)).
|
||||||
|
|
||||||
|
|
||||||
:- non_counted_backtracking staggered_sc/2.
|
:- non_counted_backtracking staggered_sc/2.
|
||||||
|
|
||||||
staggered_sc(G, _) :- '$call'(G).
|
staggered_sc(G, _) :- call(G).
|
||||||
staggered_sc(_, G) :- '$call'(G).
|
staggered_sc(_, G) :- call(G).
|
||||||
|
|
||||||
|
|
||||||
!.
|
!.
|
||||||
@@ -257,7 +262,7 @@ control_entry_point_(G) :-
|
|||||||
:- non_counted_backtracking cont_list_to_goal/2.
|
:- non_counted_backtracking cont_list_to_goal/2.
|
||||||
|
|
||||||
cont_list_goal([Cont], Cont) :- !.
|
cont_list_goal([Cont], Cont) :- !.
|
||||||
cont_list_goal(Conts, builtins:dispatch_call_list(Conts)).
|
cont_list_goal(Conts, '$call'(builtins:dispatch_call_list(Conts))).
|
||||||
|
|
||||||
|
|
||||||
:- non_counted_backtracking module_qualified_cut/1.
|
:- non_counted_backtracking module_qualified_cut/1.
|
||||||
@@ -289,7 +294,7 @@ dispatch_prep(Gs, B, [Cont|Conts]) :-
|
|||||||
dispatch_prep(G2, B, IConts1),
|
dispatch_prep(G2, B, IConts1),
|
||||||
cont_list_goal(IConts0, Cont0),
|
cont_list_goal(IConts0, Cont0),
|
||||||
cont_list_goal(IConts1, Cont1),
|
cont_list_goal(IConts1, Cont1),
|
||||||
Cont = builtins:staggered_sc(Cont0, Cont1),
|
Cont = '$call'(builtins:staggered_sc(Cont0, Cont1)),
|
||||||
Conts = []
|
Conts = []
|
||||||
; functor(Gs, ->, 2) ->
|
; functor(Gs, ->, 2) ->
|
||||||
arg(1, Gs, G1),
|
arg(1, Gs, G1),
|
||||||
@@ -298,10 +303,10 @@ dispatch_prep(Gs, B, [Cont|Conts]) :-
|
|||||||
dispatch_prep(G2, B, IConts2),
|
dispatch_prep(G2, B, IConts2),
|
||||||
cont_list_goal(IConts1, Cont1),
|
cont_list_goal(IConts1, Cont1),
|
||||||
cont_list_goal(IConts2, Cont2),
|
cont_list_goal(IConts2, Cont2),
|
||||||
Cont = builtins:staggered_if_then(Cont1, Cont2),
|
Cont = '$call'(builtins:staggered_if_then(Cont1, Cont2)),
|
||||||
Conts = []
|
Conts = []
|
||||||
; ( Gs == ! ; module_qualified_cut(Gs) ) ->
|
; ( Gs == ! ; module_qualified_cut(Gs) ) ->
|
||||||
Cont = builtins:set_cp(B),
|
Cont = '$call'(builtins:set_cp(B)),
|
||||||
Conts = []
|
Conts = []
|
||||||
; Cont = Gs,
|
; Cont = Gs,
|
||||||
Conts = []
|
Conts = []
|
||||||
@@ -318,56 +323,56 @@ dispatch_prep(Gs, B, [Cont|Conts]) :-
|
|||||||
dispatch_call_list([]).
|
dispatch_call_list([]).
|
||||||
dispatch_call_list([G1,G2,G3,G4,G5,G6,G7,G8|Gs]) :-
|
dispatch_call_list([G1,G2,G3,G4,G5,G6,G7,G8|Gs]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)),
|
'$call_with_inference_counting'(call(G2)),
|
||||||
'$call_with_inference_counting'('$call'(G3)),
|
'$call_with_inference_counting'(call(G3)),
|
||||||
'$call_with_inference_counting'('$call'(G4)),
|
'$call_with_inference_counting'(call(G4)),
|
||||||
'$call_with_inference_counting'('$call'(G5)),
|
'$call_with_inference_counting'(call(G5)),
|
||||||
'$call_with_inference_counting'('$call'(G6)),
|
'$call_with_inference_counting'(call(G6)),
|
||||||
'$call_with_inference_counting'('$call'(G7)),
|
'$call_with_inference_counting'(call(G7)),
|
||||||
'$call_with_inference_counting'('$call'(G8)),
|
'$call_with_inference_counting'(call(G8)),
|
||||||
dispatch_call_list(Gs).
|
dispatch_call_list(Gs).
|
||||||
dispatch_call_list([G1,G2,G3,G4,G5,G6,G7]) :-
|
dispatch_call_list([G1,G2,G3,G4,G5,G6,G7]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)),
|
'$call_with_inference_counting'(call(G2)),
|
||||||
'$call_with_inference_counting'('$call'(G3)),
|
'$call_with_inference_counting'(call(G3)),
|
||||||
'$call_with_inference_counting'('$call'(G4)),
|
'$call_with_inference_counting'(call(G4)),
|
||||||
'$call_with_inference_counting'('$call'(G5)),
|
'$call_with_inference_counting'(call(G5)),
|
||||||
'$call_with_inference_counting'('$call'(G6)),
|
'$call_with_inference_counting'(call(G6)),
|
||||||
'$call_with_inference_counting'('$call'(G7)).
|
'$call_with_inference_counting'(call(G7)).
|
||||||
dispatch_call_list([G1,G2,G3,G4,G5,G6]) :-
|
dispatch_call_list([G1,G2,G3,G4,G5,G6]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)),
|
'$call_with_inference_counting'(call(G2)),
|
||||||
'$call_with_inference_counting'('$call'(G3)),
|
'$call_with_inference_counting'(call(G3)),
|
||||||
'$call_with_inference_counting'('$call'(G4)),
|
'$call_with_inference_counting'(call(G4)),
|
||||||
'$call_with_inference_counting'('$call'(G5)),
|
'$call_with_inference_counting'(call(G5)),
|
||||||
'$call_with_inference_counting'('$call'(G6)).
|
'$call_with_inference_counting'(call(G6)).
|
||||||
dispatch_call_list([G1,G2,G3,G4,G5]) :-
|
dispatch_call_list([G1,G2,G3,G4,G5]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)),
|
'$call_with_inference_counting'(call(G2)),
|
||||||
'$call_with_inference_counting'('$call'(G3)),
|
'$call_with_inference_counting'(call(G3)),
|
||||||
'$call_with_inference_counting'('$call'(G4)),
|
'$call_with_inference_counting'(call(G4)),
|
||||||
'$call_with_inference_counting'('$call'(G5)).
|
'$call_with_inference_counting'(call(G5)).
|
||||||
dispatch_call_list([G1,G2,G3,G4]) :-
|
dispatch_call_list([G1,G2,G3,G4]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)),
|
'$call_with_inference_counting'(call(G2)),
|
||||||
'$call_with_inference_counting'('$call'(G3)),
|
'$call_with_inference_counting'(call(G3)),
|
||||||
'$call_with_inference_counting'('$call'(G4)).
|
'$call_with_inference_counting'(call(G4)).
|
||||||
dispatch_call_list([G1,G2,G3]) :-
|
dispatch_call_list([G1,G2,G3]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)),
|
'$call_with_inference_counting'(call(G2)),
|
||||||
'$call_with_inference_counting'('$call'(G3)).
|
'$call_with_inference_counting'(call(G3)).
|
||||||
dispatch_call_list([G1,G2]) :-
|
dispatch_call_list([G1,G2]) :-
|
||||||
!,
|
!,
|
||||||
'$call_with_inference_counting'('$call'(G1)),
|
'$call_with_inference_counting'(call(G1)),
|
||||||
'$call_with_inference_counting'('$call'(G2)).
|
'$call_with_inference_counting'(call(G2)).
|
||||||
dispatch_call_list([G1]) :-
|
dispatch_call_list([G1]) :-
|
||||||
'$call_with_inference_counting'('$call'(G1)).
|
'$call_with_inference_counting'(call(G1)).
|
||||||
|
|
||||||
|
|
||||||
% univ.
|
% univ.
|
||||||
@@ -444,7 +449,7 @@ get_args([Arg|Args], Func, I0, N) :-
|
|||||||
get_args(Args, Func, I1, N).
|
get_args(Args, Func, I1, N).
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate parse_options_list(?, 0, ?, ?, ?).
|
:- meta_predicate parse_options_list(?, 2, ?, ?, ?).
|
||||||
|
|
||||||
parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
|
parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
|
||||||
'$skip_max_list'(_, _, Options, Tail),
|
'$skip_max_list'(_, _, Options, Tail),
|
||||||
@@ -455,7 +460,10 @@ parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
|
|||||||
; Tail \== [] ->
|
; Tail \== [] ->
|
||||||
throw(error(type_error(list, Options), Stub)) % 8.11.5.3e)
|
throw(error(type_error(list, Options), Stub)) % 8.11.5.3e)
|
||||||
),
|
),
|
||||||
( lists:maplist(nonvar, Options),
|
( lists:maplist('$call'(nonvar), Options), % need '$call' because
|
||||||
|
% maplist isn't
|
||||||
|
% declared as a
|
||||||
|
% meta-predicate yet
|
||||||
catch(lists:maplist(Selector, Options, OptionPairs0),
|
catch(lists:maplist(Selector, Options, OptionPairs0),
|
||||||
error(E, _),
|
error(E, _),
|
||||||
builtins:throw(error(E, Stub))) ->
|
builtins:throw(error(E, Stub))) ->
|
||||||
@@ -619,8 +627,6 @@ term_variables(Term, Vars) :-
|
|||||||
|
|
||||||
% exceptions.
|
% exceptions.
|
||||||
|
|
||||||
:- meta_predicate catch(0, ?, 0).
|
|
||||||
|
|
||||||
:- non_counted_backtracking catch/3.
|
:- non_counted_backtracking catch/3.
|
||||||
|
|
||||||
catch(G,C,R) :-
|
catch(G,C,R) :-
|
||||||
@@ -633,7 +639,7 @@ catch(G,C,R) :-
|
|||||||
|
|
||||||
catch(G,C,R,Bb) :-
|
catch(G,C,R,Bb) :-
|
||||||
'$install_new_block'(NBb),
|
'$install_new_block'(NBb),
|
||||||
'$call_with_inference_counting'('$call'(G)),
|
'$call_with_inference_counting'(call(G)),
|
||||||
end_block(Bb, NBb).
|
end_block(Bb, NBb).
|
||||||
catch(G,C,R,Bb) :-
|
catch(G,C,R,Bb) :-
|
||||||
'$reset_block'(Bb),
|
'$reset_block'(Bb),
|
||||||
@@ -655,7 +661,7 @@ end_block(Bb, NBb) :-
|
|||||||
handle_ball(C, C, R) :-
|
handle_ball(C, C, R) :-
|
||||||
!,
|
!,
|
||||||
'$erase_ball',
|
'$erase_ball',
|
||||||
'$call'(R).
|
call(R).
|
||||||
handle_ball(_, _, _) :-
|
handle_ball(_, _, _) :-
|
||||||
'$unwind_stack'.
|
'$unwind_stack'.
|
||||||
|
|
||||||
@@ -671,7 +677,7 @@ throw(Ball) :-
|
|||||||
:- non_counted_backtracking '$iterate_find_all'/4.
|
:- non_counted_backtracking '$iterate_find_all'/4.
|
||||||
|
|
||||||
'$iterate_find_all'(Template, Goal, _, LhOffset) :-
|
'$iterate_find_all'(Template, Goal, _, LhOffset) :-
|
||||||
'$call_with_inference_counting'('$call'(Goal)),
|
'$call_with_inference_counting'(call(Goal)),
|
||||||
'$copy_to_lh'(LhOffset, Template),
|
'$copy_to_lh'(LhOffset, Template),
|
||||||
'$fail'.
|
'$fail'.
|
||||||
'$iterate_find_all'(_, _, Solutions, LhOffset) :-
|
'$iterate_find_all'(_, _, Solutions, LhOffset) :-
|
||||||
@@ -697,7 +703,7 @@ findall(Template, Goal, Solutions) :-
|
|||||||
:- non_counted_backtracking '$iterate_find_all_diff'/5.
|
:- non_counted_backtracking '$iterate_find_all_diff'/5.
|
||||||
|
|
||||||
'$iterate_find_all_diff'(Template, Goal, _, _, LhOffset) :-
|
'$iterate_find_all_diff'(Template, Goal, _, _, LhOffset) :-
|
||||||
'$call_with_inference_counting'('$call'(Goal)),
|
'$call_with_inference_counting'(call(Goal)),
|
||||||
'$copy_to_lh'(LhOffset, Template),
|
'$copy_to_lh'(LhOffset, Template),
|
||||||
'$fail'.
|
'$fail'.
|
||||||
'$iterate_find_all_diff'(_, _, Solutions0, Solutions1, LhOffset) :-
|
'$iterate_find_all_diff'(_, _, Solutions0, Solutions1, LhOffset) :-
|
||||||
@@ -897,33 +903,7 @@ module_asserta_clause(Head, Body, Module) :-
|
|||||||
; throw(error(type_error(callable, Head), asserta/1))
|
; throw(error(type_error(callable, Head), asserta/1))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
:- meta_predicate asserta(:).
|
||||||
asserta_clause(Head, Body) :-
|
|
||||||
( var(Head) ->
|
|
||||||
throw(error(instantiation_error, asserta/1))
|
|
||||||
; callable(Head), functor(Head, Name, Arity) ->
|
|
||||||
( Name == (:),
|
|
||||||
Arity =:= 2 ->
|
|
||||||
arg(1, Head, Module),
|
|
||||||
arg(2, Head, HeadAndBody),
|
|
||||||
( HeadAndBody = (F :- Body1) ->
|
|
||||||
true
|
|
||||||
; F = HeadAndBody,
|
|
||||||
Body1 = true
|
|
||||||
),
|
|
||||||
module_asserta_clause(F, Body1, Module)
|
|
||||||
; '$head_is_dynamic'(user, Head) ->
|
|
||||||
call_asserta(Head, Body, Name, Arity, user)
|
|
||||||
; '$no_such_predicate'(user, Head) ->
|
|
||||||
call_asserta(Head, Body, Name, Arity, user)
|
|
||||||
; throw(error(permission_error(modify, static_procedure, Name/Arity),
|
|
||||||
asserta/1))
|
|
||||||
)
|
|
||||||
; throw(error(type_error(callable, Head), asserta/1))
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate asserta(0).
|
|
||||||
|
|
||||||
asserta(Clause0) :-
|
asserta(Clause0) :-
|
||||||
loader:strip_module(Clause0, Module, Clause),
|
loader:strip_module(Clause0, Module, Clause),
|
||||||
@@ -959,33 +939,7 @@ call_assertz(Head, Body, Name, Arity, Module) :-
|
|||||||
functor(_, Name, Arity),
|
functor(_, Name, Arity),
|
||||||
'$assertz'(Head, Body, Name, Arity, Module).
|
'$assertz'(Head, Body, Name, Arity, Module).
|
||||||
|
|
||||||
|
:- meta_predicate assertz(:).
|
||||||
assertz_clause(Head, Body) :-
|
|
||||||
( var(Head) ->
|
|
||||||
throw(error(instantiation_error, assertz/1))
|
|
||||||
; callable(Head), functor(Head, Name, Arity) ->
|
|
||||||
( Name == (:),
|
|
||||||
Arity =:= 2 ->
|
|
||||||
arg(1, Head, Module),
|
|
||||||
arg(2, Head, HeadAndBody),
|
|
||||||
( HeadAndBody = (F :- Body1) ->
|
|
||||||
true
|
|
||||||
; F = HeadAndBody,
|
|
||||||
Body1 = true
|
|
||||||
),
|
|
||||||
module_assertz_clause(F, Body1, Module)
|
|
||||||
; '$head_is_dynamic'(user, Head) ->
|
|
||||||
call_assertz(Head, Body, Name, Arity, user)
|
|
||||||
; '$no_such_predicate'(user, Head) ->
|
|
||||||
call_assertz(Head, Body, Name, Arity, user)
|
|
||||||
; throw(error(permission_error(modify, static_procedure, Name/Arity),
|
|
||||||
assertz/1))
|
|
||||||
)
|
|
||||||
; throw(error(type_error(callable, Head), assertz/1))
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate assertz(0).
|
|
||||||
|
|
||||||
assertz(Clause0) :-
|
assertz(Clause0) :-
|
||||||
loader:strip_module(Clause0, Module, Clause),
|
loader:strip_module(Clause0, Module, Clause),
|
||||||
@@ -1086,7 +1040,7 @@ retract_clause(Head, Body) :-
|
|||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate retract(0).
|
:- meta_predicate retract(:).
|
||||||
|
|
||||||
retract(Clause0) :-
|
retract(Clause0) :-
|
||||||
loader:strip_module(Clause0, Module, Clause),
|
loader:strip_module(Clause0, Module, Clause),
|
||||||
@@ -1102,7 +1056,7 @@ retract(Clause0) :-
|
|||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate retractall(0).
|
:- meta_predicate retractall(:).
|
||||||
|
|
||||||
retractall(Head) :-
|
retractall(Head) :-
|
||||||
retract_clause(Head, _),
|
retract_clause(Head, _),
|
||||||
@@ -1139,7 +1093,7 @@ module_abolish(Pred, Module) :-
|
|||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate abolish(0).
|
:- meta_predicate abolish(:).
|
||||||
|
|
||||||
abolish(Pred) :-
|
abolish(Pred) :-
|
||||||
( var(Pred) ->
|
( var(Pred) ->
|
||||||
|
|||||||
@@ -1122,6 +1122,8 @@ indomain(1).
|
|||||||
% CountAnd = 1.
|
% CountAnd = 1.
|
||||||
% ==
|
% ==
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sat_count(Sat0, N) :-
|
sat_count(Sat0, N) :-
|
||||||
catch((parse_sat(Sat0, Sat),
|
catch((parse_sat(Sat0, Sat),
|
||||||
sat_bdd(Sat, BDD),
|
sat_bdd(Sat, BDD),
|
||||||
|
|||||||
@@ -7611,7 +7611,7 @@ verify_attributes(Var, Other, Gs) :-
|
|||||||
),
|
),
|
||||||
domain_contains(Dom, Other),
|
domain_contains(Dom, Other),
|
||||||
phrase(trigger_props(Ps), [Q], [_]),
|
phrase(trigger_props(Ps), [Q], [_]),
|
||||||
Gs = [phrase(do_queue, [Q], _)]
|
Gs = [phrase(clpz:do_queue, [Q], _)]
|
||||||
; ( get_atts(Other, clpz(clpz_attr(_,_,_,OD,OPs,_))) ->
|
; ( get_atts(Other, clpz(clpz_attr(_,_,_,OD,OPs,_))) ->
|
||||||
domains_intersection(OD, Dom, Dom1),
|
domains_intersection(OD, Dom, Dom1),
|
||||||
append_propagators(Ps, OPs, Ps1),
|
append_propagators(Ps, OPs, Ps1),
|
||||||
@@ -7619,7 +7619,7 @@ verify_attributes(Var, Other, Gs) :-
|
|||||||
variables_same_queue([Var,Other]),
|
variables_same_queue([Var,Other]),
|
||||||
phrase((fd_put(Other,Dom1,Ps1),
|
phrase((fd_put(Other,Dom1,Ps1),
|
||||||
trigger_props(Ps1)), [Q0], _),
|
trigger_props(Ps1)), [Q0], _),
|
||||||
Gs = [phrase(do_queue, [Q0], _)]
|
Gs = [phrase(clpz:do_queue, [Q0], _)]
|
||||||
; put_atts(Other, clpz(CLPZ)),
|
; put_atts(Other, clpz(CLPZ)),
|
||||||
Gs = []
|
Gs = []
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ load_context(GRBody, Module, GRBody0) :-
|
|||||||
true
|
true
|
||||||
; prolog_load_context(module, Module) ->
|
; prolog_load_context(module, Module) ->
|
||||||
true
|
true
|
||||||
; true
|
; Module = user
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ phrase(GRBody, S0, S) :-
|
|||||||
( var(GRBody0) ->
|
( var(GRBody0) ->
|
||||||
instantiation_error(phrase/3)
|
instantiation_error(phrase/3)
|
||||||
; dcg_body(GRBody0, S0, S, GRBody1, Module) ->
|
; dcg_body(GRBody0, S0, S, GRBody1, Module) ->
|
||||||
call(GRBody1)
|
call(Module:GRBody1)
|
||||||
; type_error(callable, GRBody0, phrase/3)
|
; type_error(callable, GRBody0, phrase/3)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
type_error/3
|
type_error/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
|
:- meta_predicate check_(1, ?, ?).
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
must_be(Type, Term)
|
must_be(Type, Term)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(dcgs)).
|
:- use_module(library(dcgs)).
|
||||||
|
|
||||||
:- meta_predicate freeze(?, 0).
|
:- meta_predicate freeze(?, :).
|
||||||
|
|
||||||
:- attribute frozen/1.
|
:- attribute frozen/1.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
%% for builtins that are not part of the ISO standard.
|
|
||||||
%% must be loaded at the REPL with
|
|
||||||
|
|
||||||
%% ?- use_module(library(iso_ext)).
|
|
||||||
|
|
||||||
:- module(iso_ext, [bb_b_put/2,
|
:- module(iso_ext, [bb_b_put/2,
|
||||||
bb_get/2,
|
bb_get/2,
|
||||||
bb_put/2,
|
bb_put/2,
|
||||||
@@ -14,7 +9,6 @@
|
|||||||
partial_string_tail/2,
|
partial_string_tail/2,
|
||||||
setup_call_cleanup/3,
|
setup_call_cleanup/3,
|
||||||
call_nth/2,
|
call_nth/2,
|
||||||
% variant/2,
|
|
||||||
copy_term_nat/2]).
|
copy_term_nat/2]).
|
||||||
|
|
||||||
:- use_module(library(error), [can_be/2,
|
:- use_module(library(error), [can_be/2,
|
||||||
@@ -64,7 +58,7 @@ call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
|
|||||||
|
|
||||||
setup_call_cleanup(S, G, C) :-
|
setup_call_cleanup(S, G, C) :-
|
||||||
'$get_b_value'(B),
|
'$get_b_value'(B),
|
||||||
'$call_with_inference_counting'('$call'(S)),
|
'$call_with_inference_counting'(call(S)),
|
||||||
'$set_cp_by_default'(B),
|
'$set_cp_by_default'(B),
|
||||||
'$get_current_block'(Bb),
|
'$get_current_block'(Bb),
|
||||||
( C = _:CC,
|
( C = _:CC,
|
||||||
@@ -80,7 +74,7 @@ setup_call_cleanup(S, G, C) :-
|
|||||||
scc_helper(C, G, Bb) :-
|
scc_helper(C, G, Bb) :-
|
||||||
'$get_cp'(Cp),
|
'$get_cp'(Cp),
|
||||||
'$install_scc_cleaner'(C, NBb),
|
'$install_scc_cleaner'(C, NBb),
|
||||||
'$call_with_inference_counting'('$call'(G)),
|
'$call_with_inference_counting'(call(G)),
|
||||||
( '$check_cp'(Cp) ->
|
( '$check_cp'(Cp) ->
|
||||||
'$reset_block'(Bb),
|
'$reset_block'(Bb),
|
||||||
run_cleaners_without_handling(Cp)
|
run_cleaners_without_handling(Cp)
|
||||||
@@ -115,7 +109,7 @@ run_cleaners_with_handling :-
|
|||||||
run_cleaners_without_handling(Cp) :-
|
run_cleaners_without_handling(Cp) :-
|
||||||
'$get_scc_cleaner'(C),
|
'$get_scc_cleaner'(C),
|
||||||
'$get_level'(B),
|
'$get_level'(B),
|
||||||
'$call'(C),
|
call(C),
|
||||||
'$set_cp_by_default'(B),
|
'$set_cp_by_default'(B),
|
||||||
run_cleaners_without_handling(Cp).
|
run_cleaners_without_handling(Cp).
|
||||||
run_cleaners_without_handling(Cp) :-
|
run_cleaners_without_handling(Cp) :-
|
||||||
@@ -170,7 +164,7 @@ install_inference_counter(B, L, Count0) :-
|
|||||||
call_with_inference_limit(G, L, R, Bb, B) :-
|
call_with_inference_limit(G, L, R, Bb, B) :-
|
||||||
'$install_new_block'(NBb),
|
'$install_new_block'(NBb),
|
||||||
'$install_inference_counter'(B, L, Count0),
|
'$install_inference_counter'(B, L, Count0),
|
||||||
'$call_with_inference_counting'('$call'(G)),
|
'$call_with_inference_counting'(call(G)),
|
||||||
'$inference_level'(R, B),
|
'$inference_level'(R, B),
|
||||||
'$remove_inference_counter'(B, Count1),
|
'$remove_inference_counter'(B, Count1),
|
||||||
is(Diff, L - (Count1 - Count0)),
|
is(Diff, L - (Count1 - Count0)),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
map_list_to_pairs/3]).
|
map_list_to_pairs/3]).
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate map_list_to_pairs(0, ?, ?).
|
:- meta_predicate map_list_to_pairs(2, ?, ?).
|
||||||
|
|
||||||
pairs_keys_values([], [], []).
|
pairs_keys_values([], [], []).
|
||||||
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
|
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
|
||||||
|
|||||||
@@ -30,13 +30,10 @@ non(false, true).
|
|||||||
|
|
||||||
:- meta_predicate(tfilter(2, ?, ?)).
|
:- meta_predicate(tfilter(2, ?, ?)).
|
||||||
|
|
||||||
tfilter(C_2, Es, Fs) :-
|
tfilter(_, [], []).
|
||||||
i_tfilter(Es, C_2, Fs).
|
tfilter(C_2, [E|Es], Fs0) :-
|
||||||
|
|
||||||
i_tfilter([], _, []).
|
|
||||||
i_tfilter([E|Es], C_2, Fs0) :-
|
|
||||||
if_(call(C_2, E), Fs0 = [E|Fs], Fs0 = Fs),
|
if_(call(C_2, E), Fs0 = [E|Fs], Fs0 = Fs),
|
||||||
i_tfilter(Es, C_2, Fs).
|
tfilter(C_2, Es, Fs).
|
||||||
|
|
||||||
:- meta_predicate(tpartition(2, ?, ?, ?)).
|
:- meta_predicate(tpartition(2, ?, ?, ?)).
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ table_and_status_for_variant(V,T,S) :-
|
|||||||
tbd_table_status(T,S).
|
tbd_table_status(T,S).
|
||||||
|
|
||||||
|
|
||||||
:- meta_predicate start_tabling(?, 0).
|
:- meta_predicate start_tabling(?, :).
|
||||||
|
|
||||||
start_tabling(Wrapper,Worker) :-
|
start_tabling(Wrapper,Worker) :-
|
||||||
put_new_trie_table_link,
|
put_new_trie_table_link,
|
||||||
|
|||||||
1618
src/loader.pl
1618
src/loader.pl
File diff suppressed because it is too large
Load Diff
@@ -390,7 +390,6 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
|
|||||||
pub(crate) fn pow(n1: Number, n2: Number, culprit: Atom) -> Result<Number, MachineStubGen> {
|
pub(crate) fn pow(n1: Number, n2: Number, culprit: Atom) -> Result<Number, MachineStubGen> {
|
||||||
if n2.is_negative() && n1.is_zero() {
|
if n2.is_negative() && n1.is_zero() {
|
||||||
let stub_gen = move || functor_stub(culprit, 2);
|
let stub_gen = move || functor_stub(culprit, 2);
|
||||||
|
|
||||||
return Err(undefined_eval_error(stub_gen));
|
return Err(undefined_eval_error(stub_gen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1183,7 +1182,7 @@ impl MachineState {
|
|||||||
|
|
||||||
let result = arena_alloc!(
|
let result = arena_alloc!(
|
||||||
drop_iter_on_err!(self, iter, rdiv(r1, r2)),
|
drop_iter_on_err!(self, iter, rdiv(r1, r2)),
|
||||||
self.arena
|
&mut self.arena
|
||||||
);
|
);
|
||||||
|
|
||||||
self.interms.push(Number::Rational(result));
|
self.interms.push(Number::Rational(result));
|
||||||
|
|||||||
@@ -28,11 +28,13 @@ call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
|
|||||||
sort(Modules0, Modules),
|
sort(Modules0, Modules),
|
||||||
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
|
|
||||||
|
error_handler(M, evaluation_error((M:verify_attributes)/3), []).
|
||||||
|
% error_handler(_, existence_error(procedure, verify_attributes/3), []).
|
||||||
|
|
||||||
verify_attrs([Module|Modules], Var, Value, [Module-Goals|ListOfGoalLists]) :-
|
verify_attrs([Module|Modules], Var, Value, [Module-Goals|ListOfGoalLists]) :-
|
||||||
catch(Module:verify_attributes(Var, Value, Goals),
|
catch(Module:verify_attributes(Var, Value, Goals),
|
||||||
error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
|
error(E, verify_attributes/3),
|
||||||
Goals = []),
|
error_handler(Module, E, Goals)),
|
||||||
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
verify_attrs([], _, _, []).
|
verify_attrs([], _, _, []).
|
||||||
|
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ fn merge_indexed_subsequences(
|
|||||||
|
|
||||||
*o = 0;
|
*o = 0;
|
||||||
|
|
||||||
return Some(IndexPtr::Index(outer_threaded_choice_instr_loc + 1));
|
return Some(IndexPtr::index(outer_threaded_choice_instr_loc + 1));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
@@ -785,7 +785,7 @@ fn remove_non_leading_clause(
|
|||||||
|
|
||||||
*o = 0;
|
*o = 0;
|
||||||
|
|
||||||
Some(IndexPtr::Index(preceding_choice_instr_loc + 1))
|
Some(IndexPtr::index(preceding_choice_instr_loc + 1))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@@ -820,7 +820,7 @@ fn finalize_retract(
|
|||||||
retraction_info,
|
retraction_info,
|
||||||
&compilation_target,
|
&compilation_target,
|
||||||
key,
|
key,
|
||||||
&code_index,
|
code_index,
|
||||||
index_ptr,
|
index_ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -849,9 +849,9 @@ fn remove_leading_unindexed_clause(
|
|||||||
retraction_info,
|
retraction_info,
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(IndexPtr::Index(index_ptr))
|
Some(IndexPtr::index(index_ptr))
|
||||||
} else {
|
} else {
|
||||||
Some(IndexPtr::DynamicUndefined)
|
Some(IndexPtr::dynamic_undefined())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1131,9 +1131,9 @@ fn prepend_compiled_clause(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if skeleton.core.is_dynamic {
|
if skeleton.core.is_dynamic {
|
||||||
IndexPtr::DynamicIndex(clause_loc)
|
IndexPtr::dynamic_index(clause_loc)
|
||||||
} else {
|
} else {
|
||||||
IndexPtr::Index(clause_loc)
|
IndexPtr::index(clause_loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1268,9 +1268,9 @@ fn append_compiled_clause(
|
|||||||
|
|
||||||
code_ptr_opt.map(|p| {
|
code_ptr_opt.map(|p| {
|
||||||
if skeleton.core.is_dynamic {
|
if skeleton.core.is_dynamic {
|
||||||
IndexPtr::DynamicIndex(p)
|
IndexPtr::dynamic_index(p)
|
||||||
} else {
|
} else {
|
||||||
IndexPtr::Index(p)
|
IndexPtr::index(p)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1306,8 +1306,8 @@ fn print_overwrite_warning(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match code_ptr {
|
match code_ptr.tag() {
|
||||||
IndexPtr::DynamicUndefined | IndexPtr::Undefined => return,
|
IndexPtrTag::DynamicUndefined | IndexPtrTag::Undefined => return,
|
||||||
_ if is_dynamic => return,
|
_ if is_dynamic => return,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -1471,16 +1471,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let index_ptr = if settings.is_dynamic() {
|
let index_ptr = if settings.is_dynamic() {
|
||||||
IndexPtr::DynamicIndex(code_ptr)
|
IndexPtr::dynamic_index(code_ptr)
|
||||||
} else {
|
} else {
|
||||||
IndexPtr::Index(code_ptr)
|
IndexPtr::index(code_ptr)
|
||||||
};
|
};
|
||||||
|
|
||||||
set_code_index(
|
set_code_index(
|
||||||
&mut self.payload.retraction_info,
|
&mut self.payload.retraction_info,
|
||||||
&predicates.compilation_target,
|
&predicates.compilation_target,
|
||||||
key,
|
key,
|
||||||
&code_index,
|
code_index,
|
||||||
index_ptr,
|
index_ptr,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1704,7 +1704,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
&mut self.payload.retraction_info,
|
&mut self.payload.retraction_info,
|
||||||
&compilation_target,
|
&compilation_target,
|
||||||
key,
|
key,
|
||||||
&code_index,
|
code_index,
|
||||||
new_code_ptr,
|
new_code_ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1745,7 +1745,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
&mut self.payload.retraction_info,
|
&mut self.payload.retraction_info,
|
||||||
&compilation_target,
|
&compilation_target,
|
||||||
key,
|
key,
|
||||||
&code_index,
|
code_index,
|
||||||
new_code_ptr,
|
new_code_ptr,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1870,7 +1870,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
skeleton.clauses[target_pos].clause_start;
|
skeleton.clauses[target_pos].clause_start;
|
||||||
|
|
||||||
let index_ptr_opt = if target_pos == 0 {
|
let index_ptr_opt = if target_pos == 0 {
|
||||||
Some(IndexPtr::Index(clause_loc))
|
Some(IndexPtr::index(clause_loc))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -2384,13 +2384,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
match self.wam_prelude.indices.modules.get_mut(&filename) {
|
match self.wam_prelude.indices.modules.get_mut(&filename) {
|
||||||
Some(ref mut module) => {
|
Some(ref mut module) => {
|
||||||
let index_ptr = code_index.get();
|
let index_ptr = code_index.get();
|
||||||
let code_index = module.code_dir.entry(key).or_insert(code_index);
|
let code_index = module.code_dir.entry(key)
|
||||||
|
.or_insert(code_index)
|
||||||
|
.clone();
|
||||||
|
|
||||||
set_code_index(
|
set_code_index(
|
||||||
&mut self.payload.retraction_info,
|
&mut self.payload.retraction_info,
|
||||||
&CompilationTarget::Module(filename),
|
&CompilationTarget::Module(filename),
|
||||||
key,
|
key,
|
||||||
&code_index,
|
code_index,
|
||||||
index_ptr,
|
index_ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2418,3 +2420,54 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// standalone functions for compiling auxiliary goals used by expand_goal.
|
||||||
|
impl Machine {
|
||||||
|
pub(crate) fn get_or_insert_qualified_code_index(
|
||||||
|
&mut self,
|
||||||
|
module_name: HeapCellValue,
|
||||||
|
key: PredicateKey,
|
||||||
|
) -> CodeIndex {
|
||||||
|
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> = Loader::new(
|
||||||
|
self,
|
||||||
|
LiveTermStream::new(ListingSource::User),
|
||||||
|
);
|
||||||
|
|
||||||
|
let module_name = if module_name.get_tag() == HeapCellValueTag::Atom {
|
||||||
|
cell_as_atom!(module_name)
|
||||||
|
} else {
|
||||||
|
atom!("user")
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.get_or_insert_qualified_code_index(module_name, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn compile_standalone_clause(
|
||||||
|
&mut self,
|
||||||
|
term_loc: RegType,
|
||||||
|
vars: &[Term],
|
||||||
|
) -> Result<(), SessionError> {
|
||||||
|
let mut compile = || {
|
||||||
|
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> = Loader::new(
|
||||||
|
self,
|
||||||
|
LiveTermStream::new(ListingSource::User),
|
||||||
|
);
|
||||||
|
|
||||||
|
let term = loader.read_term_from_heap(term_loc)?;
|
||||||
|
let clause = build_rule_body(vars, term);
|
||||||
|
|
||||||
|
let settings = CodeGenSettings {
|
||||||
|
global_clock_tick: None,
|
||||||
|
is_extensible: false,
|
||||||
|
non_counted_bt: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.compile_standalone_clause(clause, settings)
|
||||||
|
};
|
||||||
|
|
||||||
|
let StandaloneCompileResult { clause_code, .. } = compile()?;
|
||||||
|
self.code.extend(clause_code.into_iter());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
|
use crate::machine::get_structure_index;
|
||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
@@ -248,6 +249,14 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
let hcv = self.target[addr + 1 + i];
|
let hcv = self.target[addr + 1 + i];
|
||||||
self.target.push(hcv);
|
self.target.push(hcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let index_cell = self.target[addr + 1 + arity];
|
||||||
|
|
||||||
|
if get_structure_index(index_cell).is_some() {
|
||||||
|
// copy the index pointer trailing this
|
||||||
|
// inlined or expanded goal.
|
||||||
|
self.target.push(index_cell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str, h) => {
|
(HeapCellValueTag::Str, h) => {
|
||||||
*self.value_at_scan() = str_loc_as_cell!(h);
|
*self.value_at_scan() = str_loc_as_cell!(h);
|
||||||
|
|||||||
@@ -57,18 +57,28 @@ impl MachineState {
|
|||||||
let a2 = self.registers[2];
|
let a2 = self.registers[2];
|
||||||
let a3 = self.registers[3];
|
let a3 = self.registers[3];
|
||||||
|
|
||||||
|
let check_atom = |machine_st: &mut MachineState, name: Atom, arity: usize| -> Result<(), MachineStub> {
|
||||||
|
match name {
|
||||||
|
atom!(">") | atom!("<") | atom!("=") if arity == 0 => {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let err = machine_st.domain_error(DomainErrorType::Order, a1);
|
||||||
|
Err(machine_st.error_form(err, stub_gen()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
read_heap_cell!(a1,
|
read_heap_cell!(a1,
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
|
check_atom(self, name, arity)?;
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
match name {
|
check_atom(self, name, arity)?;
|
||||||
atom!(">") | atom!("<") | atom!("=") => {
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let err = self.domain_error(DomainErrorType::Order, a1);
|
|
||||||
return Err(self.error_form(err, stub_gen()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
|
||||||
}
|
}
|
||||||
@@ -360,8 +370,9 @@ impl Machine {
|
|||||||
debug_assert!(arity == 0);
|
debug_assert!(arity == 0);
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str) => {
|
(HeapCellValueTag::Str, st) => {
|
||||||
s
|
let arity = cell_as_atom_cell!(self.machine_st.heap[st]).get_arity();
|
||||||
|
if arity == 0 { c } else { s }
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Cons, ptr) => {
|
(HeapCellValueTag::Cons, ptr) => {
|
||||||
match ptr.get_tag() {
|
match ptr.get_tag() {
|
||||||
@@ -421,6 +432,9 @@ impl Machine {
|
|||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
Literal::Atom(atom)
|
Literal::Atom(atom)
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
Literal::Atom(cell_as_atom_cell!(self.machine_st.heap[s]).get_name())
|
||||||
|
}
|
||||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||||
match_untyped_arena_ptr!(cons_ptr,
|
match_untyped_arena_ptr!(cons_ptr,
|
||||||
(ArenaHeaderTag::Rational, r) => {
|
(ArenaHeaderTag::Rational, r) => {
|
||||||
@@ -597,6 +611,7 @@ impl Machine {
|
|||||||
&mut self.machine_st,
|
&mut self.machine_st,
|
||||||
try_numeric_result!(sub(n1, n2, &mut self.machine_st.arena), stub_gen)
|
try_numeric_result!(sub(n1, n2, &mut self.machine_st.arena), stub_gen)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
&Instruction::Mul(ref a1, ref a2, t) => {
|
&Instruction::Mul(ref a1, ref a2, t) => {
|
||||||
@@ -675,7 +690,7 @@ impl Machine {
|
|||||||
|
|
||||||
self.machine_st.interms[t - 1] = Number::Rational(arena_alloc!(
|
self.machine_st.interms[t - 1] = Number::Rational(arena_alloc!(
|
||||||
try_or_throw_gen!(&mut self.machine_st, rdiv(r1, r2)),
|
try_or_throw_gen!(&mut self.machine_st, rdiv(r1, r2)),
|
||||||
self.machine_st.arena
|
&mut self.machine_st.arena
|
||||||
));
|
));
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
@@ -688,6 +703,7 @@ impl Machine {
|
|||||||
&mut self.machine_st,
|
&mut self.machine_st,
|
||||||
int_floor_div(n1, n2, &mut self.machine_st.arena)
|
int_floor_div(n1, n2, &mut self.machine_st.arena)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
&Instruction::IDiv(ref a1, ref a2, t) => {
|
&Instruction::IDiv(ref a1, ref a2, t) => {
|
||||||
@@ -698,6 +714,7 @@ impl Machine {
|
|||||||
&mut self.machine_st,
|
&mut self.machine_st,
|
||||||
idiv(n1, n2, &mut self.machine_st.arena)
|
idiv(n1, n2, &mut self.machine_st.arena)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
&Instruction::Abs(ref a1, t) => {
|
&Instruction::Abs(ref a1, t) => {
|
||||||
@@ -1122,17 +1139,7 @@ impl Machine {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
&Instruction::NeckCut => {
|
&Instruction::NeckCut => {
|
||||||
let b = self.machine_st.b;
|
self.machine_st.neck_cut();
|
||||||
let b0 = self.machine_st.b0;
|
|
||||||
|
|
||||||
if b > b0 {
|
|
||||||
self.machine_st.b = b0;
|
|
||||||
|
|
||||||
if b > self.machine_st.e {
|
|
||||||
self.machine_st.stack.truncate(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
&Instruction::GetLevel(r) => {
|
&Instruction::GetLevel(r) => {
|
||||||
@@ -1298,7 +1305,6 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
&Instruction::DefaultCallRead(_) => {
|
&Instruction::DefaultCallRead(_) => {
|
||||||
try_or_throw!(self.machine_st, self.read());
|
try_or_throw!(self.machine_st, self.read());
|
||||||
|
|
||||||
step_or_fail!(self, self.machine_st.p += 1);
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
}
|
}
|
||||||
&Instruction::DefaultExecuteRead(_) => {
|
&Instruction::DefaultExecuteRead(_) => {
|
||||||
@@ -2354,6 +2360,16 @@ impl Machine {
|
|||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let arity = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
self.machine_st.p += 1;
|
||||||
|
} else {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char) => {
|
(HeapCellValueTag::Char) => {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
@@ -2373,6 +2389,16 @@ impl Machine {
|
|||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let arity = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
self.machine_st.p = self.machine_st.cp;
|
||||||
|
} else {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char) => {
|
(HeapCellValueTag::Char) => {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
@@ -2396,6 +2422,16 @@ impl Machine {
|
|||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let arity = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
self.machine_st.p += 1;
|
||||||
|
} else {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
@@ -2416,6 +2452,16 @@ impl Machine {
|
|||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let arity = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
self.machine_st.p = self.machine_st.cp;
|
||||||
|
} else {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
@@ -2425,10 +2471,21 @@ impl Machine {
|
|||||||
let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
|
let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
|
||||||
|
|
||||||
read_heap_cell!(d,
|
read_heap_cell!(d,
|
||||||
(HeapCellValueTag::Str | HeapCellValueTag::Lis |
|
(HeapCellValueTag::Lis |
|
||||||
HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
|
HeapCellValueTag::PStrLoc |
|
||||||
|
HeapCellValueTag::CStr) => {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let arity = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_arity();
|
||||||
|
|
||||||
|
if arity > 0 {
|
||||||
|
self.machine_st.p += 1;
|
||||||
|
} else {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||||
if arity > 0 {
|
if arity > 0 {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
@@ -2445,10 +2502,21 @@ impl Machine {
|
|||||||
let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
|
let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
|
||||||
|
|
||||||
read_heap_cell!(d,
|
read_heap_cell!(d,
|
||||||
(HeapCellValueTag::Str | HeapCellValueTag::Lis |
|
(HeapCellValueTag::Lis |
|
||||||
HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
|
HeapCellValueTag::PStrLoc |
|
||||||
|
HeapCellValueTag::CStr) => {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let arity = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_arity();
|
||||||
|
|
||||||
|
if arity > 0 {
|
||||||
|
self.machine_st.p = self.machine_st.cp;
|
||||||
|
} else {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||||
if arity > 0 {
|
if arity > 0 {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
@@ -3500,7 +3568,10 @@ impl Machine {
|
|||||||
self.dynamic_module_resolution(arity - 2)
|
self.dynamic_module_resolution(arity - 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
try_or_throw!(self.machine_st, self.call_clause(module_name, key));
|
try_or_throw!(
|
||||||
|
self.machine_st,
|
||||||
|
self.call_clause(module_name, key)
|
||||||
|
);
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -3512,7 +3583,10 @@ impl Machine {
|
|||||||
self.dynamic_module_resolution(arity - 2)
|
self.dynamic_module_resolution(arity - 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
try_or_throw!(self.machine_st, self.execute_clause(module_name, key));
|
try_or_throw!(
|
||||||
|
self.machine_st,
|
||||||
|
self.execute_clause(module_name, key)
|
||||||
|
);
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -4886,7 +4960,7 @@ impl Machine {
|
|||||||
&Instruction::ExecuteStripModule(_) => {
|
&Instruction::ExecuteStripModule(_) => {
|
||||||
let (module_loc, qualified_goal) = self.machine_st.strip_module(
|
let (module_loc, qualified_goal) = self.machine_st.strip_module(
|
||||||
self.machine_st.registers[1],
|
self.machine_st.registers[1],
|
||||||
self.machine_st.registers[2]
|
self.machine_st.registers[2],
|
||||||
);
|
);
|
||||||
|
|
||||||
let target_module_loc = self.machine_st.registers[2];
|
let target_module_loc = self.machine_st.registers[2];
|
||||||
@@ -4915,6 +4989,44 @@ impl Machine {
|
|||||||
try_or_throw!(self.machine_st, self.prepare_call_clause(arity));
|
try_or_throw!(self.machine_st, self.prepare_call_clause(arity));
|
||||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
}
|
}
|
||||||
|
&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(_) => {
|
||||||
|
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(_) => {
|
||||||
|
self.is_expanded_or_inlined();
|
||||||
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
|
}
|
||||||
|
&Instruction::ExecuteIsExpandedOrInlined(_) => {
|
||||||
|
self.is_expanded_or_inlined();
|
||||||
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
|
}
|
||||||
|
&Instruction::CallInlineCallN(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));
|
||||||
|
|
||||||
|
if self.machine_st.fail {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Instruction::ExecuteInlineCallN(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));
|
||||||
|
|
||||||
|
if self.machine_st.fail {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ use crate::atom_table::*;
|
|||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use crate::heap_iter::FocusedHeapIter;
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
pub(crate) trait UnmarkPolicy {
|
pub(crate) trait UnmarkPolicy {
|
||||||
@@ -69,6 +72,14 @@ pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> {
|
|||||||
_marker: PhantomData<UMP>,
|
_marker: PhantomData<UMP>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> {
|
||||||
|
#[inline]
|
||||||
|
fn focus(&self) -> usize {
|
||||||
|
self.current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, UMP: UnmarkPolicy> Drop for StacklessPreOrderHeapIter<'a, UMP> {
|
impl<'a, UMP: UnmarkPolicy> Drop for StacklessPreOrderHeapIter<'a, UMP> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.current == self.start {
|
if self.current == self.start {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
|
use crate::machine::machine_indices::*;
|
||||||
use crate::machine::partial_string::*;
|
use crate::machine::partial_string::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
@@ -17,6 +18,9 @@ impl From<Literal> for HeapCellValue {
|
|||||||
match literal {
|
match literal {
|
||||||
Literal::Atom(name) => atom_as_cell!(name),
|
Literal::Atom(name) => atom_as_cell!(name),
|
||||||
Literal::Char(c) => char_as_cell!(c),
|
Literal::Char(c) => char_as_cell!(c),
|
||||||
|
Literal::CodeIndex(ptr) => {
|
||||||
|
untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(ptr))
|
||||||
|
}
|
||||||
Literal::Fixnum(n) => fixnum_as_cell!(n),
|
Literal::Fixnum(n) => fixnum_as_cell!(n),
|
||||||
Literal::Integer(bigint_ptr) => {
|
Literal::Integer(bigint_ptr) => {
|
||||||
typed_arena_ptr_as_cell!(bigint_ptr)
|
typed_arena_ptr_as_cell!(bigint_ptr)
|
||||||
@@ -65,6 +69,9 @@ impl TryFrom<HeapCellValue> for Literal {
|
|||||||
(ArenaHeaderTag::Rational, n) => {
|
(ArenaHeaderTag::Rational, n) => {
|
||||||
Ok(Literal::Rational(n))
|
Ok(Literal::Rational(n))
|
||||||
}
|
}
|
||||||
|
(ArenaHeaderTag::IndexPtr, _ip) => {
|
||||||
|
Ok(Literal::CodeIndex(CodeIndex::from(cons_ptr)))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ pub(super) fn set_code_index(
|
|||||||
retraction_info: &mut RetractionInfo,
|
retraction_info: &mut RetractionInfo,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
code_index: &CodeIndex,
|
mut code_index: CodeIndex,
|
||||||
code_ptr: IndexPtr,
|
code_ptr: IndexPtr,
|
||||||
) {
|
) {
|
||||||
let record = match compilation_target {
|
let record = match compilation_target {
|
||||||
CompilationTarget::User => {
|
CompilationTarget::User => {
|
||||||
if IndexPtr::Undefined == code_index.get() {
|
if IndexPtrTag::Undefined == code_index.get().tag() {
|
||||||
code_index.set(code_ptr);
|
code_index.set(code_ptr);
|
||||||
RetractionRecord::AddedUserPredicate(key)
|
RetractionRecord::AddedUserPredicate(key)
|
||||||
} else {
|
} else {
|
||||||
@@ -35,7 +35,7 @@ pub(super) fn set_code_index(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CompilationTarget::Module(ref module_name) => {
|
CompilationTarget::Module(ref module_name) => {
|
||||||
if IndexPtr::Undefined == code_index.get() {
|
if IndexPtrTag::Undefined == code_index.get().tag() {
|
||||||
code_index.set(code_ptr);
|
code_index.set(code_ptr);
|
||||||
RetractionRecord::AddedModulePredicate(*module_name, key)
|
RetractionRecord::AddedModulePredicate(*module_name, key)
|
||||||
} else {
|
} else {
|
||||||
@@ -48,12 +48,10 @@ pub(super) fn set_code_index(
|
|||||||
retraction_info.push_record(record);
|
retraction_info.push_record(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_op_decl_as_module_export(
|
fn add_op_decl_as_module_export<'a, LS: LoadState<'a>>(
|
||||||
|
payload: &mut LS::LoaderFieldType,
|
||||||
module_op_dir: &mut OpDir,
|
module_op_dir: &mut OpDir,
|
||||||
compilation_target: &CompilationTarget,
|
|
||||||
retraction_info: &mut RetractionInfo,
|
|
||||||
wam_op_dir: &mut OpDir,
|
wam_op_dir: &mut OpDir,
|
||||||
module_op_exports: &mut ModuleOpExports,
|
|
||||||
op_decl: &OpDecl,
|
op_decl: &OpDecl,
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
@@ -65,20 +63,21 @@ fn add_op_decl_as_module_export(
|
|||||||
|
|
||||||
match op_decl.insert_into_op_dir(wam_op_dir) {
|
match op_decl.insert_into_op_dir(wam_op_dir) {
|
||||||
Some(op_desc) => {
|
Some(op_desc) => {
|
||||||
retraction_info.push_record(RetractionRecord::ReplacedUserOp(
|
payload.retraction_info.push_record(RetractionRecord::ReplacedUserOp(
|
||||||
*op_decl,
|
*op_decl,
|
||||||
op_desc,
|
op_desc,
|
||||||
));
|
));
|
||||||
|
|
||||||
module_op_exports.push((*op_decl, Some(op_desc)));
|
payload.module_op_exports.push((*op_decl, Some(op_desc)));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl));
|
payload.retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl));
|
||||||
module_op_exports.push((*op_decl, None));
|
payload.module_op_exports.push((*op_decl, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_op_decl(retraction_info, compilation_target, module_op_dir, op_decl);
|
let compilation_target = payload.compilation_target;
|
||||||
|
add_op_decl(&mut payload.retraction_info, &compilation_target, module_op_dir, op_decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_op_decl(
|
pub(super) fn add_op_decl(
|
||||||
@@ -117,8 +116,8 @@ pub(super) fn add_op_decl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn import_module_exports(
|
pub(super) fn import_module_exports<'a, LS: LoadState<'a>>(
|
||||||
retraction_info: &mut RetractionInfo,
|
payload: &mut LS::LoaderFieldType,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
imported_module: &Module,
|
imported_module: &Module,
|
||||||
code_dir: &mut CodeDir,
|
code_dir: &mut CodeDir,
|
||||||
@@ -135,16 +134,18 @@ pub(super) fn import_module_exports(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let arena = &mut LS::machine_st(payload).arena;
|
||||||
|
|
||||||
let target_code_index = code_dir
|
let target_code_index = code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::default(arena))
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
set_code_index(
|
set_code_index(
|
||||||
retraction_info,
|
&mut payload.retraction_info,
|
||||||
compilation_target,
|
compilation_target,
|
||||||
key,
|
key,
|
||||||
&target_code_index,
|
target_code_index,
|
||||||
src_code_index.get(),
|
src_code_index.get(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -155,7 +156,7 @@ pub(super) fn import_module_exports(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModuleExport::OpDecl(ref op_decl) => {
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
add_op_decl(retraction_info, compilation_target, op_dir, op_decl);
|
add_op_decl(&mut payload.retraction_info, compilation_target, op_dir, op_decl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,15 +164,14 @@ pub(super) fn import_module_exports(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_module_exports_into_module(
|
fn import_module_exports_into_module<'a, LS: LoadState<'a>>(
|
||||||
retraction_info: &mut RetractionInfo,
|
payload: &mut LS::LoaderFieldType,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
imported_module: &Module,
|
imported_module: &Module,
|
||||||
code_dir: &mut CodeDir,
|
code_dir: &mut CodeDir,
|
||||||
op_dir: &mut OpDir,
|
op_dir: &mut OpDir,
|
||||||
meta_predicates: &mut MetaPredicateDir,
|
meta_predicates: &mut MetaPredicateDir,
|
||||||
wam_op_dir: &mut OpDir,
|
wam_op_dir: &mut OpDir,
|
||||||
module_op_exports: &mut ModuleOpExports,
|
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
for export in imported_module.module_decl.exports.iter() {
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
match export {
|
match export {
|
||||||
@@ -183,16 +183,18 @@ fn import_module_exports_into_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let arena = &mut LS::machine_st(payload).arena;
|
||||||
|
|
||||||
let target_code_index = code_dir
|
let target_code_index = code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::default(arena))
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
set_code_index(
|
set_code_index(
|
||||||
retraction_info,
|
&mut payload.retraction_info,
|
||||||
compilation_target,
|
compilation_target,
|
||||||
key,
|
key,
|
||||||
&target_code_index,
|
target_code_index,
|
||||||
src_code_index.get(),
|
src_code_index.get(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -203,12 +205,10 @@ fn import_module_exports_into_module(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModuleExport::OpDecl(ref op_decl) => {
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
add_op_decl_as_module_export(
|
add_op_decl_as_module_export::<LS>(
|
||||||
|
payload,
|
||||||
op_dir,
|
op_dir,
|
||||||
compilation_target,
|
|
||||||
retraction_info,
|
|
||||||
wam_op_dir,
|
wam_op_dir,
|
||||||
module_op_exports,
|
|
||||||
op_decl,
|
op_decl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -218,14 +218,12 @@ fn import_module_exports_into_module(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_qualified_module_exports(
|
fn import_qualified_module_exports<'a, LS: LoadState<'a>>(
|
||||||
retraction_info: &mut RetractionInfo,
|
payload: &mut LS::LoaderFieldType,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
imported_module: &Module,
|
imported_module: &Module,
|
||||||
exports: &IndexSet<ModuleExport>,
|
exports: &IndexSet<ModuleExport>,
|
||||||
code_dir: &mut CodeDir,
|
wam_prelude: &mut MachinePreludeView,
|
||||||
op_dir: &mut OpDir,
|
|
||||||
meta_predicates: &mut MetaPredicateDir,
|
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
for export in imported_module.module_decl.exports.iter() {
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
if !exports.contains(export) {
|
if !exports.contains(export) {
|
||||||
@@ -237,20 +235,22 @@ fn import_qualified_module_exports(
|
|||||||
let key = (*name, *arity);
|
let key = (*name, *arity);
|
||||||
|
|
||||||
if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
|
if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
|
||||||
meta_predicates.insert(key.clone(), meta_specs.clone());
|
wam_prelude.indices.meta_predicates.insert(key.clone(), meta_specs.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
let target_code_index = code_dir
|
let arena = &mut LS::machine_st(payload).arena;
|
||||||
|
|
||||||
|
let target_code_index = wam_prelude.indices.code_dir
|
||||||
.entry(key.clone())
|
.entry(key.clone())
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena))
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
set_code_index(
|
set_code_index(
|
||||||
retraction_info,
|
&mut payload.retraction_info,
|
||||||
compilation_target,
|
compilation_target,
|
||||||
key,
|
key,
|
||||||
&target_code_index,
|
target_code_index,
|
||||||
src_code_index.get(),
|
src_code_index.get(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -261,7 +261,12 @@ fn import_qualified_module_exports(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModuleExport::OpDecl(ref op_decl) => {
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
add_op_decl(retraction_info, compilation_target, op_dir, op_decl);
|
add_op_decl(
|
||||||
|
&mut payload.retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
&mut wam_prelude.indices.op_dir,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,17 +274,17 @@ fn import_qualified_module_exports(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_qualified_module_exports_into_module(
|
fn import_qualified_module_exports_into_module<'a, LS: LoadState<'a>>(
|
||||||
retraction_info: &mut RetractionInfo,
|
payload: &mut LS::LoaderFieldType,
|
||||||
compilation_target: &CompilationTarget,
|
|
||||||
imported_module: &Module,
|
imported_module: &Module,
|
||||||
exports: &IndexSet<ModuleExport>,
|
exports: &IndexSet<ModuleExport>,
|
||||||
code_dir: &mut CodeDir,
|
code_dir: &mut CodeDir,
|
||||||
op_dir: &mut OpDir,
|
op_dir: &mut OpDir,
|
||||||
meta_predicates: &mut MetaPredicateDir,
|
meta_predicates: &mut MetaPredicateDir,
|
||||||
wam_op_dir: &mut OpDir,
|
wam_op_dir: &mut OpDir,
|
||||||
module_op_exports: &mut ModuleOpExports,
|
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
|
let payload_compilation_target = payload.compilation_target;
|
||||||
|
|
||||||
for export in imported_module.module_decl.exports.iter() {
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
if !exports.contains(export) {
|
if !exports.contains(export) {
|
||||||
continue;
|
continue;
|
||||||
@@ -294,16 +299,18 @@ fn import_qualified_module_exports_into_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let arena = &mut LS::machine_st(payload).arena;
|
||||||
|
|
||||||
let target_code_index = code_dir
|
let target_code_index = code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena))
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
set_code_index(
|
set_code_index(
|
||||||
retraction_info,
|
&mut payload.retraction_info,
|
||||||
compilation_target,
|
&payload_compilation_target,
|
||||||
key,
|
key,
|
||||||
&target_code_index,
|
target_code_index,
|
||||||
src_code_index.get(),
|
src_code_index.get(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -314,12 +321,10 @@ fn import_qualified_module_exports_into_module(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModuleExport::OpDecl(ref op_decl) => {
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
add_op_decl_as_module_export(
|
add_op_decl_as_module_export::<LS>(
|
||||||
|
payload,
|
||||||
op_dir,
|
op_dir,
|
||||||
compilation_target,
|
|
||||||
retraction_info,
|
|
||||||
wam_op_dir,
|
wam_op_dir,
|
||||||
module_op_exports,
|
|
||||||
op_decl,
|
op_decl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -464,7 +469,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (key, code_index) in &removed_module.code_dir {
|
for (key, code_index) in removed_module.code_dir.iter_mut() {
|
||||||
match removed_module
|
match removed_module
|
||||||
.local_extensible_predicates
|
.local_extensible_predicates
|
||||||
.get(&(CompilationTarget::User, *key))
|
.get(&(CompilationTarget::User, *key))
|
||||||
@@ -473,7 +478,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_index_ptr = code_index.replace(IndexPtr::Undefined);
|
let old_index_ptr = code_index.replace(IndexPtr::undefined());
|
||||||
|
|
||||||
self.payload.retraction_info
|
self.payload.retraction_info
|
||||||
.push_record(RetractionRecord::ReplacedModulePredicate(
|
.push_record(RetractionRecord::ReplacedModulePredicate(
|
||||||
@@ -512,11 +517,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
for export in removed_module.module_decl.exports.iter() {
|
for export in removed_module.module_decl.exports.iter() {
|
||||||
match export {
|
match export {
|
||||||
ModuleExport::PredicateKey(ref key) => {
|
ModuleExport::PredicateKey(ref key) => {
|
||||||
match (removed_module.code_dir.get(key), code_dir.get(key)) {
|
match (removed_module.code_dir.get(key), code_dir.get_mut(key)) {
|
||||||
(Some(module_code_index), Some(target_code_index))
|
(Some(module_code_index), Some(target_code_index))
|
||||||
if module_code_index.get() == target_code_index.get() =>
|
if module_code_index.get() == target_code_index.get() =>
|
||||||
{
|
{
|
||||||
let old_index_ptr = target_code_index.replace(IndexPtr::Undefined);
|
let old_index_ptr = target_code_index.replace(IndexPtr::undefined());
|
||||||
retraction_info.push_record(predicate_retractor(*key, old_index_ptr));
|
retraction_info.push_record(predicate_retractor(*key, old_index_ptr));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -584,7 +589,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
Some(ref mut module) => module
|
Some(ref mut module) => module
|
||||||
.code_dir
|
.code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::new(
|
||||||
|
IndexPtr::undefined(),
|
||||||
|
&mut LS::machine_st(&mut self.payload).arena,
|
||||||
|
))
|
||||||
.clone(),
|
.clone(),
|
||||||
None => {
|
None => {
|
||||||
self.add_dynamically_generated_module(module_name);
|
self.add_dynamically_generated_module(module_name);
|
||||||
@@ -593,7 +601,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
Some(ref mut module) => module
|
Some(ref mut module) => module
|
||||||
.code_dir
|
.code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::new(
|
||||||
|
IndexPtr::undefined(),
|
||||||
|
&mut LS::machine_st(&mut self.payload).arena,
|
||||||
|
))
|
||||||
.clone(),
|
.clone(),
|
||||||
None => {
|
None => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -608,13 +619,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
compilation_target: CompilationTarget,
|
compilation_target: CompilationTarget,
|
||||||
) -> CodeIndex {
|
) -> CodeIndex {
|
||||||
|
let arena = &mut LS::machine_st(&mut self.payload).arena;
|
||||||
|
|
||||||
match compilation_target {
|
match compilation_target {
|
||||||
CompilationTarget::User => self
|
CompilationTarget::User => self
|
||||||
.wam_prelude
|
.wam_prelude
|
||||||
.indices
|
.indices
|
||||||
.code_dir
|
.code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena))
|
||||||
.clone(),
|
.clone(),
|
||||||
CompilationTarget::Module(module_name) => {
|
CompilationTarget::Module(module_name) => {
|
||||||
self.get_or_insert_local_code_index(module_name, key)
|
self.get_or_insert_local_code_index(module_name, key)
|
||||||
@@ -627,13 +640,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
module_name: Atom,
|
module_name: Atom,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
) -> CodeIndex {
|
) -> CodeIndex {
|
||||||
|
let arena = &mut LS::machine_st(&mut self.payload).arena;
|
||||||
|
|
||||||
if module_name == atom!("user") {
|
if module_name == atom!("user") {
|
||||||
return self
|
return self
|
||||||
.wam_prelude
|
.wam_prelude
|
||||||
.indices
|
.indices
|
||||||
.code_dir
|
.code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena))
|
||||||
.clone();
|
.clone();
|
||||||
} else {
|
} else {
|
||||||
self.get_or_insert_local_code_index(module_name, key)
|
self.get_or_insert_local_code_index(module_name, key)
|
||||||
@@ -732,14 +747,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
CompilationTarget::Module(ref module_name) => {
|
CompilationTarget::Module(ref module_name) => {
|
||||||
match self.wam_prelude.indices.modules.get_mut(module_name) {
|
match self.wam_prelude.indices.modules.get_mut(module_name) {
|
||||||
Some(ref mut module) => {
|
Some(ref mut module) => {
|
||||||
let payload: &mut LoadStatePayload<_> = &mut self.payload;
|
add_op_decl_as_module_export::<LS>(
|
||||||
|
&mut self.payload,
|
||||||
add_op_decl_as_module_export(
|
|
||||||
&mut module.op_dir,
|
&mut module.op_dir,
|
||||||
&payload.compilation_target,
|
|
||||||
&mut payload.retraction_info,
|
|
||||||
&mut self.wam_prelude.indices.op_dir,
|
&mut self.wam_prelude.indices.op_dir,
|
||||||
&mut payload.module_op_exports,
|
|
||||||
op_decl,
|
op_decl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -752,7 +763,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_clause_type(&mut self, name: Atom, arity: usize) -> ClauseType {
|
pub(super) fn get_clause_type(&mut self, name: Atom, arity: usize) -> ClauseType {
|
||||||
match ClauseType::from(name, arity) {
|
let arena = &mut LS::machine_st(&mut self.payload).arena;
|
||||||
|
|
||||||
|
match ClauseType::from(name, arity, arena) {
|
||||||
ClauseType::Named(arity, name, _) => {
|
ClauseType::Named(arity, name, _) => {
|
||||||
let payload_compilation_target = self.payload.compilation_target;
|
let payload_compilation_target = self.payload.compilation_target;
|
||||||
|
|
||||||
@@ -773,7 +786,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
name: Atom,
|
name: Atom,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
) -> ClauseType {
|
) -> ClauseType {
|
||||||
match ClauseType::from(name, arity) {
|
let arena = &mut LS::machine_st(&mut self.payload).arena;
|
||||||
|
|
||||||
|
match ClauseType::from(name, arity, arena) {
|
||||||
ClauseType::Named(arity, name, _) => {
|
ClauseType::Named(arity, name, _) => {
|
||||||
let key = (name, arity);
|
let key = (name, arity);
|
||||||
let idx = self.get_or_insert_qualified_code_index(module_name, key);
|
let idx = self.get_or_insert_qualified_code_index(module_name, key);
|
||||||
@@ -784,6 +799,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn get_meta_specs(&self, name: Atom, arity: usize) -> Option<&Vec<MetaSpec>> {
|
||||||
|
self.wam_prelude
|
||||||
|
.indices
|
||||||
|
.get_meta_predicate_spec(
|
||||||
|
name,
|
||||||
|
arity,
|
||||||
|
&self.payload.compilation_target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn add_meta_predicate_record(
|
pub(super) fn add_meta_predicate_record(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_name: Atom,
|
module_name: Atom,
|
||||||
@@ -894,8 +919,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
import_module_exports(
|
import_module_exports::<LS>(
|
||||||
&mut self.payload.retraction_info,
|
&mut self.payload,
|
||||||
&module_compilation_target,
|
&module_compilation_target,
|
||||||
builtins,
|
builtins,
|
||||||
code_dir,
|
code_dir,
|
||||||
@@ -992,14 +1017,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
|
|
||||||
for export in &module.module_decl.exports {
|
for export in &module.module_decl.exports {
|
||||||
if let ModuleExport::OpDecl(ref op_decl) = export {
|
if let ModuleExport::OpDecl(ref op_decl) = export {
|
||||||
let payload: &mut LoadStatePayload<_> = &mut self.payload;
|
add_op_decl_as_module_export::<LS>(
|
||||||
|
&mut self.payload,
|
||||||
add_op_decl_as_module_export(
|
|
||||||
&mut module.op_dir,
|
&mut module.op_dir,
|
||||||
&payload.compilation_target, // this is a Module.
|
|
||||||
&mut payload.retraction_info,
|
|
||||||
&mut self.wam_prelude.indices.op_dir,
|
&mut self.wam_prelude.indices.op_dir,
|
||||||
&mut payload.module_op_exports,
|
|
||||||
op_decl,
|
op_decl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1018,8 +1039,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
|
|
||||||
match &payload_compilation_target {
|
match &payload_compilation_target {
|
||||||
CompilationTarget::User => {
|
CompilationTarget::User => {
|
||||||
import_module_exports(
|
import_module_exports::<LS>(
|
||||||
&mut self.payload.retraction_info,
|
&mut self.payload,
|
||||||
&payload_compilation_target,
|
&payload_compilation_target,
|
||||||
&module,
|
&module,
|
||||||
&mut self.wam_prelude.indices.code_dir,
|
&mut self.wam_prelude.indices.code_dir,
|
||||||
@@ -1030,17 +1051,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
CompilationTarget::Module(ref defining_module_name) => {
|
CompilationTarget::Module(ref defining_module_name) => {
|
||||||
match self.wam_prelude.indices.modules.get_mut(defining_module_name) {
|
match self.wam_prelude.indices.modules.get_mut(defining_module_name) {
|
||||||
Some(ref mut target_module) => {
|
Some(ref mut target_module) => {
|
||||||
let payload: &mut LoadStatePayload<_> = &mut self.payload;
|
import_module_exports_into_module::<LS>(
|
||||||
|
&mut self.payload,
|
||||||
import_module_exports_into_module(
|
|
||||||
&mut payload.retraction_info,
|
|
||||||
&payload_compilation_target,
|
&payload_compilation_target,
|
||||||
&module,
|
&module,
|
||||||
&mut target_module.code_dir,
|
&mut target_module.code_dir,
|
||||||
&mut target_module.op_dir,
|
&mut target_module.op_dir,
|
||||||
&mut target_module.meta_predicates,
|
&mut target_module.meta_predicates,
|
||||||
&mut self.wam_prelude.indices.op_dir,
|
&mut self.wam_prelude.indices.op_dir,
|
||||||
&mut payload.module_op_exports,
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -1070,47 +1088,38 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
if let Some(module) = self.wam_prelude.indices.modules.remove(&module_name) {
|
if let Some(module) = self.wam_prelude.indices.modules.remove(&module_name) {
|
||||||
let payload_compilation_target = self.payload.compilation_target;
|
let payload_compilation_target = self.payload.compilation_target;
|
||||||
|
|
||||||
match &payload_compilation_target {
|
let result = match &payload_compilation_target {
|
||||||
CompilationTarget::User => {
|
CompilationTarget::User => {
|
||||||
import_qualified_module_exports(
|
import_qualified_module_exports::<LS>(
|
||||||
&mut self.payload.retraction_info,
|
&mut self.payload,
|
||||||
&payload_compilation_target,
|
&payload_compilation_target,
|
||||||
&module,
|
&module,
|
||||||
&exports,
|
&exports,
|
||||||
&mut self.wam_prelude.indices.code_dir,
|
&mut self.wam_prelude,
|
||||||
&mut self.wam_prelude.indices.op_dir,
|
)
|
||||||
&mut self.wam_prelude.indices.meta_predicates,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
CompilationTarget::Module(ref defining_module_name) => {
|
CompilationTarget::Module(ref defining_module_name) => {
|
||||||
match self.wam_prelude.indices.modules.get_mut(defining_module_name) {
|
match self.wam_prelude.indices.modules.get_mut(defining_module_name) {
|
||||||
Some(ref mut target_module) => {
|
Some(ref mut target_module) => {
|
||||||
let payload: &mut LoadStatePayload<_> = &mut self.payload;
|
import_qualified_module_exports_into_module::<LS>(
|
||||||
|
&mut self.payload,
|
||||||
import_qualified_module_exports_into_module(
|
|
||||||
&mut payload.retraction_info,
|
|
||||||
&payload_compilation_target,
|
|
||||||
&module,
|
&module,
|
||||||
&exports,
|
&exports,
|
||||||
&mut target_module.code_dir,
|
&mut target_module.code_dir,
|
||||||
&mut target_module.op_dir,
|
&mut target_module.op_dir,
|
||||||
&mut target_module.meta_predicates,
|
&mut target_module.meta_predicates,
|
||||||
&mut self.wam_prelude.indices.op_dir,
|
&mut self.wam_prelude.indices.op_dir,
|
||||||
&mut payload.module_op_exports,
|
)
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// we find ourselves here because we're trying to import
|
Err(SessionError::ModuleCannotImportSelf(module_name))
|
||||||
// a module into itself as it is being defined.
|
|
||||||
self.wam_prelude.indices.modules.insert(module_name, module);
|
|
||||||
return Err(SessionError::ModuleCannotImportSelf(module_name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
self.wam_prelude.indices.modules.insert(module_name, module);
|
self.wam_prelude.indices.modules.insert(module_name, module);
|
||||||
Ok(())
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
|
Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
|
||||||
}
|
}
|
||||||
@@ -1168,7 +1177,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
indices: self.wam_prelude.indices,
|
indices: self.wam_prelude.indices,
|
||||||
code: self.wam_prelude.code,
|
code: self.wam_prelude.code,
|
||||||
load_contexts: self.wam_prelude.load_contexts,
|
load_contexts: self.wam_prelude.load_contexts,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
subloader.load()?
|
subloader.load()?
|
||||||
@@ -1231,7 +1240,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
indices: self.wam_prelude.indices,
|
indices: self.wam_prelude.indices,
|
||||||
code: self.wam_prelude.code,
|
code: self.wam_prelude.code,
|
||||||
load_contexts: self.wam_prelude.load_contexts,
|
load_contexts: self.wam_prelude.load_contexts,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
subloader.load()?
|
subloader.load()?
|
||||||
|
|||||||
@@ -510,6 +510,21 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap()));
|
term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap()));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(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) {
|
||||||
|
term_stack.push(
|
||||||
|
Term::Literal(Cell::default(), Literal::CodeIndex(idx))
|
||||||
|
);
|
||||||
|
|
||||||
|
arity += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if arity == 0 {
|
if arity == 0 {
|
||||||
term_stack.push(Term::Literal(Cell::default(), Literal::Atom(name)));
|
term_stack.push(Term::Literal(Cell::default(), Literal::Atom(name)));
|
||||||
} else {
|
} else {
|
||||||
@@ -708,7 +723,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
module
|
module
|
||||||
.code_dir
|
.code_dir
|
||||||
.get_mut(&key)
|
.get_mut(&key)
|
||||||
.map(|code_idx| code_idx.replace(old_code_idx));
|
.map(|code_idx| code_idx.set(old_code_idx));
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
@@ -733,7 +748,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
.indices
|
.indices
|
||||||
.code_dir
|
.code_dir
|
||||||
.get_mut(&key)
|
.get_mut(&key)
|
||||||
.map(|code_idx| code_idx.replace(old_code_idx));
|
.map(|code_idx| code_idx.set(old_code_idx));
|
||||||
}
|
}
|
||||||
RetractionRecord::AddedIndex(index_key, clause_loc) => {
|
RetractionRecord::AddedIndex(index_key, clause_loc) => {
|
||||||
// WAS: inner_index_locs) => {
|
// WAS: inner_index_locs) => {
|
||||||
@@ -1271,13 +1286,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
|
|
||||||
let code_index = self.get_or_insert_code_index(key, compilation_target);
|
let code_index = self.get_or_insert_code_index(key, compilation_target);
|
||||||
|
|
||||||
if let IndexPtr::Undefined = code_index.get() {
|
if code_index.is_undefined() {
|
||||||
set_code_index(
|
set_code_index(
|
||||||
&mut self.payload.retraction_info,
|
&mut self.payload.retraction_info,
|
||||||
&compilation_target,
|
&compilation_target,
|
||||||
key,
|
key,
|
||||||
&code_index,
|
code_index,
|
||||||
IndexPtr::DynamicUndefined,
|
IndexPtr::dynamic_undefined(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1491,7 +1506,6 @@ impl Machine {
|
|||||||
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
|
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
|
||||||
|
|
||||||
let declare_module = || {
|
let declare_module = || {
|
||||||
// let export_list = export_list?;
|
|
||||||
let exports = loader.extract_module_export_list_from_heap(temp_v!(2))?;
|
let exports = loader.extract_module_export_list_from_heap(temp_v!(2))?;
|
||||||
|
|
||||||
let module_decl = ModuleDecl {
|
let module_decl = ModuleDecl {
|
||||||
@@ -2019,10 +2033,10 @@ impl Machine {
|
|||||||
.indices
|
.indices
|
||||||
.remove_predicate_skeleton(&compilation_target, &key);
|
.remove_predicate_skeleton(&compilation_target, &key);
|
||||||
|
|
||||||
let code_index = loader
|
let mut code_index = loader
|
||||||
.get_or_insert_code_index(key, compilation_target);
|
.get_or_insert_code_index(key, compilation_target);
|
||||||
|
|
||||||
code_index.set(IndexPtr::Undefined);
|
code_index.set(IndexPtr::undefined());
|
||||||
|
|
||||||
loader.payload.compilation_target = clause_clause_compilation_target;
|
loader.payload.compilation_target = clause_clause_compilation_target;
|
||||||
|
|
||||||
@@ -2187,7 +2201,7 @@ impl Machine {
|
|||||||
|
|
||||||
let (predicate_name, arity) = self
|
let (predicate_name, arity) = self
|
||||||
.machine_st
|
.machine_st
|
||||||
.read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]);
|
.read_predicate_key(self.machine_st.registers[2], self.machine_st.registers[3]);
|
||||||
|
|
||||||
let compilation_target = match module_name {
|
let compilation_target = match module_name {
|
||||||
atom!("user") => CompilationTarget::User,
|
atom!("user") => CompilationTarget::User,
|
||||||
@@ -2313,7 +2327,7 @@ impl Machine {
|
|||||||
.machine_st
|
.machine_st
|
||||||
.read_predicate_key(self.machine_st.registers[1], self.machine_st.registers[2]);
|
.read_predicate_key(self.machine_st.registers[1], self.machine_st.registers[2]);
|
||||||
|
|
||||||
match ClauseType::from(key.0, key.1) {
|
match ClauseType::from(key.0, key.1, &mut self.machine_st.arena) {
|
||||||
ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN(_) => {
|
ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN(_) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2355,14 +2369,19 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn load_module(
|
pub(super) fn load_module(
|
||||||
|
machine_st: &mut MachineState,
|
||||||
code_dir: &mut CodeDir,
|
code_dir: &mut CodeDir,
|
||||||
op_dir: &mut OpDir,
|
op_dir: &mut OpDir,
|
||||||
meta_predicate_dir: &mut MetaPredicateDir,
|
meta_predicate_dir: &mut MetaPredicateDir,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
module: &Module,
|
module: &Module,
|
||||||
) {
|
) {
|
||||||
import_module_exports(
|
let ts = LiveTermStream::new(ListingSource::User);
|
||||||
&mut RetractionInfo::new(0),
|
let payload = LoadStatePayload::new(0, ts);
|
||||||
|
let mut payload = LiveLoadAndMachineState::new(machine_st, payload);
|
||||||
|
|
||||||
|
import_module_exports::<LiveLoadAndMachineState>(
|
||||||
|
&mut payload,
|
||||||
&compilation_target,
|
&compilation_target,
|
||||||
module,
|
module,
|
||||||
code_dir,
|
code_dir,
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ use crate::arena::*;
|
|||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::fixtures::*;
|
use crate::fixtures::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::instructions::*;
|
|
||||||
use crate::machine::loader::*;
|
use crate::machine::loader::*;
|
||||||
use crate::machine::machine_state::*;
|
use crate::machine::machine_state::*;
|
||||||
use crate::machine::streams::Stream;
|
use crate::machine::streams::Stream;
|
||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use modular_bitfield::{BitfieldSpecifier, bitfield};
|
||||||
|
use modular_bitfield::specifiers::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::ops::Deref;
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
@@ -59,9 +59,6 @@ impl PartialOrd<Ref> for HeapCellValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h1) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h1) => {
|
||||||
// _ if self.is_ref() => {
|
|
||||||
// let h1 = self.get_value();
|
|
||||||
|
|
||||||
match r.get_tag() {
|
match r.get_tag() {
|
||||||
RefTag::StackCell => Some(Ordering::Less),
|
RefTag::StackCell => Some(Ordering::Less),
|
||||||
_ => {
|
_ => {
|
||||||
@@ -77,52 +74,133 @@ impl PartialOrd<Ref> for HeapCellValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum IndexPtr {
|
#[bits = 7]
|
||||||
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
pub enum IndexPtrTag {
|
||||||
DynamicIndex(usize),
|
DynamicUndefined = 0b1000101, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||||
Index(usize),
|
DynamicIndex = 0b1000110,
|
||||||
Undefined,
|
Index = 0b1000111,
|
||||||
|
Undefined = 0b1001000,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[bitfield]
|
||||||
pub struct CodeIndex(pub(crate) Rc<Cell<IndexPtr>>);
|
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
|
pub struct IndexPtr {
|
||||||
|
pub p: B56,
|
||||||
|
#[allow(unused)] m: bool,
|
||||||
|
pub tag: IndexPtrTag,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for CodeIndex {
|
impl IndexPtr {
|
||||||
type Target = Cell<IndexPtr>;
|
pub(crate) fn dynamic_undefined() -> Self {
|
||||||
|
IndexPtr::new()
|
||||||
|
.with_p(0)
|
||||||
|
.with_m(false)
|
||||||
|
.with_tag(IndexPtrTag::DynamicUndefined)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
pub(crate) fn undefined() -> Self {
|
||||||
fn deref(&self) -> &Self::Target {
|
IndexPtr::new()
|
||||||
self.0.deref()
|
.with_p(0)
|
||||||
|
.with_m(false)
|
||||||
|
.with_tag(IndexPtrTag::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn dynamic_index(p: usize) -> Self {
|
||||||
|
IndexPtr::new()
|
||||||
|
.with_p(p as u64)
|
||||||
|
.with_m(false)
|
||||||
|
.with_tag(IndexPtrTag::DynamicIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn index(p: usize) -> Self {
|
||||||
|
IndexPtr::new()
|
||||||
|
.with_p(p as u64)
|
||||||
|
.with_m(false)
|
||||||
|
.with_tag(IndexPtrTag::Index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Ord, Hash, PartialOrd, Eq, PartialEq)]
|
||||||
|
pub struct CodeIndex(TypedArenaPtr<IndexPtr>);
|
||||||
|
|
||||||
|
const_assert!(std::mem::align_of::<CodeIndex>() == 8);
|
||||||
|
|
||||||
|
impl From<CodeIndex> for UntypedArenaPtr {
|
||||||
|
#[inline(always)]
|
||||||
|
fn from(ptr: CodeIndex) -> UntypedArenaPtr {
|
||||||
|
unsafe { std::mem::transmute(ptr.0.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UntypedArenaPtr> for CodeIndex {
|
||||||
|
#[inline(always)]
|
||||||
|
fn from(ptr: UntypedArenaPtr) -> CodeIndex {
|
||||||
|
CodeIndex(TypedArenaPtr::new(ptr.get_ptr() as *mut IndexPtr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TypedArenaPtr<IndexPtr>> for CodeIndex {
|
||||||
|
#[inline(always)]
|
||||||
|
fn from(ptr: TypedArenaPtr<IndexPtr>) -> CodeIndex {
|
||||||
|
CodeIndex(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodeIndex {
|
impl CodeIndex {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new(ptr: IndexPtr) -> Self {
|
pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self {
|
||||||
CodeIndex(Rc::new(Cell::new(ptr)))
|
CodeIndex(arena_alloc!(ptr, arena))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
|
pub(crate) fn default(arena: &mut Arena) -> Self {
|
||||||
|
CodeIndex::new(IndexPtr::undefined(), arena)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub(crate) fn is_undefined(&self) -> bool {
|
pub(crate) fn is_undefined(&self) -> bool {
|
||||||
match self.0.get() {
|
match self.0.tag() {
|
||||||
IndexPtr::Undefined => true, // | &IndexPtr::DynamicUndefined => true,
|
IndexPtrTag::Undefined => true, // | &IndexPtr::DynamicUndefined => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn is_dynamic_undefined(&self) -> bool {
|
||||||
|
match self.0.tag() {
|
||||||
|
IndexPtrTag::DynamicUndefined => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn local(&self) -> Option<usize> {
|
pub(crate) fn local(&self) -> Option<usize> {
|
||||||
match self.0.get() {
|
match self.0.tag() {
|
||||||
IndexPtr::Index(i) => Some(i),
|
IndexPtrTag::Index => Some(self.0.p() as usize),
|
||||||
IndexPtr::DynamicIndex(i) => Some(i),
|
IndexPtrTag::DynamicIndex => Some(self.0.p() as usize),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn get(&self) -> IndexPtr {
|
||||||
|
*self.0.deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CodeIndex {
|
#[inline(always)]
|
||||||
fn default() -> Self {
|
pub(crate) fn set(&mut self, value: IndexPtr) {
|
||||||
CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)))
|
*self.0.deref_mut() = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn replace(&mut self, value: IndexPtr) -> IndexPtr {
|
||||||
|
std::mem::replace(self.0.deref_mut(), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn as_ptr(&self) -> *const IndexPtr {
|
||||||
|
self.0.as_ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,19 +347,22 @@ impl IndexStore {
|
|||||||
module: Atom,
|
module: Atom,
|
||||||
) -> Option<CodeIndex> {
|
) -> Option<CodeIndex> {
|
||||||
if module == atom!("user") {
|
if module == atom!("user") {
|
||||||
match ClauseType::from(name, arity) {
|
/*match ClauseType::from(name, arity) {
|
||||||
ClauseType::Named(arity, name, _) => self.code_dir.get(&(name, arity)).cloned(),
|
ClauseType::Named(arity, name, _) => */
|
||||||
_ => None,
|
self.code_dir.get(&(name, arity)).cloned()
|
||||||
}
|
/* _ => None,
|
||||||
|
}*/
|
||||||
} else {
|
} else {
|
||||||
self.modules
|
self.modules
|
||||||
.get(&module)
|
.get(&module)
|
||||||
.and_then(|module| match ClauseType::from(name, arity) {
|
.and_then(|module|/* |module| match ClauseType::from(name, arity) {
|
||||||
ClauseType::Named(arity, name, _) => {
|
ClauseType::Named(arity, name, _) => { */
|
||||||
module.code_dir.get(&(name, arity)).cloned()
|
module.code_dir.get(&(name, arity)).cloned()
|
||||||
|
/*
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
} */
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -418,6 +418,17 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
if let Some(c) = name.as_char() {
|
||||||
|
chars.push(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -454,6 +465,20 @@ impl MachineState {
|
|||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn neck_cut(&mut self) {
|
||||||
|
let b = self.b;
|
||||||
|
let b0 = self.b0;
|
||||||
|
|
||||||
|
if b > b0 {
|
||||||
|
self.b = b0;
|
||||||
|
|
||||||
|
if b > self.e {
|
||||||
|
self.stack.truncate(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Safety: the atom_tbl lives for the lifetime of the machine, as does the helper, so the ptr
|
// Safety: the atom_tbl lives for the lifetime of the machine, as does the helper, so the ptr
|
||||||
// will always be valid.
|
// will always be valid.
|
||||||
pub fn read_term_from_user_input(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
pub fn read_term_from_user_input(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
||||||
@@ -666,6 +691,13 @@ impl MachineState {
|
|||||||
debug_assert_eq!(_arity, 0);
|
debug_assert_eq!(_arity, 0);
|
||||||
var_names.insert(var, Rc::new(name.as_str().to_owned()));
|
var_names.insert(var, Rc::new(name.as_str().to_owned()));
|
||||||
}
|
}
|
||||||
|
(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()));
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@@ -677,34 +709,64 @@ impl MachineState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ignore_ops = read_heap_cell!(ignore_ops,
|
||||||
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let numbervars = read_heap_cell!(numbervars,
|
||||||
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let quoted = read_heap_cell!(quoted,
|
||||||
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let mut printer = HCPrinter::new(
|
let mut printer = HCPrinter::new(
|
||||||
&mut self.heap,
|
&mut self.heap,
|
||||||
&mut self.arena,
|
|
||||||
op_dir,
|
op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
term_to_be_printed,
|
term_to_be_printed,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let HeapCellValueTag::Atom = ignore_ops.get_tag() {
|
printer.ignore_ops = ignore_ops;
|
||||||
let name = cell_as_atom!(ignore_ops);
|
printer.numbervars = numbervars;
|
||||||
printer.ignore_ops = name == atom!("true");
|
printer.quoted = quoted;
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let HeapCellValueTag::Atom = numbervars.get_tag() {
|
|
||||||
let name = cell_as_atom!(numbervars);
|
|
||||||
printer.numbervars = name == atom!("true");
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let HeapCellValueTag::Atom = quoted.get_tag() {
|
|
||||||
let name = cell_as_atom!(quoted);
|
|
||||||
printer.quoted = name == atom!("true");
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
|
|
||||||
match Number::try_from(max_depth) {
|
match Number::try_from(max_depth) {
|
||||||
Ok(Number::Fixnum(n)) => {
|
Ok(Number::Fixnum(n)) => {
|
||||||
|
|||||||
@@ -347,10 +347,27 @@ impl MachineState {
|
|||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
self.fail = cstr_atom != atom!("[]");
|
self.fail = cstr_atom != atom!("[]");
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
self.fail = atom == atom!("") && name != atom!("[]");
|
||||||
|
} else {
|
||||||
|
// this is intentionally the same policy for
|
||||||
|
// value.tag() == Lis and PStrLoc. they're not
|
||||||
|
// grouped together to allow for arity == 0.
|
||||||
|
self.unify_partial_string(atom_as_cstr_cell!(atom), value);
|
||||||
|
|
||||||
|
if !self.pdl.is_empty() {
|
||||||
|
self.unify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::CStr, cstr_atom) => {
|
(HeapCellValueTag::CStr, cstr_atom) => {
|
||||||
self.fail = atom != cstr_atom;
|
self.fail = atom != cstr_atom;
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
|
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
|
||||||
self.unify_partial_string(atom_as_cstr_cell!(atom), value);
|
self.unify_partial_string(atom_as_cstr_cell!(atom), value);
|
||||||
|
|
||||||
if !self.pdl.is_empty() {
|
if !self.pdl.is_empty() {
|
||||||
@@ -553,6 +570,12 @@ impl MachineState {
|
|||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
self.fail = !(arity == 0 && name == atom);
|
self.fail = !(arity == 0 && name == atom);
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
self.fail = !(arity == 0 && name == atom);
|
||||||
|
}
|
||||||
(HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => {
|
(HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => {
|
||||||
self.fail = cstr_atom != atom!("");
|
self.fail = cstr_atom != atom!("");
|
||||||
}
|
}
|
||||||
@@ -587,6 +610,16 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if let Some(c2) = name.as_char() {
|
||||||
|
self.fail = !(c == c2 && arity == 0);
|
||||||
|
} else {
|
||||||
|
self.fail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char, c2) => {
|
(HeapCellValueTag::Char, c2) => {
|
||||||
if c != c2 {
|
if c != c2 {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
@@ -739,11 +772,6 @@ impl MachineState {
|
|||||||
self.unify_atom(name, d2);
|
self.unify_atom(name, d2);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str, s1) => {
|
(HeapCellValueTag::Str, s1) => {
|
||||||
if d2.is_constant() {
|
|
||||||
self.fail = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if tabu_list.contains(&(d1, d2)) {
|
if tabu_list.contains(&(d1, d2)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -969,9 +997,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Atom, (n2, a2)) => {
|
(HeapCellValueTag::Atom, (n2, a2)) => {
|
||||||
if !(a1 == 0 && a2 == 0 && n1 == n2) {
|
self.fail = !(a1 == 0 && a2 == 0 && n1 == n2);
|
||||||
self.fail = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::AttrVar, h) => {
|
(HeapCellValueTag::AttrVar, h) => {
|
||||||
if self.bind_with_occurs_check(Ref::attr_var(h), str_loc_as_cell!(s1)) {
|
if self.bind_with_occurs_check(Ref::attr_var(h), str_loc_as_cell!(s1)) {
|
||||||
@@ -1285,11 +1311,6 @@ impl MachineState {
|
|||||||
self.unify_atom(name, d2);
|
self.unify_atom(name, d2);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str, s1) => {
|
(HeapCellValueTag::Str, s1) => {
|
||||||
if d2.is_constant() {
|
|
||||||
self.fail = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if tabu_list.contains(&(d1, d2)) {
|
if tabu_list.contains(&(d1, d2)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1492,8 +1513,8 @@ impl MachineState {
|
|||||||
let v1 = self.store(s1);
|
let v1 = self.store(s1);
|
||||||
let v2 = self.store(s2);
|
let v2 = self.store(s2);
|
||||||
|
|
||||||
let order_cat_v1 = v1.order_category();
|
let order_cat_v1 = v1.order_category(&self.heap);
|
||||||
let order_cat_v2 = v2.order_category();
|
let order_cat_v2 = v2.order_category(&self.heap);
|
||||||
|
|
||||||
if order_cat_v1 != order_cat_v2 {
|
if order_cat_v1 != order_cat_v2 {
|
||||||
self.pdl.clear();
|
self.pdl.clear();
|
||||||
@@ -1552,6 +1573,15 @@ impl MachineState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n2 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
if n1 != n2 {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(n1.cmp(&n2));
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@@ -1579,11 +1609,67 @@ impl MachineState {
|
|||||||
return Some(c1.cmp(&c2));
|
return Some(c1.cmp(&c2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n2 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
if let Some(c2) = n2.as_char() {
|
||||||
|
if c1 != c2 {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(c1.cmp(&c2));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(
|
||||||
|
Some(c1).cmp(&n2.chars().next())
|
||||||
|
.then(Ordering::Less)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n1 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
read_heap_cell!(v2,
|
||||||
|
(HeapCellValueTag::Atom, (n2, _a2)) => {
|
||||||
|
if n1 != n2 {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(n1.cmp(&n2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Char, c2) => {
|
||||||
|
if let Some(c1) = n1.as_char() {
|
||||||
|
if c1 != c2 {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(c1.cmp(&c2));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(
|
||||||
|
n1.chars().next().cmp(&Some(c2))
|
||||||
|
.then(Ordering::Greater)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n2 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
if n1 != n2 {
|
||||||
|
self.pdl.clear();
|
||||||
|
return Some(n1.cmp(&n2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -1597,8 +1683,8 @@ impl MachineState {
|
|||||||
) -> Option<Ordering> {
|
) -> Option<Ordering> {
|
||||||
let compound = Some(TermOrderCategory::Compound);
|
let compound = Some(TermOrderCategory::Compound);
|
||||||
|
|
||||||
if iter2.focus.order_category() != compound {
|
if iter2.focus.order_category(iter2.heap) != compound {
|
||||||
Some(compound.cmp(&iter2.focus.order_category()))
|
Some(compound.cmp(&iter2.focus.order_category(iter2.heap)))
|
||||||
} else {
|
} else {
|
||||||
let c1 = match iteratee {
|
let c1 = match iteratee {
|
||||||
PStrIteratee::Char(_, c) => c,
|
PStrIteratee::Char(_, c) => c,
|
||||||
@@ -2116,7 +2202,7 @@ impl MachineState {
|
|||||||
heap_bound_deref(iter.heap, value),
|
heap_bound_deref(iter.heap, value),
|
||||||
));
|
));
|
||||||
|
|
||||||
if value.is_compound() {
|
if value.is_compound(iter.heap) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2403,6 +2489,21 @@ impl MachineState {
|
|||||||
a1.as_var().unwrap(),
|
a1.as_var().unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, atom_arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if atom_arity == 0 {
|
||||||
|
self.try_functor_fabricate_struct(
|
||||||
|
name,
|
||||||
|
arity as usize,
|
||||||
|
a1.as_var().unwrap(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let err = self.type_error(ValidType::Atomic, store_name);
|
||||||
|
return Err(self.error_form(err, stub_gen()));
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
let c = self.atom_tbl.build_with(&c.to_string());
|
let c = self.atom_tbl.build_with(&c.to_string());
|
||||||
|
|
||||||
@@ -2444,6 +2545,17 @@ impl MachineState {
|
|||||||
let err = self.instantiation_error();
|
let err = self.instantiation_error();
|
||||||
Err(self.error_form(err, stub_gen()))
|
Err(self.error_form(err, stub_gen()))
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if name == atom!("[]") && arity == 0 {
|
||||||
|
Ok(vec![])
|
||||||
|
} else {
|
||||||
|
let err = self.type_error(ValidType::List, value);
|
||||||
|
Err(self.error_form(err, stub_gen()))
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
if name == atom!("[]") && arity == 0 {
|
if name == atom!("[]") && arity == 0 {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
@@ -2484,6 +2596,17 @@ impl MachineState {
|
|||||||
(HeapCellValueTag::PStrLoc, l) => {
|
(HeapCellValueTag::PStrLoc, l) => {
|
||||||
return self.try_from_partial_string(result, l, stub_gen, a1);
|
return self.try_from_partial_string(result, l, stub_gen, a1);
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if name == atom!("[]") && arity == 0 {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
let err = self.type_error(ValidType::List, a1);
|
||||||
|
return Err(self.error_form(err, stub_gen()));
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
if name == atom!("[]") && arity == 0 {
|
if name == atom!("[]") && arity == 0 {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ impl MockWAM {
|
|||||||
|
|
||||||
let mut printer = HCPrinter::new(
|
let mut printer = HCPrinter::new(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&mut self.machine_st.arena,
|
|
||||||
&self.op_dir,
|
&self.op_dir,
|
||||||
PrinterOutputter::new(),
|
PrinterOutputter::new(),
|
||||||
heap_loc_as_cell!(term_write_result.heap_loc),
|
heap_loc_as_cell!(term_write_result.heap_loc),
|
||||||
@@ -272,6 +271,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(ref mut builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
|
if let Some(ref mut builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
|
||||||
load_module(
|
load_module(
|
||||||
|
&mut wam.machine_st,
|
||||||
&mut wam.indices.code_dir,
|
&mut wam.indices.code_dir,
|
||||||
&mut wam.indices.op_dir,
|
&mut wam.indices.op_dir,
|
||||||
&mut wam.indices.meta_predicates,
|
&mut wam.indices.meta_predicates,
|
||||||
@@ -297,6 +297,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
|
if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
|
||||||
load_module(
|
load_module(
|
||||||
|
&mut wam.machine_st,
|
||||||
&mut wam.indices.code_dir,
|
&mut wam.indices.code_dir,
|
||||||
&mut wam.indices.op_dir,
|
&mut wam.indices.op_dir,
|
||||||
&mut wam.indices.meta_predicates,
|
&mut wam.indices.meta_predicates,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ pub mod streams;
|
|||||||
pub mod system_calls;
|
pub mod system_calls;
|
||||||
pub mod term_stream;
|
pub mod term_stream;
|
||||||
|
|
||||||
|
use crate::arena::*;
|
||||||
use crate::arithmetic::*;
|
use crate::arithmetic::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
@@ -160,6 +161,24 @@ pub(crate) fn import_builtin_impls(code_dir: &CodeDir, builtins: &mut Module) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn get_structure_index(value: HeapCellValue) -> Option<CodeIndex> {
|
||||||
|
read_heap_cell!(value,
|
||||||
|
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||||
|
match_untyped_arena_ptr!(cons_ptr,
|
||||||
|
(ArenaHeaderTag::IndexPtr, ip) => {
|
||||||
|
return Some(CodeIndex::from(ip));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
|
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
|
||||||
@@ -220,6 +239,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(toplevel) = self.indices.modules.get(&atom!("$toplevel")) {
|
if let Some(toplevel) = self.indices.modules.get(&atom!("$toplevel")) {
|
||||||
load_module(
|
load_module(
|
||||||
|
&mut self.machine_st,
|
||||||
&mut self.indices.code_dir,
|
&mut self.indices.code_dir,
|
||||||
&mut self.indices.op_dir,
|
&mut self.indices.op_dir,
|
||||||
&mut self.indices.meta_predicates,
|
&mut self.indices.meta_predicates,
|
||||||
@@ -287,7 +307,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn configure_modules(&mut self) {
|
pub(crate) fn configure_modules(&mut self) {
|
||||||
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir) {
|
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir, arena: &mut Arena) {
|
||||||
for arity in 1..66 {
|
for arity in 1..66 {
|
||||||
let key = (atom!("call"), arity);
|
let key = (atom!("call"), arity);
|
||||||
|
|
||||||
@@ -295,7 +315,7 @@ impl Machine {
|
|||||||
Some(src_code_index) => {
|
Some(src_code_index) => {
|
||||||
let target_code_index = target_code_dir
|
let target_code_index = target_code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined));
|
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena));
|
||||||
|
|
||||||
target_code_index.set(src_code_index.get());
|
target_code_index.set(src_code_index.get());
|
||||||
}
|
}
|
||||||
@@ -311,6 +331,7 @@ impl Machine {
|
|||||||
// Import loader's exports into the builtins module so they will be
|
// Import loader's exports into the builtins module so they will be
|
||||||
// implicitly included in every further module.
|
// implicitly included in every further module.
|
||||||
load_module(
|
load_module(
|
||||||
|
&mut self.machine_st,
|
||||||
&mut builtins.code_dir,
|
&mut builtins.code_dir,
|
||||||
&mut builtins.op_dir,
|
&mut builtins.op_dir,
|
||||||
&mut builtins.meta_predicates,
|
&mut builtins.meta_predicates,
|
||||||
@@ -331,10 +352,10 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (_, target_module) in self.indices.modules.iter_mut() {
|
for (_, target_module) in self.indices.modules.iter_mut() {
|
||||||
update_call_n_indices(&loader, &mut target_module.code_dir);
|
update_call_n_indices(&loader, &mut target_module.code_dir, &mut self.machine_st.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_call_n_indices(&loader, &mut self.indices.code_dir);
|
update_call_n_indices(&loader, &mut self.indices.code_dir, &mut self.machine_st.arena);
|
||||||
|
|
||||||
self.indices.modules.insert(atom!("loader"), loader);
|
self.indices.modules.insert(atom!("loader"), loader);
|
||||||
} else {
|
} else {
|
||||||
@@ -393,7 +414,10 @@ impl Machine {
|
|||||||
|
|
||||||
for (p, instr) in self.code[impls_offset ..].iter().enumerate() {
|
for (p, instr) in self.code[impls_offset ..].iter().enumerate() {
|
||||||
let key = instr.to_name_and_arity();
|
let key = instr.to_name_and_arity();
|
||||||
self.indices.code_dir.insert(key, CodeIndex::new(IndexPtr::Index(p + impls_offset)));
|
self.indices.code_dir.insert(
|
||||||
|
key,
|
||||||
|
CodeIndex::new(IndexPtr::index(p + impls_offset), &mut self.machine_st.arena),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,6 +479,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
|
if let Some(builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
|
||||||
load_module(
|
load_module(
|
||||||
|
&mut wam.machine_st,
|
||||||
&mut wam.indices.code_dir,
|
&mut wam.indices.code_dir,
|
||||||
&mut wam.indices.op_dir,
|
&mut wam.indices.op_dir,
|
||||||
&mut wam.indices.meta_predicates,
|
&mut wam.indices.meta_predicates,
|
||||||
@@ -480,6 +505,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
|
if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
|
||||||
load_module(
|
load_module(
|
||||||
|
&mut wam.machine_st,
|
||||||
&mut wam.indices.code_dir,
|
&mut wam.indices.code_dir,
|
||||||
&mut wam.indices.op_dir,
|
&mut wam.indices.op_dir,
|
||||||
&mut wam.indices.meta_predicates,
|
&mut wam.indices.meta_predicates,
|
||||||
@@ -666,18 +692,20 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
|
fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
|
||||||
match idx {
|
let compiled_tl_index = idx.p() as usize;
|
||||||
IndexPtr::DynamicUndefined => {
|
|
||||||
|
match idx.tag() {
|
||||||
|
IndexPtrTag::DynamicUndefined => {
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
}
|
}
|
||||||
IndexPtr::Undefined => {
|
IndexPtrTag::Undefined => {
|
||||||
return Err(self.machine_st.throw_undefined_error(name, arity));
|
return Err(self.machine_st.throw_undefined_error(name, arity));
|
||||||
}
|
}
|
||||||
IndexPtr::DynamicIndex(compiled_tl_index) => {
|
IndexPtrTag::DynamicIndex => {
|
||||||
self.machine_st.dynamic_mode = FirstOrNext::First;
|
self.machine_st.dynamic_mode = FirstOrNext::First;
|
||||||
self.machine_st.call_at_index(arity, compiled_tl_index);
|
self.machine_st.call_at_index(arity, compiled_tl_index);
|
||||||
}
|
}
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtrTag::Index => {
|
||||||
self.machine_st.call_at_index(arity, compiled_tl_index);
|
self.machine_st.call_at_index(arity, compiled_tl_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -687,18 +715,20 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_execute(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
|
fn try_execute(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
|
||||||
match idx {
|
let compiled_tl_index = idx.p() as usize;
|
||||||
IndexPtr::DynamicUndefined => {
|
|
||||||
|
match idx.tag() {
|
||||||
|
IndexPtrTag::DynamicUndefined => {
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
}
|
}
|
||||||
IndexPtr::Undefined => {
|
IndexPtrTag::Undefined => {
|
||||||
return Err(self.machine_st.throw_undefined_error(name, arity));
|
return Err(self.machine_st.throw_undefined_error(name, arity));
|
||||||
}
|
}
|
||||||
IndexPtr::DynamicIndex(compiled_tl_index) => {
|
IndexPtrTag::DynamicIndex => {
|
||||||
self.machine_st.dynamic_mode = FirstOrNext::First;
|
self.machine_st.dynamic_mode = FirstOrNext::First;
|
||||||
self.machine_st.execute_at_index(arity, compiled_tl_index);
|
self.machine_st.execute_at_index(arity, compiled_tl_index);
|
||||||
}
|
}
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtrTag::Index => {
|
||||||
self.machine_st.execute_at_index(arity, compiled_tl_index)
|
self.machine_st.execute_at_index(arity, compiled_tl_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -470,14 +470,133 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
|
||||||
|
loader: &mut Loader<'a, LS>,
|
||||||
|
module_name: Atom,
|
||||||
|
terms: Vec<Term>,
|
||||||
|
meta_specs: Vec<MetaSpec>,
|
||||||
|
) -> Vec<Term> {
|
||||||
|
let mut arg_terms = Vec::with_capacity(terms.len());
|
||||||
|
|
||||||
|
for (term, meta_spec) in terms.into_iter().zip(meta_specs.iter()) {
|
||||||
|
if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
|
||||||
|
if let Some(name) = term.name() {
|
||||||
|
if name == atom!("$call") {
|
||||||
|
arg_terms.push(term);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let arity = term.arity();
|
||||||
|
|
||||||
|
if let Term::Clause(_, _, ref terms) = &term {
|
||||||
|
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
|
||||||
|
arg_terms.push(term);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_qualified_name(
|
||||||
|
module_term: &Term,
|
||||||
|
qualified_term: &Term,
|
||||||
|
) -> Option<(Atom, Atom)> {
|
||||||
|
if let Term::Literal(_, Literal::Atom(module_name)) = module_term {
|
||||||
|
if let Some(name) = qualified_term.name() {
|
||||||
|
return Some((*module_name, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
let (idx, term) = match term {
|
||||||
|
Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => {
|
||||||
|
if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1])
|
||||||
|
{
|
||||||
|
(
|
||||||
|
loader.get_or_insert_qualified_code_index(
|
||||||
|
module_name,
|
||||||
|
(name, terms[1].arity() + supp_args),
|
||||||
|
),
|
||||||
|
terms.pop().unwrap(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
arg_terms.push(Term::Clause(cell, atom!(":"), terms));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
term => {
|
||||||
|
(
|
||||||
|
loader.get_or_insert_qualified_code_index(
|
||||||
|
module_name,
|
||||||
|
(name, arity + supp_args),
|
||||||
|
),
|
||||||
|
term,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let term = match term {
|
||||||
|
Term::Clause(cell, name, mut terms) => {
|
||||||
|
terms.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx)));
|
||||||
|
Term::Clause(cell, name, terms)
|
||||||
|
}
|
||||||
|
Term::Literal(cell, Literal::Atom(name)) => {
|
||||||
|
Term::Clause(
|
||||||
|
cell,
|
||||||
|
name,
|
||||||
|
vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
term => term,
|
||||||
|
};
|
||||||
|
|
||||||
|
arg_terms.push(term);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arg_terms.push(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
arg_terms
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clause_to_query_term<'a, LS: LoadState<'a>>(
|
fn clause_to_query_term<'a, LS: LoadState<'a>>(
|
||||||
loader: &mut Loader<'a, LS>,
|
loader: &mut Loader<'a, LS>,
|
||||||
name: Atom,
|
name: Atom,
|
||||||
terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
call_policy: CallPolicy,
|
call_policy: CallPolicy,
|
||||||
) -> QueryTerm {
|
) -> QueryTerm {
|
||||||
let ct = loader.get_clause_type(name, terms.len());
|
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
|
||||||
|
// supplementary code vector indices are unnecessary for
|
||||||
|
// root-level clauses.
|
||||||
|
terms.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ct = loader.get_clause_type(name, terms.len());
|
||||||
|
|
||||||
|
if let ClauseType::Named(arity, name, idx) = ct {
|
||||||
|
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
|
||||||
|
let module_name = loader.payload.compilation_target.module_name();
|
||||||
|
let terms = build_meta_predicate_clause(
|
||||||
|
loader,
|
||||||
|
module_name,
|
||||||
|
terms,
|
||||||
|
meta_specs,
|
||||||
|
);
|
||||||
|
|
||||||
|
return QueryTerm::Clause(
|
||||||
|
Cell::default(),
|
||||||
|
ClauseType::Named(arity, name, idx),
|
||||||
|
terms,
|
||||||
|
call_policy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ct = ClauseType::Named(arity, name, idx);
|
||||||
|
}
|
||||||
|
|
||||||
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
|
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,13 +605,120 @@ fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
|
|||||||
loader: &mut Loader<'a, LS>,
|
loader: &mut Loader<'a, LS>,
|
||||||
module_name: Atom,
|
module_name: Atom,
|
||||||
name: Atom,
|
name: Atom,
|
||||||
terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
call_policy: CallPolicy,
|
call_policy: CallPolicy,
|
||||||
) -> QueryTerm {
|
) -> QueryTerm {
|
||||||
let ct = loader.get_qualified_clause_type(module_name, name, terms.len());
|
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
|
||||||
|
// supplementary code vector indices are unnecessary for
|
||||||
|
// root-level clauses.
|
||||||
|
terms.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ct = loader.get_qualified_clause_type(module_name, name, terms.len());
|
||||||
|
|
||||||
|
if let ClauseType::Named(arity, name, idx) = ct {
|
||||||
|
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
|
||||||
|
let terms = build_meta_predicate_clause(
|
||||||
|
loader,
|
||||||
|
module_name,
|
||||||
|
terms,
|
||||||
|
meta_specs,
|
||||||
|
);
|
||||||
|
|
||||||
|
return QueryTerm::Clause(
|
||||||
|
Cell::default(),
|
||||||
|
ClauseType::Named(arity, name, idx),
|
||||||
|
terms,
|
||||||
|
call_policy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ct = ClauseType::Named(arity, name, idx);
|
||||||
|
}
|
||||||
|
|
||||||
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
|
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compute_head(term: &Term) -> Vec<Term> {
|
||||||
|
let mut vars = IndexSet::new();
|
||||||
|
|
||||||
|
for term in post_order_iter(term) {
|
||||||
|
if let TermRef::Var(_, _, v) = term {
|
||||||
|
vars.insert(v.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vars.insert(Rc::new(String::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<Term>) {
|
||||||
|
// 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<Term>) {
|
||||||
|
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<Term>) {
|
||||||
|
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)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Preprocessor {
|
pub(crate) struct Preprocessor {
|
||||||
queue: VecDeque<VecDeque<Term>>,
|
queue: VecDeque<VecDeque<Term>>,
|
||||||
@@ -514,86 +740,6 @@ impl Preprocessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_head(&self, term: &Term) -> Vec<Term> {
|
|
||||||
let mut vars = IndexSet::new();
|
|
||||||
|
|
||||||
for term in post_order_iter(term) {
|
|
||||||
if let TermRef::Var(_, _, v) = term {
|
|
||||||
vars.insert(v.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vars.insert(Rc::new(String::from("!")));
|
|
||||||
vars.into_iter()
|
|
||||||
.map(|v| Term::Var(Cell::default(), v))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fabricate_rule_body(&self, vars: &Vec<Term>, body_term: Term) -> Term {
|
|
||||||
let head_term = Term::Clause(Cell::default(), atom!(""), vars.clone());
|
|
||||||
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 fabricate_rule(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
|
|
||||||
// collect the vars of body_term into a head, return the num_vars
|
|
||||||
// (the arity) as well.
|
|
||||||
let vars = self.compute_head(&body_term);
|
|
||||||
let rule = self.fabricate_rule_body(&vars, body_term);
|
|
||||||
|
|
||||||
(vars, VecDeque::from(vec![rule]))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
|
|
||||||
let vars = self.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!(","));
|
|
||||||
|
|
||||||
self.fabricate_rule_body(&vars, clause)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
(vars, results)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fabricate_if_then(&self, prec: Term, conq: Term) -> (JumpStub, VecDeque<Term>) {
|
|
||||||
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],
|
|
||||||
);
|
|
||||||
|
|
||||||
self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_query_term<'a, LS: LoadState<'a>>(
|
fn to_query_term<'a, LS: LoadState<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
loader: &mut Loader<'a, LS>,
|
loader: &mut Loader<'a, LS>,
|
||||||
@@ -605,7 +751,9 @@ impl Preprocessor {
|
|||||||
Ok(QueryTerm::BlockedCut)
|
Ok(QueryTerm::BlockedCut)
|
||||||
} else {
|
} else {
|
||||||
Ok(clause_to_query_term(
|
Ok(clause_to_query_term(
|
||||||
loader, name, vec![],
|
loader,
|
||||||
|
name,
|
||||||
|
vec![],
|
||||||
self.settings.default_call_policy(),
|
self.settings.default_call_policy(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -618,7 +766,7 @@ impl Preprocessor {
|
|||||||
(atom!(";"), 2) => {
|
(atom!(";"), 2) => {
|
||||||
let term = Term::Clause(r, name, terms);
|
let term = Term::Clause(r, name, terms);
|
||||||
|
|
||||||
let (stub, clauses) = self.fabricate_disjunct(term);
|
let (stub, clauses) = build_disjunct(term);
|
||||||
self.queue.push_back(clauses);
|
self.queue.push_back(clauses);
|
||||||
|
|
||||||
Ok(QueryTerm::Jump(stub))
|
Ok(QueryTerm::Jump(stub))
|
||||||
@@ -627,7 +775,7 @@ impl Preprocessor {
|
|||||||
let conq = terms.pop().unwrap();
|
let conq = terms.pop().unwrap();
|
||||||
let prec = terms.pop().unwrap();
|
let prec = terms.pop().unwrap();
|
||||||
|
|
||||||
let (stub, clauses) = self.fabricate_if_then(prec, conq);
|
let (stub, clauses) = build_if_then(prec, conq);
|
||||||
self.queue.push_back(clauses);
|
self.queue.push_back(clauses);
|
||||||
|
|
||||||
Ok(QueryTerm::Jump(stub))
|
Ok(QueryTerm::Jump(stub))
|
||||||
@@ -644,7 +792,7 @@ impl Preprocessor {
|
|||||||
let terms = vec![prec, conq];
|
let terms = vec![prec, conq];
|
||||||
|
|
||||||
let term = Term::Clause(Cell::default(), atom!(";"), terms);
|
let term = Term::Clause(Cell::default(), atom!(";"), terms);
|
||||||
let (stub, clauses) = self.fabricate_disjunct(term);
|
let (stub, clauses) = build_disjunct(term);
|
||||||
|
|
||||||
debug_assert!(clauses.len() > 0);
|
debug_assert!(clauses.len() > 0);
|
||||||
self.queue.push_back(clauses);
|
self.queue.push_back(clauses);
|
||||||
@@ -689,8 +837,8 @@ impl Preprocessor {
|
|||||||
|
|
||||||
Ok(clause_to_query_term(
|
Ok(clause_to_query_term(
|
||||||
loader,
|
loader,
|
||||||
name,
|
atom!("call"),
|
||||||
terms,
|
vec![Term::Clause(r, name, terms)],
|
||||||
self.settings.default_call_policy(),
|
self.settings.default_call_policy(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1254,6 +1254,18 @@ impl MachineState {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
|
if name != atom!("[]") {
|
||||||
|
Some(name)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -1270,6 +1282,19 @@ impl MachineState {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
|
match name {
|
||||||
|
atom!("eof_code") => EOFAction::EOFCode,
|
||||||
|
atom!("error") => EOFAction::Error,
|
||||||
|
atom!("reset") => EOFAction::Reset,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -1280,6 +1305,13 @@ impl MachineState {
|
|||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
name == atom!("true")
|
name == atom!("true")
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name == atom!("true")
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -1294,6 +1326,17 @@ impl MachineState {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
match name {
|
||||||
|
atom!("text") => StreamType::Text,
|
||||||
|
atom!("binary") => StreamType::Binary,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -1334,6 +1377,24 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
|
return match stream_aliases.get(&name) {
|
||||||
|
Some(stream) if !stream.is_null_stream() => Ok(*stream),
|
||||||
|
_ => {
|
||||||
|
let stub = functor_stub(caller, arity);
|
||||||
|
let addr = atom_as_cell!(name);
|
||||||
|
|
||||||
|
let existence_error = self.existence_error(ExistenceError::Stream(addr));
|
||||||
|
|
||||||
|
Err(self.error_form(existence_error, stub))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
(HeapCellValueTag::Cons, ptr) => {
|
(HeapCellValueTag::Cons, ptr) => {
|
||||||
match_untyped_arena_ptr!(ptr,
|
match_untyped_arena_ptr!(ptr,
|
||||||
(ArenaHeaderTag::Stream, stream) => {
|
(ArenaHeaderTag::Stream, stream) => {
|
||||||
@@ -1404,7 +1465,7 @@ impl MachineState {
|
|||||||
let stub = functor_stub(caller, arity);
|
let stub = functor_stub(caller, arity);
|
||||||
let err = self.permission_error(perm, err_atom, stream_as_cell!(stream));
|
let err = self.permission_error(perm, err_atom, stream_as_cell!(stream));
|
||||||
|
|
||||||
return self.error_form(err, stub);
|
self.error_form(err, stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1432,7 +1493,7 @@ impl MachineState {
|
|||||||
let stub = functor_stub(stub_name, stub_arity);
|
let stub = functor_stub(stub_name, stub_arity);
|
||||||
let err = self.permission_error(Permission::Open, atom!("source_sink"), culprit);
|
let err = self.permission_error(Permission::Open, atom!("source_sink"), culprit);
|
||||||
|
|
||||||
return self.error_form(err, stub);
|
self.error_form(err, stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn occupied_alias_permission_error(
|
pub(crate) fn occupied_alias_permission_error(
|
||||||
@@ -1442,24 +1503,22 @@ impl MachineState {
|
|||||||
stub_arity: usize,
|
stub_arity: usize,
|
||||||
) -> MachineStub {
|
) -> MachineStub {
|
||||||
let stub = functor_stub(stub_name, stub_arity);
|
let stub = functor_stub(stub_name, stub_arity);
|
||||||
let alias_name = atom!("alias");
|
|
||||||
|
|
||||||
let err = self.permission_error(
|
let err = self.permission_error(
|
||||||
Permission::Open,
|
Permission::Open,
|
||||||
atom!("source_sink"),
|
atom!("source_sink"),
|
||||||
functor!(alias_name, [atom(alias)]),
|
functor!(atom!("alias"), [atom(alias)]),
|
||||||
);
|
);
|
||||||
|
|
||||||
return self.error_form(err, stub);
|
self.error_form(err, stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn reposition_error(&mut self, stub_name: Atom, stub_arity: usize) -> MachineStub {
|
pub(crate) fn reposition_error(&mut self, stub_name: Atom, stub_arity: usize) -> MachineStub {
|
||||||
let stub = functor_stub(stub_name, stub_arity);
|
let stub = functor_stub(stub_name, stub_arity);
|
||||||
|
|
||||||
let rep_stub = functor!(atom!("reposition"), [atom(atom!("true"))]);
|
let rep_stub = functor!(atom!("reposition"), [atom(atom!("true"))]);
|
||||||
let err = self.permission_error(Permission::Open, atom!("source_sink"), rep_stub);
|
let err = self.permission_error(Permission::Open, atom!("source_sink"), rep_stub);
|
||||||
|
|
||||||
return self.error_form(err, stub);
|
self.error_form(err, stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_stream_properties(
|
pub(crate) fn check_stream_properties(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::heap_iter::*;
|
|||||||
use crate::heap_print::*;
|
use crate::heap_print::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine;
|
use crate::machine;
|
||||||
use crate::machine::{Machine, VERIFY_ATTR_INTERRUPT_LOC};
|
use crate::machine::{Machine, VERIFY_ATTR_INTERRUPT_LOC, get_structure_index};
|
||||||
use crate::machine::code_walker::*;
|
use crate::machine::code_walker::*;
|
||||||
use crate::machine::copier::*;
|
use crate::machine::copier::*;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
@@ -29,22 +29,27 @@ use crate::types::*;
|
|||||||
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
|
use fxhash::{FxBuildHasher, FxHasher};
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
use ref_thread_local::{RefThreadLocal, ref_thread_local};
|
use ref_thread_local::{RefThreadLocal, ref_thread_local};
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::hash::{BuildHasher, BuildHasherDefault};
|
||||||
use std::io::{ErrorKind, Read, Write};
|
use std::io::{ErrorKind, Read, Write};
|
||||||
use std::iter::{once, FromIterator};
|
use std::iter::{once, FromIterator};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::net::{TcpListener, TcpStream};
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use chrono::{offset::Local, DateTime};
|
use chrono::{offset::Local, DateTime};
|
||||||
use cpu_time::ProcessTime;
|
use cpu_time::ProcessTime;
|
||||||
@@ -173,6 +178,16 @@ impl BrentAlgState {
|
|||||||
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
return if name == atom!("[]") && arity == 0 {
|
||||||
|
CycleSearchResult::ProperList(self.num_steps())
|
||||||
|
} else {
|
||||||
|
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
||||||
|
};
|
||||||
|
}
|
||||||
(HeapCellValueTag::Lis, l) => {
|
(HeapCellValueTag::Lis, l) => {
|
||||||
return CycleSearchResult::UntouchedList(self.num_steps(), l);
|
return CycleSearchResult::UntouchedList(self.num_steps(), l);
|
||||||
}
|
}
|
||||||
@@ -439,6 +454,30 @@ impl BrentAlgState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn variable_set<S: BuildHasher>(
|
||||||
|
&mut self,
|
||||||
|
seen_set: &mut IndexSet<HeapCellValue, S>,
|
||||||
|
value: HeapCellValue,
|
||||||
|
) {
|
||||||
|
let mut iter = stackful_preorder_iter(&mut self.heap, value);
|
||||||
|
|
||||||
|
while let Some(value) = iter.next() {
|
||||||
|
let value = unmark_cell_bits!(value);
|
||||||
|
|
||||||
|
if value.is_var() {
|
||||||
|
let value = unmark_cell_bits!(heap_bound_store(
|
||||||
|
iter.heap,
|
||||||
|
heap_bound_deref(iter.heap, value)
|
||||||
|
));
|
||||||
|
|
||||||
|
if value.is_var() {
|
||||||
|
seen_set.insert(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn skip_max_list_cycle(&mut self, lam: usize) {
|
fn skip_max_list_cycle(&mut self, lam: usize) {
|
||||||
fn step(heap: &[HeapCellValue], mut value: HeapCellValue) -> usize {
|
fn step(heap: &[HeapCellValue], mut value: HeapCellValue) -> usize {
|
||||||
loop {
|
loop {
|
||||||
@@ -820,6 +859,16 @@ impl MachineState {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
Some(AtomOrString::Atom(name))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
Some(AtomOrString::String(c.to_string()))
|
Some(AtomOrString::String(c.to_string()))
|
||||||
}
|
}
|
||||||
@@ -924,6 +973,289 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn call_inline(
|
||||||
|
&mut self,
|
||||||
|
arity: usize,
|
||||||
|
call_at_index: impl Fn(&mut Machine, Atom, usize, IndexPtr) -> CallResult,
|
||||||
|
) -> CallResult {
|
||||||
|
let arity = arity - 1;
|
||||||
|
let goal = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
||||||
|
|
||||||
|
let load_registers = |machine_st: &mut MachineState, goal: HeapCellValue| -> Option<PredicateKey> {
|
||||||
|
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 {
|
||||||
|
for idx in (1 .. arity + 1).rev() {
|
||||||
|
machine_st.registers[idx + goal_arity] = machine_st.registers[idx + 1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for idx in 1 .. arity + 1 {
|
||||||
|
machine_st.registers[idx] = machine_st.registers[idx + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx in 1 .. goal_arity + 1 {
|
||||||
|
machine_st.registers[idx] = machine_st.heap[s+idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((name, goal_arity))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
read_heap_cell!(goal,
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let goal_arity = cell_as_atom_cell!(self.machine_st.heap[s]).get_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() || code_index.is_dynamic_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 => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn compile_inline_or_expanded_goal(&mut self) -> CallResult {
|
||||||
|
let goal = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
||||||
|
let module_name = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]));
|
||||||
|
|
||||||
|
// supp_vars are the supplementary variables generated by
|
||||||
|
// complete_partial_goal prior to goal_expansion.
|
||||||
|
let mut supp_vars = IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
|
|
||||||
|
self.machine_st.variable_set(&mut supp_vars, self.machine_st.registers[2]);
|
||||||
|
|
||||||
|
struct GoalAnalysisResult {
|
||||||
|
is_simple_goal: bool,
|
||||||
|
goal: HeapCellValue,
|
||||||
|
key: PredicateKey,
|
||||||
|
expanded_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
||||||
|
supp_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = read_heap_cell!(goal,
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
let mut expanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
|
|
||||||
|
// fill expanded_vars with variables of the partial
|
||||||
|
// goal pre-completion by complete_partial_goal.
|
||||||
|
for idx in s + 1 .. s + arity - supp_vars.len() + 1 {
|
||||||
|
self.machine_st.variable_set(&mut expanded_vars, self.machine_st.heap[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_simple_goal = if arity >= supp_vars.len() {
|
||||||
|
// post_supp_args are the arguments to the
|
||||||
|
// post-expansion complete goal gathered from the
|
||||||
|
// final supp_vars.len() arguments. they must
|
||||||
|
// agree in supp_vars in order of entry of
|
||||||
|
// insertion as well as the previous
|
||||||
|
// supp_vars.len() argument's variables being
|
||||||
|
// disjoint from them. if they are not, the
|
||||||
|
// expanded goal are not simple.
|
||||||
|
|
||||||
|
let post_supp_args = self.machine_st.heap[s+arity-supp_vars.len()+1 .. s+arity+1]
|
||||||
|
.iter()
|
||||||
|
.cloned();
|
||||||
|
|
||||||
|
post_supp_args
|
||||||
|
.zip(supp_vars.iter())
|
||||||
|
.all(|(arg_term, supp_var)| {
|
||||||
|
let arg_term = self.machine_st.store(self.machine_st.deref(arg_term));
|
||||||
|
|
||||||
|
if arg_term.is_var() && supp_var.is_var() {
|
||||||
|
return arg_term == *supp_var;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}) && expanded_vars.intersection(&supp_vars).next().is_none()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let goal = if is_simple_goal {
|
||||||
|
let h = self.machine_st.heap.len();
|
||||||
|
let arity = arity - supp_vars.len();
|
||||||
|
|
||||||
|
for idx in 0 .. arity + 1 {
|
||||||
|
let value = self.machine_st.heap[s + idx];
|
||||||
|
self.machine_st.heap.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.machine_st.heap[h] = atom_as_cell!(name, arity);
|
||||||
|
|
||||||
|
str_loc_as_cell!(h)
|
||||||
|
} else {
|
||||||
|
goal
|
||||||
|
};
|
||||||
|
|
||||||
|
GoalAnalysisResult {
|
||||||
|
is_simple_goal,
|
||||||
|
goal,
|
||||||
|
key: (name, arity),
|
||||||
|
expanded_vars,
|
||||||
|
supp_vars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
|
let h = self.machine_st.heap.len();
|
||||||
|
self.machine_st.heap.push(goal);
|
||||||
|
|
||||||
|
GoalAnalysisResult {
|
||||||
|
is_simple_goal: true,
|
||||||
|
goal: str_loc_as_cell!(h),
|
||||||
|
key: (name, 0),
|
||||||
|
expanded_vars: IndexSet::with_hasher(FxBuildHasher::default()),
|
||||||
|
supp_vars,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Char, c) => {
|
||||||
|
let name = self.machine_st.atom_tbl.build_with(&c.to_string());
|
||||||
|
|
||||||
|
let h = self.machine_st.heap.len();
|
||||||
|
self.machine_st.heap.push(atom_as_cell!(name));
|
||||||
|
|
||||||
|
GoalAnalysisResult {
|
||||||
|
is_simple_goal: true,
|
||||||
|
goal: str_loc_as_cell!(h),
|
||||||
|
key: (name, 0),
|
||||||
|
expanded_vars: IndexSet::with_hasher(FxBuildHasher::default()),
|
||||||
|
supp_vars,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if result.key.0 == atom!(":") {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let expanded_term = if result.is_simple_goal {
|
||||||
|
let idx = self.get_or_insert_qualified_code_index(module_name, result.key);
|
||||||
|
self.machine_st.heap.push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
|
||||||
|
result.goal
|
||||||
|
} else {
|
||||||
|
// all supp_vars must appear later!
|
||||||
|
let vars = IndexSet::<HeapCellValue, BuildHasherDefault<FxHasher>>::from_iter(
|
||||||
|
result.expanded_vars.difference(&result.supp_vars).cloned()
|
||||||
|
);
|
||||||
|
|
||||||
|
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()))))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let helper_clause_loc = self.code.len();
|
||||||
|
|
||||||
|
match self.compile_standalone_clause(temp_v!(1), &vars) {
|
||||||
|
Err(e) => {
|
||||||
|
let err = self.machine_st.session_error(e);
|
||||||
|
let stub = functor_stub(atom!("call"), result.key.1);
|
||||||
|
|
||||||
|
return Err(self.machine_st.error_form(err, stub));
|
||||||
|
}
|
||||||
|
Ok(()) => {
|
||||||
|
let h = self.machine_st.heap.len();
|
||||||
|
|
||||||
|
self.machine_st.heap.push(atom_as_cell!(atom!("$aux"), 0));
|
||||||
|
|
||||||
|
for value in result.expanded_vars.difference(&result.supp_vars).cloned() {
|
||||||
|
self.machine_st.heap.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let anon_str_arity = self.machine_st.heap.len() - h - 1;
|
||||||
|
|
||||||
|
self.machine_st.heap[h] = atom_as_cell!(atom!("$aux"), anon_str_arity);
|
||||||
|
|
||||||
|
let idx = CodeIndex::new(
|
||||||
|
IndexPtr::index(helper_clause_loc),
|
||||||
|
&mut self.machine_st.arena,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.machine_st.heap.push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
|
||||||
|
|
||||||
|
str_loc_as_cell!(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let truncated_goal = self.machine_st.registers[3];
|
||||||
|
unify!(&mut self.machine_st, expanded_term, truncated_goal);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn is_expanded_or_inlined(&mut self) {
|
||||||
|
let (_module_loc, qualified_goal) = self.machine_st.strip_module(
|
||||||
|
self.machine_st.registers[1],
|
||||||
|
empty_list_as_cell!(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if HeapCellValueTag::Str == qualified_goal.get_tag() {
|
||||||
|
let s = qualified_goal.get_value();
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if name == atom!("$call") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.machine_st.heap.len() > s + 1 + arity {
|
||||||
|
let idx_cell = self.machine_st.heap[s + 1 + arity];
|
||||||
|
|
||||||
|
if HeapCellValueTag::Cons == idx_cell.get_tag() {
|
||||||
|
match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell),
|
||||||
|
(ArenaHeaderTag::IndexPtr, _ip) => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn prepare_call_clause(&mut self, arity: usize) -> CallResult {
|
pub(crate) fn prepare_call_clause(&mut self, arity: usize) -> CallResult {
|
||||||
let (module_loc, qualified_goal) = self.machine_st.strip_module(
|
let (module_loc, qualified_goal) = self.machine_st.strip_module(
|
||||||
@@ -1391,6 +1723,19 @@ impl Machine {
|
|||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
|
unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
self.machine_st.unify_complete_string(
|
||||||
|
name,
|
||||||
|
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
if arity == 0 {
|
if arity == 0 {
|
||||||
self.machine_st.unify_complete_string(
|
self.machine_st.unify_complete_string(
|
||||||
@@ -1454,6 +1799,20 @@ impl Machine {
|
|||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
let iter = name.chars()
|
||||||
|
.map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
|
||||||
|
|
||||||
|
let h = iter_to_heap_list(&mut self.machine_st.heap, iter);
|
||||||
|
unify!(self.machine_st, heap_loc_as_cell!(h), self.machine_st.registers[2]);
|
||||||
|
} else {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
||||||
let stub_gen = || functor_stub(atom!("atom_codes"), 2);
|
let stub_gen = || functor_stub(atom!("atom_codes"), 2);
|
||||||
|
|
||||||
@@ -1482,6 +1841,17 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
||||||
|
|
||||||
let len: i64 = read_heap_cell!(a1,
|
let len: i64 = read_heap_cell!(a1,
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
name.chars().count() as i64
|
||||||
|
} else {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
if arity == 0 {
|
if arity == 0 {
|
||||||
name.chars().count() as i64
|
name.chars().count() as i64
|
||||||
@@ -2019,6 +2389,13 @@ impl Machine {
|
|||||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
name.as_char().unwrap()
|
name.as_char().unwrap()
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name.as_char().unwrap()
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
@@ -2080,6 +2457,13 @@ impl Machine {
|
|||||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
name.as_char().unwrap()
|
name.as_char().unwrap()
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name.as_char().unwrap()
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -3016,18 +3400,48 @@ impl Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
narity: usize,
|
narity: usize,
|
||||||
) -> Result<(Atom, PredicateKey), MachineStub> {
|
) -> Result<(Atom, PredicateKey), MachineStub> {
|
||||||
let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
|
let module_name = self.machine_st.store(self.machine_st.deref(
|
||||||
self.machine_st.registers[1 + narity]
|
self.machine_st.registers[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.machine_st.store(self.machine_st.deref(
|
let goal = self.machine_st.store(self.machine_st.deref(
|
||||||
self.machine_st.registers[2 + narity]
|
self.machine_st.registers[2]
|
||||||
));
|
));
|
||||||
|
|
||||||
let (name, arity, s) = self.machine_st.setup_call_n_init_goal_info(goal, narity)?;
|
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() {
|
for i in (arity + 1..arity + narity + 1).rev() {
|
||||||
self.machine_st.registers[i] = self.machine_st.registers[i - arity];
|
self.machine_st.registers[i] = self.machine_st.registers[i + 2 - arity];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ordering::Equal => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 1..arity + 1 {
|
for i in 1..arity + 1 {
|
||||||
@@ -3122,6 +3536,9 @@ impl Machine {
|
|||||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
cell_as_atom!(self.machine_st.heap[s])
|
||||||
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
self.machine_st.atom_tbl.build_with(&c.to_string())
|
self.machine_st.atom_tbl.build_with(&c.to_string())
|
||||||
}
|
}
|
||||||
@@ -3544,6 +3961,9 @@ impl Machine {
|
|||||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
cell_as_atom!(self.machine_st.heap[s])
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -3906,7 +4326,7 @@ impl Machine {
|
|||||||
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
.get_name_and_arity();
|
.get_name_and_arity();
|
||||||
|
|
||||||
let ct = ClauseType::from(name, arity);
|
let ct = ClauseType::from(name, arity, &mut self.machine_st.arena);
|
||||||
|
|
||||||
if ct.is_inlined() || ct.is_builtin() {
|
if ct.is_inlined() || ct.is_builtin() {
|
||||||
true
|
true
|
||||||
@@ -3917,10 +4337,10 @@ impl Machine {
|
|||||||
module_name,
|
module_name,
|
||||||
)
|
)
|
||||||
.map(|index| index.get())
|
.map(|index| index.get())
|
||||||
.unwrap_or(IndexPtr::DynamicUndefined);
|
.unwrap_or(IndexPtr::dynamic_undefined());
|
||||||
|
|
||||||
match index {
|
match index.tag() {
|
||||||
IndexPtr::DynamicUndefined | IndexPtr::Undefined => false,
|
IndexPtrTag::DynamicUndefined | IndexPtrTag::Undefined => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3928,7 +4348,7 @@ impl Machine {
|
|||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
let ct = ClauseType::from(name, 0);
|
let ct = ClauseType::from(name, 0, &mut self.machine_st.arena);
|
||||||
|
|
||||||
if ct.is_inlined() || ct.is_builtin() {
|
if ct.is_inlined() || ct.is_builtin() {
|
||||||
true
|
true
|
||||||
@@ -3939,10 +4359,10 @@ impl Machine {
|
|||||||
module_name,
|
module_name,
|
||||||
)
|
)
|
||||||
.map(|index| index.get())
|
.map(|index| index.get())
|
||||||
.unwrap_or(IndexPtr::DynamicUndefined);
|
.unwrap_or(IndexPtr::dynamic_undefined());
|
||||||
|
|
||||||
match index {
|
match index.tag() {
|
||||||
IndexPtr::DynamicUndefined => false,
|
IndexPtrTag::DynamicUndefined => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4208,7 +4628,9 @@ impl Machine {
|
|||||||
LOC_INIT.call_once(|| {
|
LOC_INIT.call_once(|| {
|
||||||
if let Some(builtins) = self.indices.modules.get(&atom!("builtins")) {
|
if let Some(builtins) = self.indices.modules.get(&atom!("builtins")) {
|
||||||
match builtins.code_dir.get(&(atom!("staggered_sc"), 2)).map(|cell| cell.get()) {
|
match builtins.code_dir.get(&(atom!("staggered_sc"), 2)).map(|cell| cell.get()) {
|
||||||
Some(IndexPtr::Index(p)) => {
|
Some(ip) if ip.tag() == IndexPtrTag::Index => {
|
||||||
|
let p = ip.p() as usize;
|
||||||
|
|
||||||
match &self.code[p] {
|
match &self.code[p] {
|
||||||
&Instruction::TryMeElse(o) => {
|
&Instruction::TryMeElse(o) => {
|
||||||
SEMICOLON_SECOND_BRANCH_LOC = p + o;
|
SEMICOLON_SECOND_BRANCH_LOC = p + o;
|
||||||
@@ -4253,30 +4675,40 @@ impl Machine {
|
|||||||
pub(crate) fn next_ep(&mut self) {
|
pub(crate) fn next_ep(&mut self) {
|
||||||
let first_arg = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
let first_arg = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
||||||
|
|
||||||
read_heap_cell!(first_arg,
|
let next_ep_atom = |machine_st: &mut MachineState, name, arity| {
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
|
||||||
debug_assert_eq!(name, atom!("first"));
|
debug_assert_eq!(name, atom!("first"));
|
||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
if self.machine_st.e == 0 {
|
if machine_st.e == 0 {
|
||||||
self.machine_st.fail = true;
|
machine_st.fail = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let and_frame = self.machine_st.stack.index_and_frame(self.machine_st.e);
|
let and_frame = machine_st.stack.index_and_frame(machine_st.e);
|
||||||
let cp = and_frame.prelude.cp - 1;
|
let cp = and_frame.prelude.cp - 1;
|
||||||
|
|
||||||
let e = and_frame.prelude.e;
|
let e = and_frame.prelude.e;
|
||||||
let e = Fixnum::build_with(i64::try_from(e).unwrap());
|
let e = Fixnum::build_with(i64::try_from(e).unwrap());
|
||||||
|
|
||||||
let p = str_loc_as_cell!(self.machine_st.heap.len());
|
let p = str_loc_as_cell!(machine_st.heap.len());
|
||||||
|
|
||||||
self.machine_st.heap.extend(functor!(atom!("dir_entry"), [fixnum(cp)]));
|
machine_st.heap.extend(functor!(atom!("dir_entry"), [fixnum(cp)]));
|
||||||
self.machine_st.unify_fixnum(e, self.machine_st.registers[2]);
|
machine_st.unify_fixnum(e, machine_st.registers[2]);
|
||||||
|
|
||||||
if !self.machine_st.fail {
|
if !machine_st.fail {
|
||||||
unify!(self.machine_st, p, self.machine_st.registers[3]);
|
unify!(machine_st, p, machine_st.registers[3]);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
read_heap_cell!(first_arg,
|
||||||
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
|
next_ep_atom(&mut self.machine_st, name, arity);
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
next_ep_atom(&mut self.machine_st, name, arity);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Fixnum, n) => {
|
(HeapCellValueTag::Fixnum, n) => {
|
||||||
let e = n.get_num() as usize;
|
let e = n.get_num() as usize;
|
||||||
@@ -4346,6 +4778,13 @@ impl Machine {
|
|||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
self.machine_st.fail = non_quoted_token(name.as_str().chars());
|
self.machine_st.fail = non_quoted_token(name.as_str().chars());
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
self.machine_st.fail = non_quoted_token(name.as_str().chars());
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
}
|
}
|
||||||
@@ -4480,6 +4919,13 @@ impl Machine {
|
|||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
debug_assert_eq!(arity, 0);
|
||||||
|
name
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.atom_tbl.build_with(&match Number::try_from(port) {
|
self.machine_st.atom_tbl.build_with(&match Number::try_from(port) {
|
||||||
Ok(Number::Fixnum(n)) => n.get_num().to_string(),
|
Ok(Number::Fixnum(n)) => n.get_num().to_string(),
|
||||||
@@ -5011,26 +5457,9 @@ impl Machine {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut seen_set = IndexSet::new();
|
let mut seen_set = IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
|
|
||||||
{
|
self.machine_st.variable_set(&mut seen_set, stored_v);
|
||||||
let mut iter = stackful_preorder_iter(&mut self.machine_st.heap, stored_v);
|
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
|
||||||
let value = unmark_cell_bits!(value);
|
|
||||||
|
|
||||||
if value.is_var() {
|
|
||||||
let value = unmark_cell_bits!(heap_bound_store(
|
|
||||||
iter.heap,
|
|
||||||
heap_bound_deref(iter.heap, value)
|
|
||||||
));
|
|
||||||
|
|
||||||
if value.is_var() {
|
|
||||||
seen_set.insert(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let outcome = heap_loc_as_cell!(
|
let outcome = heap_loc_as_cell!(
|
||||||
iter_to_heap_list(&mut self.machine_st.heap, seen_set.into_iter())
|
iter_to_heap_list(&mut self.machine_st.heap, seen_set.into_iter())
|
||||||
@@ -5271,9 +5700,15 @@ impl Machine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let result = printer.print().result();
|
let result = printer.print().result();
|
||||||
let chars = put_complete_string(&mut self.machine_st.heap, &result, &mut self.machine_st.atom_tbl);
|
let chars = put_complete_string(
|
||||||
|
&mut self.machine_st.heap,
|
||||||
|
&result,
|
||||||
|
&mut self.machine_st.atom_tbl,
|
||||||
|
);
|
||||||
|
|
||||||
let result_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
|
let result_addr = self.machine_st.store(self.machine_st.deref(
|
||||||
|
self.machine_st.registers[1]
|
||||||
|
));
|
||||||
|
|
||||||
if let Some(var) = result_addr.as_var() {
|
if let Some(var) = result_addr.as_var() {
|
||||||
self.machine_st.bind(var, chars);
|
self.machine_st.bind(var, chars);
|
||||||
|
|||||||
@@ -272,6 +272,12 @@ macro_rules! match_untyped_arena_ptr_pat_body {
|
|||||||
#[allow(unused_braces)]
|
#[allow(unused_braces)]
|
||||||
$code
|
$code
|
||||||
}};
|
}};
|
||||||
|
($ptr:ident, IndexPtr, $ip:ident, $code:expr) => {{
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut $ip = TypedArenaPtr::new(unsafe { std::mem::transmute::<_, *mut IndexPtr>($ptr.get_ptr()) });
|
||||||
|
#[allow(unused_braces)]
|
||||||
|
$code
|
||||||
|
}};
|
||||||
($ptr:ident, $($tags:tt)|+, $s:ident, $code:expr) => {{
|
($ptr:ident, $($tags:tt)|+, $s:ident, $code:expr) => {{
|
||||||
let $s = Stream::from_tag($ptr.get_tag(), $ptr.payload_offset());
|
let $s = Stream::from_tag($ptr.get_tag(), $ptr.payload_offset());
|
||||||
#[allow(unused_braces)]
|
#[allow(unused_braces)]
|
||||||
@@ -292,6 +298,12 @@ macro_rules! match_untyped_arena_ptr_pat {
|
|||||||
| ArenaHeaderTag::StandardOutputStream
|
| ArenaHeaderTag::StandardOutputStream
|
||||||
| ArenaHeaderTag::StandardErrorStream
|
| ArenaHeaderTag::StandardErrorStream
|
||||||
};
|
};
|
||||||
|
(IndexPtr) => {
|
||||||
|
ArenaHeaderTag::IndexPtrUndefined |
|
||||||
|
ArenaHeaderTag::IndexPtrDynamicUndefined |
|
||||||
|
ArenaHeaderTag::IndexPtrDynamicIndex |
|
||||||
|
ArenaHeaderTag::IndexPtrIndex
|
||||||
|
};
|
||||||
($tag:ident) => {
|
($tag:ident) => {
|
||||||
ArenaHeaderTag::$tag
|
ArenaHeaderTag::$tag
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
|
use crate::machine::machine_indices::*;
|
||||||
use crate::parser::char_reader::*;
|
use crate::parser::char_reader::*;
|
||||||
use crate::types::HeapCellValueTag;
|
use crate::types::HeapCellValueTag;
|
||||||
|
|
||||||
@@ -530,6 +531,7 @@ impl Neg for Fixnum {
|
|||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
Char(char),
|
Char(char),
|
||||||
|
CodeIndex(CodeIndex),
|
||||||
Fixnum(Fixnum),
|
Fixnum(Fixnum),
|
||||||
Integer(TypedArenaPtr<Integer>),
|
Integer(TypedArenaPtr<Integer>),
|
||||||
Rational(TypedArenaPtr<Rational>),
|
Rational(TypedArenaPtr<Rational>),
|
||||||
@@ -551,6 +553,7 @@ impl fmt::Display for Literal {
|
|||||||
write!(f, "{}", atom.flat_index())
|
write!(f, "{}", atom.flat_index())
|
||||||
}
|
}
|
||||||
Literal::Char(c) => write!(f, "'{}'", *c as u32),
|
Literal::Char(c) => write!(f, "'{}'", *c as u32),
|
||||||
|
Literal::CodeIndex(i) => write!(f, "{:x}", i.as_ptr() as u64),
|
||||||
Literal::Fixnum(n) => write!(f, "{}", n.get_num()),
|
Literal::Fixnum(n) => write!(f, "{}", n.get_num()),
|
||||||
Literal::Integer(ref n) => write!(f, "{}", n),
|
Literal::Integer(ref n) => write!(f, "{}", n),
|
||||||
Literal::Rational(ref n) => write!(f, "{}", n),
|
Literal::Rational(ref n) => write!(f, "{}", n),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use lexical::parse_lossy;
|
use lexical::parse_lossy;
|
||||||
|
|
||||||
|
use crate::arena::ArenaAllocated;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
pub use crate::machine::machine_state::*;
|
pub use crate::machine::machine_state::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ impl<'a, 'b> TermWriter<'a, 'b> {
|
|||||||
self.push_stub_addr();
|
self.push_stub_addr();
|
||||||
self.push_stub_addr();
|
self.push_stub_addr();
|
||||||
}
|
}
|
||||||
&TermRef::Clause(Level::Root, _, ref ct, subterms) => {
|
&TermRef::Clause(Level::Root, _, name, subterms) => {
|
||||||
if subterms.len() > MAX_ARITY {
|
if subterms.len() > MAX_ARITY {
|
||||||
return Err(CompilationError::ExceededMaxArity);
|
return Err(CompilationError::ExceededMaxArity);
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ impl<'a, 'b> TermWriter<'a, 'b> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.queue.push_back((subterms.len(), h + 2));
|
self.queue.push_back((subterms.len(), h + 2));
|
||||||
let named = atom_as_cell!(ct.name(), subterms.len());
|
let named = atom_as_cell!(name, subterms.len());
|
||||||
|
|
||||||
self.heap.push(named);
|
self.heap.push(named);
|
||||||
|
|
||||||
@@ -358,9 +358,9 @@ impl<'a, 'b> TermWriter<'a, 'b> {
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
&TermRef::Clause(_, _, ref ct, subterms) => {
|
&TermRef::Clause(_, _, name, subterms) => {
|
||||||
self.queue.push_back((subterms.len(), h + 1));
|
self.queue.push_back((subterms.len(), h + 1));
|
||||||
let named = atom_as_cell!(ct.name(), subterms.len());
|
let named = atom_as_cell!(name, subterms.len());
|
||||||
|
|
||||||
self.heap.push(named);
|
self.heap.push(named);
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ pub(crate) trait CompilationTarget<'a> {
|
|||||||
fn subterm_to_value(r: RegType) -> Instruction;
|
fn subterm_to_value(r: RegType) -> Instruction;
|
||||||
|
|
||||||
fn clause_arg_to_instr(r: RegType) -> Instruction;
|
fn clause_arg_to_instr(r: RegType) -> Instruction;
|
||||||
|
|
||||||
|
fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CompilationTarget<'a> for FactInstruction {
|
impl<'a> CompilationTarget<'a> for FactInstruction {
|
||||||
@@ -106,6 +108,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
|||||||
fn clause_arg_to_instr(val: RegType) -> Instruction {
|
fn clause_arg_to_instr(val: RegType) -> Instruction {
|
||||||
Instruction::UnifyVariable(val)
|
Instruction::UnifyVariable(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn trim_structure_by_last_arg(_instr: &mut Instruction, _last_arg: &Term) {
|
||||||
|
// a no-op for facts.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CompilationTarget<'a> for QueryInstruction {
|
impl<'a> CompilationTarget<'a> for QueryInstruction {
|
||||||
@@ -176,4 +182,21 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
|
|||||||
fn clause_arg_to_instr(val: RegType) -> Instruction {
|
fn clause_arg_to_instr(val: RegType) -> Instruction {
|
||||||
Instruction::SetValue(val)
|
Instruction::SetValue(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the final argument of the structure is a Literal::Index,
|
||||||
|
// decrement the arity of the PutStructure instruction by 1.
|
||||||
|
fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term) {
|
||||||
|
if let Instruction::PutStructure(_, ref mut arity, _) = instr {
|
||||||
|
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
|
||||||
|
// it is acceptable if arity == 0 is the result of
|
||||||
|
// this decrement. call/N will have to read the index
|
||||||
|
// constant for '$call_inline' to succeed. to find it,
|
||||||
|
// it must know the heap location of the index.
|
||||||
|
// self.store must stop before reading the atom into a
|
||||||
|
// register.
|
||||||
|
|
||||||
|
*arity -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ submit_query_and_print_results_(Term, VarList) :-
|
|||||||
'$get_b_value'(B),
|
'$get_b_value'(B),
|
||||||
bb_put('$report_all', false),
|
bb_put('$report_all', false),
|
||||||
bb_put('$report_n_more', 0),
|
bb_put('$report_n_more', 0),
|
||||||
'$call'(Term),
|
call(user:Term),
|
||||||
write_eqs_and_read_input(B, VarList),
|
write_eqs_and_read_input(B, VarList),
|
||||||
!.
|
!.
|
||||||
submit_query_and_print_results_(_, _) :-
|
submit_query_and_print_results_(_, _) :-
|
||||||
@@ -192,12 +192,12 @@ submit_query_and_print_results_(_, _) :-
|
|||||||
nl.
|
nl.
|
||||||
|
|
||||||
|
|
||||||
submit_query_and_print_results(Term0, VarList) :-
|
submit_query_and_print_results(Term, VarList) :-
|
||||||
( functor(Term0, call, _) ->
|
% ( functor(Term0, call, _) ->
|
||||||
Term = Term0 % prevent pre-mature expansion of incomplete goal
|
% Term = Term0 % prevent pre-mature expansion of incomplete goal
|
||||||
% in the first argument, which is done by call/N
|
% % in the first argument, which is done by call/N
|
||||||
; expand_goal(Term0, user, Term)
|
% ; expand_goal(Term0, user, Term)
|
||||||
),
|
% ),
|
||||||
bb_put('$answer_count', 0),
|
bb_put('$answer_count', 0),
|
||||||
submit_query_and_print_results_(Term, VarList).
|
submit_query_and_print_results_(Term, VarList).
|
||||||
|
|
||||||
@@ -301,6 +301,7 @@ write_eqs_and_read_input(B, VarList) :-
|
|||||||
append(Equations, AttrGoals, Goals),
|
append(Equations, AttrGoals, Goals),
|
||||||
% one layer of depth added for (=/2) functor
|
% one layer of depth added for (=/2) functor
|
||||||
maplist(\Term^Vs^term_variables_under_max_depth(Term, 22, Vs), Equations, EquationVars),
|
maplist(\Term^Vs^term_variables_under_max_depth(Term, 22, Vs), Equations, EquationVars),
|
||||||
|
% maplist(term_variables_under_max_depth(22), Equations, EquationVars),
|
||||||
append([AttrGoalVars | EquationVars], Vars1),
|
append([AttrGoalVars | EquationVars], Vars1),
|
||||||
term_variables(Vars1, Vars2), % deduplicate vars of Vars1 but preserve their order.
|
term_variables(Vars1, Vars2), % deduplicate vars of Vars1 but preserve their order.
|
||||||
charsio:extend_var_list(Vars2, VarList, NewVarList0, fabricated),
|
charsio:extend_var_list(Vars2, VarList, NewVarList0, fabricated),
|
||||||
|
|||||||
41
src/types.rs
41
src/types.rs
@@ -301,7 +301,7 @@ impl fmt::Debug for HeapCellValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<TypedArenaPtr<T>> for HeapCellValue {
|
impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(arena_ptr: TypedArenaPtr<T>) -> HeapCellValue {
|
fn from(arena_ptr: TypedArenaPtr<T>) -> HeapCellValue {
|
||||||
HeapCellValue::from(arena_ptr.header_ptr() as u64)
|
HeapCellValue::from(arena_ptr.header_ptr() as u64)
|
||||||
@@ -441,14 +441,16 @@ impl HeapCellValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_compound(self) -> bool {
|
pub fn is_compound(self, heap: &[HeapCellValue]) -> bool {
|
||||||
match self.get_tag() {
|
match self.get_tag() {
|
||||||
HeapCellValueTag::Str
|
HeapCellValueTag::Str => {
|
||||||
| HeapCellValueTag::Lis
|
cell_as_atom_cell!(heap[self.get_value()]).get_arity() > 0
|
||||||
| HeapCellValueTag::CStr
|
}
|
||||||
| HeapCellValueTag::PStr
|
HeapCellValueTag::Lis |
|
||||||
| HeapCellValueTag::PStrLoc
|
HeapCellValueTag::CStr |
|
||||||
| HeapCellValueTag::PStrOffset => {
|
HeapCellValueTag::PStr |
|
||||||
|
HeapCellValueTag::PStrLoc |
|
||||||
|
HeapCellValueTag::PStrOffset => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
HeapCellValueTag::Atom => {
|
HeapCellValueTag::Atom => {
|
||||||
@@ -582,7 +584,7 @@ impl HeapCellValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn order_category(self) -> Option<TermOrderCategory> {
|
pub fn order_category(self, heap: &[HeapCellValue]) -> Option<TermOrderCategory> {
|
||||||
match Number::try_from(self).ok() {
|
match Number::try_from(self).ok() {
|
||||||
Some(Number::Integer(_)) | Some(Number::Fixnum(_)) | Some(Number::Rational(_)) => {
|
Some(Number::Integer(_)) | Some(Number::Fixnum(_)) | Some(Number::Rational(_)) => {
|
||||||
Some(TermOrderCategory::Integer)
|
Some(TermOrderCategory::Integer)
|
||||||
@@ -601,9 +603,19 @@ impl HeapCellValue {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc |
|
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc |
|
||||||
HeapCellValueTag::CStr | HeapCellValueTag::Str => {
|
HeapCellValueTag::CStr => {
|
||||||
Some(TermOrderCategory::Compound)
|
Some(TermOrderCategory::Compound)
|
||||||
}
|
}
|
||||||
|
HeapCellValueTag::Str => {
|
||||||
|
let value = heap[self.get_value()];
|
||||||
|
let arity = cell_as_atom_cell!(value).get_arity();
|
||||||
|
|
||||||
|
if arity == 0 {
|
||||||
|
Some(TermOrderCategory::Atom)
|
||||||
|
} else {
|
||||||
|
Some(TermOrderCategory::Compound)
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -628,7 +640,7 @@ const_assert!(mem::size_of::<HeapCellValue>() == 8);
|
|||||||
|
|
||||||
#[bitfield]
|
#[bitfield]
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct UntypedArenaPtr {
|
pub struct UntypedArenaPtr {
|
||||||
ptr: B61,
|
ptr: B61,
|
||||||
m: bool,
|
m: bool,
|
||||||
@@ -644,6 +656,13 @@ impl From<*const ArenaHeader> for UntypedArenaPtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<*const IndexPtr> for UntypedArenaPtr {
|
||||||
|
#[inline]
|
||||||
|
fn from(ptr: *const IndexPtr) -> UntypedArenaPtr {
|
||||||
|
unsafe { mem::transmute(ptr) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<UntypedArenaPtr> for *const ArenaHeader {
|
impl From<UntypedArenaPtr> for *const ArenaHeader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(ptr: UntypedArenaPtr) -> *const ArenaHeader {
|
fn from(ptr: UntypedArenaPtr) -> *const ArenaHeader {
|
||||||
|
|||||||
Reference in New Issue
Block a user