Merge pull request #1980 from Skgland/atomtable

make AtomTable consurrency safe
This commit is contained in:
Mark Thom
2023-09-05 12:32:20 -06:00
committed by GitHub
57 changed files with 12089 additions and 9791 deletions

View File

@@ -20,7 +20,7 @@ jobs:
- { os: macos-11, rust-version: stable, shell: bash, target: 'x86_64-apple-darwin' } - { os: macos-11, rust-version: stable, shell: bash, target: 'x86_64-apple-darwin' }
- { os: ubuntu-20.04, rust-version: stable, shell: bash, extra: true, target: 'x86_64-unknown-linux-gnu' } - { os: ubuntu-20.04, rust-version: stable, shell: bash, extra: true, target: 'x86_64-unknown-linux-gnu' }
- { os: ubuntu-20.04, rust-version: stable, shell: bash, target: 'i686-unknown-linux-gnu' } - { os: ubuntu-20.04, rust-version: stable, shell: bash, target: 'i686-unknown-linux-gnu' }
- { os: ubuntu-20.04, rust-version: 1.65, shell: bash, target: 'x86_64-unknown-linux-gnu'} - { os: ubuntu-20.04, rust-version: "1.70", shell: bash, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-20.04, rust-version: beta, shell: bash, target: 'x86_64-unknown-linux-gnu'} - { os: ubuntu-20.04, rust-version: beta, shell: bash, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-20.04, rust-version: nightly, shell: bash, target: 'x86_64-unknown-linux-gnu'} - { os: ubuntu-20.04, rust-version: nightly, shell: bash, target: 'x86_64-unknown-linux-gnu'}
defaults: defaults:

View File

@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
keywords = ["prolog", "prolog-interpreter", "prolog-system"] keywords = ["prolog", "prolog-interpreter", "prolog-system"]
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
build = "build/main.rs" build = "build/main.rs"
rust-version = "1.63" rust-version = "1.70"
[features] [features]
default = ["ffi", "repl", "hostname", "tls", "http"] default = ["ffi", "repl", "hostname", "tls", "http"]
@@ -19,6 +19,7 @@ repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
hostname = ["dep:hostname"] hostname = ["dep:hostname"]
tls = ["dep:native-tls"] tls = ["dep:native-tls"]
http = ["dep:hyper", "dep:reqwest"] http = ["dep:hyper", "dep:reqwest"]
rust_beta_channel = []
[build-dependencies] [build-dependencies]
indexmap = "1.0.2" indexmap = "1.0.2"

View File

@@ -590,7 +590,10 @@ enum SystemClauseType {
UnattributedVar, UnattributedVar,
#[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))] #[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))]
GetDBRefs, GetDBRefs,
#[strum_discriminants(strum(props(Arity = "2", Name = "$keysort_with_constant_var_ordering")))] #[strum_discriminants(strum(props(
Arity = "2",
Name = "$keysort_with_constant_var_ordering"
)))]
KeySortWithConstantVarOrdering, KeySortWithConstantVarOrdering,
REPL(REPLCodePtr), REPL(REPLCodePtr),
} }
@@ -847,7 +850,8 @@ fn add_discriminant_data<DiscriminantT>(
prefix: &'static str, prefix: &'static str,
variant_data: &mut Vec<(&'static str, Arity, Variant)>, variant_data: &mut Vec<(&'static str, Arity, Variant)>,
) -> (&'static str, Arity) ) -> (&'static str, Arity)
where DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug where
DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug,
{ {
let name = prop_from_ident::<DiscriminantT>(&variant.ident, "Name"); let name = prop_from_ident::<DiscriminantT>(&variant.ident, "Name");
let arity = Arity::from(prop_from_ident::<DiscriminantT>(&variant.ident, "Arity")); let arity = Arity::from(prop_from_ident::<DiscriminantT>(&variant.ident, "Arity"));
@@ -2300,7 +2304,8 @@ pub fn generate_instructions_rs() -> TokenStream {
instr_data.generate_instruction_enum_loop(input); instr_data.generate_instruction_enum_loop(input);
let instr_variants: Vec<_> = instr_data.instr_variants let instr_variants: Vec<_> = instr_data
.instr_variants
.iter() .iter()
.cloned() .cloned()
.map(|(_, _, _, variant)| variant) .map(|(_, _, _, variant)| variant)
@@ -2339,7 +2344,8 @@ pub fn generate_instructions_rs() -> TokenStream {
for (name, arity, variant) in instr_data.compare_number_variants { for (name, arity, variant) in instr_data.compare_number_variants {
let ident = variant.ident.clone(); let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields let variant_fields: Vec<_> = variant
.fields
.into_iter() .into_iter()
.map(|field| { .map(|field| {
let ty = field.ty; let ty = field.ty;
@@ -2382,25 +2388,19 @@ pub fn generate_instructions_rs() -> TokenStream {
.map(|n| format_ident!("f_{}", n)) .map(|n| format_ident!("f_{}", n))
.collect(); .collect();
clause_type_to_instr_arms.push( clause_type_to_instr_arms.push(quote! {
quote! {
ClauseType::Inlined( ClauseType::Inlined(
InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*)) InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*))
) => Instruction::#instr_ident(#(*#placeholder_ids),*) ) => Instruction::#instr_ident(#(*#placeholder_ids),*)
} });
);
is_inbuilt_arms.push( is_inbuilt_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
is_inlined_arms.push( is_inlined_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
} }
for (name, arity, variant) in instr_data.compare_term_variants { for (name, arity, variant) in instr_data.compare_term_variants {
@@ -2412,36 +2412,31 @@ pub fn generate_instructions_rs() -> TokenStream {
) )
}); });
clause_type_name_arms.push( clause_type_name_arms.push(quote! {
quote! {
ClauseType::BuiltIn( ClauseType::BuiltIn(
BuiltInClauseType::CompareTerm(CompareTerm::#ident) BuiltInClauseType::CompareTerm(CompareTerm::#ident)
) => atom!(#name) ) => atom!(#name)
} });
);
let ident = variant.ident; let ident = variant.ident;
let instr_ident = format_ident!("Call{}", ident); let instr_ident = format_ident!("Call{}", ident);
clause_type_to_instr_arms.push( clause_type_to_instr_arms.push(quote! {
quote! {
ClauseType::BuiltIn( ClauseType::BuiltIn(
BuiltInClauseType::CompareTerm(CompareTerm::#ident) BuiltInClauseType::CompareTerm(CompareTerm::#ident)
) => Instruction::#instr_ident ) => Instruction::#instr_ident
} });
);
is_inbuilt_arms.push( is_inbuilt_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
} }
for (name, arity, variant) in instr_data.builtin_type_variants { for (name, arity, variant) in instr_data.builtin_type_variants {
let ident = variant.ident.clone(); let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields let variant_fields: Vec<_> = variant
.fields
.into_iter() .into_iter()
.map(|field| { .map(|field| {
let ty = field.ty; let ty = field.ty;
@@ -2498,17 +2493,16 @@ pub fn generate_instructions_rs() -> TokenStream {
} }
}); });
is_inbuilt_arms.push( is_inbuilt_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
} }
for (name, arity, variant) in instr_data.inlined_type_variants { for (name, arity, variant) in instr_data.inlined_type_variants {
let ident = variant.ident.clone(); let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields let variant_fields: Vec<_> = variant
.fields
.into_iter() .into_iter()
.map(|field| { .map(|field| {
if field.ty.type_id() == TypeId::of::<usize>() { if field.ty.type_id() == TypeId::of::<usize>() {
@@ -2555,31 +2549,26 @@ pub fn generate_instructions_rs() -> TokenStream {
.map(|n| format_ident!("f_{}", n)) .map(|n| format_ident!("f_{}", n))
.collect(); .collect();
clause_type_to_instr_arms.push( clause_type_to_instr_arms.push(quote! {
quote! {
ClauseType::Inlined( ClauseType::Inlined(
InlinedClauseType::#ident(#(#placeholder_ids),*) InlinedClauseType::#ident(#(#placeholder_ids),*)
) => Instruction::#instr_ident(*#(#placeholder_ids),*) ) => Instruction::#instr_ident(*#(#placeholder_ids),*)
} });
);
is_inbuilt_arms.push( is_inbuilt_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
is_inlined_arms.push( is_inlined_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
} }
for (name, arity, variant) in instr_data.system_clause_type_variants { for (name, arity, variant) in instr_data.system_clause_type_variants {
let ident = variant.ident.clone(); let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields let variant_fields: Vec<_> = variant
.fields
.into_iter() .into_iter()
.map(|field| { .map(|field| {
if field.ty == parse_quote! { usize } { if field.ty == parse_quote! { usize } {
@@ -2665,8 +2654,7 @@ pub fn generate_instructions_rs() -> TokenStream {
} }
}); });
is_inbuilt_arms.push( is_inbuilt_arms.push(if let Arity::Ident("arity") = &arity {
if let Arity::Ident("arity") = &arity {
quote! { quote! {
(atom!(#name), _arity) => true (atom!(#name), _arity) => true
} }
@@ -2674,14 +2662,14 @@ pub fn generate_instructions_rs() -> TokenStream {
quote! { quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} }
} });
);
} }
for (name, arity, variant) in instr_data.repl_code_ptr_variants { for (name, arity, variant) in instr_data.repl_code_ptr_variants {
let ident = variant.ident.clone(); let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields let variant_fields: Vec<_> = variant
.fields
.into_iter() .into_iter()
.map(|field| { .map(|field| {
if field.ty.type_id() == TypeId::of::<usize>() { if field.ty.type_id() == TypeId::of::<usize>() {
@@ -2742,11 +2730,9 @@ pub fn generate_instructions_rs() -> TokenStream {
} }
}); });
is_inbuilt_arms.push( is_inbuilt_arms.push(quote! {
quote! {
(atom!(#name), #arity) => true (atom!(#name), #arity) => true
} });
);
} }
for (name, arity, variant) in instr_data.clause_type_variants { for (name, arity, variant) in instr_data.clause_type_variants {
@@ -2768,7 +2754,8 @@ pub fn generate_instructions_rs() -> TokenStream {
continue; continue;
} }
let variant_fields: Vec<_> = variant.fields let variant_fields: Vec<_> = variant
.fields
.into_iter() .into_iter()
.map(|field| { .map(|field| {
if field.ty == parse_quote! { usize } { if field.ty == parse_quote! { usize } {
@@ -2817,14 +2804,13 @@ pub fn generate_instructions_rs() -> TokenStream {
} }
}); });
is_inbuilt_arms.push( is_inbuilt_arms.push(quote! {
quote! {
(atom!(#name), _arity) => true (atom!(#name), _arity) => true
} });
);
} }
let to_execute_arms: Vec<_> = instr_data.instr_variants let to_execute_arms: Vec<_> = instr_data
.instr_variants
.iter() .iter()
.cloned() .cloned()
.filter_map(|(_, _, _, variant)| { .filter_map(|(_, _, _, variant)| {
@@ -2837,9 +2823,8 @@ pub fn generate_instructions_rs() -> TokenStream {
0 0
}; };
let placeholder_ids: Vec<_> = (0 .. enum_arity) let placeholder_ids: Vec<_> =
.map(|n| format_ident!("f_{}", n)) (0..enum_arity).map(|n| format_ident!("f_{}", n)).collect();
.collect();
if variant_string.starts_with("Call") { if variant_string.starts_with("Call") {
let execute_ident = format_ident!("Execute{}", variant_string["Call".len()..]); let execute_ident = format_ident!("Execute{}", variant_string["Call".len()..]);
@@ -2876,7 +2861,8 @@ pub fn generate_instructions_rs() -> TokenStream {
}) })
.collect(); .collect();
let is_execute_arms: Vec<_> = instr_data.instr_variants let is_execute_arms: Vec<_> = instr_data
.instr_variants
.iter() .iter()
.cloned() .cloned()
.filter_map(|(_, _, _, variant)| { .filter_map(|(_, _, _, variant)| {
@@ -2919,7 +2905,8 @@ pub fn generate_instructions_rs() -> TokenStream {
}) })
.collect(); .collect();
let to_default_arms: Vec<_> = instr_data.instr_variants let to_default_arms: Vec<_> = instr_data
.instr_variants
.iter() .iter()
.cloned() .cloned()
.filter_map(|(_, _, countable_inference, variant)| { .filter_map(|(_, _, countable_inference, variant)| {
@@ -2936,9 +2923,8 @@ pub fn generate_instructions_rs() -> TokenStream {
0 0
}; };
let placeholder_ids: Vec<_> = (0 .. enum_arity) let placeholder_ids: Vec<_> =
.map(|n| format_ident!("f_{}", n)) (0..enum_arity).map(|n| format_ident!("f_{}", n)).collect();
.collect();
Some(if enum_arity == 0 { Some(if enum_arity == 0 {
quote! { quote! {
@@ -2957,7 +2943,8 @@ pub fn generate_instructions_rs() -> TokenStream {
}) })
.collect(); .collect();
let control_flow_arms: Vec<_> = instr_data.instr_variants let control_flow_arms: Vec<_> = instr_data
.instr_variants
.iter() .iter()
.cloned() .cloned()
.filter_map(|(_, _, _, variant)| { .filter_map(|(_, _, _, variant)| {
@@ -2985,7 +2972,8 @@ pub fn generate_instructions_rs() -> TokenStream {
}) })
.collect(); .collect();
let instr_macro_arms: Vec<_> = instr_data.instr_variants let instr_macro_arms: Vec<_> = instr_data
.instr_variants
.iter() .iter()
.rev() // produce default, execute & default & execute cases first. .rev() // produce default, execute & default & execute cases first.
.cloned() .cloned()
@@ -2994,7 +2982,7 @@ pub fn generate_instructions_rs() -> TokenStream {
let variant_string = variant.ident.to_string(); let variant_string = variant.ident.to_string();
let arity = match arity { let arity = match arity {
Arity::Static(arity) => arity, Arity::Static(arity) => arity,
_ => 1 _ => 1,
}; };
Some(if variant_string.starts_with("Execute") { Some(if variant_string.starts_with("Execute") {
@@ -3071,7 +3059,8 @@ pub fn generate_instructions_rs() -> TokenStream {
}) })
.collect(); .collect();
let name_and_arity_arms: Vec<_> = instr_data.instr_variants let name_and_arity_arms: Vec<_> = instr_data
.instr_variants
.into_iter() .into_iter()
.map(|(name, arity, _, variant)| { .map(|(name, arity, _, variant)| {
let ident = &variant.ident; let ident = &variant.ident;
@@ -3303,8 +3292,10 @@ pub fn generate_instructions_rs() -> TokenStream {
fn is_callable(id: &Ident) -> bool { fn is_callable(id: &Ident) -> bool {
let id = id.to_string(); let id = id.to_string();
id.starts_with("Call") || id.starts_with("Execute") || id.starts_with("DefaultCall") || id.starts_with("Call")
id.starts_with("DefaultExecute") || id.starts_with("Execute")
|| id.starts_with("DefaultCall")
|| id.starts_with("DefaultExecute")
} }
fn is_non_default_callable(id: &Ident) -> bool { fn is_non_default_callable(id: &Ident) -> bool {
@@ -3325,7 +3316,8 @@ fn create_instr_variant(id: Ident, mut variant: Variant) -> Variant {
} }
fn prop_from_ident<DiscriminantT>(id: &Ident, key: &'static str) -> &'static str fn prop_from_ident<DiscriminantT>(id: &Ident, key: &'static str) -> &'static str
where DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug where
DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug,
{ {
let disc = match DiscriminantT::from_str(id.to_string().as_str()) { let disc = match DiscriminantT::from_str(id.to_string().as_str()) {
Ok(disc) => disc, Ok(disc) => disc,
@@ -3345,7 +3337,7 @@ fn prop_from_ident<DiscriminantT>(id: &Ident, key: &'static str) -> &'static str
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum Arity { enum Arity {
Static(usize), Static(usize),
Ident(&'static str) Ident(&'static str),
} }
impl From<&'static str> for Arity { impl From<&'static str> for Arity {
@@ -3437,9 +3429,13 @@ impl InstructionData {
(name, arity, CountableInference::NotCounted) (name, arity, CountableInference::NotCounted)
} else if id == "InstructionTemplate" { } else if id == "InstructionTemplate" {
( prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Name"), (
Arity::from(prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Arity")), prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Name"),
CountableInference::NotCounted Arity::from(prop_from_ident::<InstructionTemplateDiscriminants>(
&variant.ident,
"Arity",
)),
CountableInference::NotCounted,
) )
} else if id == "ClauseType" { } else if id == "ClauseType" {
let (name, arity) = add_discriminant_data::<ClauseTypeDiscriminants>( let (name, arity) = add_discriminant_data::<ClauseTypeDiscriminants>(
@@ -3461,14 +3457,11 @@ impl InstructionData {
variant.ident.clone() variant.ident.clone()
}; };
let generated_variant = create_instr_variant( let generated_variant =
format_ident!("{}{}", prefix, v_ident), create_instr_variant(format_ident!("{}{}", prefix, v_ident), variant.clone());
variant.clone(),
);
self.instr_variants.push( self.instr_variants
(name, arity, countable_inference, generated_variant) .push((name, arity, countable_inference, generated_variant));
);
} }
fn generate_instruction_enum_loop(&mut self, input: syn::DeriveInput) { fn generate_instruction_enum_loop(&mut self, input: syn::DeriveInput) {
@@ -3490,10 +3483,10 @@ impl InstructionData {
self.label_variant(&input.ident, "Call", variant.clone()); self.label_variant(&input.ident, "Call", variant.clone());
self.label_variant(&input.ident, "Execute", variant.clone()); self.label_variant(&input.ident, "Execute", variant.clone());
if input.ident == "BuiltInClauseType" || if input.ident == "BuiltInClauseType"
input.ident == "CompareNumber" || || input.ident == "CompareNumber"
input.ident == "CompareTerm" || || input.ident == "CompareTerm"
input.ident == "ClauseType" || input.ident == "ClauseType"
{ {
self.label_variant(&input.ident, "DefaultCall", variant.clone()); self.label_variant(&input.ident, "DefaultCall", variant.clone());
self.label_variant(&input.ident, "DefaultExecute", variant); self.label_variant(&input.ident, "DefaultExecute", variant);

View File

@@ -1,7 +1,7 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use syn::*;
use syn::parse::*; use syn::parse::*;
use syn::visit::*; use syn::visit::*;
use syn::*;
use indexmap::IndexSet; use indexmap::IndexSet;
@@ -11,7 +11,9 @@ struct StaticStrVisitor {
impl StaticStrVisitor { impl StaticStrVisitor {
fn new() -> Self { fn new() -> Self {
Self { static_strs: IndexSet::new() } Self {
static_strs: IndexSet::new(),
}
} }
} }

491
flamegraph.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 4.8 MiB

View File

@@ -4,12 +4,16 @@ use crate::machine::loader::LiveLoadState;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::raw_block::*; use crate::raw_block::*;
use crate::rcu::Rcu;
use crate::rcu::RcuRef;
use crate::read::*; use crate::read::*;
use ordered_float::OrderedFloat;
use crate::parser::dashu::{Integer, Rational}; use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat;
use tokio::sync::RwLock;
use std::alloc; use std::alloc;
use std::cell::UnsafeCell;
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::mem; use std::mem;
@@ -22,7 +26,9 @@ 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 { ArenaAllocated::alloc($arena, result) } unsafe {
ArenaAllocated::alloc($arena, result)
}
}}; }};
} }
@@ -31,23 +37,35 @@ macro_rules! float_alloc {
($e:expr, $arena:expr) => {{ ($e:expr, $arena:expr) => {{
let result = $e; let result = $e;
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
unsafe { $arena.f64_tbl.build_with(result) } unsafe {
$arena.f64_tbl.build_with(result).as_ptr()
}
}}; }};
} }
#[cfg(test)] use std::sync::Arc;
use std::cell::RefCell; use std::sync::Mutex;
use std::sync::Weak;
const F64_TABLE_INIT_SIZE: usize = 1 << 16; const F64_TABLE_INIT_SIZE: usize = 1 << 16;
const F64_TABLE_ALIGN: usize = 8; const F64_TABLE_ALIGN: usize = 8;
#[cfg(test)] #[inline(always)]
thread_local! { fn global_f64table() -> &'static RwLock<Weak<F64Table>> {
static F64_TABLE_BUF_BASE: RefCell<*const u8> = RefCell::new(ptr::null_mut()); #[cfg(feature = "rust_beta_channel")]
{
// const Weak::new will be stabilized in 1.73 which is currently in beta,
// till then we need a OnceLock for initialization
static GLOBAL_ATOM_TABLE: RwLock<Weak<F64Table>> = RwLock::const_new(Weak::new());
&GLOBAL_ATOM_TABLE
}
#[cfg(not(feature = "rust_beta_channel"))]
{
use std::sync::OnceLock;
static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<F64Table>>> = OnceLock::new();
GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
}
} }
#[cfg(not(test))]
static mut F64_TABLE_BUF_BASE: *const u8 = ptr::null_mut();
impl RawBlockTraits for F64Table { impl RawBlockTraits for F64Table {
#[inline] #[inline]
@@ -63,69 +81,86 @@ impl RawBlockTraits for F64Table {
#[derive(Debug)] #[derive(Debug)]
pub struct F64Table { pub struct F64Table {
block: RawBlock<F64Table>, block: Rcu<RawBlock<F64Table>>,
} update: Mutex<()>,
impl Drop for F64Table {
fn drop(&mut self) {
self.block.deallocate();
}
}
#[cfg(test)]
fn set_f64_tbl_buf_base(ptr: *const u8) {
F64_TABLE_BUF_BASE.with(|f64_table_buf_base| {
*f64_table_buf_base.borrow_mut() = ptr;
});
}
#[cfg(test)]
pub(crate) fn get_f64_tbl_buf_base() -> *const u8 {
F64_TABLE_BUF_BASE.with(|f64_table_buf_base| *f64_table_buf_base.borrow())
}
#[cfg(not(test))]
fn set_f64_tbl_buf_base(ptr: *const u8) {
unsafe {
F64_TABLE_BUF_BASE = ptr;
}
}
#[cfg(not(test))]
pub(crate) fn get_f64_tbl_buf_base() -> *const u8 {
unsafe { F64_TABLE_BUF_BASE }
} }
#[inline(always)] #[inline(always)]
pub fn lookup_float(offset: usize) -> *mut OrderedFloat<f64> { pub fn lookup_float(
let base = get_f64_tbl_buf_base() as usize; offset: F64Offset,
(base + offset) as *mut _ ) -> RcuRef<RawBlock<F64Table>, UnsafeCell<OrderedFloat<f64>>> {
let f64table = global_f64table()
.blocking_read()
.upgrade()
.expect("We should only be looking up floats while there is a float table");
RcuRef::try_map(f64table.block.active_epoch(), |raw_block| unsafe {
raw_block
.base
.offset(offset.0 as isize)
.cast_mut()
.cast::<UnsafeCell<OrderedFloat<f64>>>()
.as_ref()
})
.expect("The offset should result in a non-null pointer")
} }
impl F64Table { impl F64Table {
#[inline] #[inline]
pub fn new() -> Self { pub fn new() -> Arc<Self> {
let table = Self { block: RawBlock::new() }; let upgraded = global_f64table().blocking_read().upgrade();
set_f64_tbl_buf_base(table.block.base); // don't inline upgraded, otherwise temporary will be dropped too late in case of None
table if let Some(atom_table) = upgraded {
atom_table
} else {
let mut guard = global_f64table().blocking_write();
// try to upgrade again in case we lost the race on the write lock
if let Some(atom_table) = guard.upgrade() {
atom_table
} else {
let atom_table = Arc::new(Self {
block: Rcu::new(RawBlock::new()),
update: Mutex::new(()),
});
*guard = Arc::downgrade(&atom_table);
atom_table
}
}
} }
pub unsafe fn build_with(&mut self, value: f64) -> F64Ptr { pub unsafe fn build_with(&self, value: f64) -> F64Offset {
let update_guard = self.update.lock();
// we don't have an index table for lookups as AtomTable does so
// just get the epoch after we take the upgrade lock
let mut block_epoch = self.block.active_epoch();
let mut ptr; let mut ptr;
loop { loop {
ptr = self.block.alloc(mem::size_of::<f64>()); ptr = block_epoch.alloc(mem::size_of::<f64>());
if ptr.is_null() { if ptr.is_null() {
self.block.grow(); let new_block = block_epoch.grow_new().unwrap();
set_f64_tbl_buf_base(self.block.base); self.block.replace(new_block);
block_epoch = self.block.active_epoch();
} else { } else {
break; break;
} }
} }
ptr::write(ptr as *mut OrderedFloat<f64>, OrderedFloat(value)); ptr::write(ptr as *mut OrderedFloat<f64>, OrderedFloat(value));
F64Ptr(ptr::NonNull::new_unchecked(ptr as *mut _))
let float = F64Offset {
0: ptr as usize - block_epoch.base as usize,
};
// atometable would have to update the index table at this point
// expicit drop to ensure we don't accidentally drop it early
drop(update_guard);
float
} }
} }
@@ -276,7 +311,9 @@ impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
#[inline] #[inline]
pub fn set_tag(&mut self, tag: ArenaHeaderTag) { pub fn set_tag(&mut self, tag: ArenaHeaderTag) {
unsafe { (*self.header_ptr_mut()).set_tag(tag); } unsafe {
(*self.header_ptr_mut()).set_tag(tag);
}
} }
#[inline] #[inline]
@@ -334,12 +371,18 @@ pub trait ArenaAllocated: Sized {
} }
} }
#[derive(Copy, Clone, Debug)] #[derive(Debug)]
pub struct F64Ptr(pub ptr::NonNull<OrderedFloat<f64>>); pub struct F64Ptr(RcuRef<RawBlock<F64Table>, UnsafeCell<OrderedFloat<f64>>>);
impl Clone for F64Ptr {
fn clone(&self) -> Self {
Self(RcuRef::clone(&self.0))
}
}
impl PartialEq for F64Ptr { impl PartialEq for F64Ptr {
fn eq(&self, other: &F64Ptr) -> bool { fn eq(&self, other: &F64Ptr) -> bool {
self.0 == other.0 || &**self == &**other RcuRef::ptr_eq(&self.0, &other.0) || self.deref() == other.deref()
} }
} }
@@ -375,28 +418,26 @@ impl Deref for F64Ptr {
#[inline] #[inline]
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
unsafe { &*self.0.as_ptr() } unsafe { &*self.0.get().as_ref().unwrap() }
} }
} }
impl DerefMut for F64Ptr { impl DerefMut for F64Ptr {
#[inline] #[inline]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.0.as_ptr() } unsafe { &mut *self.0.get().as_mut().unwrap() }
} }
} }
impl F64Ptr { impl F64Ptr {
#[inline(always)] #[inline(always)]
pub fn from_offset(offset: usize) -> Self { pub fn from_offset(offset: F64Offset) -> Self {
unsafe { Self(lookup_float(offset))
F64Ptr(ptr::NonNull::new_unchecked(lookup_float(offset)))
}
} }
#[inline(always)] #[inline(always)]
pub fn as_offset(&self) -> F64Offset { pub fn as_offset(&self) -> F64Offset {
F64Offset(self.0.as_ptr() as usize - get_f64_tbl_buf_base() as usize) F64Offset(self.0.get() as usize - RcuRef::get_root(&self.0).base as usize)
} }
} }
@@ -416,7 +457,7 @@ impl F64Offset {
#[inline(always)] #[inline(always)]
pub fn as_ptr(self) -> F64Ptr { pub fn as_ptr(self) -> F64Ptr {
F64Ptr::from_offset(self.0) F64Ptr::from_offset(self)
} }
#[inline(always)] #[inline(always)]
@@ -672,7 +713,7 @@ struct AllocSlab {
#[derive(Debug)] #[derive(Debug)]
pub struct Arena { pub struct Arena {
base: *mut AllocSlab, base: *mut AllocSlab,
pub f64_tbl: F64Table, pub f64_tbl: Arc<F64Table>,
} }
unsafe impl Send for Arena {} unsafe impl Send for Arena {}
@@ -681,7 +722,10 @@ unsafe impl Sync for Arena {}
impl Arena { impl Arena {
#[inline] #[inline]
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(),
}
} }
} }
@@ -731,8 +775,7 @@ unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => { ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
ptr::drop_in_place(value.payload_offset::<LiveLoadState>()); ptr::drop_in_place(value.payload_offset::<LiveLoadState>());
} }
ArenaHeaderTag::Dropped => { ArenaHeaderTag::Dropped => {}
}
ArenaHeaderTag::TcpListener => { ArenaHeaderTag::TcpListener => {
ptr::drop_in_place(value.payload_offset::<TcpListener>()); ptr::drop_in_place(value.payload_offset::<TcpListener>());
} }
@@ -750,10 +793,11 @@ 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::IndexPtrUndefined | ArenaHeaderTag::NullStream
ArenaHeaderTag::IndexPtrDynamicUndefined | ArenaHeaderTag::IndexPtrDynamicIndex | | ArenaHeaderTag::IndexPtrUndefined
ArenaHeaderTag::IndexPtrIndex => { | ArenaHeaderTag::IndexPtrDynamicUndefined
} | ArenaHeaderTag::IndexPtrDynamicIndex
| ArenaHeaderTag::IndexPtrIndex => {}
} }
} }
@@ -801,23 +845,25 @@ const_assert!(mem::size_of::<OrderedFloat<f64>>() == 8);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::ops::Deref;
use crate::machine::mock_wam::*; use crate::machine::mock_wam::*;
use crate::machine::partial_string::*; use crate::machine::partial_string::*;
use ordered_float::OrderedFloat;
use crate::parser::dashu::{Integer, Rational}; use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat;
#[test] #[test]
fn float_ptr_cast() { fn float_ptr_cast() {
let mut wam = MockWAM::new(); let wam = MockWAM::new();
let f = 0f64; let f = 0f64;
let fp = float_alloc!(f, wam.machine_st.arena); let fp = float_alloc!(f, wam.machine_st.arena);
let mut cell = HeapCellValue::from(fp); let mut cell = HeapCellValue::from(fp.clone());
assert_eq!(cell.get_tag(), HeapCellValueTag::F64); assert_eq!(cell.get_tag(), HeapCellValueTag::F64);
assert_eq!(cell.get_mark_bit(), false); assert_eq!(cell.get_mark_bit(), false);
assert_eq!(*fp, OrderedFloat(f)); assert_eq!(fp.deref(), &OrderedFloat(f));
cell.set_mark_bit(true); cell.set_mark_bit(true);
@@ -847,7 +893,10 @@ mod tests {
match const_value.to_untyped_arena_ptr() { match const_value.to_untyped_arena_ptr() {
Some(arena_ptr) => { Some(arena_ptr) => {
assert_eq!(arena_ptr.into_bytes(), const_value.to_untyped_arena_ptr_bytes()); assert_eq!(
arena_ptr.into_bytes(),
const_value.to_untyped_arena_ptr_bytes()
);
} }
None => { None => {
assert!(false); assert!(false);
@@ -860,7 +909,10 @@ mod tests {
match stream_cell.to_untyped_arena_ptr() { match stream_cell.to_untyped_arena_ptr() {
Some(arena_ptr) => { Some(arena_ptr) => {
assert_eq!(arena_ptr.into_bytes(), stream_cell.to_untyped_arena_ptr_bytes()); assert_eq!(
arena_ptr.into_bytes(),
stream_cell.to_untyped_arena_ptr_bytes()
);
} }
None => { None => {
assert!(false); assert!(false);
@@ -875,8 +927,7 @@ 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> = let big_int_ptr: TypedArenaPtr<Integer> = arena_alloc!(big_int, &mut wam.machine_st.arena);
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());
@@ -951,8 +1002,8 @@ mod tests {
let f_atom = atom!("f"); let f_atom = atom!("f");
let g_atom = atom!("g"); let g_atom = atom!("g");
assert_eq!(f_atom.as_str(), "f"); assert_eq!(&*f_atom.as_str(), "f");
assert_eq!(g_atom.as_str(), "g"); assert_eq!(&*g_atom.as_str(), "g");
let f_atom_cell = atom_as_cell!(f_atom); let f_atom_cell = atom_as_cell!(f_atom);
let g_atom_cell = atom_as_cell!(g_atom); let g_atom_cell = atom_as_cell!(g_atom);
@@ -962,7 +1013,7 @@ mod tests {
match f_atom_cell.to_atom() { match f_atom_cell.to_atom() {
Some(atom) => { Some(atom) => {
assert_eq!(f_atom, atom); assert_eq!(f_atom, atom);
assert_eq!(atom.as_str(), "f"); assert_eq!(&*atom.as_str(), "f");
} }
None => { None => {
assert!(false); assert!(false);
@@ -973,7 +1024,7 @@ mod tests {
(HeapCellValueTag::Atom, (atom, arity)) => { (HeapCellValueTag::Atom, (atom, arity)) => {
assert_eq!(f_atom, atom); assert_eq!(f_atom, atom);
assert_eq!(arity, 0); assert_eq!(arity, 0);
assert_eq!(atom.as_str(), "f"); assert_eq!(&*atom.as_str(), "f");
} }
_ => { unreachable!() } _ => { unreachable!() }
); );
@@ -982,21 +1033,22 @@ mod tests {
(HeapCellValueTag::Atom, (atom, arity)) => { (HeapCellValueTag::Atom, (atom, arity)) => {
assert_eq!(g_atom, atom); assert_eq!(g_atom, atom);
assert_eq!(arity, 0); assert_eq!(arity, 0);
assert_eq!(atom.as_str(), "g"); assert_eq!(&*atom.as_str(), "g");
} }
_ => { unreachable!() } _ => { unreachable!() }
); );
// complete string // complete string
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "ronan", &mut wam.machine_st.atom_tbl); let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "ronan", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr); assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr);
match pstr_cell.to_pstr() { match pstr_cell.to_pstr() {
Some(pstr) => { Some(pstr) => {
assert_eq!(pstr.as_str_from(0), "ronan"); assert_eq!(&*pstr.as_str_from(0), "ronan");
} }
None => { None => {
assert!(false); assert!(false);
@@ -1006,7 +1058,7 @@ mod tests {
read_heap_cell!(pstr_cell, read_heap_cell!(pstr_cell,
(HeapCellValueTag::PStr, pstr_atom) => { (HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom); let pstr = PartialString::from(pstr_atom);
assert_eq!(pstr.as_str_from(0), "ronan"); assert_eq!(&*pstr.as_str_from(0), "ronan");
} }
_ => { unreachable!() } _ => { unreachable!() }
); );
@@ -1115,7 +1167,7 @@ mod tests {
read_heap_cell!(cell, read_heap_cell!(cell,
(HeapCellValueTag::Atom, (el, _arity)) => { (HeapCellValueTag::Atom, (el, _arity)) => {
assert_eq!(el.flat_index(), empty_list_as_cell!().get_value()); assert_eq!(el.flat_index(), empty_list_as_cell!().get_value());
assert_eq!(el.as_str(), "[]"); assert_eq!(&*el.as_str(), "[]");
} }
_ => { unreachable!() } _ => { unreachable!() }
); );

View File

@@ -158,13 +158,13 @@ fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: &Literal) -> Result<(), Ari
Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))), Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))),
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))), Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))),
Literal::Atom(name) if name == &atom!("e") => interm.push(ArithmeticTerm::Number( Literal::Atom(name) if name == &atom!("e") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::E)) Number::Float(OrderedFloat(std::f64::consts::E)),
)), )),
Literal::Atom(name) if name == &atom!("pi") => interm.push(ArithmeticTerm::Number( Literal::Atom(name) if name == &atom!("pi") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::PI)) Number::Float(OrderedFloat(std::f64::consts::PI)),
)), )),
Literal::Atom(name) if name == &atom!("epsilon") => interm.push(ArithmeticTerm::Number( Literal::Atom(name) if name == &atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::EPSILON)) Number::Float(OrderedFloat(std::f64::EPSILON)),
)), )),
_ => return Err(ArithmeticError::NonEvaluableFunctor(*c, 0)), _ => return Err(ArithmeticError::NonEvaluableFunctor(*c, 0)),
} }
@@ -326,23 +326,14 @@ impl<'a> ArithmeticEvaluator<'a> {
let var_num = name.to_var_num().unwrap(); let var_num = name.to_var_num().unwrap();
let r = if lvl == Level::Shallow { let r = if lvl == Level::Shallow {
self.marker.mark_non_callable( self.marker
var_num, .mark_non_callable(var_num, arg, term_loc, cell, &mut code)
arg,
term_loc,
cell,
&mut code,
)
} else if term_loc.is_last() || cell.get().norm().reg_num() == 0 { } else if term_loc.is_last() || cell.get().norm().reg_num() == 0 {
let r = self.marker.get_binding(var_num); let r = self.marker.get_binding(var_num);
if r.reg_num() == 0 { if r.reg_num() == 0 {
self.marker.mark_var::<QueryInstruction>( self.marker.mark_var::<QueryInstruction>(
var_num, var_num, lvl, cell, term_loc, &mut code,
lvl,
cell,
term_loc,
&mut code,
); );
cell.get().norm() cell.get().norm()
} else { } else {
@@ -434,7 +425,7 @@ fn classify_float(f: f64) -> Result<f64, EvalError> {
} }
} }
FpCategory::Nan => Err(EvalError::Undefined), FpCategory::Nan => Err(EvalError::Undefined),
_ => Ok(f) _ => Ok(f),
} }
} }
@@ -549,8 +540,12 @@ impl PartialEq for Number {
(&Number::Fixnum(n1), &Number::Float(n2)) => OrderedFloat(n1.get_num() as f64).eq(&n2), (&Number::Fixnum(n1), &Number::Float(n2)) => OrderedFloat(n1.get_num() as f64).eq(&n2),
(&Number::Float(n1), &Number::Fixnum(n2)) => n1.eq(&OrderedFloat(n2.get_num() as f64)), (&Number::Float(n1), &Number::Fixnum(n2)) => n1.eq(&OrderedFloat(n2.get_num() as f64)),
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.eq(n2), (&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.eq(n2),
(&Number::Integer(ref n1), Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).eq(n2), (&Number::Integer(ref n1), Number::Float(n2)) => {
(&Number::Float(n1), &Number::Integer(ref n2)) => n1.eq(&OrderedFloat(n2.to_f64().value())), OrderedFloat(n1.to_f64().value()).eq(n2)
}
(&Number::Float(n1), &Number::Integer(ref n2)) => {
n1.eq(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Integer(ref n1), &Number::Rational(ref n2)) => { (&Number::Integer(ref n1), &Number::Rational(ref n2)) => {
#[cfg(feature = "num")] #[cfg(feature = "num")]
{ {
@@ -571,8 +566,12 @@ impl PartialEq for Number {
&**n1 == &**n2 &**n1 == &**n2
} }
} }
(&Number::Rational(ref n1), &Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).eq(&n2), (&Number::Rational(ref n1), &Number::Float(n2)) => {
(&Number::Float(n1), &Number::Rational(ref n2)) => n1.eq(&OrderedFloat(n2.to_f64().value())), OrderedFloat(n1.to_f64().value()).eq(&n2)
}
(&Number::Float(n1), &Number::Rational(ref n2)) => {
n1.eq(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Float(f1), &Number::Float(f2)) => f1.eq(&f2), (&Number::Float(f1), &Number::Float(f2)) => f1.eq(&f2),
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.eq(&r2), (&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.eq(&r2),
} }
@@ -641,7 +640,9 @@ impl Ord for Number {
(&Number::Float(n1), &Number::Fixnum(n2)) => n1.cmp(&OrderedFloat(n2.get_num() as f64)), (&Number::Float(n1), &Number::Fixnum(n2)) => n1.cmp(&OrderedFloat(n2.get_num() as f64)),
(&Number::Integer(n1), &Number::Integer(n2)) => (*n1).cmp(&*n2), (&Number::Integer(n1), &Number::Integer(n2)) => (*n1).cmp(&*n2),
(&Number::Integer(n1), Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).cmp(n2), (&Number::Integer(n1), Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).cmp(n2),
(&Number::Float(n1), &Number::Integer(ref n2)) => n1.cmp(&OrderedFloat(n2.to_f64().value())), (&Number::Float(n1), &Number::Integer(ref n2)) => {
n1.cmp(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Integer(n1), &Number::Rational(n2)) => { (&Number::Integer(n1), &Number::Rational(n2)) => {
#[cfg(feature = "num")] #[cfg(feature = "num")]
{ {
@@ -662,8 +663,12 @@ impl Ord for Number {
(&*n1).partial_cmp(&*n2).unwrap_or(Ordering::Less) (&*n1).partial_cmp(&*n2).unwrap_or(Ordering::Less)
} }
} }
(&Number::Rational(n1), &Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).cmp(&n2), (&Number::Rational(n1), &Number::Float(n2)) => {
(&Number::Float(n1), &Number::Rational(n2)) => n1.cmp(&OrderedFloat(n2.to_f64().value())), OrderedFloat(n1.to_f64().value()).cmp(&n2)
}
(&Number::Float(n1), &Number::Rational(n2)) => {
n1.cmp(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Float(f1), &Number::Float(f2)) => f1.cmp(&f2), (&Number::Float(f1), &Number::Float(f2)) => f1.cmp(&f2),
(&Number::Rational(r1), &Number::Rational(r2)) => (*r1).cmp(&*r2), (&Number::Rational(r1), &Number::Rational(r2)) => (*r1).cmp(&*r2),
} }

View File

@@ -1,18 +1,23 @@
use crate::parser::ast::MAX_ARITY; use crate::parser::ast::MAX_ARITY;
use crate::raw_block::*; use crate::raw_block::*;
use crate::rcu::{Rcu, RcuRef};
use crate::types::*; use crate::types::*;
use std::borrow::Borrow;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::mem; use std::mem;
use std::ops::Deref;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use std::str; use std::str;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
use indexmap::IndexSet; use indexmap::IndexSet;
use modular_bitfield::prelude::*; use modular_bitfield::prelude::*;
use tokio::sync::RwLock;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Atom { pub struct Atom {
@@ -33,65 +38,43 @@ impl<'a> From<&'a Atom> for Atom {
impl From<bool> for Atom { impl From<bool> for Atom {
#[inline] #[inline]
fn from(value: bool) -> Self { fn from(value: bool) -> Self {
if value { atom!("true") } else { atom!("false") } if value {
atom!("true")
} else {
atom!("false")
}
}
}
impl indexmap::Equivalent<Atom> for str {
fn equivalent(&self, key: &Atom) -> bool {
&*key.as_str() == self
} }
} }
const ATOM_TABLE_INIT_SIZE: usize = 1 << 16; const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
const ATOM_TABLE_ALIGN: usize = 8; const ATOM_TABLE_ALIGN: usize = 8;
#[cfg(test)] #[inline(always)]
thread_local! { fn global_atom_table() -> &'static RwLock<Weak<AtomTable>> {
static ATOM_TABLE_BUF_BASE: std::cell::RefCell<*const u8> = std::cell::RefCell::new(ptr::null_mut()); #[cfg(feature = "rust_beta_channel")]
}
#[cfg(not(test))]
static ATOM_TABLE_BUF_BASE: std::sync::atomic::AtomicPtr<u8> =
std::sync::atomic::AtomicPtr::new(ptr::null_mut());
fn set_atom_tbl_buf_base(old_ptr: *const u8, new_ptr: *const u8) -> Result<(), *const u8> {
#[cfg(test)]
{ {
ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| { // const Weak::new will be stabilized in 1.73 which is currently in beta,
let mut borrow = atom_table_buf_base.borrow_mut(); // till then we need a OnceLock for initialization
if *borrow != old_ptr { static GLOBAL_ATOM_TABLE: RwLock<Weak<AtomTable>> = RwLock::const_new(Weak::new());
Err(*borrow) &GLOBAL_ATOM_TABLE
} else {
*borrow = new_ptr;
Ok(())
} }
})?; #[cfg(not(feature = "rust_beta_channel"))]
};
#[cfg(not(test))]
{ {
ATOM_TABLE_BUF_BASE use std::sync::OnceLock;
.compare_exchange( static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<AtomTable>>> = OnceLock::new();
old_ptr.cast_mut(), GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
new_ptr.cast_mut(),
std::sync::atomic::Ordering::Relaxed,
std::sync::atomic::Ordering::Relaxed,
)
.map_err(|ptr| ptr.cast_const())
}?;
Ok(())
}
pub(crate) fn get_atom_tbl_buf_base() -> *const u8 {
#[cfg(test)]
{
ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| *atom_table_buf_base.borrow())
}
#[cfg(not(test))]
{
ATOM_TABLE_BUF_BASE.load(std::sync::atomic::Ordering::Relaxed)
} }
} }
#[test] #[inline(always)]
#[should_panic(expected = "Overwriting atom table base pointer")] fn arc_atom_table() -> Option<Arc<AtomTable>> {
fn atomtable_is_not_concurrency_safe() { global_atom_table().blocking_read().upgrade()
let _table_a = AtomTable::new();
let _table_b = AtomTable::new();
} }
impl RawBlockTraits for AtomTable { impl RawBlockTraits for AtomTable {
@@ -109,9 +92,11 @@ impl RawBlockTraits for AtomTable {
#[bitfield] #[bitfield]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct AtomHeader { struct AtomHeader {
#[allow(unused)] m: bool, #[allow(unused)]
m: bool,
len: B50, len: B50,
#[allow(unused)] padding: B13, #[allow(unused)]
padding: B13,
} }
impl AtomHeader { impl AtomHeader {
@@ -120,13 +105,6 @@ impl AtomHeader {
} }
} }
impl Borrow<str> for Atom {
#[inline]
fn borrow(&self) -> &str {
self.as_str()
}
}
impl Hash for Atom { impl Hash for Atom {
#[inline] #[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) { fn hash<H: Hasher>(&self, hasher: &mut H) {
@@ -142,29 +120,75 @@ macro_rules! is_char {
}; };
} }
pub enum AtomString<'a> {
Static(&'a str),
Dynamic(AtomTableRef<str>),
}
impl AtomString<'_> {
pub fn map<F>(self, f: F) -> Self
where
for<'a> F: FnOnce(&'a str) -> &'a str,
{
match self {
Self::Static(reference) => Self::Static(f(reference)),
Self::Dynamic(guard) => Self::Dynamic(AtomTableRef::map(guard, f)),
}
}
}
impl std::fmt::Debug for AtomString<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(self.deref(), f)
}
}
impl std::fmt::Display for AtomString<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(self.deref(), f)
}
}
impl std::ops::Deref for AtomString<'_> {
type Target = str;
fn deref(&self) -> &Self::Target {
match self {
Self::Static(reference) => reference,
Self::Dynamic(guard) => guard.deref(),
}
}
}
impl rustyline::completion::Candidate for AtomString<'_> {
fn display(&self) -> &str {
self.deref()
}
fn replacement(&self) -> &str {
self.deref()
}
}
impl Atom { impl Atom {
#[inline]
pub fn buf(self) -> *const u8 {
let ptr = self.as_ptr();
if ptr.is_null() {
return ptr::null();
}
(ptr as usize + mem::size_of::<AtomHeader>()) as *const u8
}
#[inline(always)] #[inline(always)]
pub fn is_static(self) -> bool { pub fn is_static(self) -> bool {
(self.index as usize) < STRINGS.len() << 3 (self.index as usize) < STRINGS.len() << 3
} }
#[inline(always)] #[inline(always)]
pub fn as_ptr(self) -> *const u8 { pub fn as_ptr(self) -> Option<AtomTableRef<u8>> {
if self.is_static() { if self.is_static() {
ptr::null() None
} else { } else {
(get_atom_tbl_buf_base() as usize + (self.index as usize) - (STRINGS.len() << 3)) as *const u8 let atom_table =
arc_atom_table().expect("We should only have an Atom while there is an AtomTable");
unsafe {
AtomTableRef::try_map(atom_table.buf(), |buf| {
(buf as *const u8)
.offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
.as_ref()
})
}
} }
} }
@@ -178,7 +202,9 @@ impl Atom {
if self.is_static() { if self.is_static() {
STRINGS[(self.index >> 3) as usize].len() STRINGS[(self.index >> 3) as usize].len()
} else { } else {
unsafe { ptr::read(self.as_ptr() as *const AtomHeader).len() as _ } let ptr = self.as_ptr().unwrap();
let ptr = ptr.deref() as *const u8 as *const AtomHeader;
unsafe { ptr::read(ptr) }.len() as _
} }
} }
@@ -194,41 +220,44 @@ impl Atom {
let c1 = it.next(); let c1 = it.next();
let c2 = it.next(); let c2 = it.next();
if c2.is_none() { c1 } else { None } if c2.is_none() {
c1
} else {
None
}
} }
#[inline] #[inline]
pub fn chars(&self) -> str::Chars { pub fn as_str(&self) -> AtomString<'static> {
self.as_str().chars() if self.is_static() {
} AtomString::Static(STRINGS[(self.index >> 3) as usize])
} else {
#[inline] if let Some(ptr) = self.as_ptr() {
pub fn as_str(&self) -> &str { AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| {
unsafe { let header =
let ptr = self.as_ptr(); unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
if ptr.is_null() {
return STRINGS[(self.index >> 3) as usize];
}
let header = ptr::read::<AtomHeader>(ptr as *const _);
let len = header.len() as usize; let len = header.len() as usize;
let buf = (ptr as usize + mem::size_of::<AtomHeader>()) as *mut u8; let buf =
unsafe { (ptr as *const u8).offset(mem::size_of::<AtomHeader>() as isize) };
str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) }
}))
} else {
AtomString::Static(&STRINGS[(self.index >> 3) as usize])
}
} }
} }
pub fn defrock_brackets(&self, atom_tbl: &mut AtomTable) -> Self { pub fn defrock_brackets(&self, atom_tbl: &AtomTable) -> Self {
let s = self.as_str(); let s = self.as_str();
let s = if s.starts_with('(') && s.ends_with(')') { let sub_str = if s.starts_with('(') && s.ends_with(')') {
&s['('.len_utf8()..s.len() - ')'.len_utf8()] &s['('.len_utf8()..s.len() - ')'.len_utf8()]
} else { } else {
return *self; return *self;
}; };
atom_tbl.build_with(s) AtomTable::build_with(&atom_tbl, &sub_str)
} }
} }
@@ -248,93 +277,121 @@ impl PartialOrd for Atom {
impl Ord for Atom { impl Ord for Atom {
#[inline] #[inline]
fn cmp(&self, other: &Atom) -> Ordering { fn cmp(&self, other: &Atom) -> Ordering {
self.as_str().cmp(other.as_str()) self.as_str().cmp(&*other.as_str())
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct AtomTable { pub struct InnerAtomTable {
block: RawBlock<AtomTable>, block: RawBlock<AtomTable>,
pub table: IndexSet<Atom>, pub table: Rcu<IndexSet<Atom>>,
} }
#[cold] #[derive(Debug)]
fn atom_table_base_pointer_mismatch(expected: *const u8, got: *const u8) -> ! { pub struct AtomTable {
assert_eq!(expected, got, "Overwriting atom table base pointer, expected old value to be {expected:p}, but found {got:p}"); inner: Rcu<InnerAtomTable>,
unreachable!("This should only be called in a case of a mismatch as such the assert_eq should have failed!") // this lock is taking during resizing
update: Mutex<()>,
} }
impl Drop for AtomTable { pub type AtomTableRef<M> = RcuRef<InnerAtomTable, M>;
fn drop(&mut self) {
if let Err(got) = set_atom_tbl_buf_base(self.block.base, ptr::null()) { impl InnerAtomTable {
atom_table_base_pointer_mismatch(self.block.base, got); #[inline(always)]
} fn lookup_str(self: &InnerAtomTable, string: &str) -> Option<Atom> {
self.block.deallocate(); STATIC_ATOMS_MAP
.get(string)
.cloned()
.or_else(|| self.table.active_epoch().get(string).cloned())
} }
} }
impl AtomTable { impl AtomTable {
#[inline] #[inline]
pub fn new() -> Self { pub fn new() -> Arc<Self> {
let mut block = RawBlock::new(); let upgraded = global_atom_table().blocking_read().upgrade();
// don't inline upgraded, otherwise temporary will be dropped too late in case of None
if let Err(got) = set_atom_tbl_buf_base(ptr::null(), block.base) { if let Some(atom_table) = upgraded {
block.deallocate(); atom_table
atom_table_base_pointer_mismatch(ptr::null(), got); } else {
let mut guard = global_atom_table().blocking_write();
// try to upgrade again in case we lost the race on the write lock
if let Some(atom_table) = guard.upgrade() {
atom_table
} else {
let atom_table = Arc::new(Self {
inner: Rcu::new(InnerAtomTable {
block: RawBlock::new(),
table: Rcu::new(IndexSet::new()),
}),
update: Mutex::new(()),
});
*guard = Arc::downgrade(&atom_table);
atom_table
} }
Self {
block,
table: IndexSet::new(),
} }
} }
#[inline] #[inline]
pub fn buf(&self) -> *const u8 { pub fn buf(&self) -> AtomTableRef<u8> {
self.block.base as *const u8 AtomTableRef::<InnerAtomTable>::map(self.inner.active_epoch(), |inner| {
unsafe { inner.block.base.as_ref() }.unwrap()
})
} }
#[inline] pub fn active_table(&self) -> RcuRef<IndexSet<Atom>, IndexSet<Atom>> {
pub fn top(&self) -> *const u8 { self.inner.active_epoch().table.active_epoch()
self.block.top
} }
#[inline(always)] pub fn build_with(atom_table: &AtomTable, string: &str) -> Atom {
fn lookup_str(&self, string: &str) -> Option<Atom> { loop {
STATIC_ATOMS_MAP.get(string).or_else(|| self.table.get(string)).cloned() let mut block_epoch = atom_table.inner.active_epoch();
} let mut table_epoch = block_epoch.table.active_epoch();
pub fn build_with(&mut self, string: &str) -> Atom { if let Some(atom) = block_epoch.lookup_str(string) {
if let Some(atom) = self.lookup_str(string) {
return atom; return atom;
} }
unsafe { // take a lock to prevent concurrent updates
let update_guard = atom_table.update.lock().unwrap();
let is_same_allocation =
RcuRef::same_epoch(&block_epoch, &atom_table.inner.active_epoch());
let is_same_atom_list =
RcuRef::same_epoch(&table_epoch, &block_epoch.table.active_epoch());
if !(is_same_allocation && is_same_atom_list) {
// some other thread raced us between our lookup and
// us aquring the update lock,
// try again
continue;
}
let size = mem::size_of::<AtomHeader>() + string.len(); let size = mem::size_of::<AtomHeader>() + string.len();
let align_offset = 8 * mem::align_of::<AtomHeader>(); let align_offset = 8 * mem::align_of::<AtomHeader>();
let size = (size & !(align_offset - 1)) + align_offset; let size = (size & !(align_offset - 1)) + align_offset;
let len_ptr = { unsafe {
let mut ptr; let len_ptr = loop {
let ptr = block_epoch.block.alloc(size);
loop {
ptr = self.block.alloc(size);
if ptr.is_null() { if ptr.is_null() {
let old_base = self.block.base; // garbage collection would go here
self.block.grow(); let new_block = block_epoch.block.grow_new().unwrap();
if let Err(got) = set_atom_tbl_buf_base(old_base, self.block.base) { let new_table = Rcu::new(table_epoch.clone());
atom_table_base_pointer_mismatch(old_base, got); let new_alloc = InnerAtomTable {
} block: new_block,
table: new_table,
};
atom_table.inner.replace(new_alloc);
block_epoch = atom_table.inner.active_epoch();
table_epoch = block_epoch.table.active_epoch();
} else { } else {
break; break ptr;
} }
}
ptr
}; };
let ptr_base = self.block.base as usize; let ptr_base = block_epoch.block.base as usize;
write_to_ptr(string, len_ptr); write_to_ptr(string, len_ptr);
@@ -342,12 +399,21 @@ impl AtomTable {
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64, index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
}; };
self.table.insert(atom); let mut table = table_epoch.clone();
table.insert(atom);
block_epoch.table.replace(table);
atom // expicit drop to ensure we don't accidentally drop it early
drop(update_guard);
return atom;
} }
} }
} }
}
unsafe impl Send for AtomTable {}
unsafe impl Sync for AtomTable {}
#[bitfield] #[bitfield]
#[repr(u64)] #[repr(u64)]
@@ -355,9 +421,12 @@ impl AtomTable {
pub struct AtomCell { pub struct AtomCell {
name: B46, name: B46,
arity: B10, arity: B10,
#[allow(unused)] f: bool, #[allow(unused)]
#[allow(unused)] m: bool, f: bool,
#[allow(unused)] tag: B6, #[allow(unused)]
m: bool,
#[allow(unused)]
tag: B6,
} }
impl AtomCell { impl AtomCell {

View File

@@ -1,11 +1,12 @@
fn main() -> std::process::ExitCode { fn main() -> std::process::ExitCode {
use std::sync::atomic::Ordering;
use scryer_prolog::*; use scryer_prolog::*;
use std::sync::atomic::Ordering;
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
ctrlc::set_handler(move || { ctrlc::set_handler(move || {
scryer_prolog::machine::INTERRUPT.store(true, Ordering::Relaxed); scryer_prolog::machine::INTERRUPT.store(true, Ordering::Relaxed);
}).unwrap(); })
.unwrap();
let mut wam = machine::Machine::new(); let mut wam = machine::Machine::new();
wam.run_top_level() wam.run_top_level()

View File

@@ -1,14 +1,14 @@
use crate::atom_table::*;
use crate::parser::ast::*;
use crate::temp_v;
use crate::allocator::*; use crate::allocator::*;
use crate::arithmetic::*; use crate::arithmetic::*;
use crate::atom_table::*;
use crate::debray_allocator::*; use crate::debray_allocator::*;
use crate::forms::*; use crate::forms::*;
use crate::indexing::*; use crate::indexing::*;
use crate::instructions::*; use crate::instructions::*;
use crate::iterators::*; use crate::iterators::*;
use crate::parser::ast::*;
use crate::targets::*; use crate::targets::*;
use crate::temp_v;
use crate::types::*; use crate::types::*;
use crate::instr; use crate::instr;
@@ -48,12 +48,17 @@ impl BranchCodeStack {
} }
fn code<'a>(&'a mut self, default_code: &'a mut CodeDeque) -> &'a mut CodeDeque { fn code<'a>(&'a mut self, default_code: &'a mut CodeDeque) -> &'a mut CodeDeque {
self.stack.last_mut() self.stack
.last_mut()
.and_then(|stack| stack.last_mut()) .and_then(|stack| stack.last_mut())
.unwrap_or(default_code) .unwrap_or(default_code)
} }
fn push_missing_vars(&mut self, depth: usize, marker: &mut DebrayAllocator) -> SubsumedBranchHits { fn push_missing_vars(
&mut self,
depth: usize,
marker: &mut DebrayAllocator,
) -> SubsumedBranchHits {
let mut subsumed_hits = SubsumedBranchHits::with_hasher(FxBuildHasher::default()); let mut subsumed_hits = SubsumedBranchHits::with_hasher(FxBuildHasher::default());
for idx in (self.stack.len() - depth..self.stack.len()).rev() { for idx in (self.stack.len() - depth..self.stack.len()).rev() {
@@ -119,7 +124,9 @@ impl BranchCodeStack {
for mut branch_arm in self.stack.drain(self.stack.len() - depth..).rev() { for mut branch_arm in self.stack.drain(self.stack.len() - depth..).rev() {
let num_branch_arms = branch_arm.len(); let num_branch_arms = branch_arm.len();
branch_arm.last_mut().map(|code| code.extend(combined_code.drain(..))); branch_arm
.last_mut()
.map(|code| code.extend(combined_code.drain(..)));
for (idx, code) in branch_arm.into_iter().enumerate() { for (idx, code) in branch_arm.into_iter().enumerate() {
combined_code.push_back(if idx == 0 { combined_code.push_back(if idx == 0 {
@@ -255,7 +262,7 @@ impl CodeGenSettings {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CodeGenerator<'a> { pub(crate) struct CodeGenerator<'a> {
pub(crate) atom_tbl: &'a mut AtomTable, pub(crate) atom_tbl: &'a AtomTable,
marker: DebrayAllocator, marker: DebrayAllocator,
settings: CodeGenSettings, settings: CodeGenSettings,
pub(crate) skeleton: PredicateSkeleton, pub(crate) skeleton: PredicateSkeleton,
@@ -269,13 +276,7 @@ impl DebrayAllocator {
vr: &Cell<VarReg>, vr: &Cell<VarReg>,
code: &mut CodeDeque, code: &mut CodeDeque,
) -> RegType { ) -> RegType {
self.mark_var::<QueryInstruction>( self.mark_var::<QueryInstruction>(var_num, Level::Shallow, vr, term_loc, code);
var_num,
Level::Shallow,
vr,
term_loc,
code,
);
vr.get().norm() vr.get().norm()
} }
@@ -308,8 +309,8 @@ impl DebrayAllocator {
// decrement the arity of the PutStructure instruction by 1. // decrement the arity of the PutStructure instruction by 1.
fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term) { fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term) {
match instr { match instr {
Instruction::PutStructure(_, ref mut arity, _) | Instruction::PutStructure(_, ref mut arity, _)
Instruction::GetStructure(.., ref mut arity, _) => { | Instruction::GetStructure(.., ref mut arity, _) => {
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg { if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
// it is acceptable if arity == 0 is the result of // it is acceptable if arity == 0 is the result of
// this decrement. call/N will have to read the index // this decrement. call/N will have to read the index
@@ -352,16 +353,16 @@ impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> {
fn structure_cell(term: &Term) -> Option<&Cell<RegType>> { fn structure_cell(term: &Term) -> Option<&Cell<RegType>> {
match term { match term {
&Term::Cons(ref cell, ..) | &Term::Cons(ref cell, ..)
&Term::Clause(ref cell, ..) | | &Term::Clause(ref cell, ..)
Term::PartialString(ref cell, ..) | | Term::PartialString(ref cell, ..)
Term::CompleteString(ref cell, ..) => Some(cell), | Term::CompleteString(ref cell, ..) => Some(cell),
_ => None, _ => None,
} }
} }
impl<'b> CodeGenerator<'b> { impl<'b> CodeGenerator<'b> {
pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self { pub(crate) fn new(atom_tbl: &'b AtomTable, settings: CodeGenSettings) -> Self {
CodeGenerator { CodeGenerator {
atom_tbl, atom_tbl,
marker: DebrayAllocator::new(), marker: DebrayAllocator::new(),
@@ -392,7 +393,8 @@ impl<'b> CodeGenerator<'b> {
target: &mut CodeDeque, target: &mut CodeDeque,
) { ) {
if self.marker.var_data.records[var_num].num_occurrences > 1 { if self.marker.var_data.records[var_num].num_occurrences > 1 {
self.marker.mark_var::<Target>(var_num, Level::Deep, cell, term_loc, target); self.marker
.mark_var::<Target>(var_num, Level::Deep, cell, term_loc, target);
} else { } else {
Self::add_or_increment_void_instr::<Target>(target); Self::add_or_increment_void_instr::<Target>(target);
} }
@@ -408,31 +410,33 @@ impl<'b> CodeGenerator<'b> {
&Term::AnonVar => { &Term::AnonVar => {
Self::add_or_increment_void_instr::<Target>(target); Self::add_or_increment_void_instr::<Target>(target);
} }
&Term::Cons(ref cell, ..) | &Term::Cons(ref cell, ..)
&Term::Clause(ref cell, ..) | | &Term::Clause(ref cell, ..)
Term::PartialString(ref cell, ..) | | Term::PartialString(ref cell, ..)
Term::CompleteString(ref cell, ..) => { | Term::CompleteString(ref cell, ..) => {
self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target); self.marker
.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
target.push_back(Target::clause_arg_to_instr(cell.get())); target.push_back(Target::clause_arg_to_instr(cell.get()));
} }
&Term::Literal(_, ref constant) => { &Term::Literal(_, ref constant) => {
target.push_back(Target::constant_subterm(constant.clone())); target.push_back(Target::constant_subterm(constant.clone()));
} }
&Term::Var(ref cell, ref var_ptr) => { &Term::Var(ref cell, ref var_ptr) => {
self.deep_var_instr::<Target>(cell, var_ptr.to_var_num().unwrap(), term_loc, target); self.deep_var_instr::<Target>(
cell,
var_ptr.to_var_num().unwrap(),
term_loc,
target,
);
} }
}; };
} }
fn compile_target<'a, Target, Iter>( fn compile_target<'a, Target, Iter>(&mut self, iter: Iter, term_loc: GenContext) -> CodeDeque
&mut self,
iter: Iter,
term_loc: GenContext,
) -> CodeDeque
where where
Target: crate::targets::CompilationTarget<'a>, Target: crate::targets::CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>, Iter: Iterator<Item = TermRef<'a>>,
CodeGenerator<'b>: AddToFreeList<'a, Target> CodeGenerator<'b>: AddToFreeList<'a, Target>,
{ {
let mut target = CodeDeque::new(); let mut target = CodeDeque::new();
@@ -442,14 +446,19 @@ impl<'b> CodeGenerator<'b> {
if let GenContext::Head = term_loc { if let GenContext::Head = term_loc {
self.marker.advance_arg(); self.marker.advance_arg();
} else { } else {
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, name, 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_back(Target::to_structure(lvl, name, terms.len(), cell.get())); target.push_back(Target::to_structure(lvl, name, terms.len(), cell.get()));
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get()); <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
self,
cell.get(),
);
if let Some(instr) = target.back_mut() { if let Some(instr) = target.back_mut() {
if let Some(term) = terms.last() { if let Some(term) = terms.last() {
@@ -462,38 +471,52 @@ impl<'b> CodeGenerator<'b> {
} }
for subterm in terms { for subterm in terms {
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, subterm); <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, subterm,
);
} }
} }
TermRef::Cons(lvl, cell, head, tail) => { TermRef::Cons(lvl, cell, head, tail) => {
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_back(Target::to_list(lvl, cell.get())); target.push_back(Target::to_list(lvl, cell.get()));
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get()); <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
self,
cell.get(),
);
self.subterm_to_instr::<Target>(head, term_loc, &mut target); self.subterm_to_instr::<Target>(head, term_loc, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, &mut target); self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, head); <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, tail); self, head,
);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, tail,
);
} }
TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => { TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
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_back(Target::to_pstr(lvl, *string, cell.get(), false)); target.push_back(Target::to_pstr(lvl, *string, cell.get(), false));
} }
TermRef::Literal(lvl @ Level::Shallow, cell, constant) => { TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
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_back(Target::to_constant(lvl, *constant, cell.get())); target.push_back(Target::to_constant(lvl, *constant, cell.get()));
} }
TermRef::PartialString(lvl, cell, string, tail) => { TermRef::PartialString(lvl, cell, string, tail) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target); self.marker
let atom = self.atom_tbl.build_with(&string); .mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
let atom = AtomTable::build_with(&self.atom_tbl, &string);
target.push_back(Target::to_pstr(lvl, atom, cell.get(), true)); target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
self.subterm_to_instr::<Target>(tail, term_loc, &mut target); self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
} }
TermRef::CompleteString(lvl, cell, atom) => { TermRef::CompleteString(lvl, cell, atom) => {
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_back(Target::to_pstr(lvl, atom, cell.get(), false)); target.push_back(Target::to_pstr(lvl, atom, cell.get(), false));
} }
TermRef::Var(lvl @ Level::Shallow, cell, var) => { TermRef::Var(lvl @ Level::Shallow, cell, var) => {
@@ -563,9 +586,9 @@ impl<'b> CodeGenerator<'b> {
compare_number_instr!(cmp, at_1, at_2) compare_number_instr!(cmp, at_1, at_2)
} }
&InlinedClauseType::IsAtom(..) => match &terms[0] { &InlinedClauseType::IsAtom(..) => match &terms[0] {
&Term::Literal(_, Literal::Char(_)) | &Term::Literal(_, Literal::Char(_))
&Term::Literal(_, Literal::Atom(atom!("[]"))) | | &Term::Literal(_, Literal::Atom(atom!("[]")))
&Term::Literal(_, Literal::Atom(..)) => { | &Term::Literal(_, Literal::Atom(..)) => {
instr!("$succeed") instr!("$succeed")
} }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
@@ -586,11 +609,11 @@ impl<'b> CodeGenerator<'b> {
} }
}, },
&InlinedClauseType::IsAtomic(..) => match &terms[0] { &InlinedClauseType::IsAtomic(..) => match &terms[0] {
&Term::AnonVar | &Term::AnonVar
&Term::Clause(..) | | &Term::Clause(..)
&Term::Cons(..) | | &Term::Cons(..)
&Term::PartialString(..) | | &Term::PartialString(..)
&Term::CompleteString(..) => { | &Term::CompleteString(..) => {
instr!("$fail") instr!("$fail")
} }
&Term::Literal(_, Literal::String(_)) => { &Term::Literal(_, Literal::String(_)) => {
@@ -614,11 +637,11 @@ impl<'b> CodeGenerator<'b> {
} }
}, },
&InlinedClauseType::IsCompound(..) => match &terms[0] { &InlinedClauseType::IsCompound(..) => match &terms[0] {
&Term::Clause(..) | &Term::Clause(..)
&Term::Cons(..) | | &Term::Cons(..)
&Term::PartialString(..) | | &Term::PartialString(..)
&Term::CompleteString(..) | | &Term::CompleteString(..)
&Term::Literal(_, Literal::String(..)) => { | &Term::Literal(_, Literal::String(..)) => {
instr!("$succeed") instr!("$succeed")
} }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
@@ -644,7 +667,13 @@ impl<'b> CodeGenerator<'b> {
} }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1); self.marker.reset_arg(1);
let r = self.marker.mark_non_callable(name.to_var_num().unwrap(), 1, term_loc, vr, code); let r = self.marker.mark_non_callable(
name.to_var_num().unwrap(),
1,
term_loc,
vr,
code,
);
instr!("rational", r) instr!("rational", r)
} }
_ => { _ => {
@@ -673,10 +702,10 @@ impl<'b> CodeGenerator<'b> {
} }
}, },
&InlinedClauseType::IsNumber(..) => match &terms[0] { &InlinedClauseType::IsNumber(..) => match &terms[0] {
&Term::Literal(_, Literal::Float(_)) | &Term::Literal(_, Literal::Float(_))
&Term::Literal(_, Literal::Rational(_)) | | &Term::Literal(_, Literal::Rational(_))
&Term::Literal(_, Literal::Integer(_)) | | &Term::Literal(_, Literal::Integer(_))
&Term::Literal(_, Literal::Fixnum(_)) => { | &Term::Literal(_, Literal::Fixnum(_)) => {
instr!("$succeed") instr!("$succeed")
} }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
@@ -718,8 +747,7 @@ impl<'b> CodeGenerator<'b> {
} }
}, },
&InlinedClauseType::IsInteger(..) => match &terms[0] { &InlinedClauseType::IsInteger(..) => match &terms[0] {
&Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => {
&Term::Literal(_, Literal::Fixnum(_)) => {
instr!("$succeed") instr!("$succeed")
} }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
@@ -740,11 +768,11 @@ impl<'b> CodeGenerator<'b> {
} }
}, },
&InlinedClauseType::IsVar(..) => match &terms[0] { &InlinedClauseType::IsVar(..) => match &terms[0] {
&Term::Literal(..) | &Term::Literal(..)
&Term::Clause(..) | | &Term::Clause(..)
&Term::Cons(..) | | &Term::Cons(..)
&Term::PartialString(..) | | &Term::PartialString(..)
&Term::CompleteString(..) => { | &Term::CompleteString(..) => {
instr!("$fail") instr!("$fail")
} }
&Term::AnonVar => { &Term::AnonVar => {
@@ -791,11 +819,11 @@ impl<'b> CodeGenerator<'b> {
call_policy: CallPolicy, call_policy: CallPolicy,
) -> Result<(), CompilationError> { ) -> Result<(), CompilationError> {
macro_rules! compile_expr { macro_rules! compile_expr {
($self:expr, $terms:expr, $term_loc:expr, $code:expr) => ({ ($self:expr, $terms:expr, $term_loc:expr, $code:expr) => {{
let (acode, at) = $self.compile_arith_expr($terms, 1, $term_loc, 2)?; let (acode, at) = $self.compile_arith_expr($terms, 1, $term_loc, 2)?;
$code.extend(acode.into_iter()); $code.extend(acode.into_iter());
at at
}); }};
} }
self.marker.reset_arg(2); self.marker.reset_arg(2);
@@ -843,10 +871,13 @@ impl<'b> CodeGenerator<'b> {
compile_expr!(self, &terms[1], term_loc, code) compile_expr!(self, &terms[1], term_loc, code)
} }
} }
&Term::Literal(_, c @ Literal::Integer(_) | &Term::Literal(
c @ Literal::Float(_) | _,
c @ Literal::Rational(_) | c @ Literal::Integer(_)
c @ Literal::Fixnum(_)) => { | c @ Literal::Float(_)
| c @ Literal::Rational(_)
| c @ Literal::Fixnum(_),
) => {
let v = HeapCellValue::from(c); let v = HeapCellValue::from(c);
code.push_back(instr!("put_constant", Level::Shallow, v, temp_v!(1))); code.push_back(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
@@ -939,15 +970,29 @@ impl<'b> CodeGenerator<'b> {
ClauseType::BuiltIn(BuiltInClauseType::Is(..)), ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
ref terms, ref terms,
call_policy, call_policy,
) => self.compile_is_call(terms, branch_code_stack.code(code), term_loc, call_policy)?, ) => self.compile_is_call(
terms,
branch_code_stack.code(code),
term_loc,
call_policy,
)?,
&QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => { &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
self.compile_inlined(ct, terms, term_loc, branch_code_stack.code(code))? self.compile_inlined(
ct,
terms,
term_loc,
branch_code_stack.code(code),
)?
} }
&QueryTerm::Fail => { &QueryTerm::Fail => {
branch_code_stack.code(code).push_back(instr!("$fail")); branch_code_stack.code(code).push_back(instr!("$fail"));
} }
term @ &QueryTerm::Clause(..) => { term @ &QueryTerm::Clause(..) => {
self.compile_query_line(term, term_loc, branch_code_stack.code(code)); self.compile_query_line(
term,
term_loc,
branch_code_stack.code(code),
);
if self.marker.max_reg_allocated() > MAX_ARITY { if self.marker.max_reg_allocated() > MAX_ARITY {
return Err(CompilationError::ExceededMaxArity); return Err(CompilationError::ExceededMaxArity);
@@ -975,7 +1020,8 @@ impl<'b> CodeGenerator<'b> {
} }
ClauseItem::BranchEnd(depth) => { ClauseItem::BranchEnd(depth) => {
if !clause_iter.in_tail_position() { if !clause_iter.in_tail_position() {
let subsumed_hits = branch_code_stack.push_missing_vars(depth, &mut self.marker); let subsumed_hits =
branch_code_stack.push_missing_vars(depth, &mut self.marker);
self.marker.pop_branch(depth, subsumed_hits); self.marker.pop_branch(depth, subsumed_hits);
branch_code_stack.push_jump_instrs(depth); branch_code_stack.push_jump_instrs(depth);
} else { } else {
@@ -1001,8 +1047,15 @@ impl<'b> CodeGenerator<'b> {
Ok(()) Ok(())
} }
pub(crate) fn compile_rule(&mut self, rule: &Rule, var_data: VarData) -> Result<Code, CompilationError> { pub(crate) fn compile_rule(
let Rule { head: (_, args), clauses } = rule; &mut self,
rule: &Rule,
var_data: VarData,
) -> Result<Code, CompilationError> {
let Rule {
head: (_, args),
clauses,
} = rule;
self.marker.var_data = var_data; self.marker.var_data = var_data;
let mut code = VecDeque::new(); let mut code = VecDeque::new();
@@ -1023,7 +1076,11 @@ impl<'b> CodeGenerator<'b> {
Ok(Vec::from(code)) Ok(Vec::from(code))
} }
pub(crate) fn compile_fact(&mut self, fact: &Fact, var_data: VarData) -> Result<Code, CompilationError> { pub(crate) fn compile_fact(
&mut self,
fact: &Fact,
var_data: VarData,
) -> Result<Code, CompilationError> {
let mut code = Vec::new(); let mut code = Vec::new();
self.marker.var_data = var_data; self.marker.var_data = var_data;
@@ -1031,10 +1088,7 @@ impl<'b> CodeGenerator<'b> {
self.marker.reset_at_head(args); self.marker.reset_at_head(args);
let iter = FactInstruction::iter(&fact.head); let iter = FactInstruction::iter(&fact.head);
let compiled_fact = self.compile_target::<FactInstruction, _>( let compiled_fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);
iter,
GenContext::Head,
);
if self.marker.max_reg_allocated() > MAX_ARITY { if self.marker.max_reg_allocated() > MAX_ARITY {
return Err(CompilationError::ExceededMaxArity); return Err(CompilationError::ExceededMaxArity);
@@ -1059,7 +1113,7 @@ impl<'b> CodeGenerator<'b> {
&QueryTerm::Clause(_, ref ct, _, call_policy) => { &QueryTerm::Clause(_, ref ct, _, call_policy) => {
self.add_call(code, ct.to_instr(), call_policy); self.add_call(code, ct.to_instr(), call_policy);
} }
_ => unreachable!() _ => unreachable!(),
}; };
} }
@@ -1072,8 +1126,7 @@ impl<'b> CodeGenerator<'b> {
if let Some(args) = clause.args() { if let Some(args) = clause.args() {
for (instantiated_arg_index, arg) in args.iter().enumerate() { for (instantiated_arg_index, arg) in args.iter().enumerate() {
match arg { match arg {
Term::Var(..) | Term::AnonVar => { Term::Var(..) | Term::AnonVar => {}
}
_ => { _ => {
if optimal_index != instantiated_arg_index { if optimal_index != instantiated_arg_index {
if left >= right { if left >= right {
@@ -1098,7 +1151,11 @@ impl<'b> CodeGenerator<'b> {
} }
if left < right { if left < right {
subseqs.push(ClauseSpan { left, right, instantiated_arg_index: optimal_index }); subseqs.push(ClauseSpan {
left,
right,
instantiated_arg_index: optimal_index,
});
} }
optimal_index = 0; optimal_index = 0;
@@ -1129,11 +1186,8 @@ impl<'b> CodeGenerator<'b> {
optimal_index: usize, optimal_index: usize,
) -> Result<Code, CompilationError> { ) -> Result<Code, CompilationError> {
let mut code = VecDeque::new(); let mut code = VecDeque::new();
let mut code_offsets = CodeOffsets::new( let mut code_offsets =
I::new(), CodeOffsets::new(I::new(), optimal_index + 1, self.settings.non_counted_bt);
optimal_index + 1,
self.settings.non_counted_bt,
);
let mut skip_stub_try_me_else = false; let mut skip_stub_try_me_else = false;
let clauses_len = clauses.len(); let clauses_len = clauses.len();
@@ -1178,7 +1232,9 @@ impl<'b> CodeGenerator<'b> {
skip_stub_try_me_else = !self.settings.is_dynamic(); skip_stub_try_me_else = !self.settings.is_dynamic();
} }
let arg = clause.args().and_then(|args| args.iter().nth(optimal_index)); let arg = clause
.args()
.and_then(|args| args.iter().nth(optimal_index));
if let Some(arg) = arg { if let Some(arg) = arg {
let index = code.len(); let index = code.len();
@@ -1221,7 +1277,12 @@ impl<'b> CodeGenerator<'b> {
let split_pred = Self::split_predicate(&clauses); let split_pred = Self::split_predicate(&clauses);
let multi_seq = split_pred.len() > 1; let multi_seq = split_pred.len() > 1;
for ClauseSpan { left, right, instantiated_arg_index } in split_pred { for ClauseSpan {
left,
right,
instantiated_arg_index,
} in split_pred
{
let skel_lower_bound = self.skeleton.clauses.len(); let skel_lower_bound = self.skeleton.clauses.len();
let code_segment = if self.settings.is_dynamic() { let code_segment = if self.settings.is_dynamic() {
self.compile_pred_subseq::<DynamicCodeIndices>( self.compile_pred_subseq::<DynamicCodeIndices>(
@@ -1252,9 +1313,8 @@ impl<'b> CodeGenerator<'b> {
if self.settings.is_extensible { if self.settings.is_extensible {
let segment_is_indexed = code_segment[0].to_indexing_line().is_some(); let segment_is_indexed = code_segment[0].to_indexing_line().is_some();
for clause_index_info in self.skeleton.clauses for clause_index_info in
.make_contiguous()[skel_lower_bound..] self.skeleton.clauses.make_contiguous()[skel_lower_bound..].iter_mut()
.iter_mut()
{ {
clause_index_info.clause_start += clause_index_info.clause_start +=
clause_start_offset + 2 * (segment_is_indexed as usize); clause_start_offset + 2 * (segment_is_indexed as usize);

View File

@@ -76,11 +76,16 @@ impl BranchStack {
} }
} }
fn safety_unneeded_in_branch(&self, safety: &VarSafetyStatus, branch: &BranchDesignator) -> bool { fn safety_unneeded_in_branch(
&self,
safety: &VarSafetyStatus,
branch: &BranchDesignator,
) -> bool {
match safety { match safety {
VarSafetyStatus::Needed => false, VarSafetyStatus::Needed => false,
VarSafetyStatus::LocallyUnneeded(planter_branch) => VarSafetyStatus::LocallyUnneeded(planter_branch) => {
self.branch_subsumes(planter_branch, branch), self.branch_subsumes(planter_branch, branch)
}
VarSafetyStatus::GloballyUnneeded => true, VarSafetyStatus::GloballyUnneeded => true,
} }
} }
@@ -91,7 +96,9 @@ impl BranchStack {
let num_branches = occurrences.num_branches; let num_branches = occurrences.num_branches;
let entry = occurrences.hits.entry(var_num) let entry = occurrences
.hits
.entry(var_num)
.or_insert_with(|| BitVec::repeat(false, num_branches)); .or_insert_with(|| BitVec::repeat(false, num_branches));
entry.set(occurrences.current_branch, true); entry.set(occurrences.current_branch, true);
@@ -105,11 +112,15 @@ impl BranchStack {
pub(crate) fn current_branch_designator(&self) -> BranchDesignator { pub(crate) fn current_branch_designator(&self) -> BranchDesignator {
let branch_stack_num = self.len(); let branch_stack_num = self.len();
let branch_num = self.last() let branch_num = self
.last()
.map(|occurrences| occurrences.current_branch) .map(|occurrences| occurrences.current_branch)
.unwrap_or(0); .unwrap_or(0);
BranchDesignator { branch_stack_num, branch_num } BranchDesignator {
branch_stack_num,
branch_num,
}
} }
#[inline] #[inline]
@@ -156,13 +167,23 @@ impl DebrayAllocator {
match &mut self.var_data.records[var_num].allocation { match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, ref mut allocation) => { VarAlloc::Perm(_, ref mut allocation) => {
match allocation { match allocation {
PermVarAllocation::Done { shallow_safety, deep_safety, .. } => { PermVarAllocation::Done {
if !self.branch_stack.safety_unneeded_in_branch(shallow_safety, &branch_designator) { shallow_safety,
deep_safety,
..
} => {
if !self
.branch_stack
.safety_unneeded_in_branch(shallow_safety, &branch_designator)
{
let branch_occurrences = self.branch_stack.last_mut().unwrap(); let branch_occurrences = self.branch_stack.last_mut().unwrap();
branch_occurrences.shallow_safety.insert(var_num); branch_occurrences.shallow_safety.insert(var_num);
} }
if !self.branch_stack.safety_unneeded_in_branch(deep_safety, &branch_designator) { if !self
.branch_stack
.safety_unneeded_in_branch(deep_safety, &branch_designator)
{
let branch_occurrences = self.branch_stack.last_mut().unwrap(); let branch_occurrences = self.branch_stack.last_mut().unwrap();
branch_occurrences.deep_safety.insert(var_num); branch_occurrences.deep_safety.insert(var_num);
} }
@@ -182,15 +203,15 @@ impl DebrayAllocator {
pub(crate) fn pop_branch(&mut self, depth: usize, subsumed_hits: SubsumedBranchHits) { pub(crate) fn pop_branch(&mut self, depth: usize, subsumed_hits: SubsumedBranchHits) {
let removed_branches = self.branch_stack.drain_branches(depth); let removed_branches = self.branch_stack.drain_branches(depth);
let (deep_safety, shallow_safety) = removed_branches let (deep_safety, shallow_safety) = removed_branches.into_iter().fold(
.into_iter() (BitSet::default(), BitSet::default()),
.fold((BitSet::default(), BitSet::default()),
|(mut deep_safety, mut shallow_safety), branch_occurrences| { |(mut deep_safety, mut shallow_safety), branch_occurrences| {
deep_safety.union_with(&branch_occurrences.deep_safety); deep_safety.union_with(&branch_occurrences.deep_safety);
shallow_safety.union_with(&branch_occurrences.shallow_safety); shallow_safety.union_with(&branch_occurrences.shallow_safety);
(deep_safety, shallow_safety) (deep_safety, shallow_safety)
}); },
);
let branch_designator = self.branch_stack.current_branch_designator(); let branch_designator = self.branch_stack.current_branch_designator();
@@ -201,7 +222,7 @@ impl DebrayAllocator {
(&latest_branch.deep_safety, &latest_branch.shallow_safety) (&latest_branch.deep_safety, &latest_branch.shallow_safety)
} }
None => (&deep_safety, &shallow_safety) None => (&deep_safety, &shallow_safety),
}; };
for var_num in subsumed_hits.iter().cloned() { for var_num in subsumed_hits.iter().cloned() {
@@ -221,10 +242,13 @@ impl DebrayAllocator {
); );
if running_count < num_occurrences { if running_count < num_occurrences {
*allocation = PermVarAllocation::Done { shallow_safety, deep_safety }; *allocation = PermVarAllocation::Done {
shallow_safety,
deep_safety,
};
} }
} }
_ => unreachable!() _ => unreachable!(),
} }
} }
@@ -244,9 +268,11 @@ impl DebrayAllocator {
fn occurs_shallowly_in_head(&self, var_num: usize, r: usize) -> bool { fn occurs_shallowly_in_head(&self, var_num: usize, r: usize) -> bool {
match &self.var_data.records[var_num].allocation { match &self.var_data.records[var_num].allocation {
VarAlloc::Temp { temp_var_data, term_loc: GenContext::Head, .. } => { VarAlloc::Temp {
temp_var_data.use_set.contains(&(GenContext::Head, r)) temp_var_data,
} term_loc: GenContext::Head,
..
} => temp_var_data.use_set.contains(&(GenContext::Head, r)),
_ => false, _ => false,
} }
} }
@@ -325,12 +351,14 @@ impl DebrayAllocator {
match &self.var_data.records[t_var].allocation { match &self.var_data.records[t_var].allocation {
VarAlloc::Temp { temp_var_data, .. } => { VarAlloc::Temp { temp_var_data, .. } => {
if !temp_var_data.use_set.contains(&(GenContext::Last(chunk_num), k)) { if !temp_var_data
.use_set
.contains(&(GenContext::Last(chunk_num), k))
{
return Some((t_var, self.alloc_with_ca(t_var))); return Some((t_var, self.alloc_with_ca(t_var)));
} }
} }
_ => { _ => {}
}
} }
None None
@@ -356,7 +384,9 @@ impl DebrayAllocator {
self.shallow_temp_mappings.swap_remove(&k); self.shallow_temp_mappings.swap_remove(&k);
self.shallow_temp_mappings.insert(r.reg_num(), var_num); self.shallow_temp_mappings.insert(r.reg_num(), var_num);
self.var_data.records[var_num].allocation.set_register(r.reg_num()); self.var_data.records[var_num]
.allocation
.set_register(r.reg_num());
self.in_use.insert(r.reg_num()); self.in_use.insert(r.reg_num());
} }
} }
@@ -417,12 +447,9 @@ impl DebrayAllocator {
fn in_place(&self, var_num: usize, term_loc: GenContext, r: RegType, k: usize) -> bool { fn in_place(&self, var_num: usize, term_loc: GenContext, r: RegType, k: usize) -> bool {
match term_loc { match term_loc {
GenContext::Head if !r.is_perm() => r.reg_num() == k, GenContext::Head if !r.is_perm() => r.reg_num() == k,
_ => { _ => match &self.var_data.records[var_num].allocation {
match &self.var_data.records[var_num].allocation { &VarAlloc::Temp { temp_reg, .. } if r.reg_num() == k => temp_reg == k,
&VarAlloc::Temp { temp_reg, .. } if r.reg_num() == k =>
temp_reg == k,
_ => false, _ => false,
}
}, },
} }
} }
@@ -483,8 +510,7 @@ impl DebrayAllocator {
VarAlloc::Perm(p, PermVarAllocation::Pending) if *p > 0 => { VarAlloc::Perm(p, PermVarAllocation::Pending) if *p > 0 => {
return Some(std::mem::replace(p, 0)); return Some(std::mem::replace(p, 0));
} }
_ => { _ => {}
}
} }
} else { } else {
return None; return None;
@@ -500,8 +526,7 @@ impl DebrayAllocator {
*allocation = PermVarAllocation::Pending; *allocation = PermVarAllocation::Pending;
self.add_perm_to_free_list(chunk_num, var_num); self.add_perm_to_free_list(chunk_num, var_num);
} }
_ => { _ => {}
}
} }
} }
@@ -509,7 +534,14 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator(); let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation { match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { VarAlloc::Perm(
_,
PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
) => {
*deep_safety = VarSafetyStatus::unneeded(branch_designator); *deep_safety = VarSafetyStatus::unneeded(branch_designator);
*shallow_safety = VarSafetyStatus::unneeded(branch_designator); *shallow_safety = VarSafetyStatus::unneeded(branch_designator);
} }
@@ -524,7 +556,14 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator(); let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation { match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { VarAlloc::Perm(
_,
PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
) => {
// GetVariable in head chunk is considered safe. // GetVariable in head chunk is considered safe.
if lvl == Level::Deep { if lvl == Level::Deep {
*deep_safety = VarSafetyStatus::unneeded(branch_designator); *deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -532,12 +571,16 @@ impl DebrayAllocator {
} else if term_loc == GenContext::Head { } else if term_loc == GenContext::Head {
*shallow_safety = VarSafetyStatus::GloballyUnneeded; *shallow_safety = VarSafetyStatus::GloballyUnneeded;
} else { } else {
if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() { if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned()
{
match &mut self.var_data.records[temp_var_num].allocation { match &mut self.var_data.records[temp_var_num].allocation {
VarAlloc::Temp { ref mut to_perm_var_num, .. } => { VarAlloc::Temp {
ref mut to_perm_var_num,
..
} => {
*to_perm_var_num = Some(var_num); *to_perm_var_num = Some(var_num);
} }
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@@ -560,8 +603,18 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator(); let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation { match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => { VarAlloc::Perm(
if !self.in_tail_position || self.branch_stack.safety_unneeded_in_branch(shallow_safety, &branch_designator) { _,
PermVarAllocation::Done {
ref mut shallow_safety,
..
},
) => {
if !self.in_tail_position
|| self
.branch_stack
.safety_unneeded_in_branch(shallow_safety, &branch_designator)
{
Target::argument_to_value(r, arg_c) Target::argument_to_value(r, arg_c)
} else { } else {
*shallow_safety = VarSafetyStatus::unneeded(branch_designator); *shallow_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -569,7 +622,10 @@ impl DebrayAllocator {
} }
} }
VarAlloc::Temp { ref mut safety, .. } => { VarAlloc::Temp { ref mut safety, .. } => {
if self.branch_stack.safety_unneeded_in_branch(safety, &branch_designator) { if self
.branch_stack
.safety_unneeded_in_branch(safety, &branch_designator)
{
Target::argument_to_value(r, arg_c) Target::argument_to_value(r, arg_c)
} else { } else {
*safety = VarSafetyStatus::GloballyUnneeded; *safety = VarSafetyStatus::GloballyUnneeded;
@@ -590,8 +646,17 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator(); let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation { match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => { VarAlloc::Perm(
if self.branch_stack.safety_unneeded_in_branch(deep_safety, &branch_designator) { _,
PermVarAllocation::Done {
ref mut deep_safety,
..
},
) => {
if self
.branch_stack
.safety_unneeded_in_branch(deep_safety, &branch_designator)
{
Target::subterm_to_value(r) Target::subterm_to_value(r)
} else { } else {
*deep_safety = VarSafetyStatus::unneeded(branch_designator); *deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -599,7 +664,10 @@ impl DebrayAllocator {
} }
} }
VarAlloc::Temp { ref mut safety, .. } => { VarAlloc::Temp { ref mut safety, .. } => {
if self.branch_stack.safety_unneeded_in_branch(safety, &branch_designator) { if self
.branch_stack
.safety_unneeded_in_branch(safety, &branch_designator)
{
Target::subterm_to_value(r) Target::subterm_to_value(r)
} else { } else {
*safety = VarSafetyStatus::unneeded(branch_designator); *safety = VarSafetyStatus::unneeded(branch_designator);
@@ -626,7 +694,7 @@ impl Allocator for DebrayAllocator {
in_use: BitSet::default(), in_use: BitSet::default(),
temp_free_list: vec![], temp_free_list: vec![],
perm_free_list: VecDeque::new(), perm_free_list: VecDeque::new(),
branch_stack: BranchStack { stack: vec![] } branch_stack: BranchStack { stack: vec![] },
} }
} }
@@ -705,12 +773,14 @@ impl Allocator for DebrayAllocator {
} }
r @ RegType::Perm(_) => { r @ RegType::Perm(_) => {
let is_new_var = match &mut self.var_data.records[var_num].allocation { let is_new_var = match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, allocation) => if allocation.pending() { VarAlloc::Perm(_, allocation) => {
if allocation.pending() {
*allocation = PermVarAllocation::done(); *allocation = PermVarAllocation::done();
true true
} else { } else {
false false
}, }
}
_ => unreachable!(), _ => unreachable!(),
}; };
@@ -828,7 +898,9 @@ impl Allocator for DebrayAllocator {
if !r.is_perm() && r.reg_num() == 0 { if !r.is_perm() && r.reg_num() == 0 {
self.in_use.insert(idx + 1); self.in_use.insert(idx + 1);
self.shallow_temp_mappings.insert(idx + 1, var_num); self.shallow_temp_mappings.insert(idx + 1, var_num);
self.var_data.records[var_num].allocation.set_register(idx + 1); self.var_data.records[var_num]
.allocation
.set_register(idx + 1);
} }
} }
} }

View File

@@ -24,12 +24,12 @@ use crate::atom_table::Atom;
use std::alloc::{alloc, Layout}; use std::alloc::{alloc, Layout};
use std::any::Any; use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error;
use std::ffi::{CString, c_void};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::error::Error;
use std::ffi::{c_void, CString};
use libffi::low::{ffi_cif, types, CodePtr, ffi_abi_FFI_DEFAULT_ABI, prep_cif, ffi_type, type_tag}; use libffi::low::{ffi_abi_FFI_DEFAULT_ABI, ffi_cif, ffi_type, prep_cif, type_tag, types, CodePtr};
use libloading::{Symbol, Library}; use libloading::{Library, Symbol};
pub struct FunctionDefinition { pub struct FunctionDefinition {
pub name: String, pub name: String,
@@ -74,7 +74,14 @@ impl ForeignFunctionTable {
let mut struct_type: ffi_type = Default::default(); let mut struct_type: ffi_type = Default::default();
struct_type.type_ = type_tag::STRUCT; struct_type.type_ = type_tag::STRUCT;
struct_type.elements = fields.as_mut_ptr(); struct_type.elements = fields.as_mut_ptr();
self.structs.insert(name.to_string(), StructImpl { ffi_type: struct_type, fields, atom_fields}); self.structs.insert(
name.to_string(),
StructImpl {
ffi_type: struct_type,
fields,
atom_fields,
},
);
} }
fn map_type_ffi(&mut self, source: &Atom) -> *mut ffi_type { fn map_type_ffi(&mut self, source: &Atom) -> *mut ffi_type {
@@ -94,47 +101,59 @@ impl ForeignFunctionTable {
atom!("ptr") => &mut types::pointer, atom!("ptr") => &mut types::pointer,
atom!("f32") => &mut types::float, atom!("f32") => &mut types::float,
atom!("f64") => &mut types::double, atom!("f64") => &mut types::double,
struct_name => { struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
match self.structs.get_mut(struct_name.as_str()) { Some(ref mut struct_type) => &mut struct_type.ffi_type,
Some(ref mut struct_type) => { None => unreachable!(),
&mut struct_type.ffi_type
}, },
None => unreachable!()
}
}
} }
} }
} }
pub(crate) fn load_library(&mut self, library_name: &str, functions: &Vec<FunctionDefinition>) -> Result<(), Box<dyn Error>> { pub(crate) fn load_library(
&mut self,
library_name: &str,
functions: &Vec<FunctionDefinition>,
) -> Result<(), Box<dyn Error>> {
let mut ff_table: ForeignFunctionTable = Default::default(); let mut ff_table: ForeignFunctionTable = Default::default();
unsafe { unsafe {
let library = Library::new(library_name)?; let library = Library::new(library_name)?;
for function in functions { for function in functions {
let symbol_name: CString = CString::new(function.name.clone())?; let symbol_name: CString = CString::new(function.name.clone())?;
let code_ptr: Symbol<*mut c_void> = library.get(&symbol_name.into_bytes_with_nul())?; let code_ptr: Symbol<*mut c_void> =
let mut args: Vec<_> = function.args.iter().map(|x| self.map_type_ffi(&x)).collect(); library.get(&symbol_name.into_bytes_with_nul())?;
let mut args: Vec<_> = function
.args
.iter()
.map(|x| self.map_type_ffi(&x))
.collect();
let mut cif: ffi_cif = Default::default(); let mut cif: ffi_cif = Default::default();
prep_cif( prep_cif(
&mut cif, &mut cif,
ffi_abi_FFI_DEFAULT_ABI, ffi_abi_FFI_DEFAULT_ABI,
args.len(), args.len(),
self.map_type_ffi(&function.return_value), self.map_type_ffi(&function.return_value),
args.as_mut_ptr() args.as_mut_ptr(),
).unwrap(); )
.unwrap();
let return_struct_name = if (*self.map_type_ffi(&function.return_value)).type_ as u32 == libffi::raw::FFI_TYPE_STRUCT { let return_struct_name = if (*self.map_type_ffi(&function.return_value)).type_
as u32
== libffi::raw::FFI_TYPE_STRUCT
{
Some(function.return_value.as_str().to_string()) Some(function.return_value.as_str().to_string())
} else { } else {
None None
}; };
ff_table.table.insert(function.name.clone(), FunctionImpl { ff_table.table.insert(
function.name.clone(),
FunctionImpl {
cif, cif,
args, args,
code_ptr: CodePtr(code_ptr.into_raw().into_raw() as *mut _), code_ptr: CodePtr(code_ptr.into_raw().into_raw() as *mut _),
return_struct_name, return_struct_name,
}); },
);
} }
std::mem::forget(library); std::mem::forget(library);
} }
@@ -142,21 +161,24 @@ impl ForeignFunctionTable {
Ok(()) Ok(())
} }
fn build_pointer_args(args: &mut Vec<Value>, type_args: &Vec<*mut ffi_type>, structs_table: &mut HashMap<String, StructImpl>) -> Result<PointerArgs, FFIError> { fn build_pointer_args(
args: &mut Vec<Value>,
type_args: &Vec<*mut ffi_type>,
structs_table: &mut HashMap<String, StructImpl>,
) -> Result<PointerArgs, FFIError> {
let mut pointers = Vec::with_capacity(args.len()); let mut pointers = Vec::with_capacity(args.len());
let mut _memory = Vec::new(); let mut _memory = Vec::new();
for i in 0..args.len() { for i in 0..args.len() {
let field_type = type_args[i]; let field_type = type_args[i];
unsafe { unsafe {
macro_rules! push_int { macro_rules! push_int {
($type:ty) => { ($type:ty) => {{
{ let n: $type = <$type>::try_from(args[i].as_int()?)
let n: $type = <$type>::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; .map_err(|_| FFIError::ValueDontFit)?;
let mut box_value = Box::new(n) as Box<dyn Any>; let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void); pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value); _memory.push(box_value);
} }};
}
} }
match (*field_type).type_ as u32 { match (*field_type).type_ as u32 {
@@ -173,38 +195,43 @@ impl ForeignFunctionTable {
let mut box_value = Box::new(n) as Box<dyn Any>; let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void); pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value); _memory.push(box_value);
}, }
libffi::raw::FFI_TYPE_DOUBLE => { libffi::raw::FFI_TYPE_DOUBLE => {
let n: f64 = args[i].as_float()?; let n: f64 = args[i].as_float()?;
let mut box_value = Box::new(n) as Box<dyn Any>; let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void); pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value); _memory.push(box_value);
}, }
libffi::raw::FFI_TYPE_POINTER => { libffi::raw::FFI_TYPE_POINTER => {
let ptr: *mut c_void = args[i].as_ptr()?; let ptr: *mut c_void = args[i].as_ptr()?;
pointers.push(ptr); pointers.push(ptr);
}, }
libffi::raw::FFI_TYPE_STRUCT => { libffi::raw::FFI_TYPE_STRUCT => {
let (mut ptr, _size, _align) = Self::build_struct(&mut args[i], structs_table)?; let (mut ptr, _size, _align) =
Self::build_struct(&mut args[i], structs_table)?;
pointers.push(&mut *ptr as *mut _ as *mut c_void); pointers.push(&mut *ptr as *mut _ as *mut c_void);
_memory.push(ptr); _memory.push(ptr);
}, }
_ => return Err(FFIError::InvalidFFIType) _ => return Err(FFIError::InvalidFFIType),
} }
} }
} }
Ok(PointerArgs { Ok(PointerArgs { pointers, _memory })
pointers,
_memory
})
} }
fn build_struct(arg: &mut Value, structs_table: &mut HashMap<String, StructImpl>) -> Result<(Box<dyn Any>, usize, usize), FFIError> { fn build_struct(
arg: &mut Value,
structs_table: &mut HashMap<String, StructImpl>,
) -> Result<(Box<dyn Any>, usize, usize), FFIError> {
unsafe { unsafe {
match arg { match arg {
Value::Struct(ref name, ref mut struct_args) => { Value::Struct(ref name, ref mut struct_args) => {
if let Some(ref mut struct_type) = structs_table.clone().get_mut(name) { if let Some(ref mut struct_type) = structs_table.clone().get_mut(name) {
let layout = Layout::from_size_align(struct_type.ffi_type.size, struct_type.ffi_type.alignment.into()).unwrap(); let layout = Layout::from_size_align(
struct_type.ffi_type.size,
struct_type.ffi_type.alignment.into(),
)
.unwrap();
let align = struct_type.ffi_type.alignment as usize; let align = struct_type.ffi_type.alignment as usize;
let size = struct_type.ffi_type.size; let size = struct_type.ffi_type.size;
let ptr = alloc(layout) as *mut c_void; let ptr = alloc(layout) as *mut c_void;
@@ -212,24 +239,22 @@ impl ForeignFunctionTable {
for i in 0..(struct_type.fields.len() - 1) { for i in 0..(struct_type.fields.len() - 1) {
macro_rules! try_write_int { macro_rules! try_write_int {
($type:ty) => { ($type:ty) => {{
{ field_ptr = field_ptr
field_ptr = field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>())); .add(field_ptr.align_offset(std::mem::align_of::<$type>()));
let n: $type = <$type>::try_from(struct_args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; let n: $type = <$type>::try_from(struct_args[i].as_int()?)
.map_err(|_| FFIError::ValueDontFit)?;
std::ptr::write(field_ptr as *mut $type, n); std::ptr::write(field_ptr as *mut $type, n);
field_ptr = field_ptr.add(std::mem::size_of::<$type>()); field_ptr = field_ptr.add(std::mem::size_of::<$type>());
} }};
}
} }
macro_rules! write { macro_rules! write {
($type:ty, $value:expr) => { ($type:ty, $value:expr) => {{
{
let data: $type = $value; let data: $type = $value;
std::ptr::write(field_ptr as *mut $type, data); std::ptr::write(field_ptr as *mut $type, data);
field_ptr = field_ptr.add(align); field_ptr = field_ptr.add(align);
} }};
}
} }
let field = struct_type.fields[i]; let field = struct_type.fields[i];
@@ -242,16 +267,27 @@ impl ForeignFunctionTable {
libffi::raw::FFI_TYPE_SINT32 => try_write_int!(i32), libffi::raw::FFI_TYPE_SINT32 => try_write_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => try_write_int!(u64), libffi::raw::FFI_TYPE_UINT64 => try_write_int!(u64),
libffi::raw::FFI_TYPE_SINT64 => try_write_int!(i64), libffi::raw::FFI_TYPE_SINT64 => try_write_int!(i64),
libffi::raw::FFI_TYPE_POINTER => write!(*mut c_void, struct_args[i].as_ptr()?), libffi::raw::FFI_TYPE_POINTER => {
libffi::raw::FFI_TYPE_FLOAT => write!(f32, struct_args[i].as_float()? as f32), write!(*mut c_void, struct_args[i].as_ptr()?)
libffi::raw::FFI_TYPE_DOUBLE => write!(f64, struct_args[i].as_float()?), }
libffi::raw::FFI_TYPE_FLOAT => {
write!(f32, struct_args[i].as_float()? as f32)
}
libffi::raw::FFI_TYPE_DOUBLE => {
write!(f64, struct_args[i].as_float()?)
}
libffi::raw::FFI_TYPE_STRUCT => { libffi::raw::FFI_TYPE_STRUCT => {
let (struct_ptr, struct_size, struct_align) = Self::build_struct(&mut struct_args[i], structs_table)?; let (struct_ptr, struct_size, struct_align) =
Self::build_struct(&mut struct_args[i], structs_table)?;
field_ptr = field_ptr.add(field_ptr.align_offset(struct_align)); field_ptr = field_ptr.add(field_ptr.align_offset(struct_align));
std::ptr::copy(& *struct_ptr as *const _ as *const c_void, field_ptr as *mut c_void, struct_size); std::ptr::copy(
&*struct_ptr as *const _ as *const c_void,
field_ptr as *mut c_void,
struct_size,
);
field_ptr = field_ptr.add(struct_size); field_ptr = field_ptr.add(struct_size);
}, }
_ => { _ => {
unreachable!() unreachable!()
} }
@@ -262,29 +298,28 @@ impl ForeignFunctionTable {
return Err(FFIError::InvalidStructName); return Err(FFIError::InvalidStructName);
} }
} }
_ => return Err(FFIError::ValueCast) _ => return Err(FFIError::ValueCast),
} }
} }
} }
pub fn exec(&mut self, name: &str, mut args: Vec<Value>) -> Result<Value, FFIError> { pub fn exec(&mut self, name: &str, mut args: Vec<Value>) -> Result<Value, FFIError> {
let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?; let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?;
let mut pointer_args = Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?; let mut pointer_args =
Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?;
return unsafe { return unsafe {
macro_rules! call_and_return { macro_rules! call_and_return {
($type:ty) => { ($type:ty) => {{
{
let mut n: Box<u8> = Box::new(0); let mut n: Box<u8> = Box::new(0);
libffi::raw::ffi_call( libffi::raw::ffi_call(
&mut function_impl.cif, &mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()), Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void, &mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
); );
Ok(Value::Int(i64::from(*n))) Ok(Value::Int(i64::from(*n)))
} }};
}
} }
match (*function_impl.cif.rtype).type_ as u32 { match (*function_impl.cif.rtype).type_ as u32 {
@@ -301,10 +336,12 @@ impl ForeignFunctionTable {
&mut function_impl.cif, &mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()), Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void, &mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
); );
Ok(Value::Int(i64::try_from(*n).map_err(|_| FFIError::ValueDontFit)?)) Ok(Value::Int(
}, i64::try_from(*n).map_err(|_| FFIError::ValueDontFit)?,
))
}
libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64), libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64),
libffi::raw::FFI_TYPE_POINTER => call_and_return!(*mut c_void), libffi::raw::FFI_TYPE_POINTER => call_and_return!(*mut c_void),
libffi::raw::FFI_TYPE_FLOAT => { libffi::raw::FFI_TYPE_FLOAT => {
@@ -313,42 +350,54 @@ impl ForeignFunctionTable {
&mut function_impl.cif, &mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()), Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void, &mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
); );
Ok(Value::Float((*n).into())) Ok(Value::Float((*n).into()))
}, }
libffi::raw::FFI_TYPE_DOUBLE => { libffi::raw::FFI_TYPE_DOUBLE => {
let mut n: Box<f64> = Box::new(0.0); let mut n: Box<f64> = Box::new(0.0);
libffi::raw::ffi_call( libffi::raw::ffi_call(
&mut function_impl.cif, &mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()), Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void, &mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
); );
Ok(Value::Float(*n)) Ok(Value::Float(*n))
}, }
libffi::raw::FFI_TYPE_STRUCT => { libffi::raw::FFI_TYPE_STRUCT => {
let name = &function_impl.return_struct_name.clone().ok_or(FFIError::StructNotFound)?; let name = &function_impl
.return_struct_name
.clone()
.ok_or(FFIError::StructNotFound)?;
let struct_type = self.structs.get(name).ok_or(FFIError::StructNotFound)?; let struct_type = self.structs.get(name).ok_or(FFIError::StructNotFound)?;
let layout = Layout::from_size_align(struct_type.ffi_type.size, struct_type.ffi_type.alignment.into()).unwrap(); let layout = Layout::from_size_align(
struct_type.ffi_type.size,
struct_type.ffi_type.alignment.into(),
)
.unwrap();
let ptr = alloc(layout) as *mut c_void; let ptr = alloc(layout) as *mut c_void;
libffi::raw::ffi_call( libffi::raw::ffi_call(
&mut function_impl.cif, &mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()), Some(*function_impl.code_ptr.as_safe_fun()),
&mut *ptr as *mut _ as *mut c_void, &mut *ptr as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
); );
let struct_val = self.read_struct(ptr, name, struct_type); let struct_val = self.read_struct(ptr, name, struct_type);
drop(Box::from_raw(ptr)); drop(Box::from_raw(ptr));
struct_val struct_val
} }
_ => unreachable!() _ => unreachable!(),
} }
}; };
} }
fn read_struct(&self, ptr: *mut c_void, name: &str, struct_type: &StructImpl) -> Result<Value, FFIError> { fn read_struct(
&self,
ptr: *mut c_void,
name: &str,
struct_type: &StructImpl,
) -> Result<Value, FFIError> {
unsafe { unsafe {
let mut returns = Vec::new(); let mut returns = Vec::new();
let mut field_ptr = ptr; let mut field_ptr = ptr;
@@ -357,14 +406,13 @@ impl ForeignFunctionTable {
let field = struct_type.fields[i]; let field = struct_type.fields[i];
macro_rules! read_and_push_int { macro_rules! read_and_push_int {
($type:ty) => { ($type:ty) => {{
{ field_ptr =
field_ptr = field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>())); field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
let n = std::ptr::read(field_ptr as *mut $type); let n = std::ptr::read(field_ptr as *mut $type);
returns.push(Value::Int(i64::from(n))); returns.push(Value::Int(i64::from(n)));
field_ptr = field_ptr.add(std::mem::size_of::<$type>()); field_ptr = field_ptr.add(std::mem::size_of::<$type>());
} }};
}
} }
match (*field).type_ as u32 { match (*field).type_ as u32 {
@@ -375,21 +423,28 @@ impl ForeignFunctionTable {
libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32), libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32), libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => { libffi::raw::FFI_TYPE_UINT64 => {
field_ptr = field_ptr.add(field_ptr.align_offset(std::mem::align_of::<u64>())); field_ptr =
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<u64>()));
let n = std::ptr::read(field_ptr as *mut u64); let n = std::ptr::read(field_ptr as *mut u64);
returns.push(Value::Int(i64::try_from(n).map_err(|_| FFIError::ValueDontFit)?)); returns.push(Value::Int(
i64::try_from(n).map_err(|_| FFIError::ValueDontFit)?,
));
field_ptr = field_ptr.add(std::mem::size_of::<u64>()); field_ptr = field_ptr.add(std::mem::size_of::<u64>());
}, }
libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64), libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64),
libffi::raw::FFI_TYPE_POINTER => read_and_push_int!(i64), libffi::raw::FFI_TYPE_POINTER => read_and_push_int!(i64),
libffi::raw::FFI_TYPE_STRUCT => { libffi::raw::FFI_TYPE_STRUCT => {
let substruct = struct_type.atom_fields[i].as_str(); let substruct = struct_type.atom_fields[i].as_str();
let struct_type = self.structs.get(substruct).ok_or(FFIError::StructNotFound)?; let struct_type = self
field_ptr = field_ptr.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize)); .structs
let struct_val = self.read_struct(field_ptr, substruct, struct_type); .get(&*substruct)
.ok_or(FFIError::StructNotFound)?;
field_ptr = field_ptr
.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize));
let struct_val = self.read_struct(field_ptr, &*substruct, struct_type);
returns.push(struct_val?); returns.push(struct_val?);
field_ptr = field_ptr.add(struct_type.ffi_type.size); field_ptr = field_ptr.add(struct_type.ffi_type.size);
}, }
_ => { _ => {
unreachable!() unreachable!()
} }
@@ -428,7 +483,7 @@ impl Value {
match self { match self {
Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void), Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void),
Value::Int(n) => Ok(*n as *mut c_void), Value::Int(n) => Ok(*n as *mut c_void),
_ => Err(FFIError::ValueCast) _ => Err(FFIError::ValueCast),
} }
} }
} }

View File

@@ -7,8 +7,8 @@ use crate::machine::loader::PredicateQueue;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::parser::CompositeOpDesc;
use crate::parser::dashu::{Integer, Rational}; use crate::parser::dashu::{Integer, Rational};
use crate::parser::parser::CompositeOpDesc;
use crate::types::*; use crate::types::*;
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
@@ -58,7 +58,7 @@ impl AppendOrPrepend {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum VarComparison { pub enum VarComparison {
Indistinct, Indistinct,
Distinct Distinct,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -153,11 +153,14 @@ impl DerefMut for ChunkedTermVec {
impl ChunkedTermVec { impl ChunkedTermVec {
#[inline] #[inline]
pub fn new() -> Self { pub fn new() -> Self {
Self { chunk_vec: VecDeque::new() } Self {
chunk_vec: VecDeque::new(),
}
} }
pub fn reserve_branch(&mut self, capacity: usize) { pub fn reserve_branch(&mut self, capacity: usize) {
self.chunk_vec.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity))); self.chunk_vec
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
} }
pub fn push_branch_arm(&mut self, branch: VecDeque<ChunkedTerms>) { pub fn push_branch_arm(&mut self, branch: VecDeque<ChunkedTerms>) {
@@ -173,19 +176,22 @@ impl ChunkedTermVec {
#[inline] #[inline]
pub fn add_chunk(&mut self) { pub fn add_chunk(&mut self) {
self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![]))); self.chunk_vec
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![])));
} }
pub fn push_chunk_term(&mut self, term: QueryTerm) { pub fn push_chunk_term(&mut self, term: QueryTerm) {
match self.chunk_vec.back_mut() { match self.chunk_vec.back_mut() {
Some(ChunkedTerms::Branch(_)) => { Some(ChunkedTerms::Branch(_)) => {
self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term]))); self.chunk_vec
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
} }
Some(ChunkedTerms::Chunk(chunk)) => { Some(ChunkedTerms::Chunk(chunk)) => {
chunk.push_back(term); chunk.push_back(term);
} }
None => { None => {
self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term]))); self.chunk_vec
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
} }
} }
} }
@@ -266,7 +272,6 @@ impl ClauseInfo for Term {
fn name(&self) -> Option<Atom> { fn name(&self) -> Option<Atom> {
match self { match self {
Term::Clause(_, name, terms) => { Term::Clause(_, name, terms) => {
match name { match name {
atom!(":-") => { atom!(":-") => {
match terms.len() { match terms.len() {
@@ -285,7 +290,7 @@ impl ClauseInfo for Term {
fn arity(&self) -> usize { fn arity(&self) -> usize {
match self { match self {
Term::Clause(_, name, terms) => match name.as_str() { Term::Clause(_, name, terms) => match &*name.as_str() {
":-" => match terms.len() { ":-" => match terms.len() {
1 => 0, 1 => 0,
2 => terms[0].arity(), 2 => terms[0].arity(),
@@ -410,7 +415,6 @@ pub(crate) fn fixity(spec: u32) -> Fixity {
} }
} }
impl OpDecl { impl OpDecl {
#[inline] #[inline]
pub(crate) fn new(op_desc: OpDesc, name: Atom) -> Self { pub(crate) fn new(op_desc: OpDesc, name: Atom) -> Self {
@@ -477,35 +481,27 @@ pub enum AtomOrString {
impl AtomOrString { impl AtomOrString {
#[inline] #[inline]
pub fn as_atom(&self, atom_tbl: &mut AtomTable) -> Atom { pub fn as_atom(&self, atom_tbl: &AtomTable) -> Atom {
match self { match self {
&AtomOrString::Atom(atom) => { &AtomOrString::Atom(atom) => atom,
atom AtomOrString::String(string) => AtomTable::build_with(atom_tbl, &string),
}
AtomOrString::String(string) => {
atom_tbl.build_with(&string)
}
} }
} }
#[inline] #[inline]
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> AtomString<'_> {
match self { match self {
AtomOrString::Atom(atom) if atom == &atom!("[]") => "", AtomOrString::Atom(atom) if atom == &atom!("[]") => AtomString::Static(""),
AtomOrString::Atom(atom) => atom.as_str(), AtomOrString::Atom(atom) => atom.as_str(),
AtomOrString::String(string) => string.as_str(), AtomOrString::String(string) => AtomString::Static(string.as_str()),
} }
} }
#[inline] #[inline]
pub fn to_string(self) -> String { pub fn to_string(self) -> String {
match self { match self {
AtomOrString::Atom(atom) => { AtomOrString::Atom(atom) => atom.as_str().to_owned(),
atom.as_str().to_owned() AtomOrString::String(string) => string,
}
AtomOrString::String(string) => {
string
}
} }
} }
} }
@@ -561,9 +557,7 @@ pub(crate) fn fetch_op_spec(name: Atom, arity: usize, op_dir: &OpDir) -> Option<
} }
}) })
} }
0 => { 0 => fetch_atom_op_spec(name, None, op_dir),
fetch_atom_op_spec(name, None, op_dir)
}
_ => None, _ => None,
} }
} }
@@ -595,10 +589,7 @@ pub struct Module {
// Module's and related types are defined in forms. // Module's and related types are defined in forms.
impl Module { impl Module {
pub(crate) fn new( pub(crate) fn new(module_decl: ModuleDecl, listing_src: ListingSource) -> Self {
module_decl: ModuleDecl,
listing_src: ListingSource,
) -> Self {
Module { Module {
module_decl, module_decl,
code_dir: CodeDir::with_hasher(FxBuildHasher::default()), code_dir: CodeDir::with_hasher(FxBuildHasher::default()),
@@ -620,7 +611,7 @@ impl Module {
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()), meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()), extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher( local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
FxBuildHasher::default() FxBuildHasher::default(),
), ),
listing_src: ListingSource::DynamicallyGenerated, listing_src: ListingSource::DynamicallyGenerated,
} }
@@ -923,8 +914,10 @@ impl PredicateInfo {
#[inline] #[inline]
pub(crate) fn must_retract_local_clauses(&self, is_cross_module_clause: bool) -> bool { pub(crate) fn must_retract_local_clauses(&self, is_cross_module_clause: bool) -> bool {
self.is_extensible && self.has_clauses && !self.is_discontiguous && self.is_extensible
!(self.is_multifile && is_cross_module_clause) && self.has_clauses
&& !self.is_discontiguous
&& !(self.is_multifile && is_cross_module_clause)
} }
} }
@@ -1013,19 +1006,17 @@ impl PredicateSkeleton {
&mut self, &mut self,
clause_clause_loc: usize, clause_clause_loc: usize,
) -> Option<usize> { ) -> Option<usize> {
let search_result = self.core.clause_clause_locs let search_result = self.core.clause_clause_locs.make_contiguous()
.make_contiguous()[0..self.core.clause_assert_margin] [0..self.core.clause_assert_margin]
.binary_search_by(|loc| clause_clause_loc.cmp(&loc)); .binary_search_by(|loc| clause_clause_loc.cmp(&loc));
match search_result { match search_result {
Ok(loc) => Some(loc), Ok(loc) => Some(loc),
Err(_) => { Err(_) => self.core.clause_clause_locs.make_contiguous()
self.core.clause_clause_locs [self.core.clause_assert_margin..]
.make_contiguous()[self.core.clause_assert_margin..]
.binary_search_by(|loc| loc.cmp(&clause_clause_loc)) .binary_search_by(|loc| loc.cmp(&clause_clause_loc))
.map(|loc| loc + self.core.clause_assert_margin) .map(|loc| loc + self.core.clause_assert_margin)
.ok() .ok(),
}
} }
} }
} }

View File

@@ -73,12 +73,8 @@ impl IterStackLoc {
#[inline] #[inline]
pub fn as_ref(self) -> Ref { pub fn as_ref(self) -> Ref {
match self.heap_or_stack() { match self.heap_or_stack() {
HeapOrStackTag::Heap => { HeapOrStackTag::Heap => Ref::heap_cell(self.value() as usize),
Ref::heap_cell(self.value() as usize) HeapOrStackTag::Stack => Ref::stack_cell(self.value() as usize),
}
HeapOrStackTag::Stack => {
Ref::stack_cell(self.value() as usize)
}
} }
} }
} }
@@ -158,24 +154,16 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
#[inline] #[inline]
pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue { pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue {
match loc.heap_or_stack() { match loc.heap_or_stack() {
HeapOrStackTag::Heap => { HeapOrStackTag::Heap => &mut self.heap[loc.value() as usize],
&mut self.heap[loc.value() as usize] HeapOrStackTag::Stack => &mut self.machine_stack[loc.value() as usize],
}
HeapOrStackTag::Stack => {
&mut self.machine_stack[loc.value() as usize]
}
} }
} }
#[inline] #[inline]
pub fn read_cell(&self, loc: IterStackLoc) -> HeapCellValue { pub fn read_cell(&self, loc: IterStackLoc) -> HeapCellValue {
match loc.heap_or_stack() { match loc.heap_or_stack() {
HeapOrStackTag::Heap => { HeapOrStackTag::Heap => self.heap[loc.value() as usize],
self.heap[loc.value() as usize] HeapOrStackTag::Stack => self.machine_stack[loc.value() as usize],
}
HeapOrStackTag::Stack => {
self.machine_stack[loc.value() as usize]
}
} }
} }
@@ -228,7 +216,10 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
if !cell.get_mark_bit() { if !cell.get_mark_bit() {
cell.set_mark_bit(true); cell.set_mark_bit(true);
self.stack.push(IterStackLoc::iterable_loc(loc.value() as usize, loc.heap_or_stack())); self.stack.push(IterStackLoc::iterable_loc(
loc.value() as usize,
loc.heap_or_stack(),
));
} }
} }
@@ -236,7 +227,10 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
while let Some(h) = self.stack.pop() { while let Some(h) = self.stack.pop() {
if h.is_pending_mark() { if h.is_pending_mark() {
self.push_if_unmarked(h); self.push_if_unmarked(h);
self.stack.push(IterStackLoc::mark_loc(h.value() as usize, h.heap_or_stack())); self.stack.push(IterStackLoc::mark_loc(
h.value() as usize,
h.heap_or_stack(),
));
self.forward_if_referent_marked(h); self.forward_if_referent_marked(h);
continue; continue;
@@ -508,7 +502,6 @@ mod tests {
use super::*; use super::*;
use crate::machine::mock_wam::*; use crate::machine::mock_wam::*;
#[test] #[test]
fn heap_stackless_iter_tests() { fn heap_stackless_iter_tests() {
let mut wam = MockWAM::new(); let mut wam = MockWAM::new();
@@ -629,12 +622,12 @@ mod tests {
{ {
wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(0));
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), heap_loc_as_cell!(0)); assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
heap_loc_as_cell!(0)
);
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
@@ -650,10 +643,7 @@ mod tests {
wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(empty_list_as_cell!());
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -688,10 +678,7 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(0));
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -721,7 +708,8 @@ mod tests {
// first a 'dangling' partial string, later modified to be a two-part complete string, // first a 'dangling' partial string, later modified to be a two-part complete string,
// then a three-part cyclic string involving an uncompacted list of chars. // then a three-part cyclic string involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl); let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{ {
@@ -742,11 +730,8 @@ mod tests {
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string( let pstr_second_var_cell =
&mut wam.machine_st.heap, put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
"def",
&mut wam.machine_st.atom_tbl,
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
@@ -771,13 +756,12 @@ mod tests {
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(4)); wam.machine_st.heap.push(pstr_loc_as_cell!(4));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(2))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(2)));
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(4));
&mut wam.machine_st.heap,
pstr_loc_as_cell!(4),
);
let pstr_offset_cell = pstr_offset_as_cell!(0); let pstr_offset_cell = pstr_offset_as_cell!(0);
@@ -789,19 +773,35 @@ mod tests {
} }
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_loc_as_cell!(2)); assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
pstr_loc_as_cell!(2)
);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_loc_as_cell!(4)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_offset_as_cell!(0)); unmark_cell_bits!(wam.machine_st.heap[3]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[5]), fixnum_as_cell!(Fixnum::build_with(2))); pstr_loc_as_cell!(4)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[4]),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[5]),
fixnum_as_cell!(Fixnum::build_with(2))
);
wam.machine_st.heap.truncate(4); wam.machine_st.heap.truncate(4);
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1)); wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{ {
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
@@ -819,7 +819,9 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
{ {
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
@@ -827,8 +829,14 @@ mod tests {
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); assert_eq!(
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
@@ -1059,10 +1067,22 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), heap_loc_as_cell!(1)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(2)); unmark_cell_bits!(wam.machine_st.heap[0]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3)); heap_loc_as_cell!(1)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), heap_loc_as_cell!(3)); );
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
heap_loc_as_cell!(2)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[2]),
heap_loc_as_cell!(3)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[3]),
heap_loc_as_cell!(3)
);
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
@@ -1089,9 +1109,18 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), list_loc_as_cell!(1)); unmark_cell_bits!(wam.machine_st.heap[0]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(1)); list_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
list_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[2]),
list_loc_as_cell!(1)
);
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
@@ -1202,37 +1231,109 @@ mod tests {
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1)); unmark_cell_bits!(wam.machine_st.heap[0]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3)); list_loc_as_cell!(1)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), list_loc_as_cell!(4)); );
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), str_loc_as_cell!(6)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[5]), heap_loc_as_cell!(8)); unmark_cell_bits!(wam.machine_st.heap[1]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(f_atom, 1)); heap_loc_as_cell!(1)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(11)); );
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[8]), list_loc_as_cell!(9)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[9]), heap_loc_as_cell!(9)); unmark_cell_bits!(wam.machine_st.heap[2]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[10]), empty_list_as_cell!()); heap_loc_as_cell!(3)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[11]), attr_var_as_cell!(11)); );
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[12]), heap_loc_as_cell!(13)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[13]), list_loc_as_cell!(14)); unmark_cell_bits!(wam.machine_st.heap[3]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[14]), str_loc_as_cell!(16)); list_loc_as_cell!(4)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[15]), heap_loc_as_cell!(19)); );
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[16]), atom_as_cell!(clpz_atom, 2)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[17]), atom_as_cell!(a_atom)); unmark_cell_bits!(wam.machine_st.heap[4]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[18]), atom_as_cell!(b_atom)); str_loc_as_cell!(6)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[19]), list_loc_as_cell!(20)); );
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[20]), str_loc_as_cell!(22)); assert_eq!(
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[21]), empty_list_as_cell!()); unmark_cell_bits!(wam.machine_st.heap[5]),
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[22]), atom_as_cell!(p_atom, 1)); heap_loc_as_cell!(8)
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[23]), heap_loc_as_cell!(23)); );
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[6]),
atom_as_cell!(f_atom, 1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[7]),
heap_loc_as_cell!(11)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[8]),
list_loc_as_cell!(9)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[9]),
heap_loc_as_cell!(9)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[10]),
empty_list_as_cell!()
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[11]),
attr_var_as_cell!(11)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[12]),
heap_loc_as_cell!(13)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[13]),
list_loc_as_cell!(14)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[14]),
str_loc_as_cell!(16)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[15]),
heap_loc_as_cell!(19)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[16]),
atom_as_cell!(clpz_atom, 2)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[17]),
atom_as_cell!(a_atom)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[18]),
atom_as_cell!(b_atom)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[19]),
list_loc_as_cell!(20)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[20]),
str_loc_as_cell!(22)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[21]),
empty_list_as_cell!()
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[22]),
atom_as_cell!(p_atom, 1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[23]),
heap_loc_as_cell!(23)
);
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
fixnum_as_cell!(Fixnum::build_with(0)) fixnum_as_cell!(Fixnum::build_with(0)),
); );
assert_eq!( assert_eq!(
@@ -1256,10 +1357,7 @@ mod tests {
wam.machine_st.heap.push(atom_as_cell!(atom!("y"))); wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(1));
&mut wam.machine_st.heap,
str_loc_as_cell!(1),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -1271,10 +1369,7 @@ mod tests {
atom_as_cell!(atom!("y")) atom_as_cell!(atom!("y"))
); );
assert_eq!( assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(1)
);
assert!(iter.next().is_none()); assert!(iter.next().is_none());
} }
@@ -1288,10 +1383,7 @@ mod tests {
wam.machine_st.heap.push(atom_as_cell!(atom!("y"))); wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -1303,10 +1395,7 @@ mod tests {
atom_as_cell!(atom!("y")) atom_as_cell!(atom!("y"))
); );
assert_eq!( assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(0)
);
assert!(iter.next().is_none()); assert!(iter.next().is_none());
} }
@@ -1327,10 +1416,7 @@ mod tests {
wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(empty_list_as_cell!());
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(7));
&mut wam.machine_st.heap,
heap_loc_as_cell!(7),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -1390,10 +1476,7 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(1));
{ {
let mut iter = stackless_preorder_iter( let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -1462,7 +1545,8 @@ mod tests {
let a_atom = atom!("a"); let a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
wam.machine_st.heap wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{ {
@@ -1686,7 +1770,8 @@ mod tests {
// two-part complete string, then a three-part cyclic string // two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars. // involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl); let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{ {
@@ -1710,7 +1795,8 @@ mod tests {
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl); let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
{ {
@@ -1731,10 +1817,14 @@ mod tests {
} }
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1)); wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{ {
let mut iter = stackful_preorder_iter( let mut iter = stackful_preorder_iter(
@@ -1750,7 +1840,10 @@ mod tests {
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64))); assert_eq!(
iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(0i64))
);
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
@@ -1764,7 +1857,9 @@ mod tests {
*/ */
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
{ {
let mut iter = stackful_preorder_iter( let mut iter = stackful_preorder_iter(
@@ -1781,13 +1876,19 @@ mod tests {
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1i64))); assert_eq!(
iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(1i64))
);
let h = iter.focus(); let h = iter.focus();
assert_eq!(h.value(), 5); assert_eq!(h.value(), 5);
assert_eq!(unmark_cell_bits!(iter.heap[4]), pstr_offset_as_cell!(0)); assert_eq!(unmark_cell_bits!(iter.heap[4]), pstr_offset_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.heap[5]), fixnum_as_cell!(Fixnum::build_with(1i64))); assert_eq!(
unmark_cell_bits!(iter.heap[5]),
fixnum_as_cell!(Fixnum::build_with(1i64))
);
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
@@ -1980,10 +2081,7 @@ mod tests {
pstr_as_cell!(atom!("a string")) pstr_as_cell!(atom!("a string"))
); );
assert_eq!( assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
iter.next().unwrap(),
empty_list_as_cell!()
);
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
} }
@@ -2037,7 +2135,8 @@ mod tests {
let a_atom = atom!("a"); let a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
wam.machine_st.heap wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{ {
@@ -2075,7 +2174,8 @@ mod tests {
] ]
)); ));
for _ in 0..20 { // 0000 { for _ in 0..20 {
// 0000 {
let mut iter = stackful_post_order_iter( let mut iter = stackful_post_order_iter(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
@@ -2263,7 +2363,8 @@ mod tests {
// two-part complete string, then a three-part cyclic string // two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars. // involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl); let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{ {
@@ -2286,7 +2387,8 @@ mod tests {
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl); let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
{ {
@@ -2307,10 +2409,14 @@ mod tests {
} }
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1)); wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{ {
let mut iter = stackful_post_order_iter( let mut iter = stackful_post_order_iter(
@@ -2319,8 +2425,14 @@ mod tests {
pstr_loc_as_cell!(0), pstr_loc_as_cell!(0),
); );
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64))); assert_eq!(
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(0i64))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2329,7 +2441,9 @@ mod tests {
} }
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
{ {
let mut iter = stackful_post_order_iter( let mut iter = stackful_post_order_iter(
@@ -2338,8 +2452,14 @@ mod tests {
pstr_loc_as_cell!(0), pstr_loc_as_cell!(0),
); );
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1i64))); assert_eq!(
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(1i64))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2498,13 +2618,12 @@ mod tests {
let a_atom = atom!("a"); let a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
wam.machine_st.heap.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{ {
let mut iter = stackless_post_order_iter( let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2535,10 +2654,7 @@ mod tests {
)); ));
for _ in 0..20 { for _ in 0..20 {
let mut iter = stackless_post_order_iter( let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0)); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
@@ -2568,10 +2684,8 @@ mod tests {
{ {
wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(0));
let mut iter = stackless_post_order_iter( let mut iter =
&mut wam.machine_st.heap, stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
heap_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2587,10 +2701,8 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(1));
wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(0));
let mut iter = stackless_post_order_iter( let mut iter =
&mut wam.machine_st.heap, stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
heap_loc_as_cell!(0),
);
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2615,7 +2727,8 @@ mod tests {
wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(empty_list_as_cell!());
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2647,7 +2760,8 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(0));
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
// the cycle will be iterated twice before being detected. // the cycle will be iterated twice before being detected.
assert_eq!( assert_eq!(
@@ -2675,7 +2789,8 @@ mod tests {
} }
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
// cut the iteration short to check that all cells are // cut the iteration short to check that all cells are
// unmarked and unforwarded by the Drop instance of // unmarked and unforwarded by the Drop instance of
@@ -2705,11 +2820,13 @@ mod tests {
// two-part complete string, then a three-part cyclic string // two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars. // involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl); let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2724,16 +2841,14 @@ mod tests {
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string( let pstr_second_var_cell =
&mut wam.machine_st.heap, put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
"def",
&mut wam.machine_st.atom_tbl,
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2749,20 +2864,31 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1)); wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0)));
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
let mut pstr_loc_cell = pstr_loc_as_cell!(0); let mut pstr_loc_cell = pstr_loc_as_cell!(0);
pstr_loc_cell.set_forwarding_bit(true); pstr_loc_cell.set_forwarding_bit(true);
// assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64))); // assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); assert_eq!(
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2773,14 +2899,23 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1)));
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
//assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1))); //assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); assert_eq!(
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2801,7 +2936,8 @@ mod tests {
wam.machine_st.heap.extend(functor); wam.machine_st.heap.extend(functor);
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
@@ -2861,7 +2997,8 @@ mod tests {
wam.machine_st.heap[4] = list_loc_as_cell!(1); wam.machine_st.heap[4] = list_loc_as_cell!(1);
{ {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),

View File

@@ -29,6 +29,7 @@ use std::convert::TryFrom;
use std::iter::once; use std::iter::once;
use std::net::{IpAddr, TcpListener}; use std::net::{IpAddr, TcpListener};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
/* contains the location, name, precision and Specifier of the parent op. */ /* contains the location, name, precision and Specifier of the parent op. */
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@@ -74,7 +75,7 @@ fn needs_bracketing(child_desc: OpDesc, op: &DirectedOp) -> bool {
DirectedOp::Left(name, cell) => { DirectedOp::Left(name, cell) => {
let (priority, spec) = cell.get(); let (priority, spec) = cell.get();
if name.as_str() == "-" { if &*name.as_str() == "-" {
let child_assoc = child_desc.get_spec(); let child_assoc = child_desc.get_spec();
if is_prefix!(spec) && (is_postfix!(child_assoc) || is_infix!(child_assoc)) { if is_prefix!(spec) && (is_postfix!(child_assoc) || is_infix!(child_assoc)) {
return true; return true;
@@ -178,10 +179,9 @@ fn char_to_string(is_quoted: bool, c: char) -> String {
'\u{08}' if is_quoted => "\\b".to_string(), // UTF-8 backspace '\u{08}' if is_quoted => "\\b".to_string(), // UTF-8 backspace
'\u{07}' if is_quoted => "\\a".to_string(), // UTF-8 alert '\u{07}' if is_quoted => "\\a".to_string(), // UTF-8 alert
'\\' if is_quoted => "\\\\".to_string(), '\\' if is_quoted => "\\\\".to_string(),
' ' | '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => { ' ' | '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"'
c.to_string() | '\\' => c.to_string(),
} _ => {
_ =>
if c.is_whitespace() || c.is_control() { if c.is_whitespace() || c.is_control() {
// print all other control and whitespace characters in hex. // print all other control and whitespace characters in hex.
format!("\\x{:x}\\", c as u32) format!("\\x{:x}\\", c as u32)
@@ -190,6 +190,7 @@ fn char_to_string(is_quoted: bool, c: char) -> String {
} }
} }
} }
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
enum NumberFocus { enum NumberFocus {
@@ -217,7 +218,8 @@ enum TokenOrRedirect {
CompositeRedirect(usize, DirectedOp), CompositeRedirect(usize, DirectedOp),
CurlyBracketRedirect(usize), CurlyBracketRedirect(usize),
FunctorRedirect(usize), FunctorRedirect(usize),
#[allow(unused)] IpAddr(IpAddr), #[allow(unused)]
IpAddr(IpAddr),
NumberFocus(usize, NumberFocus, Option<DirectedOp>), NumberFocus(usize, NumberFocus, Option<DirectedOp>),
Open, Open,
Close, Close,
@@ -479,7 +481,7 @@ 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>,
atom_tbl: &'a mut AtomTable, atom_tbl: Arc<AtomTable>,
op_dir: &'a OpDir, op_dir: &'a OpDir,
state_stack: Vec<TokenOrRedirect>, state_stack: Vec<TokenOrRedirect>,
toplevel_spec: Option<DirectedOp>, toplevel_spec: Option<DirectedOp>,
@@ -548,7 +550,7 @@ 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,
atom_tbl: &'a mut AtomTable, atom_tbl: Arc<AtomTable>,
stack: &'a mut Stack, stack: &'a mut Stack,
op_dir: &'a OpDir, op_dir: &'a OpDir,
output: Outputter, output: Outputter,
@@ -625,11 +627,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} else { } else {
let op = DirectedOp::Left(name, spec); let op = DirectedOp::Left(name, spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(max_depth, op));
self.state_stack.push(TokenOrRedirect::Op(name, spec)); self.state_stack.push(TokenOrRedirect::Op(name, spec));
} }
} else { } else {
match name.as_str() { match &*name.as_str() {
"|" => { "|" => {
self.format_bar_separator_op(max_depth, name, spec); self.format_bar_separator_op(max_depth, name, spec);
return; return;
@@ -653,9 +656,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let left_directed_op = DirectedOp::Left(name, spec); let left_directed_op = DirectedOp::Left(name, spec);
let right_directed_op = DirectedOp::Right(name, spec); let right_directed_op = DirectedOp::Right(name, spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op)); self.state_stack.push(TokenOrRedirect::CompositeRedirect(
max_depth,
left_directed_op,
));
self.state_stack.push(TokenOrRedirect::Op(name, spec)); self.state_stack.push(TokenOrRedirect::Op(name, spec));
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op)); self.state_stack.push(TokenOrRedirect::CompositeRedirect(
max_depth,
right_directed_op,
));
} }
} }
} }
@@ -681,7 +690,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Close); self.state_stack.push(TokenOrRedirect::Close);
for _ in 0..arity { for _ in 0..arity {
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.state_stack.push(TokenOrRedirect::Comma); self.state_stack.push(TokenOrRedirect::Comma);
} }
@@ -738,9 +748,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
return false; return false;
} }
self.state_stack.push(TokenOrRedirect::RightCurly); self.state_stack.push(TokenOrRedirect::RightCurly);
self.state_stack.push(TokenOrRedirect::CurlyBracketRedirect(max_depth)); self.state_stack
.push(TokenOrRedirect::CurlyBracketRedirect(max_depth));
self.state_stack.push(TokenOrRedirect::LeftCurly); self.state_stack.push(TokenOrRedirect::LeftCurly);
true true
@@ -750,10 +760,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let h = self.iter.stack_last().unwrap(); let h = self.iter.stack_last().unwrap();
let cell = self.iter.read_cell(h); let cell = self.iter.read_cell(h);
let cell = heap_bound_store( let cell = heap_bound_store(&self.iter.heap, heap_bound_deref(&self.iter.heap, cell));
&self.iter.heap,
heap_bound_deref(&self.iter.heap, cell),
);
// 7.10.4 // 7.10.4
if let Some(var) = numbervar(&self.numbervars_offset, cell) { if let Some(var) = numbervar(&self.numbervars_offset, cell) {
@@ -835,10 +842,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if let Some(cell) = self.iter.next() { if let Some(cell) = self.iter.next() {
let is_cyclic = cell.get_forwarding_bit(); let is_cyclic = cell.get_forwarding_bit();
let cell = heap_bound_store( let cell = heap_bound_store(self.iter.heap, heap_bound_deref(self.iter.heap, cell));
self.iter.heap,
heap_bound_deref(self.iter.heap, cell),
);
let cell = unmark_cell_bits!(cell); let cell = unmark_cell_bits!(cell);
match self.var_names.get(&cell).cloned() { match self.var_names.get(&cell).cloned() {
@@ -891,7 +895,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} }
fn print_impromptu_atom(&mut self, atom: Atom) { fn print_impromptu_atom(&mut self, atom: Atom) {
let result = self.print_op_addendum(atom.as_str()); let result = self.print_op_addendum(&*atom.as_str());
push_space_if_amb!(self, result.as_str(), { push_space_if_amb!(self, result.as_str(), {
append_str!(self, &result); append_str!(self, &result);
@@ -1050,7 +1054,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
NumberFocus::Denominator(r), NumberFocus::Denominator(r),
left_directed_op, left_directed_op,
)); ));
self.state_stack.push(TokenOrRedirect::Op(rdiv_ct, *op_desc)); self.state_stack
.push(TokenOrRedirect::Op(rdiv_ct, *op_desc));
self.state_stack.push(TokenOrRedirect::NumberFocus( self.state_stack.push(TokenOrRedirect::NumberFocus(
max_depth, max_depth,
NumberFocus::Numerator(r), NumberFocus::Numerator(r),
@@ -1157,8 +1162,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset => { HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset => {
self.iter.pop_stack(); self.iter.pop_stack();
} }
HeapCellValueTag::CStr => { HeapCellValueTag::CStr => {}
}
_ => { _ => {
unreachable!(); unreachable!();
} }
@@ -1203,8 +1207,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
append_str!(self, "[]"); append_str!(self, "[]");
} }
} else { } else {
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack
self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap)); .push(TokenOrRedirect::FunctorRedirect(max_depth));
self.iter
.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
} }
} }
} else { } else {
@@ -1298,7 +1304,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} }
} }
self.state_stack.push(TokenOrRedirect::CloseList(switch.clone())); self.state_stack
.push(TokenOrRedirect::CloseList(switch.clone()));
Some(switch) Some(switch)
} }
@@ -1335,9 +1342,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let switch = self.close_list(cell); let switch = self.close_list(cell);
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth+1)); self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
self.open_list(switch); self.open_list(switch);
} }
@@ -1353,8 +1362,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
max_depth: usize, max_depth: usize,
) { ) {
let add_brackets = if !self.ignore_ops { let add_brackets = if !self.ignore_ops {
negated_operand || negated_operand
if let Some(ref op) = op { || if let Some(ref op) = op {
if self.numbervars && arity == 1 && name == atom!("$VAR") { if self.numbervars && arity == 1 && name == atom!("$VAR") {
!self.iter.immediate_leaf_has_property(|addr| { !self.iter.immediate_leaf_has_property(|addr| {
match Number::try_from(addr) { match Number::try_from(addr) {
@@ -1381,7 +1390,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Open); self.state_stack.push(TokenOrRedirect::Open);
if !self.outputter.ends_with(" ") { if !self.outputter.ends_with(" ") {
let parent_op = self.parent_of_first_op let parent_op = self
.parent_of_first_op
.and_then(|(parent_op, last_item_idx)| { .and_then(|(parent_op, last_item_idx)| {
// if parent_op isn't printed to the output string // if parent_op isn't printed to the output string
// already, then it doesn't border the present op // already, then it doesn't border the present op
@@ -1395,7 +1405,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
for op in &[op, parent_op] { for op in &[op, parent_op] {
if let Some(ref op) = &op { if let Some(ref op) = &op {
if op.is_left() && (op.is_prefix() || requires_space(op.as_atom().as_str(), "(")) { if op.is_left()
&& (op.is_prefix() || requires_space(&*op.as_atom().as_str(), "("))
{
self.state_stack.push(TokenOrRedirect::Space); self.state_stack.push(TokenOrRedirect::Space);
return; return;
} }
@@ -1519,7 +1531,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
max_depth, max_depth,
); );
} else { } else {
push_space_if_amb!(printer, name.as_str(), { push_space_if_amb!(printer, &*name.as_str(), {
printer.format_clause(max_depth, arity, name, None); printer.format_clause(max_depth, arity, name, None);
}); });
} }
@@ -1529,14 +1541,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if let Some(ref op) = op { if let Some(ref op) = op {
let op_is_prefix = op.is_prefix() && op.is_left(); let op_is_prefix = op.is_prefix() && op.is_left();
if op_is_prefix || printer.outputter.ends_with(&format!(" {}", op.as_atom().as_str())) { if op_is_prefix
|| printer
.outputter
.ends_with(&format!(" {}", op.as_atom().as_str()))
{
result.push(' '); result.push(' ');
} }
result.push('('); result.push('(');
} }
result += &printer.print_op_addendum(name.as_str()); result += &printer.print_op_addendum(&*name.as_str());
if op.is_some() { if op.is_some() {
result.push(')'); result.push(')');
@@ -1546,7 +1562,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
append_str!(printer, &result); append_str!(printer, &result);
}); });
} else { } else {
push_space_if_amb!(printer, name.as_str(), { push_space_if_amb!(printer, &*name.as_str(), {
printer.print_impromptu_atom(name); printer.print_impromptu_atom(name);
}); });
} }
@@ -1557,7 +1573,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
None => return, None => return,
}; };
if !addr.is_var() && !addr.is_compound(&self.iter.heap) && self.max_depth_exhausted(max_depth) { if !addr.is_var()
&& !addr.is_compound(&self.iter.heap)
&& self.max_depth_exhausted(max_depth)
{
self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
return; return;
} }
@@ -1567,7 +1586,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
print_struct(self, name, arity); print_struct(self, name, arity);
} }
(HeapCellValueTag::Char, c) => { (HeapCellValueTag::Char, c) => {
let name = self.atom_tbl.build_with(&String::from(c)); let name = AtomTable::build_with(&self.atom_tbl, &String::from(c));
print_struct(self, name, 0); print_struct(self, name, 0);
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
@@ -1585,7 +1604,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
max_depth, max_depth,
); );
} else { } else {
push_space_if_amb!(self, name.as_str(), { push_space_if_amb!(self, &*name.as_str(), {
self.format_clause(max_depth, arity, name, None); self.format_clause(max_depth, arity, name, None);
}); });
} }
@@ -1668,7 +1687,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
TokenOrRedirect::BarAsOp => append_str!(self, " | "), TokenOrRedirect::BarAsOp => append_str!(self, " | "),
TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c), TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c),
TokenOrRedirect::Op(atom, op) => { TokenOrRedirect::Op(atom, op) => {
self.print_op(atom.as_str()); self.print_op(&*atom.as_str());
if is_prefix!(op.get_spec()) { if is_prefix!(op.get_spec()) {
self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op))); self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op)));
@@ -1737,16 +1756,18 @@ mod tests {
let b_atom = atom!("b"); let b_atom = atom!("b");
let c_atom = atom!("c"); let c_atom = atom!("c");
wam.machine_st.heap.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
heap_loc_as_cell!(0) heap_loc_as_cell!(0),
); );
let output = printer.print(); let output = printer.print();
@@ -1771,11 +1792,11 @@ mod tests {
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
heap_loc_as_cell!(0) heap_loc_as_cell!(0),
); );
let output = printer.print(); let output = printer.print();
@@ -1795,11 +1816,11 @@ mod tests {
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
heap_loc_as_cell!(0) heap_loc_as_cell!(0),
); );
let output = printer.print(); let output = printer.print();
@@ -1808,14 +1829,16 @@ 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.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
heap_loc_as_cell!(0) heap_loc_as_cell!(0),
); );
printer.var_names.insert(list_loc_as_cell!(1), VarPtr::from("L")); printer
.var_names
.insert(list_loc_as_cell!(1), VarPtr::from("L"));
let output = printer.print(); let output = printer.print();
@@ -1839,7 +1862,7 @@ mod tests {
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -1858,7 +1881,7 @@ mod tests {
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -1875,14 +1898,16 @@ 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.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
heap_loc_as_cell!(0) heap_loc_as_cell!(0),
); );
printer.var_names.insert(list_loc_as_cell!(1), VarPtr::from("L")); printer
.var_names
.insert(list_loc_as_cell!(1), VarPtr::from("L"));
let output = printer.print(); let output = printer.print();
@@ -1905,11 +1930,11 @@ 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.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
heap_loc_as_cell!(0) heap_loc_as_cell!(0),
); );
printer.max_depth = 5; printer.max_depth = 5;
@@ -1923,16 +1948,16 @@ mod tests {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
put_partial_string(&mut wam.machine_st.heap, "abc", &mut wam.machine_st.atom_tbl); put_partial_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
pstr_loc_as_cell!(0) pstr_loc_as_cell!(0),
); );
let output = printer.print(); let output = printer.print();
@@ -1956,7 +1981,7 @@ 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.atom_tbl, Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -2000,35 +2025,39 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir.insert( wam.op_dir
(atom!("+"), Fixity::In), .insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
OpDesc::build_with(500, YFX as u8), wam.op_dir
); .insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
wam.op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
assert_eq!(&wam.parse_and_print_term("[a|[] + b].").unwrap(), "[a|[]+b]"); assert_eq!(
&wam.parse_and_print_term("[a|[] + b].").unwrap(),
"[a|[]+b]"
);
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(), "[a|[b|c]*d]"); assert_eq!(
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
"[a|[b|c]*d]"
);
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir.insert( wam.op_dir
(atom!("fy"), Fixity::Pre), .insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY as u8));
OpDesc::build_with(9, FY as u8),
wam.op_dir
.insert((atom!("yf"), Fixity::Post), OpDesc::build_with(9, YF as u8));
assert_eq!(
&wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(),
"(fy (fy 1)yf)yf"
); );
wam.op_dir.insert( assert_eq!(
(atom!("yf"), Fixity::Post), &wam.parse_and_print_term("fy(fy(yf(fy(1)))).").unwrap(),
OpDesc::build_with(9, YF as u8), "fy fy (fy 1)yf"
); );
assert_eq!(&wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(), "(fy (fy 1)yf)yf");
assert_eq!(&wam.parse_and_print_term("fy(fy(yf(fy(1)))).").unwrap(), "fy fy (fy 1)yf");
} }
} }

View File

@@ -1,13 +1,13 @@
use std::sync::{Arc, Mutex, Condvar};
use std::future::Future;
use std::pin::Pin;
use http_body_util::Full;
use bytes::Bytes; use bytes::Bytes;
use http_body_util::Full;
use hyper::service::Service; use hyper::service::Service;
use hyper::{body::Incoming as IncomingBody, Request, Response}; use hyper::{body::Incoming as IncomingBody, Request, Response};
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Condvar, Mutex};
pub struct HttpListener { pub struct HttpListener {
pub incoming: std::sync::mpsc::Receiver<HttpRequest> pub incoming: std::sync::mpsc::Receiver<HttpRequest>,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -31,7 +31,10 @@ impl Service<Request<IncomingBody>> for HttpService {
// new connection! // new connection!
// we send the Request info to Prolog // we send the Request info to Prolog
let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new())); let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
let http_request = HttpRequest { request: req, response: Arc::clone(&response) }; let http_request = HttpRequest {
request: req,
response: Arc::clone(&response),
};
self.tx.send(http_request).unwrap(); self.tx.send(http_request).unwrap();
// we wait for the Response info from Prolog // we wait for the Response info from Prolog
@@ -46,9 +49,7 @@ impl Service<Request<IncomingBody>> for HttpService {
let (_, response, _) = &*response; let (_, response, _) = &*response;
let response = response.lock().unwrap().take(); let response = response.lock().unwrap().take();
let res = response.expect("Data race error in HTTP Server"); let res = response.expect("Data race error in HTTP Server");
Box::pin(async move { Box::pin(async move { Ok(res) })
Ok(res)
})
} }
} }
} }

View File

@@ -150,17 +150,20 @@ impl<'a> IndexingCodeMergingPtr<'a> {
let third_level_index = if self.append_or_prepend.is_append() { let third_level_index = if self.append_or_prepend.is_append() {
vec![ vec![
IndexedChoiceInstruction::Try(external), IndexedChoiceInstruction::Try(external),
IndexedChoiceInstruction::Trust(index) IndexedChoiceInstruction::Trust(index),
].into() ]
.into()
} else { } else {
vec![ vec![
IndexedChoiceInstruction::Try(index), IndexedChoiceInstruction::Try(index),
IndexedChoiceInstruction::Trust(external) IndexedChoiceInstruction::Trust(external),
].into() ]
.into()
}; };
let indexing_code_len = self.indexing_code.len(); let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index)); self.indexing_code
.push(IndexingLine::IndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] { match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => {
@@ -188,7 +191,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
}; };
let indexing_code_len = self.indexing_code.len(); let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::DynamicIndexedChoice(third_level_index)); self.indexing_code
.push(IndexingLine::DynamicIndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] { match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => {
@@ -275,10 +279,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
); );
} }
None | Some(IndexingCodePtr::Fail) => { None | Some(IndexingCodePtr::Fail) => {
constants.insert( constants
overlapping_constant, .insert(overlapping_constant, IndexingCodePtr::External(index));
IndexingCodePtr::External(index),
);
} }
Some(IndexingCodePtr::DynamicExternal(o)) => { Some(IndexingCodePtr::DynamicExternal(o)) => {
self.add_dynamic_indexed_choice_for_constant( self.add_dynamic_indexed_choice_for_constant(
@@ -345,16 +347,10 @@ impl<'a> IndexingCodeMergingPtr<'a> {
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => {
match constants.get(&constant).cloned() { match constants.get(&constant).cloned() {
None | Some(IndexingCodePtr::Fail) if self.is_dynamic => { None | Some(IndexingCodePtr::Fail) if self.is_dynamic => {
constants.insert( constants.insert(constant, IndexingCodePtr::DynamicExternal(index));
constant,
IndexingCodePtr::DynamicExternal(index),
);
} }
None | Some(IndexingCodePtr::Fail) => { None | Some(IndexingCodePtr::Fail) => {
constants.insert( constants.insert(constant, IndexingCodePtr::External(index));
constant,
IndexingCodePtr::External(index),
);
} }
Some(IndexingCodePtr::DynamicExternal(o)) => { Some(IndexingCodePtr::DynamicExternal(o)) => {
self.add_dynamic_indexed_choice_for_constant(o, constant, index); self.add_dynamic_indexed_choice_for_constant(o, constant, index);
@@ -432,17 +428,20 @@ impl<'a> IndexingCodeMergingPtr<'a> {
let third_level_index = if self.append_or_prepend.is_append() { let third_level_index = if self.append_or_prepend.is_append() {
vec![ vec![
IndexedChoiceInstruction::Try(external), IndexedChoiceInstruction::Try(external),
IndexedChoiceInstruction::Trust(index) IndexedChoiceInstruction::Trust(index),
].into() ]
.into()
} else { } else {
vec![ vec![
IndexedChoiceInstruction::Try(index), IndexedChoiceInstruction::Try(index),
IndexedChoiceInstruction::Trust(external) IndexedChoiceInstruction::Trust(external),
].into() ]
.into()
}; };
let indexing_code_len = self.indexing_code.len(); let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index)); self.indexing_code
.push(IndexingLine::IndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] { match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => {
@@ -470,7 +469,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
}; };
let indexing_code_len = self.indexing_code.len(); let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::DynamicIndexedChoice(third_level_index)); self.indexing_code
.push(IndexingLine::DynamicIndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] { match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => {
@@ -584,13 +584,15 @@ impl<'a> IndexingCodeMergingPtr<'a> {
let third_level_index = if self.append_or_prepend.is_append() { let third_level_index = if self.append_or_prepend.is_append() {
vec![ vec![
IndexedChoiceInstruction::Try(o), IndexedChoiceInstruction::Try(o),
IndexedChoiceInstruction::Trust(index) IndexedChoiceInstruction::Trust(index),
].into() ]
.into()
} else { } else {
vec![ vec![
IndexedChoiceInstruction::Try(index), IndexedChoiceInstruction::Try(index),
IndexedChoiceInstruction::Trust(o) IndexedChoiceInstruction::Trust(o),
].into() ]
.into()
}; };
self.indexing_code self.indexing_code
@@ -636,11 +638,7 @@ pub(crate) fn merge_clause_index(
for overlapping_constant in overlapping_constants { for overlapping_constant in overlapping_constants {
merging_ptr.offset = 0; merging_ptr.offset = 0;
merging_ptr.index_overlapping_constant( merging_ptr.index_overlapping_constant(*constant, *overlapping_constant, offset);
*constant,
*overlapping_constant,
offset,
);
} }
} }
OptArgIndexKey::Structure(_, index_loc, name, arity) => { OptArgIndexKey::Structure(_, index_loc, name, arity) => {
@@ -1060,8 +1058,7 @@ fn cap_choice_seq(prelude: &mut [IndexedChoiceInstruction]) {
#[inline] #[inline]
fn cap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) { fn cap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
prelude.last_mut().map(|instr| { prelude.last_mut().map(|instr| match instr {
match instr {
IndexedChoiceInstruction::Retry(i) => { IndexedChoiceInstruction::Retry(i) => {
*instr = IndexedChoiceInstruction::Trust(*i); *instr = IndexedChoiceInstruction::Trust(*i);
} }
@@ -1069,14 +1066,12 @@ fn cap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
*instr = IndexedChoiceInstruction::DefaultTrust(*i); *instr = IndexedChoiceInstruction::DefaultTrust(*i);
} }
_ => {} _ => {}
}
}); });
} }
#[inline] #[inline]
fn uncap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) { fn uncap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
prelude.last_mut().map(|instr| { prelude.last_mut().map(|instr| match instr {
match instr {
IndexedChoiceInstruction::Trust(i) => { IndexedChoiceInstruction::Trust(i) => {
*instr = IndexedChoiceInstruction::Retry(*i); *instr = IndexedChoiceInstruction::Retry(*i);
} }
@@ -1084,7 +1079,6 @@ fn uncap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
*instr = IndexedChoiceInstruction::DefaultRetry(*i); *instr = IndexedChoiceInstruction::DefaultRetry(*i);
} }
_ => {} _ => {}
}
}); });
} }
@@ -1099,7 +1093,7 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) {
pub(crate) fn constant_key_alternatives( pub(crate) fn constant_key_alternatives(
constant: Literal, constant: Literal,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
// arena: &mut Arena, // arena: &mut Arena,
) -> Vec<Literal> { ) -> Vec<Literal> {
let mut constants = vec![]; let mut constants = vec![];
@@ -1111,7 +1105,7 @@ pub(crate) fn constant_key_alternatives(
} }
} }
Literal::Char(c) => { Literal::Char(c) => {
let atom = atom_tbl.build_with(&c.to_string()); let atom = AtomTable::build_with(&atom_tbl, &c.to_string());
constants.push(Literal::Atom(atom)); constants.push(Literal::Atom(atom));
} }
/* /*
@@ -1129,9 +1123,11 @@ pub(crate) fn constant_key_alternatives(
*/ */
Literal::Integer(ref n) => { Literal::Integer(ref n) => {
if let Some(n) = n.to_isize() { if let Some(n) = n.to_isize() {
Fixnum::build_with_checked(n as i64).map(|n| { Fixnum::build_with_checked(n as i64)
.map(|n| {
constants.push(Literal::Fixnum(n)); constants.push(Literal::Fixnum(n));
}).unwrap(); })
.unwrap();
} }
} }
_ => {} _ => {}
@@ -1159,11 +1155,19 @@ pub(crate) trait Indexer {
fn new() -> Self; fn new() -> Self;
fn constants(&mut self) -> &mut IndexMap<Literal, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>; fn constants(
&mut self,
) -> &mut IndexMap<Literal, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn lists(&mut self) -> &mut VecDeque<Self::ThirdLevelIndex>; fn lists(&mut self) -> &mut VecDeque<Self::ThirdLevelIndex>;
fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>; fn structures(
&mut self,
) -> &mut IndexMap<(Atom, usize), VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn compute_index(is_initial_index: bool, index: usize, non_counted_bt: bool) -> Self::ThirdLevelIndex; fn compute_index(
is_initial_index: bool,
index: usize,
non_counted_bt: bool,
) -> Self::ThirdLevelIndex;
fn second_level_index<IndexKey: Eq + Hash>( fn second_level_index<IndexKey: Eq + Hash>(
indices: IndexMap<IndexKey, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>, indices: IndexMap<IndexKey, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>,
@@ -1199,7 +1203,9 @@ impl Indexer for StaticCodeIndices {
} }
#[inline] #[inline]
fn constants(&mut self) -> &mut IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> { fn constants(
&mut self,
) -> &mut IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
&mut self.constants &mut self.constants
} }
@@ -1209,11 +1215,17 @@ impl Indexer for StaticCodeIndices {
} }
#[inline] #[inline]
fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher> { fn structures(
&mut self,
) -> &mut IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
&mut self.structures &mut self.structures
} }
fn compute_index(is_initial_index: bool, index: usize, non_counted_bt: bool) -> IndexedChoiceInstruction { fn compute_index(
is_initial_index: bool,
index: usize,
non_counted_bt: bool,
) -> IndexedChoiceInstruction {
if is_initial_index { if is_initial_index {
IndexedChoiceInstruction::Try(index + 1) IndexedChoiceInstruction::Try(index + 1)
} else if non_counted_bt { } else if non_counted_bt {
@@ -1245,7 +1257,9 @@ impl Indexer for StaticCodeIndices {
} }
fn switch_on<IndexKey: Eq + Hash>( fn switch_on<IndexKey: Eq + Hash>(
mut instr_fn: impl FnMut(IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>) -> IndexingInstruction, mut instr_fn: impl FnMut(
IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>,
) -> IndexingInstruction,
index: &mut IndexMap<IndexKey, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>, index: &mut IndexMap<IndexKey, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
prelude: &mut VecDeque<IndexingLine>, prelude: &mut VecDeque<IndexingLine>,
) -> IndexingCodePtr { ) -> IndexingCodePtr {
@@ -1345,7 +1359,9 @@ impl Indexer for DynamicCodeIndices {
for (key, code) in indices.into_iter() { for (key, code) in indices.into_iter() {
if code.len() > 1 { if code.len() > 1 {
index_locs.insert(key, IndexingCodePtr::Internal(prelude.len() + 1)); index_locs.insert(key, IndexingCodePtr::Internal(prelude.len() + 1));
prelude.push_back(IndexingLine::DynamicIndexedChoice(code.into_iter().collect())); prelude.push_back(IndexingLine::DynamicIndexedChoice(
code.into_iter().collect(),
));
} else { } else {
code.front().map(|i| { code.front().map(|i| {
index_locs.insert(key, IndexingCodePtr::DynamicExternal(*i)); index_locs.insert(key, IndexingCodePtr::DynamicExternal(*i));
@@ -1357,7 +1373,9 @@ impl Indexer for DynamicCodeIndices {
} }
fn switch_on<IndexKey: Eq + Hash>( fn switch_on<IndexKey: Eq + Hash>(
mut instr_fn: impl FnMut(IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>) -> IndexingInstruction, mut instr_fn: impl FnMut(
IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>,
) -> IndexingInstruction,
index: &mut IndexMap<IndexKey, VecDeque<usize>, FxBuildHasher>, index: &mut IndexMap<IndexKey, VecDeque<usize>, FxBuildHasher>,
prelude: &mut VecDeque<IndexingLine>, prelude: &mut VecDeque<IndexingLine>,
) -> IndexingCodePtr { ) -> IndexingCodePtr {
@@ -1384,7 +1402,9 @@ impl Indexer for DynamicCodeIndices {
) -> IndexingCodePtr { ) -> IndexingCodePtr {
if lists.len() > 1 { if lists.len() > 1 {
let lists = mem::replace(lists, VecDeque::new()); let lists = mem::replace(lists, VecDeque::new());
prelude.push_back(IndexingLine::DynamicIndexedChoice(lists.into_iter().collect())); prelude.push_back(IndexingLine::DynamicIndexedChoice(
lists.into_iter().collect(),
));
IndexingCodePtr::Internal(1) IndexingCodePtr::Internal(1)
} else { } else {
lists lists
@@ -1434,15 +1454,23 @@ impl<I: Indexer> CodeOffsets<I> {
fn index_constant( fn index_constant(
&mut self, &mut self,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
constant: Literal, constant: Literal,
index: usize, index: usize,
) -> Vec<Literal> { ) -> Vec<Literal> {
let overlapping_constants = constant_key_alternatives(constant, atom_tbl); let overlapping_constants = constant_key_alternatives(constant, atom_tbl);
let code = self.indices.constants().entry(constant).or_insert(VecDeque::new()); let code = self
.indices
.constants()
.entry(constant)
.or_insert(VecDeque::new());
let is_initial_index = code.is_empty(); let is_initial_index = code.is_empty();
code.push_back(I::compute_index(is_initial_index, index, self.non_counted_bt)); code.push_back(I::compute_index(
is_initial_index,
index,
self.non_counted_bt,
));
for constant in &overlapping_constants { for constant in &overlapping_constants {
let code = self let code = self
@@ -1470,7 +1498,11 @@ impl<I: Indexer> CodeOffsets<I> {
let code_len = code.len(); let code_len = code.len();
let is_initial_index = code.is_empty(); let is_initial_index = code.is_empty();
code.push_back(I::compute_index(is_initial_index, index, self.non_counted_bt)); code.push_back(I::compute_index(
is_initial_index,
index,
self.non_counted_bt,
));
code_len code_len
} }
@@ -1479,7 +1511,7 @@ impl<I: Indexer> CodeOffsets<I> {
optimal_arg: &Term, optimal_arg: &Term,
index: usize, index: usize,
clause_index_info: &mut ClauseIndexInfo, clause_index_info: &mut ClauseIndexInfo,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) { ) {
match optimal_arg { match optimal_arg {
&Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => { &Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {

View File

@@ -62,9 +62,7 @@ impl<'a> TermIterState<'a> {
Term::PartialString(cell, string_buf, tail) => { Term::PartialString(cell, string_buf, tail) => {
TermIterState::InitialPartialString(lvl, cell, string_buf, tail) TermIterState::InitialPartialString(lvl, cell, string_buf, tail)
} }
Term::CompleteString(cell, atom) => { Term::CompleteString(cell, atom) => TermIterState::CompleteString(lvl, cell, *atom),
TermIterState::CompleteString(lvl, cell, *atom)
}
Term::Var(cell, var_ptr) => TermIterState::Var(lvl, cell, var_ptr.clone()), Term::Var(cell, var_ptr) => TermIterState::Var(lvl, cell, var_ptr.clone()),
} }
} }
@@ -77,7 +75,8 @@ pub(crate) struct QueryIterator<'a> {
impl<'a> QueryIterator<'a> { impl<'a> QueryIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) { fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::subterm_to_state(lvl, term)); self.state_stack
.push(TermIterState::subterm_to_state(lvl, term));
} }
/* /*
@@ -94,19 +93,16 @@ impl<'a> QueryIterator<'a> {
fn from_term(term: &'a Term) -> Self { fn from_term(term: &'a Term) -> Self {
let state = match term { let state = match term {
Term::AnonVar | Term::Cons(..) | Term::Literal(..) | Term::AnonVar
Term::PartialString(..) | Term::CompleteString(..) => { | Term::Cons(..)
| Term::Literal(..)
| Term::PartialString(..)
| Term::CompleteString(..) => {
return QueryIterator { return QueryIterator {
state_stack: vec![], state_stack: vec![],
} }
} }
Term::Clause(r, name, terms) => TermIterState::Clause( Term::Clause(r, name, terms) => TermIterState::Clause(Level::Root, 0, r, *name, terms),
Level::Root,
0,
r,
*name,
terms,
),
Term::Var(cell, var_ptr) => TermIterState::Var(Level::Root, cell, var_ptr.clone()), Term::Var(cell, var_ptr) => TermIterState::Var(Level::Root, cell, var_ptr.clone()),
}; };
@@ -118,18 +114,21 @@ impl<'a> QueryIterator<'a> {
fn extend_state(&mut self, lvl: Level, term: &'a QueryTerm) { fn extend_state(&mut self, lvl: Level, term: &'a QueryTerm) {
match term { match term {
&QueryTerm::Clause(ref cell, ClauseType::CallN(_), ref terms, _) => { &QueryTerm::Clause(ref cell, ClauseType::CallN(_), ref terms, _) => {
self.state_stack.push(TermIterState::Clause(lvl, 1, cell, atom!("$call"), terms)); self.state_stack
.push(TermIterState::Clause(lvl, 1, cell, atom!("$call"), terms));
} }
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => { &QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
self.state_stack.push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms)); self.state_stack
} .push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms));
_ => {
} }
_ => {}
} }
} }
pub fn new(term: &'a QueryTerm) -> Self { pub fn new(term: &'a QueryTerm) -> Self {
let mut iter = QueryIterator { state_stack: vec![] }; let mut iter = QueryIterator {
state_stack: vec![],
};
iter.extend_state(Level::Root, term); iter.extend_state(Level::Root, term);
iter iter
} }
@@ -170,13 +169,15 @@ impl<'a> Iterator for QueryIterator<'a> {
} }
} }
TermIterState::InitialCons(lvl, cell, head, tail) => { TermIterState::InitialCons(lvl, cell, head, tail) => {
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail)); self.state_stack
.push(TermIterState::FinalCons(lvl, cell, head, tail));
self.push_subterm(lvl.child_level(), tail); self.push_subterm(lvl.child_level(), tail);
self.push_subterm(lvl.child_level(), head); self.push_subterm(lvl.child_level(), head);
} }
TermIterState::InitialPartialString(lvl, cell, string, tail) => { TermIterState::InitialPartialString(lvl, cell, string, tail) => {
self.state_stack.push(TermIterState::FinalPartialString(lvl, cell, string, tail)); self.state_stack
.push(TermIterState::FinalPartialString(lvl, cell, string, tail));
self.push_subterm(lvl.child_level(), tail); self.push_subterm(lvl.child_level(), tail);
} }
TermIterState::FinalPartialString(lvl, cell, atom, tail) => { TermIterState::FinalPartialString(lvl, cell, atom, tail) => {
@@ -248,11 +249,7 @@ impl<'a> FactIterator<'a> {
)] )]
} }
Term::CompleteString(cell, atom) => { Term::CompleteString(cell, atom) => {
vec![TermIterState::CompleteString( vec![TermIterState::CompleteString(Level::Root, cell, *atom)]
Level::Root,
cell,
*atom,
)]
} }
Term::Literal(cell, constant) => { Term::Literal(cell, constant) => {
vec![TermIterState::Literal(Level::Root, cell, constant)] vec![TermIterState::Literal(Level::Root, cell, constant)]
@@ -319,7 +316,10 @@ pub(crate) fn post_order_iter<'a>(term: &'a Term) -> QueryIterator<'a> {
QueryIterator::from_term(term) QueryIterator::from_term(term)
} }
pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: RootIterationPolicy) -> FactIterator<'a> { pub(crate) fn breadth_first_iter<'a>(
term: &'a Term,
iterable_root: RootIterationPolicy,
) -> FactIterator<'a> {
FactIterator::new(term, iterable_root) FactIterator::new(term, iterable_root)
} }
@@ -356,18 +356,14 @@ fn state_from_chunked_terms<'a>(chunk_vec: &'a VecDeque<ChunkedTerms>) -> Clause
impl<'a> ClauseIterator<'a> { impl<'a> ClauseIterator<'a> {
pub fn new(clauses: &'a ChunkedTermVec) -> Self { pub fn new(clauses: &'a ChunkedTermVec) -> Self {
match state_from_chunked_terms(&clauses.chunk_vec) { match state_from_chunked_terms(&clauses.chunk_vec) {
state @ ClauseIteratorState::RemainingBranches(..) => { state @ ClauseIteratorState::RemainingBranches(..) => Self {
Self {
state_stack: vec![state], state_stack: vec![state],
remaining_chunks_on_stack: 0, remaining_chunks_on_stack: 0,
} },
} state @ ClauseIteratorState::RemainingChunks(..) => Self {
state @ ClauseIteratorState::RemainingChunks(..) => {
Self {
state_stack: vec![state], state_stack: vec![state],
remaining_chunks_on_stack: 1, remaining_chunks_on_stack: 1,
} },
}
} }
} }
@@ -403,14 +399,16 @@ impl<'a> Iterator for ClauseIterator<'a> {
match state { match state {
ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => { ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
if focus + 1 < chunks.len() { if focus + 1 < chunks.len() {
self.state_stack.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1)); self.state_stack
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
} else { } else {
self.remaining_chunks_on_stack -= 1; self.remaining_chunks_on_stack -= 1;
} }
match &chunks[focus] { match &chunks[focus] {
ChunkedTerms::Branch(branches) => { ChunkedTerms::Branch(branches) => {
self.state_stack.push(ClauseIteratorState::RemainingBranches(branches, 0)); self.state_stack
.push(ClauseIteratorState::RemainingBranches(branches, 0));
} }
ChunkedTerms::Chunk(chunk) => { ChunkedTerms::Chunk(chunk) => {
return Some(ClauseItem::Chunk(chunk)); return Some(ClauseItem::Chunk(chunk));
@@ -420,8 +418,11 @@ impl<'a> Iterator for ClauseIterator<'a> {
ClauseIteratorState::RemainingChunks(chunks, focus) => { ClauseIteratorState::RemainingChunks(chunks, focus) => {
debug_assert_eq!(chunks.len(), focus); debug_assert_eq!(chunks.len(), focus);
} }
ClauseIteratorState::RemainingBranches(branches, focus) if focus < branches.len() => { ClauseIteratorState::RemainingBranches(branches, focus)
self.state_stack.push(ClauseIteratorState::RemainingBranches(&branches, focus + 1)); if focus < branches.len() =>
{
self.state_stack
.push(ClauseIteratorState::RemainingBranches(&branches, focus + 1));
let state = state_from_chunked_terms(&branches[focus]); let state = state_from_chunked_terms(&branches[focus]);
if let ClauseIteratorState::RemainingChunks(..) = &state { if let ClauseIteratorState::RemainingChunks(..) = &state {

View File

@@ -17,13 +17,13 @@ pub mod codegen;
mod debray_allocator; mod debray_allocator;
#[cfg(feature = "ffi")] #[cfg(feature = "ffi")]
mod ffi; mod ffi;
mod variable_records;
mod forms; mod forms;
mod heap_iter; mod heap_iter;
pub mod heap_print; pub mod heap_print;
#[cfg(feature = "http")] #[cfg(feature = "http")]
mod http; mod http;
mod indexing; mod indexing;
mod variable_records;
#[macro_use] #[macro_use]
pub mod instructions { pub mod instructions {
include!(concat!(env!("OUT_DIR"), "/instructions.rs")); include!(concat!(env!("OUT_DIR"), "/instructions.rs"));
@@ -38,3 +38,5 @@ mod targets;
pub mod types; pub mod types;
use instructions::instr; use instructions::instr;
mod rcu;

View File

@@ -50,9 +50,7 @@ macro_rules! drop_iter_on_err {
}; };
} }
fn zero_divisor_eval_error( fn zero_divisor_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen {
stub_gen: impl Fn() -> FunctorStub + 'static,
) -> MachineStubGen {
Box::new(move |machine_st| { Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor); let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor);
let stub = stub_gen(); let stub = stub_gen();
@@ -61,9 +59,7 @@ fn zero_divisor_eval_error(
}) })
} }
fn undefined_eval_error( fn undefined_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen {
stub_gen: impl Fn() -> FunctorStub + 'static,
) -> MachineStubGen {
Box::new(move |machine_st| { Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::Undefined); let eval_error = machine_st.evaluation_error(EvalError::Undefined);
let stub = stub_gen(); let stub = stub_gen();
@@ -169,9 +165,7 @@ pub(crate) fn add(lhs: Number, rhs: Number, arena: &mut Arena) -> Result<Number,
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?)) Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
} }
(Number::Integer(n1), Number::Rational(n2)) (Number::Integer(n1), Number::Rational(n2))
| (Number::Rational(n2), Number::Integer(n1)) => { | (Number::Rational(n2), Number::Integer(n1)) => Ok(Number::arena_from(&*n1 + &*n2, arena)),
Ok(Number::arena_from(&*n1 + &*n2, arena))
}
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) (Number::Rational(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => { | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?)) Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
@@ -179,9 +173,7 @@ pub(crate) fn add(lhs: Number, rhs: Number, arena: &mut Arena) -> Result<Number,
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => { (Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
Ok(Number::Float(add_f(f1, f2)?)) Ok(Number::Float(add_f(f1, f2)?))
} }
(Number::Rational(r1), Number::Rational(r2)) => { (Number::Rational(r1), Number::Rational(r2)) => Ok(Number::arena_from(&*r1 + &*r2, arena)),
Ok(Number::arena_from(&*r1 + &*r2, arena))
}
} }
} }
@@ -197,12 +189,12 @@ pub(crate) fn neg(n: Number, arena: &mut Arena) -> Number {
Number::Integer(n) => { Number::Integer(n) => {
let n_clone: Integer = (*n).clone(); let n_clone: Integer = (*n).clone();
Number::arena_from(-Integer::from(n_clone), arena) Number::arena_from(-Integer::from(n_clone), arena)
}, }
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)), Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
Number::Rational(r) => { Number::Rational(r) => {
let r_clone: Rational = (*r).clone(); let r_clone: Rational = (*r).clone();
Number::arena_from(-Rational::from(r_clone), arena) Number::arena_from(-Rational::from(r_clone), arena)
}, }
} }
} }
@@ -219,12 +211,12 @@ pub(crate) fn abs(n: Number, arena: &mut Arena) -> Number {
Number::Integer(n) => { Number::Integer(n) => {
let n_clone: Integer = (*n).clone(); let n_clone: Integer = (*n).clone();
Number::arena_from(Integer::from(n_clone.abs()), arena) Number::arena_from(Integer::from(n_clone.abs()), arena)
}, }
Number::Float(f) => Number::Float(f.abs()), Number::Float(f) => Number::Float(f.abs()),
Number::Rational(r) => { Number::Rational(r) => {
let r_clone: Rational = (*r).clone(); let r_clone: Rational = (*r).clone();
Number::arena_from(Rational::from(r_clone.abs()), arena) Number::arena_from(Rational::from(r_clone.abs()), arena)
}, }
} }
} }
@@ -368,7 +360,11 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
(Number::Integer(n1), Number::Fixnum(n2)) => { (Number::Integer(n1), Number::Fixnum(n2)) => {
let n2_i = n2.get_num(); let n2_i = n2.get_num();
if !(&*n1 == &Integer::from(1) || &*n1 == &Integer::from(0) || &*n1 == &Integer::from(-1)) && n2_i < 0 { if !(&*n1 == &Integer::from(1)
|| &*n1 == &Integer::from(0)
|| &*n1 == &Integer::from(-1))
&& n2_i < 0
{
let n = Number::Integer(n1); let n = Number::Integer(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen)) Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else { } else {
@@ -377,7 +373,11 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
} }
} }
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
if !(&*n1 == &Integer::from(1) || &*n1 == &Integer::from(0) || &*n1 == &Integer::from(-1)) && &*n2 < &Integer::from(0) { if !(&*n1 == &Integer::from(1)
|| &*n1 == &Integer::from(0)
|| &*n1 == &Integer::from(-1))
&& &*n2 < &Integer::from(0)
{
let n = Number::Integer(n1); let n = Number::Integer(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen)) Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else { } else {
@@ -552,7 +552,7 @@ pub fn rational_from_number(
Number::Integer(n) => { Number::Integer(n) => {
let n_clone: Integer = (*n).clone(); let n_clone: Integer = (*n).clone();
Ok(arena_alloc!(Rational::from(n_clone), arena)) Ok(arena_alloc!(Rational::from(n_clone), arena))
}, }
} }
} }
@@ -668,22 +668,22 @@ pub(crate) fn shr(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
match n2.to_usize() { match n2.to_usize() {
Some(n2) => Ok(Number::arena_from(n1 >> n2, arena)), Some(n2) => Ok(Number::arena_from(n1 >> n2, arena)),
_ => { _ => Ok(Number::arena_from(n1 >> usize::max_value(), arena)),
Ok(Number::arena_from(n1 >> usize::max_value(), arena))
},
} }
} }
(Number::Integer(n1), Number::Fixnum(n2)) => match usize::try_from(n2.get_num()) { (Number::Integer(n1), Number::Fixnum(n2)) => match usize::try_from(n2.get_num()) {
Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 >> n2), arena)), Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 >> n2), arena)),
_ => { _ => Ok(Number::arena_from(
Ok(Number::arena_from(Integer::from(&*n1 >> usize::max_value()),arena)) Integer::from(&*n1 >> usize::max_value()),
}, arena,
)),
}, },
(Number::Integer(n1), Number::Integer(n2)) => match n2.to_usize() { (Number::Integer(n1), Number::Integer(n2)) => match n2.to_usize() {
Some(n2) => Ok(Number::arena_from(Integer::from(&*n1 >> n2), arena)), Some(n2) => Ok(Number::arena_from(Integer::from(&*n1 >> n2), arena)),
_ => { _ => Ok(Number::arena_from(
Ok(Number::arena_from(Integer::from(&*n1 >> usize::max_value()), arena)) Integer::from(&*n1 >> usize::max_value()),
}, arena,
)),
}, },
(Number::Integer(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)), (Number::Integer(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)),
(Number::Fixnum(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)), (Number::Fixnum(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)),
@@ -719,22 +719,25 @@ pub(crate) fn shl(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
match n2.to_u32() { match n2.to_u32() {
Some(n2) => Ok(Number::arena_from(n1.to_u64().unwrap() << n2, arena)), Some(n2) => Ok(Number::arena_from(n1.to_u64().unwrap() << n2, arena)),
_ => { _ => Ok(Number::arena_from(n1 << usize::max_value(), arena)),
Ok(Number::arena_from(n1 << usize::max_value(), arena))
}
} }
} }
(Number::Integer(n1), Number::Fixnum(n2)) => match usize::try_from(n2.get_num()) { (Number::Integer(n1), Number::Fixnum(n2)) => match usize::try_from(n2.get_num()) {
Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 << n2), arena)), Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 << n2), arena)),
_ => { _ => Ok(Number::arena_from(
Ok(Number::arena_from(Integer::from(&*n1 << usize::max_value()),arena)) Integer::from(&*n1 << usize::max_value()),
} arena,
)),
}, },
(Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() { (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
Some(n2) => Ok(Number::arena_from(Integer::from(n1.to_u64().unwrap() << n2), arena)), Some(n2) => Ok(Number::arena_from(
_ => { Integer::from(n1.to_u64().unwrap() << n2),
Ok(Number::arena_from(Integer::from(&*n1 << usize::max_value()),arena)) arena,
} )),
_ => Ok(Number::arena_from(
Integer::from(&*n1 << usize::max_value()),
arena,
)),
}, },
(Number::Integer(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)), (Number::Integer(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)),
(Number::Fixnum(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)), (Number::Fixnum(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)),
@@ -949,10 +952,7 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
Ok(Number::arena_from(result, arena)) Ok(Number::arena_from(result, arena))
} else { } else {
let value: IBig = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into(); let value: IBig = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into();
Ok(Number::arena_from( Ok(Number::arena_from(value, arena))
value,
arena,
))
} }
} }
(Number::Fixnum(n1), Number::Integer(n2)) | (Number::Integer(n2), Number::Fixnum(n1)) => { (Number::Fixnum(n1), Number::Integer(n2)) | (Number::Integer(n2), Number::Fixnum(n1)) => {
@@ -962,7 +962,10 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
} }
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
let n1_clone: Integer = (*n1).clone(); let n1_clone: Integer = (*n1).clone();
Ok(Number::arena_from(Integer::from(n1_clone.gcd(&Integer::from(n2.to_isize().unwrap()))) as IBig, arena)) Ok(Number::arena_from(
Integer::from(n1_clone.gcd(&Integer::from(n2.to_isize().unwrap()))) as IBig,
arena,
))
} }
(Number::Float(f), _) | (_, Number::Float(f)) => { (Number::Float(f), _) | (_, Number::Float(f)) => {
let n = Number::Float(f); let n = Number::Float(f);
@@ -1050,12 +1053,14 @@ pub(crate) fn atanh(n1: Number) -> Result<f64, MachineStubGen> {
let f1 = try_numeric_result!(result_f(&n1), stub_gen)?; let f1 = try_numeric_result!(result_f(&n1), stub_gen)?;
try_numeric_result!(if f1 == 1.0 || f1 == -1.0 { try_numeric_result!(
if f1 == 1.0 || f1 == -1.0 {
Err(EvalError::Undefined) Err(EvalError::Undefined)
} else { } else {
result_f(&Number::Float(OrderedFloat(f1.atanh()))) result_f(&Number::Float(OrderedFloat(f1.atanh())))
}, },
stub_gen) stub_gen
)
} }
#[inline] #[inline]
@@ -1107,7 +1112,6 @@ pub(crate) fn floor(n1: Number, arena: &mut Arena) -> Number {
rnd_i(&n1, arena) rnd_i(&n1, arena)
} }
#[inline] #[inline]
pub(crate) fn ceiling(n1: Number, arena: &mut Arena) -> Number { pub(crate) fn ceiling(n1: Number, arena: &mut Arena) -> Number {
let n1 = neg(n1, arena); let n1 = neg(n1, arena);
@@ -1167,9 +1171,10 @@ impl MachineState {
Err(_) => self.arith_eval_by_metacall(value), Err(_) => self.arith_eval_by_metacall(value),
} }
} }
&ArithmeticTerm::Interm(i) => { &ArithmeticTerm::Interm(i) => Ok(mem::replace(
Ok(mem::replace(&mut self.interms[i - 1], Number::Fixnum(Fixnum::build_with(0)))) &mut self.interms[i - 1],
} Number::Fixnum(Fixnum::build_with(0)),
)),
&ArithmeticTerm::Number(n) => Ok(n), &ArithmeticTerm::Number(n) => Ok(n),
} }
} }
@@ -1183,11 +1188,14 @@ impl MachineState {
match rational_from_number(n, caller, &mut self.arena) { match rational_from_number(n, caller, &mut self.arena) {
Ok(r) => Ok(r), Ok(r) => Ok(r),
Err(e_gen) => Err(e_gen(self)) Err(e_gen) => Err(e_gen(self)),
} }
} }
pub(crate) fn arith_eval_by_metacall(&mut self, value: HeapCellValue) -> Result<Number, MachineStub> { pub(crate) fn arith_eval_by_metacall(
&mut self,
value: HeapCellValue,
) -> Result<Number, MachineStub> {
let stub_gen = || functor_stub(atom!("is"), 2); let stub_gen = || functor_stub(atom!("is"), 2);
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value); let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value);
@@ -1493,26 +1501,11 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
let mut op_dir = default_op_dir(); let mut op_dir = default_op_dir();
op_dir.insert( op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
(atom!("+"), Fixity::In), op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8));
OpDesc::build_with(500, YFX as u8), op_dir.insert((atom!("-"), Fixity::Pre), OpDesc::build_with(200, FY as u8));
); op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
op_dir.insert( op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
(atom!("-"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("-"), Fixity::Pre),
OpDesc::build_with(200, FY as u8),
);
op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert(
(atom!("/"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
let term_write_result = let term_write_result =
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();

View File

@@ -118,12 +118,9 @@ impl MachineState {
and_frame[i] = self.registers[i]; and_frame[i] = self.registers[i];
} }
and_frame[arity + 1] = and_frame[arity + 1] = fixnum_as_cell!(Fixnum::build_with(self.b0 as i64));
fixnum_as_cell!(Fixnum::build_with(self.b0 as i64)); and_frame[arity + 2] = fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[arity + 2] = and_frame[arity + 3] = fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[arity + 3] =
fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
self.verify_attributes(); self.verify_attributes();

View File

@@ -8,7 +8,9 @@ fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> b
&Instruction::TryMeElse(offset) if offset > 0 => { &Instruction::TryMeElse(offset) if offset > 0 => {
stack.push(index + offset); stack.push(index + offset);
} }
&Instruction::DefaultRetryMeElse(offset) | &Instruction::RetryMeElse(offset) if offset > 0 => { &Instruction::DefaultRetryMeElse(offset) | &Instruction::RetryMeElse(offset)
if offset > 0 =>
{
stack.push(index + offset); stack.push(index + offset);
} }
&Instruction::DynamicElse(_, _, NextOrFail::Next(offset)) if offset > 0 => { &Instruction::DynamicElse(_, _, NextOrFail::Next(offset)) if offset > 0 => {

View File

@@ -28,17 +28,15 @@ pub(super) fn bootstrapping_compile(
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let (wam_prelude, machine_st) = wam.prelude_view_and_machine_st(); let (wam_prelude, machine_st) = wam.prelude_view_and_machine_st();
let term_stream = BootstrappingTermStream::from_char_reader( let term_stream = BootstrappingTermStream::from_char_reader(stream, machine_st, listing_src);
stream,
machine_st,
listing_src,
);
let payload = BootstrappingLoadState( let payload =
LoadStatePayload::new(wam_prelude.code.len(), term_stream) BootstrappingLoadState(LoadStatePayload::new(wam_prelude.code.len(), term_stream));
);
let loader: Loader<'_, BootstrappingLoadState> = Loader { payload, wam_prelude }; let loader: Loader<'_, BootstrappingLoadState> = Loader {
payload,
wam_prelude,
};
loader.load()?; loader.load()?;
Ok(()) Ok(())
@@ -98,8 +96,8 @@ fn derelictize_try_me_else(
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o)); retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o));
Some(mem::replace(o, 0)) Some(mem::replace(o, 0))
} }
Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) | Instruction::DynamicElse(_, _, NextOrFail::Fail(_))
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => None, | Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => None,
Instruction::TryMeElse(0) => None, Instruction::TryMeElse(0) => None,
Instruction::TryMeElse(ref mut o) => { Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *o)); retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *o));
@@ -154,8 +152,8 @@ fn merge_indices(
fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize { fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize {
loop { loop {
match &code[index] { match &code[index] {
Instruction::DynamicElse(_, _, NextOrFail::Next(i)) | Instruction::DynamicElse(_, _, NextOrFail::Next(i))
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(i)) | Instruction::DynamicInternalElse(_, _, NextOrFail::Next(i))
if *i > 0 => if *i > 0 =>
{ {
index += i; index += i;
@@ -170,16 +168,14 @@ fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize {
fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> usize { fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> usize {
loop { loop {
match &code[index] { match &code[index] {
Instruction::TryMeElse(o) | Instruction::TryMeElse(o) | Instruction::RetryMeElse(o) => {
Instruction::RetryMeElse(o) => {
if *o > 0 { if *o > 0 {
return index; return index;
} else { } else {
index = index_loc; index = index_loc;
} }
} }
&Instruction::DynamicElse(_, _, next_or_fail) => { &Instruction::DynamicElse(_, _, next_or_fail) => match next_or_fail {
match next_or_fail {
NextOrFail::Next(i) => { NextOrFail::Next(i) => {
if i == 0 { if i == 0 {
index = index_loc; index = index_loc;
@@ -190,10 +186,8 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
NextOrFail::Fail(_) => { NextOrFail::Fail(_) => {
index = index_loc; index = index_loc;
} }
} },
} &Instruction::DynamicInternalElse(_, _, next_or_fail) => match next_or_fail {
&Instruction::DynamicInternalElse(_, _, next_or_fail) => {
match next_or_fail {
NextOrFail::Next(i) => { NextOrFail::Next(i) => {
if i == 0 { if i == 0 {
index = index_loc; index = index_loc;
@@ -204,8 +198,7 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
NextOrFail::Fail(_) => { NextOrFail::Fail(_) => {
return index; return index;
} }
} },
}
Instruction::TrustMe(_) => { Instruction::TrustMe(_) => {
return index; return index;
} }
@@ -215,11 +208,7 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
index += v; index += v;
} }
IndexingCodePtr::DynamicExternal(v) => match &code[index + v] { IndexingCodePtr::DynamicExternal(v) => match &code[index + v] {
&Instruction::DynamicInternalElse( &Instruction::DynamicInternalElse(_, _, NextOrFail::Next(0)) => {
_,
_,
NextOrFail::Next(0),
) => {
return index + v; return index + v;
} }
_ => { _ => {
@@ -309,8 +298,7 @@ fn merge_indexed_subsequences(
code[inner_try_me_else_loc] = Instruction::TrustMe(o); code[inner_try_me_else_loc] = Instruction::TrustMe(o);
} }
_ => { _ => {
code[inner_try_me_else_loc] = code[inner_try_me_else_loc] = Instruction::RetryMeElse(o);
Instruction::RetryMeElse(o);
} }
}, },
} }
@@ -376,7 +364,9 @@ fn delete_from_skeleton(
} }
if skeleton.core.is_dynamic { if skeleton.core.is_dynamic {
skeleton.core.add_retracted_dynamic_clause_info(clause_index_info); skeleton
.core
.add_retracted_dynamic_clause_info(clause_index_info);
retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause( retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause(
compilation_target, compilation_target,
@@ -409,8 +399,8 @@ fn blunt_leading_choice_instr(
code[instr_loc] = Instruction::TryMeElse(*o); code[instr_loc] = Instruction::TryMeElse(*o);
return instr_loc; return instr_loc;
} }
Instruction::DynamicElse(_, _, NextOrFail::Next(_)) | Instruction::DynamicElse(_, _, NextOrFail::Next(_))
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(_)) => { | Instruction::DynamicInternalElse(_, _, NextOrFail::Next(_)) => {
return instr_loc; return instr_loc;
} }
&mut Instruction::DynamicElse(b, d, NextOrFail::Fail(o)) => { &mut Instruction::DynamicElse(b, d, NextOrFail::Fail(o)) => {
@@ -422,26 +412,19 @@ fn blunt_leading_choice_instr(
code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(0)); code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(0));
return instr_loc; return instr_loc;
} }
&mut Instruction::DynamicInternalElse( &mut Instruction::DynamicInternalElse(b, d, NextOrFail::Fail(o)) => {
b,
d,
NextOrFail::Fail(o),
) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail( retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc, instr_loc,
NextOrFail::Fail(o), NextOrFail::Fail(o),
)); ));
code[instr_loc] = Instruction::DynamicInternalElse( code[instr_loc] = Instruction::DynamicInternalElse(b, d, NextOrFail::Next(0));
b,
d,
NextOrFail::Next(0),
);
return instr_loc; return instr_loc;
} }
Instruction::TrustMe(o) => { Instruction::TrustMe(o) => {
retraction_info.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false)); retraction_info
.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
code[instr_loc] = Instruction::TryMeElse(0); code[instr_loc] = Instruction::TryMeElse(0);
return instr_loc + 1; return instr_loc + 1;
@@ -481,9 +464,9 @@ fn set_switch_var_offset_to_choice_instr(
}; };
match &code[index_loc + v] { match &code[index_loc + v] {
Instruction::TryMeElse(_) | Instruction::TryMeElse(_)
Instruction::DynamicElse(..) | | Instruction::DynamicElse(..)
Instruction::DynamicInternalElse(..) => {} | Instruction::DynamicInternalElse(..) => {}
_ => { _ => {
set_switch_var_offset(code, index_loc, offset, retraction_info); set_switch_var_offset(code, index_loc, offset, retraction_info);
} }
@@ -523,9 +506,8 @@ fn internalize_choice_instr_at(
retraction_info: &mut RetractionInfo, retraction_info: &mut RetractionInfo,
) { ) {
match &mut code[instr_loc] { match &mut code[instr_loc] {
Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) | Instruction::DynamicElse(_, _, NextOrFail::Fail(_))
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => { | Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => {}
}
Instruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0)) => { Instruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0)); retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0));
*o = NextOrFail::Fail(0); *o = NextOrFail::Fail(0);
@@ -554,18 +536,10 @@ fn internalize_choice_instr_at(
match &mut code[instr_loc + o] { match &mut code[instr_loc + o] {
Instruction::RevJmpBy(p) if *p == 0 => { Instruction::RevJmpBy(p) if *p == 0 => {
code[instr_loc] = Instruction::DynamicInternalElse( code[instr_loc] = Instruction::DynamicInternalElse(b, d, NextOrFail::Fail(o));
b,
d,
NextOrFail::Fail(o),
);
} }
_ => { _ => {
code[instr_loc] = Instruction::DynamicInternalElse( code[instr_loc] = Instruction::DynamicInternalElse(b, d, NextOrFail::Next(o));
b,
d,
NextOrFail::Next(o),
);
} }
} }
} }
@@ -609,23 +583,20 @@ fn thread_choice_instr_at_to(
*o = target_loc - instr_loc; *o = target_loc - instr_loc;
return; return;
} }
Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)) | Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))
Instruction::DynamicInternalElse( | Instruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))
_, if target_loc >= instr_loc =>
_, {
NextOrFail::Next(ref mut o),
) if target_loc >= instr_loc => {
retraction_info retraction_info
.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, *o)); .push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, *o));
*o = target_loc - instr_loc; *o = target_loc - instr_loc;
return; return;
} }
Instruction::DynamicElse(_, _, NextOrFail::Next(o)) | Instruction::DynamicElse(_, _, NextOrFail::Next(o))
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(o)) => { | Instruction::DynamicInternalElse(_, _, NextOrFail::Next(o)) => {
instr_loc += *o; instr_loc += *o;
} }
Instruction::TryMeElse(o) Instruction::TryMeElse(o) | Instruction::RetryMeElse(o) => {
| Instruction::RetryMeElse(o) => {
instr_loc += *o; instr_loc += *o;
} }
Instruction::RevJmpBy(ref mut o) if instr_loc >= target_loc => { Instruction::RevJmpBy(ref mut o) if instr_loc >= target_loc => {
@@ -642,7 +613,8 @@ fn thread_choice_instr_at_to(
{ {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail)); retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
code[instr_loc] = instr!("dynamic_else", code[instr_loc] = instr!(
"dynamic_else",
birth, birth,
death, death,
NextOrFail::Next(target_loc - instr_loc) NextOrFail::Next(target_loc - instr_loc)
@@ -653,14 +625,13 @@ fn thread_choice_instr_at_to(
Instruction::DynamicElse(_, _, NextOrFail::Fail(o)) if *o > 0 => { Instruction::DynamicElse(_, _, NextOrFail::Fail(o)) if *o > 0 => {
instr_loc += *o; instr_loc += *o;
} }
&mut Instruction::DynamicInternalElse( &mut Instruction::DynamicInternalElse(birth, death, ref mut fail)
birth, if target_loc >= instr_loc =>
death, {
ref mut fail,
) if target_loc >= instr_loc => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail)); retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
code[instr_loc] = instr!("dynamic_internal_else", code[instr_loc] = instr!(
"dynamic_internal_else",
birth, birth,
death, death,
NextOrFail::Next(target_loc - instr_loc) NextOrFail::Next(target_loc - instr_loc)
@@ -668,9 +639,7 @@ fn thread_choice_instr_at_to(
return; return;
} }
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(o)) Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(o)) if *o > 0 => {
if *o > 0 =>
{
instr_loc += *o; instr_loc += *o;
} }
Instruction::TrustMe(ref mut o) if target_loc >= instr_loc => { Instruction::TrustMe(ref mut o) if target_loc >= instr_loc => {
@@ -711,8 +680,7 @@ fn remove_non_leading_clause(
None None
} }
Instruction::TrustMe(_) => { Instruction::TrustMe(_) => match &mut code[preceding_choice_instr_loc] {
match &mut code[preceding_choice_instr_loc] {
Instruction::RetryMeElse(o) => { Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse( retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(
preceding_choice_instr_loc, preceding_choice_instr_loc,
@@ -736,8 +704,7 @@ fn remove_non_leading_clause(
_ => { _ => {
unreachable!(); unreachable!();
} }
} },
}
_ => { _ => {
unreachable!(); unreachable!();
} }
@@ -988,11 +955,7 @@ fn prepend_compiled_clause(
Instruction::TryMeElse(ref mut o) if *o == 0 => { Instruction::TryMeElse(ref mut o) if *o == 0 => {
*o = prepend_queue_len - 2; *o = prepend_queue_len - 2;
} }
Instruction::DynamicInternalElse( Instruction::DynamicInternalElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
_,
_,
ref mut o @ NextOrFail::Next(0),
) => {
*o = NextOrFail::Fail(prepend_queue_len - 2); *o = NextOrFail::Fail(prepend_queue_len - 2);
} }
_ => { _ => {
@@ -1258,7 +1221,11 @@ fn print_overwrite_warning(
_ => {} _ => {}
} }
println!("Warning: overwriting {}/{} because the clauses are discontiguous", key.0.as_str(), key.1); println!(
"Warning: overwriting {}/{} because the clauses are discontiguous",
key.0.as_str(),
key.1
);
} }
impl<'a, LS: LoadState<'a>> Loader<'a, LS> { impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
@@ -1270,8 +1237,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if let Some(path_str) = load_context.path.to_str() { if let Some(path_str) = load_context.path.to_str() {
if !path_str.is_empty() { if !path_str.is_empty() {
return Some(LS::machine_st(&mut self.payload).atom_tbl.build_with( return Some(AtomTable::build_with(
path_str &LS::machine_st(&mut self.payload).atom_tbl,
path_str,
)); ));
} }
} }
@@ -1290,10 +1258,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let clause = self.try_term_to_tl(term, &mut preprocessor)?; let clause = self.try_term_to_tl(term, &mut preprocessor)?;
// let queue = preprocessor.parse_queue(self)?; // let queue = preprocessor.parse_queue(self)?;
let mut cg = CodeGenerator::new( let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
&mut LS::machine_st(&mut self.payload).atom_tbl,
settings,
);
let clause_code = cg.compile_predicate(vec![clause])?; let clause_code = cg.compile_predicate(vec![clause])?;
@@ -1323,10 +1288,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?); clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
} }
let mut cg = CodeGenerator::new( let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
&mut LS::machine_st(&mut self.payload).atom_tbl,
settings,
);
let mut code = cg.compile_predicate(clauses)?; let mut code = cg.compile_predicate(clauses)?;
@@ -1361,12 +1323,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.clause_clause_locs .clause_clause_locs
.extend(&clause_clause_locs.make_contiguous()[0..]); .extend(&clause_clause_locs.make_contiguous()[0..]);
self.payload.retraction_info self.payload.retraction_info.push_record(
.push_record(RetractionRecord::SkeletonClauseTruncateBack( RetractionRecord::SkeletonClauseTruncateBack(
predicates.compilation_target, predicates.compilation_target,
key, key,
skeleton_clause_len, skeleton_clause_len,
)); ),
);
} }
None => { None => {
cg.skeleton cg.skeleton
@@ -1376,11 +1339,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let skeleton = cg.skeleton; let skeleton = cg.skeleton;
self.add_extensible_predicate( self.add_extensible_predicate(key, skeleton, predicates.compilation_target);
key,
skeleton,
predicates.compilation_target,
);
} }
}; };
@@ -1450,11 +1409,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new(); let mut skeleton = LocalPredicateSkeleton::new();
skeleton.clause_clause_locs = clause_clause_locs; skeleton.clause_clause_locs = clause_clause_locs;
self.add_local_extensible_predicate( self.add_local_extensible_predicate(*compilation_target, *key, skeleton);
*compilation_target,
*key,
skeleton,
);
} }
} }
} }
@@ -1490,11 +1445,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new(); let mut skeleton = LocalPredicateSkeleton::new();
skeleton.clause_clause_locs.push_front(code_len); skeleton.clause_clause_locs.push_front(code_len);
self.add_local_extensible_predicate( self.add_local_extensible_predicate(*compilation_target, *key, skeleton);
*compilation_target,
*key,
skeleton,
);
} }
} }
} }
@@ -1530,11 +1481,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new(); let mut skeleton = LocalPredicateSkeleton::new();
skeleton.clause_clause_locs.push_back(code_len); skeleton.clause_clause_locs.push_back(code_len);
self.add_local_extensible_predicate( self.add_local_extensible_predicate(*compilation_target, *key, skeleton);
*compilation_target,
*key,
skeleton,
);
} }
} }
} }
@@ -1606,7 +1553,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
skeleton.core.clause_clause_locs.push_back(code_len); skeleton.core.clause_clause_locs.push_back(code_len);
self.payload.retraction_info self.payload
.retraction_info
.push_record(RetractionRecord::SkeletonClausePopBack( .push_record(RetractionRecord::SkeletonClausePopBack(
compilation_target, compilation_target,
key, key,
@@ -1624,8 +1572,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.push_back_to_local_predicate_skeleton(&compilation_target, &key, code_len); self.push_back_to_local_predicate_skeleton(&compilation_target, &key, code_len);
let code_index = let code_index = self.get_or_insert_code_index(key, compilation_target);
self.get_or_insert_code_index(key, compilation_target);
if let Some(new_code_ptr) = result { if let Some(new_code_ptr) = result {
set_code_index( set_code_index(
@@ -1646,7 +1593,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
skeleton.core.clause_clause_locs.push_front(code_len); skeleton.core.clause_clause_locs.push_front(code_len);
skeleton.core.clause_assert_margin += 1; skeleton.core.clause_assert_margin += 1;
self.payload.retraction_info self.payload
.retraction_info
.push_record(RetractionRecord::SkeletonClausePopFront( .push_record(RetractionRecord::SkeletonClausePopFront(
compilation_target, compilation_target,
key, key,
@@ -1666,8 +1614,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.push_front_to_local_predicate_skeleton(&compilation_target, &key, code_len); self.push_front_to_local_predicate_skeleton(&compilation_target, &key, code_len);
let code_index = let code_index = self.get_or_insert_code_index(key, compilation_target);
self.get_or_insert_code_index(key, compilation_target);
set_code_index( set_code_index(
&mut self.payload.retraction_info, &mut self.payload.retraction_info,
@@ -1698,19 +1645,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.opt_arg_index_key .opt_arg_index_key
.switch_on_term_loc() .switch_on_term_loc()
{ {
Some(index_loc) => { Some(index_loc) => find_inner_choice_instr(
find_inner_choice_instr(
&self.wam_prelude.code, &self.wam_prelude.code,
skeleton.clauses[target_pos].clause_start, skeleton.clauses[target_pos].clause_start,
index_loc, index_loc,
) ),
}
None => skeleton.clauses[target_pos].clause_start, None => skeleton.clauses[target_pos].clause_start,
}; };
match &mut self.wam_prelude.code[clause_loc] { match &mut self.wam_prelude.code[clause_loc] {
Instruction::DynamicElse(_, ref mut d, _) | Instruction::DynamicElse(_, ref mut d, _)
Instruction::DynamicInternalElse(_, ref mut d, _) => { | Instruction::DynamicInternalElse(_, ref mut d, _) => {
*d = Death::Finite(LS::machine_st(&mut self.payload).global_clock); *d = Death::Finite(LS::machine_st(&mut self.payload).global_clock);
} }
_ => unreachable!(), _ => unreachable!(),
@@ -1797,8 +1742,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
skeleton.clauses[target_pos + 1].clause_start = skeleton.clauses[target_pos + 1].clause_start =
skeleton.clauses[target_pos].clause_start; skeleton.clauses[target_pos].clause_start;
let update_code_index = target_pos == 0 && let update_code_index = target_pos == 0
skeleton.clauses[target_pos + 1] && skeleton.clauses[target_pos + 1]
.opt_arg_index_key .opt_arg_index_key
.switch_on_term_loc() .switch_on_term_loc()
.is_none(); .is_none();
@@ -1964,7 +1909,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
index_loc, index_loc,
); );
let lower_bound_clause_start = skeleton.clauses[lower_bound].clause_start; let lower_bound_clause_start =
skeleton.clauses[lower_bound].clause_start;
let preceding_choice_instr_loc; let preceding_choice_instr_loc;
match &mut code[clause_start] { match &mut code[clause_start] {
@@ -2093,13 +2039,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
clause_clauses: ClauseIter, clause_clauses: ClauseIter,
append_or_prepend: AppendOrPrepend, append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let clause_predicates = clause_clauses.map(|(head, body)| { let clause_predicates = clause_clauses
Term::Clause( .map(|(head, body)| Term::Clause(Cell::default(), atom!("$clause"), vec![head, body]));
Cell::default(),
atom!("$clause"),
vec![head, body],
)
});
let clause_clause_compilation_target = match compilation_target { let clause_clause_compilation_target = match compilation_target {
CompilationTarget::User => CompilationTarget::Module(atom!("builtins")), CompilationTarget::User => CompilationTarget::Module(atom!("builtins")),
@@ -2132,21 +2073,21 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.cloned() .cloned()
.collect() .collect()
} }
Some(skeleton) => { Some(skeleton) => skeleton.core.clause_clause_locs.make_contiguous()
skeleton.core.clause_clause_locs.make_contiguous()[0..num_clause_predicates] [0..num_clause_predicates]
.iter() .iter()
.cloned() .cloned()
.collect() .collect(),
}
None => { None => {
unreachable!() unreachable!()
} }
}; };
match self.wam_prelude.indices.get_predicate_skeleton_mut( match self
&clause_clause_compilation_target, .wam_prelude
&(atom!("$clause"), 2), .indices
) { .get_predicate_skeleton_mut(&clause_clause_compilation_target, &(atom!("$clause"), 2))
{
Some(skeleton) if append_or_prepend.is_append() => { Some(skeleton) if append_or_prepend.is_append() => {
for _ in 0..num_clause_predicates { for _ in 0..num_clause_predicates {
skeleton.core.clause_clause_locs.pop_back(); skeleton.core.clause_clause_locs.pop_back();
@@ -2270,20 +2211,20 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
println!( println!(
"Warning: overwriting multifile predicate {}:{}/{} because \ "Warning: overwriting multifile predicate {}:{}/{} because \
it was not locally declared multifile.", it was not locally declared multifile.",
self.payload.predicates.compilation_target, key.0.as_str(), key.1 self.payload.predicates.compilation_target,
key.0.as_str(),
key.1
); );
} }
if let Some(skeleton) = self if let Some(skeleton) = self.wam_prelude.indices.remove_predicate_skeleton(
.wam_prelude &self.payload.predicates.compilation_target,
.indices &key,
.remove_predicate_skeleton(&self.payload.predicates.compilation_target, &key) ) {
{
let compilation_target = self.payload.predicates.compilation_target; let compilation_target = self.payload.predicates.compilation_target;
if predicate_info.is_dynamic { if predicate_info.is_dynamic {
let clause_clause_compilation_target = let clause_clause_compilation_target = match compilation_target {
match compilation_target {
CompilationTarget::User => { CompilationTarget::User => {
CompilationTarget::Module(atom!("builtins")) CompilationTarget::Module(atom!("builtins"))
} }
@@ -2301,11 +2242,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
self.payload.retraction_info.push_record( self.payload.retraction_info.push_record(
RetractionRecord::RemovedSkeleton( RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton),
compilation_target,
key,
skeleton,
),
); );
} }
} }
@@ -2328,9 +2265,7 @@ 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) let code_index = module.code_dir.entry(key).or_insert(code_index).clone();
.or_insert(code_index)
.clone();
set_code_index( set_code_index(
&mut self.payload.retraction_info, &mut self.payload.retraction_info,
@@ -2349,8 +2284,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
LS::machine_st(&mut self.payload).global_clock += 1; LS::machine_st(&mut self.payload).global_clock += 1;
let clause_clauses_len = self.payload.clause_clauses.len(); let clause_clauses_len = self.payload.clause_clauses.len();
let clauses_vec: Vec<_> = self.payload let clauses_vec: Vec<_> = self
.clause_clauses.drain(0..std::cmp::min(predicates_len, clause_clauses_len)) .payload
.clause_clauses
.drain(0..std::cmp::min(predicates_len, clause_clauses_len))
.collect(); .collect();
let compilation_target = self.payload.predicates.compilation_target; let compilation_target = self.payload.predicates.compilation_target;
@@ -2374,10 +2311,7 @@ impl Machine {
module_name: HeapCellValue, module_name: HeapCellValue,
key: PredicateKey, key: PredicateKey,
) -> CodeIndex { ) -> CodeIndex {
let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new( let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new(self, InlineTermStream {});
self,
InlineTermStream {},
);
let module_name = if module_name.get_tag() == HeapCellValueTag::Atom { let module_name = if module_name.get_tag() == HeapCellValueTag::Atom {
cell_as_atom!(module_name) cell_as_atom!(module_name)
@@ -2394,10 +2328,8 @@ impl Machine {
vars: &[Term], vars: &[Term],
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let mut compile = || { let mut compile = || {
let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new( let mut loader: Loader<'_, InlineLoadState<'_>> =
self, Loader::new(self, InlineTermStream {});
InlineTermStream {},
);
let term = loader.read_term_from_heap(term_loc)?; let term = loader.read_term_from_heap(term_loc)?;
let clause = build_rule_body(vars, term); let clause = build_rule_body(vars, term);

View File

@@ -91,12 +91,16 @@ impl<T: CopierTarget> CopyTermState<T> {
self.target.push(hcv); self.target.push(hcv);
} }
let cdr = self.target.store(self.target.deref(heap_loc_as_cell!(addr + 1))); let cdr = self
.target
.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
if !cdr.is_var() { if !cdr.is_var() {
self.trail_list_cell(addr + 1, threshold); self.trail_list_cell(addr + 1, threshold);
} else { } else {
let car = self.target.store(self.target.deref(heap_loc_as_cell!(addr))); let car = self
.target
.store(self.target.deref(heap_loc_as_cell!(addr)));
if !car.is_var() { if !car.is_var() {
self.trail_list_cell(addr, threshold); self.trail_list_cell(addr, threshold);
@@ -377,7 +381,8 @@ mod tests {
let a_atom = atom!("a"); let a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
wam.machine_st.heap wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2)); assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2));
@@ -401,20 +406,26 @@ mod tests {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl); let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl); let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1)); wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{ {
let wam = TermCopyingMockWAM { wam: &mut wam }; let wam = TermCopyingMockWAM { wam: &mut wam };
@@ -428,14 +439,20 @@ mod tests {
assert_eq!(wam.machine_st.heap[2], pstr_second_cell); assert_eq!(wam.machine_st.heap[2], pstr_second_cell);
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(4)); assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(4));
assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0)); assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
assert_eq!(wam.machine_st.heap[5], fixnum_as_cell!(Fixnum::build_with(0i64))); assert_eq!(
wam.machine_st.heap[5],
fixnum_as_cell!(Fixnum::build_with(0i64))
);
assert_eq!(wam.machine_st.heap[7], pstr_cell); assert_eq!(wam.machine_st.heap[7], pstr_cell);
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(9)); assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(9));
assert_eq!(wam.machine_st.heap[9], pstr_second_cell); assert_eq!(wam.machine_st.heap[9], pstr_second_cell);
assert_eq!(wam.machine_st.heap[10], pstr_loc_as_cell!(11)); assert_eq!(wam.machine_st.heap[10], pstr_loc_as_cell!(11));
assert_eq!(wam.machine_st.heap[11], pstr_offset_as_cell!(7)); assert_eq!(wam.machine_st.heap[11], pstr_offset_as_cell!(7));
assert_eq!(wam.machine_st.heap[12], fixnum_as_cell!(Fixnum::build_with(0i64))); assert_eq!(
wam.machine_st.heap[12],
fixnum_as_cell!(Fixnum::build_with(0i64))
);
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();

View File

@@ -108,7 +108,10 @@ pub struct BranchInfo {
impl BranchInfo { impl BranchInfo {
fn new(branch_num: BranchNumber) -> Self { fn new(branch_num: BranchNumber) -> Self {
Self { branch_num, chunks: vec![] } Self {
branch_num,
chunks: vec![],
}
} }
} }
@@ -179,14 +182,13 @@ pub struct VarData {
impl VarData { impl VarData {
fn emit_initial_get_level(&mut self, build_stack: &mut ChunkedTermVec) { fn emit_initial_get_level(&mut self, build_stack: &mut ChunkedTermVec) {
let global_cut_var_num = let global_cut_var_num = if let &Some(global_cut_var_num) = &self.global_cut_var_num {
if let &Some(global_cut_var_num) = &self.global_cut_var_num {
match &self.records[global_cut_var_num].allocation { match &self.records[global_cut_var_num].allocation {
VarAlloc::Perm(..) => Some(global_cut_var_num), VarAlloc::Perm(..) => Some(global_cut_var_num),
VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => { VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => {
Some(global_cut_var_num) Some(global_cut_var_num)
} }
_ => None _ => None,
} }
} else { } else {
None None
@@ -194,7 +196,8 @@ impl VarData {
if let Some(global_cut_var_num) = global_cut_var_num { if let Some(global_cut_var_num) = global_cut_var_num {
let term = QueryTerm::GetLevel(global_cut_var_num); let term = QueryTerm::GetLevel(global_cut_var_num);
self.records[global_cut_var_num].allocation = VarAlloc::Perm(0, PermVarAllocation::Pending); self.records[global_cut_var_num].allocation =
VarAlloc::Perm(0, PermVarAllocation::Pending);
match build_stack.front_mut() { match build_stack.front_mut() {
Some(ChunkedTerms::Branch(_)) => { Some(ChunkedTerms::Branch(_)) => {
@@ -254,11 +257,14 @@ impl VariableClassifier {
pub fn classify_fact(mut self, term: Term) -> Result<ClassifyFactResult, CompilationError> { pub fn classify_fact(mut self, term: Term) -> Result<ClassifyFactResult, CompilationError> {
self.classify_head_variables(&term)?; self.classify_head_variables(&term)?;
Ok((term, self.branch_map.separate_and_classify_variables( Ok((
term,
self.branch_map.separate_and_classify_variables(
self.var_num, self.var_num,
self.global_cut_var_num, self.global_cut_var_num,
self.current_chunk_num, self.current_chunk_num,
))) ),
))
} }
pub fn classify_rule<'a, LS: LoadState<'a>>( pub fn classify_rule<'a, LS: LoadState<'a>>(
@@ -346,9 +352,13 @@ impl VariableClassifier {
} }
fn probe_body_var(&mut self, var_info: VarInfo) { fn probe_body_var(&mut self, var_info: VarInfo) {
let term_loc = self.current_chunk_type.to_gen_context(self.current_chunk_num); let term_loc = self
.current_chunk_type
.to_gen_context(self.current_chunk_num);
let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone()) let branch_info_v = self
.branch_map
.entry(var_info.var_ptr.clone())
.or_insert_with(|| vec![]); .or_insert_with(|| vec![]);
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() { let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
@@ -396,12 +406,14 @@ impl VariableClassifier {
fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> { fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> {
match term { match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => { Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => {}
}
_ => return Err(CompilationError::InvalidRuleHead), _ => return Err(CompilationError::InvalidRuleHead),
} }
let mut classify_info = ClassifyInfo { arg_c: 1, arity: term.arity() }; let mut classify_info = ClassifyInfo {
arg_c: 1,
arity: term.arity(),
};
match term { match term {
Term::Clause(_, _, terms) => { Term::Clause(_, _, terms) => {
@@ -414,13 +426,16 @@ impl VariableClassifier {
// the body of the if let here is an inlined // the body of the if let here is an inlined
// "probe_head_var". note the difference between it // "probe_head_var". note the difference between it
// and "probe_body_var". // and "probe_body_var".
let branch_info_v = self.branch_map.entry(var_ptr.clone()) let branch_info_v = self
.branch_map
.entry(var_ptr.clone())
.or_insert_with(|| vec![]); .or_insert_with(|| vec![]);
let needs_new_branch = branch_info_v.is_empty(); let needs_new_branch = branch_info_v.is_empty();
if needs_new_branch { if needs_new_branch {
branch_info_v.push(BranchInfo::new(self.current_branch_num.clone())); branch_info_v
.push(BranchInfo::new(self.current_branch_num.clone()));
} }
let branch_info = branch_info_v.last_mut().unwrap(); let branch_info = branch_info_v.last_mut().unwrap();
@@ -509,13 +524,11 @@ impl VariableClassifier {
self.probe_in_situ_var(var_num); self.probe_in_situ_var(var_num);
build_stack.push_chunk_term( build_stack.push_chunk_term(if is_global {
if is_global {
QueryTerm::GlobalCut(var_num) QueryTerm::GlobalCut(var_num)
} else { } else {
QueryTerm::LocalCut(var_num) QueryTerm::LocalCut(var_num)
} });
);
} }
TraversalState::Fail => { TraversalState::Fail => {
build_stack.push_chunk_term(QueryTerm::Fail); build_stack.push_chunk_term(QueryTerm::Fail);
@@ -539,22 +552,28 @@ impl VariableClassifier {
classifier.probe_body_term(arg_c + 1, terms.len(), term); classifier.probe_body_term(arg_c + 1, terms.len(), term);
} }
build_stack.push_chunk_term( build_stack.push_chunk_term(clause_to_query_term(
clause_to_query_term(
loader, loader,
name, name,
terms, terms,
classifier.call_policy, classifier.call_policy,
), ));
);
}; };
match term { match term {
Term::Clause(_, name @ (atom!("->") | atom!(";") | atom!(",")), mut terms) if terms.len() == 3 => { Term::Clause(
_,
name @ (atom!("->") | atom!(";") | atom!(",")),
mut terms,
) if terms.len() == 3 => {
if let Some(last_arg) = terms.last() { if let Some(last_arg) = terms.last() {
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg { if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
terms.pop(); terms.pop();
state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), name, terms))); state_stack.push(TraversalState::Term(Term::Clause(
Cell::default(),
name,
terms,
)));
} else { } else {
add_chunk(self, name, terms); add_chunk(self, name, terms);
} }
@@ -610,8 +629,11 @@ impl VariableClassifier {
state_stack.push(TraversalState::AddBranchNum(branch_num)); state_stack.push(TraversalState::AddBranchNum(branch_num));
} }
if let TraversalState::BuildDisjunct(build_stack_len) = state_stack[final_disjunct_loc] { if let TraversalState::BuildDisjunct(build_stack_len) =
state_stack[final_disjunct_loc] = TraversalState::BuildFinalDisjunct(build_stack_len); state_stack[final_disjunct_loc]
{
state_stack[final_disjunct_loc] =
TraversalState::BuildFinalDisjunct(build_stack_len);
} }
self.current_chunk_type = ChunkType::Mid; self.current_chunk_type = ChunkType::Mid;
@@ -621,18 +643,30 @@ impl VariableClassifier {
let then_term = terms.pop().unwrap(); let then_term = terms.pop().unwrap();
let if_term = terms.pop().unwrap(); let if_term = terms.pop().unwrap();
let prev_b = if matches!(state_stack.last(), Some(TraversalState::RemoveBranchNum)) { let prev_b = if matches!(
state_stack.last(),
Some(TraversalState::RemoveBranchNum)
) {
// check if the second-to-last element is a regular BuildDisjunct, as we don't // check if the second-to-last element is a regular BuildDisjunct, as we don't
// want to add GetPrevLevel in case of a TrustMe. // want to add GetPrevLevel in case of a TrustMe.
matches!(state_stack.iter().rev().nth(1), Some(TraversalState::BuildDisjunct(..))) matches!(
state_stack.iter().rev().nth(1),
Some(TraversalState::BuildDisjunct(..))
)
} else { } else {
false false
}; };
state_stack.push(TraversalState::Term(then_term)); state_stack.push(TraversalState::Term(then_term));
state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false }); state_stack.push(TraversalState::Cut {
var_num: self.var_num,
is_global: false,
});
state_stack.push(TraversalState::Term(if_term)); state_stack.push(TraversalState::Term(if_term));
state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b }); state_stack.push(TraversalState::GetCutPoint {
var_num: self.var_num,
prev_b,
});
self.var_num += 1; self.var_num += 1;
} }
@@ -643,12 +677,22 @@ impl VariableClassifier {
build_stack.reserve_branch(2); build_stack.reserve_branch(2);
state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len)); state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len));
state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), atom!("$succeed"), vec![]))); state_stack.push(TraversalState::Term(Term::Clause(
Cell::default(),
atom!("$succeed"),
vec![],
)));
state_stack.push(TraversalState::BuildDisjunct(build_stack_len)); state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
state_stack.push(TraversalState::Fail); state_stack.push(TraversalState::Fail);
state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false }); state_stack.push(TraversalState::Cut {
var_num: self.var_num,
is_global: false,
});
state_stack.push(TraversalState::Term(not_term)); state_stack.push(TraversalState::Term(not_term));
state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b: true }); state_stack.push(TraversalState::GetCutPoint {
var_num: self.var_num,
prev_b: true,
});
self.current_chunk_type = ChunkType::Mid; self.current_chunk_type = ChunkType::Mid;
self.current_chunk_num += 1; self.current_chunk_num += 1;
@@ -668,15 +712,13 @@ impl VariableClassifier {
build_stack.add_chunk(); build_stack.add_chunk();
} }
build_stack.push_chunk_term( build_stack.push_chunk_term(qualified_clause_to_query_term(
qualified_clause_to_query_term(
loader, loader,
module_name, module_name,
predicate_name, predicate_name,
vec![], vec![],
self.call_policy, self.call_policy,
), ));
);
} }
( (
Term::Literal(_, Literal::Atom(module_name)), Term::Literal(_, Literal::Atom(module_name)),
@@ -690,15 +732,13 @@ impl VariableClassifier {
self.probe_body_term(arg_c + 1, terms.len(), term); self.probe_body_term(arg_c + 1, terms.len(), term);
} }
build_stack.push_chunk_term( build_stack.push_chunk_term(qualified_clause_to_query_term(
qualified_clause_to_query_term(
loader, loader,
module_name, module_name,
name, name,
terms, terms,
self.call_policy, self.call_policy,
), ));
);
} }
(module_name, predicate_name) => { (module_name, predicate_name) => {
if update_chunk_data(self, atom!("call"), 2) { if update_chunk_data(self, atom!("call"), 2) {
@@ -711,18 +751,18 @@ impl VariableClassifier {
terms.push(module_name); terms.push(module_name);
terms.push(predicate_name); terms.push(predicate_name);
build_stack.push_chunk_term( build_stack.push_chunk_term(clause_to_query_term(
clause_to_query_term(
loader, loader,
atom!("call"), atom!("call"),
vec![Term::Clause(Cell::default(), atom!(":"), terms)], vec![Term::Clause(Cell::default(), atom!(":"), terms)],
self.call_policy, self.call_policy,
), ));
);
} }
} }
} }
Term::Clause(_, atom!("$call_with_inference_counting"), mut terms) if terms.len() == 1 => { Term::Clause(_, atom!("$call_with_inference_counting"), mut terms)
if terms.len() == 1 =>
{
state_stack.push(TraversalState::ResetCallPolicy(self.call_policy)); state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
state_stack.push(TraversalState::Term(terms.pop().unwrap())); state_stack.push(TraversalState::Term(terms.pop().unwrap()));
@@ -738,14 +778,12 @@ impl VariableClassifier {
self.probe_body_term(1, 1, &var); self.probe_body_term(1, 1, &var);
build_stack.push_chunk_term( build_stack.push_chunk_term(clause_to_query_term(
clause_to_query_term(
loader, loader,
atom!("call"), atom!("call"),
vec![var], vec![var],
self.call_policy, self.call_policy,
), ));
);
} }
Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => { Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => {
if self.global_cut_var_num.is_none() { if self.global_cut_var_num.is_none() {
@@ -765,14 +803,12 @@ impl VariableClassifier {
build_stack.add_chunk(); build_stack.add_chunk();
} }
build_stack.push_chunk_term( build_stack.push_chunk_term(clause_to_query_term(
clause_to_query_term(
loader, loader,
name, name,
vec![], vec![],
self.call_policy, self.call_policy,
), ));
);
} }
_ => { _ => {
return Err(CompilationError::InadmissibleQueryTerm); return Err(CompilationError::InadmissibleQueryTerm);
@@ -800,8 +836,7 @@ impl BranchMap {
}; };
for (var, branches) in self.iter_mut() { for (var, branches) in self.iter_mut() {
let (mut var_num, var_num_incr) = let (mut var_num, var_num_incr) = if let Var::InSitu(var_num) = *var.borrow() {
if let Var::InSitu(var_num) = *var.borrow() {
(var_num, false) (var_num, false)
} else { } else {
(var_data.records.len(), true) (var_data.records.len(), true)
@@ -813,7 +848,8 @@ impl BranchMap {
var_data.records.push(VariableRecord::default()); var_data.records.push(VariableRecord::default());
} }
if branch.chunks.len() <= 1 { // true iff var is a temporary variable. if branch.chunks.len() <= 1 {
// true iff var is a temporary variable.
debug_assert_eq!(branch.chunks.len(), 1); debug_assert_eq!(branch.chunks.len(), 1);
let chunk = &mut branch.chunks[0]; let chunk = &mut branch.chunks[0];
@@ -822,7 +858,9 @@ impl BranchMap {
for var_info in chunk.vars.iter_mut() { for var_info in chunk.vars.iter_mut() {
if var_info.lvl == Level::Shallow { if var_info.lvl == Level::Shallow {
let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num); let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num);
temp_var_data.use_set.insert((term_loc, var_info.classify_info.arg_c)); temp_var_data
.use_set
.insert((term_loc, var_info.classify_info.arg_c));
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -130,11 +130,7 @@ pub fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: u
} }
#[inline] #[inline]
pub(crate) fn put_complete_string( pub(crate) fn put_complete_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
heap: &mut Heap,
s: &str,
atom_tbl: &mut AtomTable,
) -> HeapCellValue {
match allocate_pstr(heap, s, atom_tbl) { match allocate_pstr(heap, s, atom_tbl) {
Some(h) => { Some(h) => {
heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr. heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr.
@@ -157,11 +153,7 @@ pub(crate) fn put_complete_string(
} }
#[inline] #[inline]
pub(crate) fn put_partial_string( pub(crate) fn put_partial_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
heap: &mut Heap,
s: &str,
atom_tbl: &mut AtomTable,
) -> HeapCellValue {
match allocate_pstr(heap, s, atom_tbl) { match allocate_pstr(heap, s, atom_tbl) {
Some(h) => { Some(h) => {
pstr_loc_as_cell!(h) pstr_loc_as_cell!(h)
@@ -173,11 +165,7 @@ pub(crate) fn put_partial_string(
} }
#[inline] #[inline]
pub(crate) fn allocate_pstr( pub(crate) fn allocate_pstr(heap: &mut Heap, mut src: &str, atom_tbl: &AtomTable) -> Option<usize> {
heap: &mut Heap,
mut src: &str,
atom_tbl: &mut AtomTable,
) -> Option<usize> {
let orig_h = heap.len(); let orig_h = heap.len();
loop { loop {

View File

@@ -63,21 +63,27 @@ fn add_op_decl_as_module_export<'a, LS: LoadState<'a>>(
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) => {
payload.retraction_info.push_record(RetractionRecord::ReplacedUserOp( payload
*op_decl, .retraction_info
op_desc, .push_record(RetractionRecord::ReplacedUserOp(*op_decl, op_desc));
));
payload.module_op_exports.push((*op_decl, Some(op_desc))); payload.module_op_exports.push((*op_decl, Some(op_desc)));
} }
None => { None => {
payload.retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl)); payload
.retraction_info
.push_record(RetractionRecord::AddedUserOp(*op_decl));
payload.module_op_exports.push((*op_decl, None)); payload.module_op_exports.push((*op_decl, None));
} }
} }
let compilation_target = payload.compilation_target; let compilation_target = payload.compilation_target;
add_op_decl(&mut payload.retraction_info, &compilation_target, module_op_dir, op_decl); 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(
@@ -89,10 +95,7 @@ pub(super) fn add_op_decl(
match op_decl.insert_into_op_dir(op_dir) { match op_decl.insert_into_op_dir(op_dir) {
Some(op_desc) => match &compilation_target { Some(op_desc) => match &compilation_target {
CompilationTarget::User => { CompilationTarget::User => {
retraction_info.push_record(RetractionRecord::ReplacedUserOp( retraction_info.push_record(RetractionRecord::ReplacedUserOp(*op_decl, op_desc));
*op_decl,
op_desc,
));
} }
CompilationTarget::Module(ref module_name) => { CompilationTarget::Module(ref module_name) => {
retraction_info.push_record(RetractionRecord::ReplacedModuleOp( retraction_info.push_record(RetractionRecord::ReplacedModuleOp(
@@ -107,10 +110,8 @@ pub(super) fn add_op_decl(
retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl)); retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl));
} }
CompilationTarget::Module(ref module_name) => { CompilationTarget::Module(ref module_name) => {
retraction_info.push_record(RetractionRecord::AddedModuleOp( retraction_info
*module_name, .push_record(RetractionRecord::AddedModuleOp(*module_name, *op_decl));
*op_decl,
));
} }
}, },
} }
@@ -160,7 +161,12 @@ pub(super) fn import_module_exports<'a, LS: LoadState<'a>>(
} }
} }
ModuleExport::OpDecl(ref op_decl) => { ModuleExport::OpDecl(ref op_decl) => {
add_op_decl(&mut payload.retraction_info, compilation_target, op_dir, op_decl); add_op_decl(
&mut payload.retraction_info,
compilation_target,
op_dir,
op_decl,
);
} }
} }
} }
@@ -209,12 +215,7 @@ fn import_module_exports_into_module<'a, LS: LoadState<'a>>(
} }
} }
ModuleExport::OpDecl(ref op_decl) => { ModuleExport::OpDecl(ref op_decl) => {
add_op_decl_as_module_export::<LS>( add_op_decl_as_module_export::<LS>(payload, op_dir, wam_op_dir, op_decl);
payload,
op_dir,
wam_op_dir,
op_decl,
);
} }
} }
} }
@@ -239,13 +240,18 @@ fn import_qualified_module_exports<'a, LS: LoadState<'a>>(
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) {
wam_prelude.indices.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 arena = &mut LS::machine_st(payload).arena; let arena = &mut LS::machine_st(payload).arena;
let target_code_index = wam_prelude.indices.code_dir let target_code_index = wam_prelude
.indices
.code_dir
.entry(key.clone()) .entry(key.clone())
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena)) .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena))
.clone(); .clone();
@@ -325,12 +331,7 @@ fn import_qualified_module_exports_into_module<'a, LS: LoadState<'a>>(
} }
} }
ModuleExport::OpDecl(ref op_decl) => { ModuleExport::OpDecl(ref op_decl) => {
add_op_decl_as_module_export::<LS>( add_op_decl_as_module_export::<LS>(payload, op_dir, wam_op_dir, op_decl);
payload,
op_dir,
wam_op_dir,
op_decl,
);
} }
} }
} }
@@ -378,10 +379,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
mut clause_target_poses: Vec<Option<usize>>, mut clause_target_poses: Vec<Option<usize>>,
is_dynamic: bool, is_dynamic: bool,
) { ) {
let old_compilation_target = mem::replace( let old_compilation_target =
&mut self.payload.compilation_target, mem::replace(&mut self.payload.compilation_target, compilation_target);
compilation_target,
);
while let Some(target_pos_opt) = clause_target_poses.pop() { while let Some(target_pos_opt) = clause_target_poses.pop() {
match target_pos_opt { match target_pos_opt {
@@ -482,7 +481,8 @@ 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(
module_name, module_name,
*key, *key,
@@ -491,7 +491,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
for (key, skeleton) in removed_module.extensible_predicates.drain(..) { for (key, skeleton) in removed_module.extensible_predicates.drain(..) {
self.payload.retraction_info self.payload
.retraction_info
.push_record(RetractionRecord::RemovedSkeleton( .push_record(RetractionRecord::RemovedSkeleton(
CompilationTarget::Module(module_name), CompilationTarget::Module(module_name),
key, key,
@@ -499,7 +500,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
)); ));
} }
self.wam_prelude.indices.modules.insert(module_name, removed_module); self.wam_prelude
.indices
.modules
.insert(module_name, removed_module);
} }
pub(super) fn remove_module_exports(&mut self, module_name: Atom) { pub(super) fn remove_module_exports(&mut self, module_name: Atom) {
@@ -523,15 +527,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
(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 =
retraction_info.push_record(predicate_retractor(*key, old_index_ptr)); target_code_index.replace(IndexPtr::undefined());
retraction_info
.push_record(predicate_retractor(*key, old_index_ptr));
} }
_ => {} _ => {}
} }
} }
ModuleExport::OpDecl(op_decl) => { ModuleExport::OpDecl(op_decl) => {
let op_dir_value_opt = let op_dir_value_opt = op_dir
op_dir.remove(&(op_decl.name, fixity(op_decl.op_desc.get_spec() as u32))); .remove(&(op_decl.name, fixity(op_decl.op_desc.get_spec() as u32)));
if let Some(op_desc) = op_dir_value_opt { if let Some(op_desc) = op_dir_value_opt {
retraction_info.push_record(op_retractor(*op_decl, op_desc)); retraction_info.push_record(op_retractor(*op_decl, op_desc));
@@ -552,9 +558,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::ReplacedUserOp, RetractionRecord::ReplacedUserOp,
); );
} }
CompilationTarget::Module(target_module_name) CompilationTarget::Module(target_module_name) if target_module_name != module_name => {
if target_module_name != module_name =>
{
let predicate_retractor = |key, index_ptr| { let predicate_retractor = |key, index_ptr| {
RetractionRecord::ReplacedModulePredicate(module_name, key, index_ptr) RetractionRecord::ReplacedModulePredicate(module_name, key, index_ptr)
}; };
@@ -563,7 +567,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::ReplacedModuleOp(module_name, op_decl, op_desc) RetractionRecord::ReplacedModuleOp(module_name, op_decl, op_desc)
}; };
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&target_module_name) { if let Some(module) = self
.wam_prelude
.indices
.modules
.get_mut(&target_module_name)
{
remove_module_exports( remove_module_exports(
&removed_module, &removed_module,
&mut module.code_dir, &mut module.code_dir,
@@ -579,7 +588,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
CompilationTarget::Module(_) => {} CompilationTarget::Module(_) => {}
}; };
self.wam_prelude.indices.modules.insert(module_name, removed_module); self.wam_prelude
.indices
.modules
.insert(module_name, removed_module);
} }
fn get_or_insert_local_code_index( fn get_or_insert_local_code_index(
@@ -591,10 +603,12 @@ 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( .or_insert_with(|| {
CodeIndex::new(
IndexPtr::undefined(), IndexPtr::undefined(),
&mut LS::machine_st(&mut self.payload).arena, &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);
@@ -603,10 +617,12 @@ 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( .or_insert_with(|| {
CodeIndex::new(
IndexPtr::undefined(), IndexPtr::undefined(),
&mut LS::machine_st(&mut self.payload).arena, &mut LS::machine_st(&mut self.payload).arena,
)) )
})
.clone(), .clone(),
None => { None => {
unreachable!() unreachable!()
@@ -771,10 +787,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
ClauseType::Named(arity, name, _) => { ClauseType::Named(arity, name, _) => {
let payload_compilation_target = self.payload.compilation_target; let payload_compilation_target = self.payload.compilation_target;
let idx = self.get_or_insert_code_index( let idx = self.get_or_insert_code_index((name, arity), payload_compilation_target);
(name, arity),
payload_compilation_target,
);
ClauseType::Named(arity, name, idx) ClauseType::Named(arity, name, idx)
} }
@@ -802,9 +815,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
pub(super) fn get_meta_specs(&self, name: Atom, arity: usize) -> Option<&Vec<MetaSpec>> { pub(super) fn get_meta_specs(&self, name: Atom, arity: usize) -> Option<&Vec<MetaSpec>> {
self.wam_prelude self.wam_prelude.indices.get_meta_predicate_spec(
.indices
.get_meta_predicate_spec(
name, name,
arity, arity,
&self.payload.compilation_target, &self.payload.compilation_target,
@@ -829,19 +840,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.insert(key, meta_specs) .insert(key, meta_specs)
{ {
Some(old_meta_specs) => { Some(old_meta_specs) => {
self.payload.retraction_info self.payload.retraction_info.push_record(
.push_record(RetractionRecord::ReplacedMetaPredicate( RetractionRecord::ReplacedMetaPredicate(
module_name, module_name,
key.0, key.0,
old_meta_specs, old_meta_specs,
)); ),
);
} }
None => { None => {
self.payload.retraction_info self.payload
.push_record(RetractionRecord::AddedMetaPredicate( .retraction_info
module_name, .push_record(RetractionRecord::AddedMetaPredicate(module_name, key));
key,
));
} }
} }
} }
@@ -868,17 +878,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
None => { None => {
self.add_dynamically_generated_module(module_name); self.add_dynamically_generated_module(module_name);
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&module_name) { if let Some(module) = self.wam_prelude.indices.modules.get_mut(&module_name)
{
module.meta_predicates.insert(key.clone(), meta_specs); module.meta_predicates.insert(key.clone(), meta_specs);
} else { } else {
unreachable!() unreachable!()
} }
self.payload.retraction_info self.payload.retraction_info.push_record(
.push_record(RetractionRecord::AddedMetaPredicate( RetractionRecord::AddedMetaPredicate(module_name.clone(), key),
module_name.clone(), );
key,
));
} }
} }
} }
@@ -901,10 +910,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
&mut module.meta_predicates, &mut module.meta_predicates,
); );
self.payload.retraction_info self.payload
.retraction_info
.push_record(RetractionRecord::AddedModule(module_name.clone())); .push_record(RetractionRecord::AddedModule(module_name.clone()));
self.wam_prelude.indices.modules.insert(module_name.clone(), module); self.wam_prelude
.indices
.modules
.insert(module_name.clone(), module);
} }
fn import_builtins_in_module( fn import_builtins_in_module(
@@ -968,9 +981,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if is_dynamic { if is_dynamic {
let clause_clause_compilation_target = match compilation_target { let clause_clause_compilation_target = match compilation_target {
CompilationTarget::User => { CompilationTarget::User => CompilationTarget::Module(atom!("builtins")),
CompilationTarget::Module(atom!("builtins"))
}
module => module.clone(), module => module.clone(),
}; };
@@ -981,7 +992,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
} }
self.payload.retraction_info self.payload
.retraction_info
.push_record(RetractionRecord::ReplacedModule( .push_record(RetractionRecord::ReplacedModule(
old_module_decl, old_module_decl,
listing_src.clone(), listing_src.clone(),
@@ -1051,7 +1063,12 @@ 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) => {
import_module_exports_into_module::<LS>( import_module_exports_into_module::<LS>(
&mut self.payload, &mut self.payload,
@@ -1091,17 +1108,20 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let payload_compilation_target = self.payload.compilation_target; let payload_compilation_target = self.payload.compilation_target;
let result = match &payload_compilation_target { let result = match &payload_compilation_target {
CompilationTarget::User => { CompilationTarget::User => import_qualified_module_exports::<LS>(
import_qualified_module_exports::<LS>(
&mut self.payload, &mut self.payload,
&payload_compilation_target, &payload_compilation_target,
&module, &module,
&exports, &exports,
&mut self.wam_prelude, &mut self.wam_prelude,
) ),
}
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) => {
import_qualified_module_exports_into_module::<LS>( import_qualified_module_exports_into_module::<LS>(
&mut self.payload, &mut self.payload,
@@ -1113,9 +1133,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
&mut self.wam_prelude.indices.op_dir, &mut self.wam_prelude.indices.op_dir,
) )
} }
None => { None => Err(SessionError::ModuleCannotImportSelf(module_name)),
Err(SessionError::ModuleCannotImportSelf(module_name))
}
} }
} }
}; };
@@ -1123,29 +1141,38 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.wam_prelude.indices.modules.insert(module_name, module); self.wam_prelude.indices.modules.insert(module_name, module);
result result
} else { } else {
Err(SessionError::ExistenceError(ExistenceError::Module(module_name))) Err(SessionError::ExistenceError(ExistenceError::Module(
module_name,
)))
} }
} }
pub(crate) fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> { pub(crate) fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> {
let (stream, listing_src) = match module_src { let (stream, listing_src) = match module_src {
ModuleSource::File(filename) => { ModuleSource::File(filename) => {
let mut path_buf = PathBuf::from(filename.as_str()); let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl"); path_buf.set_extension("pl");
let file = File::open(&path_buf)?; let file = File::open(&path_buf)?;
( (
Stream::from_file_as_input(filename, file, &mut LS::machine_st(&mut self.payload).arena), Stream::from_file_as_input(
filename,
file,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::File(filename, path_buf), ListingSource::File(filename, path_buf),
) )
} }
ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) { ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) {
Some(code) => { Some(code) => {
if let Some(ref module) = self.wam_prelude.indices.modules.get(&library) { if let Some(ref module) = self.wam_prelude.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = &module.listing_src { if let ListingSource::DynamicallyGenerated = &module.listing_src {
( (
Stream::from_static_string(*code, &mut LS::machine_st(&mut self.payload).arena), Stream::from_static_string(
*code,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::User, ListingSource::User,
) )
} else { } else {
@@ -1153,7 +1180,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
} else { } else {
( (
Stream::from_static_string(*code, &mut LS::machine_st(&mut self.payload).arena), Stream::from_static_string(
*code,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::User, ListingSource::User,
) )
} }
@@ -1172,9 +1202,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
); );
let subloader: Loader<'_, BootstrappingLoadState> = Loader { let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState( payload: BootstrappingLoadState(LoadStatePayload::new(
LoadStatePayload::new(self.wam_prelude.code.len(), term_stream) self.wam_prelude.code.len(),
), term_stream,
)),
wam_prelude: MachinePreludeView { wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices, indices: self.wam_prelude.indices,
code: self.wam_prelude.code, code: self.wam_prelude.code,
@@ -1201,22 +1232,29 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let (stream, listing_src) = match module_src { let (stream, listing_src) = match module_src {
ModuleSource::File(filename) => { ModuleSource::File(filename) => {
let mut path_buf = PathBuf::from(filename.as_str()); let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl"); path_buf.set_extension("pl");
let file = File::open(&path_buf)?; let file = File::open(&path_buf)?;
( (
Stream::from_file_as_input(filename, file, &mut LS::machine_st(&mut self.payload).arena), Stream::from_file_as_input(
filename,
file,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::File(filename, path_buf), ListingSource::File(filename, path_buf),
) )
} }
ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) { ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) {
Some(code) => { Some(code) => {
if self.wam_prelude.indices.modules.contains_key(&library) { if self.wam_prelude.indices.modules.contains_key(&library) {
return self.import_qualified_module(library, exports); return self.import_qualified_module(library, exports);
} else { } else {
( (
Stream::from_static_string(*code, &mut LS::machine_st(&mut self.payload).arena), Stream::from_static_string(
*code,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::User, ListingSource::User,
) )
} }
@@ -1235,9 +1273,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
); );
let subloader: Loader<'_, BootstrappingLoadState> = Loader { let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState( payload: BootstrappingLoadState(LoadStatePayload::new(
LoadStatePayload::new(self.wam_prelude.code.len(), term_stream), self.wam_prelude.code.len(),
), term_stream,
)),
wam_prelude: MachinePreludeView { wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices, indices: self.wam_prelude.indices,
code: self.wam_prelude.code, code: self.wam_prelude.code,

View File

@@ -230,9 +230,7 @@ macro_rules! predicate_queue {
pub type LiveLoadState = LoadStatePayload<LiveTermStream>; pub type LiveLoadState = LoadStatePayload<LiveTermStream>;
pub struct BootstrappingLoadState<'a>( pub struct BootstrappingLoadState<'a>(pub LoadStatePayload<BootstrappingTermStream<'a>>);
pub LoadStatePayload<BootstrappingTermStream<'a>>
);
impl<'a> Deref for BootstrappingLoadState<'a> { impl<'a> Deref for BootstrappingLoadState<'a> {
type Target = LoadStatePayload<BootstrappingTermStream<'a>>; type Target = LoadStatePayload<BootstrappingTermStream<'a>>;
@@ -255,7 +253,10 @@ pub trait LoadState<'a>: Sized {
type TS: TermStream; type TS: TermStream;
type LoaderFieldType: DerefMut<Target = LoadStatePayload<Self::TS>>; type LoaderFieldType: DerefMut<Target = LoadStatePayload<Self::TS>>;
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType; fn new(
machine_st: &'a mut MachineState,
payload: LoadStatePayload<Self::TS>,
) -> Self::LoaderFieldType;
fn evacuate(loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError>; fn evacuate(loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError>;
fn should_drop_load_state(loader: &Loader<'a, Self>) -> bool; fn should_drop_load_state(loader: &Loader<'a, Self>) -> bool;
fn reset_machine(loader: &mut Loader<'a, Self>); fn reset_machine(loader: &mut Loader<'a, Self>);
@@ -293,14 +294,23 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
type Evacuable = TypedArenaPtr<LiveLoadState>; type Evacuable = TypedArenaPtr<LiveLoadState>;
#[inline(always)] #[inline(always)]
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType { fn new(
machine_st: &'a mut MachineState,
payload: LoadStatePayload<Self::TS>,
) -> Self::LoaderFieldType {
let load_state = arena_alloc!(payload, &mut machine_st.arena); let load_state = arena_alloc!(payload, &mut machine_st.arena);
LiveLoadAndMachineState { load_state, machine_st } LiveLoadAndMachineState {
load_state,
machine_st,
}
} }
#[inline(always)] #[inline(always)]
fn evacuate(mut loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> { fn evacuate(mut loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> {
loader.payload.load_state.set_tag(ArenaHeaderTag::InactiveLoadState); loader
.payload
.load_state
.set_tag(ArenaHeaderTag::InactiveLoadState);
Ok(loader.payload.load_state) Ok(loader.payload.load_state)
} }
@@ -332,7 +342,11 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
} }
if let Some(builtins) = loader.wam_prelude.indices.modules.get(&atom!("builtins")) { if let Some(builtins) = loader.wam_prelude.indices.modules.get(&atom!("builtins")) {
if builtins.module_decl.exports.contains(&ModuleExport::PredicateKey(key)) { if builtins
.module_decl
.exports
.contains(&ModuleExport::PredicateKey(key))
{
return Err(SessionError::CannotOverwriteBuiltIn(key)); return Err(SessionError::CannotOverwriteBuiltIn(key));
} }
} }
@@ -358,10 +372,7 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
let repo_len = loader.wam_prelude.code.len(); let repo_len = loader.wam_prelude.code.len();
loader loader.payload.retraction_info.reset(repo_len);
.payload
.retraction_info
.reset(repo_len);
loader.remove_module_op_exports(); loader.remove_module_op_exports();
@@ -419,8 +430,14 @@ impl<'a> LoadState<'a> for InlineLoadState<'a> {
type Evacuable = (); type Evacuable = ();
#[inline(always)] #[inline(always)]
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType { fn new(
InlineLoadState { machine_st, payload } machine_st: &'a mut MachineState,
payload: LoadStatePayload<Self::TS>,
) -> Self::LoaderFieldType {
InlineLoadState {
machine_st,
payload,
}
} }
fn evacuate(_loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> { fn evacuate(_loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> {
@@ -433,8 +450,7 @@ impl<'a> LoadState<'a> for InlineLoadState<'a> {
} }
#[inline(always)] #[inline(always)]
fn reset_machine(_loader: &mut Loader<'a, Self>) { fn reset_machine(_loader: &mut Loader<'a, Self>) {}
}
#[inline(always)] #[inline(always)]
fn machine_st(load_state: &mut Self::LoaderFieldType) -> &mut MachineState { fn machine_st(load_state: &mut Self::LoaderFieldType) -> &mut MachineState {
@@ -548,7 +564,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
atom!("user") => { atom!("user") => {
self.wam_prelude.indices.meta_predicates.remove(&key); self.wam_prelude.indices.meta_predicates.remove(&key);
} }
_ => match self.wam_prelude.indices.modules.get_mut(&target_module_name) { _ => match self
.wam_prelude
.indices
.modules
.get_mut(&target_module_name)
{
Some(ref mut module) => { Some(ref mut module) => {
module.meta_predicates.remove(&key); module.meta_predicates.remove(&key);
} }
@@ -566,7 +587,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.meta_predicates .meta_predicates
.insert((name, meta_specs.len()), meta_specs); .insert((name, meta_specs.len()), meta_specs);
} }
_ => match self.wam_prelude.indices.modules.get_mut(&target_module_name) { _ => match self
.wam_prelude
.indices
.modules
.get_mut(&target_module_name)
{
Some(ref mut module) => { Some(ref mut module) => {
module module
.meta_predicates .meta_predicates
@@ -773,9 +799,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
RetractionRecord::ReplacedChoiceOffset(instr_loc, offset) => { RetractionRecord::ReplacedChoiceOffset(instr_loc, offset) => {
match self.wam_prelude.code[instr_loc] { match self.wam_prelude.code[instr_loc] {
Instruction::TryMeElse(ref mut o) | Instruction::TryMeElse(ref mut o)
Instruction::RetryMeElse(ref mut o) | | Instruction::RetryMeElse(ref mut o)
Instruction::DefaultRetryMeElse(ref mut o) => { | Instruction::DefaultRetryMeElse(ref mut o) => {
*o = offset; *o = offset;
} }
_ => { _ => {
@@ -792,7 +818,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v) => { RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v) => {
match self.wam_prelude.code[index_loc] { match self.wam_prelude.code[index_loc] {
Instruction::IndexingCode(ref mut indexing_code) => match &mut indexing_code[0] { Instruction::IndexingCode(ref mut indexing_code) => {
match &mut indexing_code[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_, _,
ref mut v, ref mut v,
@@ -801,7 +828,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
*v = old_v; *v = old_v;
} }
_ => {} _ => {}
}, }
}
_ => {} _ => {}
} }
} }
@@ -941,7 +969,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.get_predicate_skeleton_mut(&compilation_target, &key) .get_predicate_skeleton_mut(&compilation_target, &key)
{ {
Some(skeleton) => { Some(skeleton) => {
if let Some(removed_clauses) = &mut skeleton.core.retracted_dynamic_clauses { if let Some(removed_clauses) =
&mut skeleton.core.retracted_dynamic_clauses
{
let clause_index_info = removed_clauses.pop().unwrap(); let clause_index_info = removed_clauses.pop().unwrap();
skeleton skeleton
@@ -1001,10 +1031,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton) => { RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton) => {
match compilation_target { match compilation_target {
CompilationTarget::User => { CompilationTarget::User => {
self.wam_prelude.indices.extensible_predicates.insert(key, skeleton); self.wam_prelude
.indices
.extensible_predicates
.insert(key, skeleton);
} }
CompilationTarget::Module(module_name) => { CompilationTarget::Module(module_name) => {
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&module_name) { if let Some(module) =
self.wam_prelude.indices.modules.get_mut(&module_name)
{
module.extensible_predicates.insert(key, skeleton); module.extensible_predicates.insert(key, skeleton);
} }
} }
@@ -1012,16 +1047,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
RetractionRecord::ReplacedDynamicElseOffset(instr_loc, next) => { RetractionRecord::ReplacedDynamicElseOffset(instr_loc, next) => {
match self.wam_prelude.code[instr_loc] { match self.wam_prelude.code[instr_loc] {
Instruction::DynamicElse( Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))
_, | Instruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o)) => {
_,
NextOrFail::Next(ref mut o),
)
| Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
) => {
*o = next; *o = next;
} }
_ => {} _ => {}
@@ -1029,16 +1056,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
RetractionRecord::AppendedNextOrFail(instr_loc, fail) => { RetractionRecord::AppendedNextOrFail(instr_loc, fail) => {
match self.wam_prelude.code[instr_loc] { match self.wam_prelude.code[instr_loc] {
Instruction::DynamicElse( Instruction::DynamicElse(_, _, ref mut next_or_fail)
_, | Instruction::DynamicInternalElse(_, _, ref mut next_or_fail) => {
_,
ref mut next_or_fail,
)
| Instruction::DynamicInternalElse(
_,
_,
ref mut next_or_fail,
) => {
*next_or_fail = fail; *next_or_fail = fail;
} }
_ => {} _ => {}
@@ -1057,15 +1076,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let export_list = machine_st.read_term_from_heap(cell)?; let export_list = machine_st.read_term_from_heap(cell)?;
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl; let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
let export_list = setup_module_export_list(export_list, atom_tbl)?; let export_list = setup_module_export_list(export_list, &atom_tbl)?;
Ok(export_list.into_iter().collect()) Ok(export_list.into_iter().collect())
} }
fn add_clause_clause(&mut self, term: Term) -> Result<(), CompilationError> { fn add_clause_clause(&mut self, term: Term) -> Result<(), CompilationError> {
match term { match term {
Term::Clause(_, atom!(":-"), mut terms) if terms.len() == 2 => Term::Clause(_, atom!(":-"), mut terms) if terms.len() == 2 => {
{
let body = terms.pop().unwrap(); let body = terms.pop().unwrap();
let head = terms.pop().unwrap(); let head = terms.pop().unwrap();
@@ -1096,20 +1114,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
match &compilation_target { match &compilation_target {
CompilationTarget::User => { CompilationTarget::User => {
match self match self.wam_prelude.indices.extensible_predicates.get_mut(&key) {
.wam_prelude
.indices
.extensible_predicates
.get_mut(&key)
{
Some(skeleton) => { Some(skeleton) => {
if !*flag_accessor(&mut skeleton.core) { if !*flag_accessor(&mut skeleton.core) {
*flag_accessor(&mut skeleton.core) = true; *flag_accessor(&mut skeleton.core) = true;
self.payload.retraction_info.push_record(retraction_fn( self.payload
compilation_target, .retraction_info
key, .push_record(retraction_fn(compilation_target, key));
));
} }
} }
None => { None => {
@@ -1117,11 +1129,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = PredicateSkeleton::new(); let mut skeleton = PredicateSkeleton::new();
*flag_accessor(&mut skeleton.core) = true; *flag_accessor(&mut skeleton.core) = true;
self.add_extensible_predicate( self.add_extensible_predicate(key, skeleton, CompilationTarget::User);
key,
skeleton,
CompilationTarget::User,
);
} else { } else {
throw_permission_error = true; throw_permission_error = true;
} }
@@ -1135,10 +1143,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if !*flag_accessor(&mut skeleton.core) { if !*flag_accessor(&mut skeleton.core) {
*flag_accessor(&mut skeleton.core) = true; *flag_accessor(&mut skeleton.core) = true;
self.payload.retraction_info.push_record(retraction_fn( self.payload
compilation_target, .retraction_info
key, .push_record(retraction_fn(compilation_target, key));
));
} }
} }
None => { None => {
@@ -1146,11 +1153,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = PredicateSkeleton::new(); let mut skeleton = PredicateSkeleton::new();
*flag_accessor(&mut skeleton.core) = true; *flag_accessor(&mut skeleton.core) = true;
self.add_extensible_predicate( self.add_extensible_predicate(key, skeleton, compilation_target);
key,
skeleton,
compilation_target,
);
} else { } else {
throw_permission_error = true; throw_permission_error = true;
} }
@@ -1162,11 +1165,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = PredicateSkeleton::new(); let mut skeleton = PredicateSkeleton::new();
*flag_accessor(&mut skeleton.core) = true; *flag_accessor(&mut skeleton.core) = true;
self.add_extensible_predicate( self.add_extensible_predicate(key, skeleton, compilation_target);
key,
skeleton,
compilation_target,
);
} }
} }
} }
@@ -1178,10 +1177,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
match payload_compilation_target { match payload_compilation_target {
CompilationTarget::User => { CompilationTarget::User => {
match self match self.wam_prelude.indices.get_local_predicate_skeleton_mut(
.wam_prelude
.indices
.get_local_predicate_skeleton_mut(
payload_compilation_target, payload_compilation_target,
compilation_target, compilation_target,
listing_src_file_name, listing_src_file_name,
@@ -1196,11 +1192,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new(); let mut skeleton = LocalPredicateSkeleton::new();
*flag_accessor(&mut skeleton) = true; *flag_accessor(&mut skeleton) = true;
self.add_local_extensible_predicate( self.add_local_extensible_predicate(compilation_target, key, skeleton);
compilation_target,
key,
skeleton,
);
} }
} }
} }
@@ -1232,11 +1224,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new(); let mut skeleton = LocalPredicateSkeleton::new();
*flag_accessor(&mut skeleton) = true; *flag_accessor(&mut skeleton) = true;
self.add_local_extensible_predicate( self.add_local_extensible_predicate(compilation_target, key, skeleton);
compilation_target,
key,
skeleton,
);
} }
} }
} }
@@ -1336,10 +1324,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let is_dynamic = self let is_dynamic = self
.wam_prelude .wam_prelude
.indices .indices
.get_predicate_skeleton( .get_predicate_skeleton(&predicates_compilation_target, &(predicate_name, arity))
&predicates_compilation_target,
&(predicate_name, arity),
)
.map(|skeleton| skeleton.core.is_dynamic) .map(|skeleton| skeleton.core.is_dynamic)
.unwrap_or(false); .unwrap_or(false);
@@ -1356,10 +1341,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let predicates_compilation_target = self.payload.predicates.compilation_target; let predicates_compilation_target = self.payload.predicates.compilation_target;
let listing_src_file_name = self.listing_src_file_name(); let listing_src_file_name = self.listing_src_file_name();
let clause_locs = match self let clause_locs = match self.wam_prelude.indices.get_local_predicate_skeleton_mut(
.wam_prelude
.indices
.get_local_predicate_skeleton_mut(
payload_compilation_target, payload_compilation_target,
predicates_compilation_target, predicates_compilation_target,
listing_src_file_name, listing_src_file_name,
@@ -1380,11 +1362,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
), ),
); );
self.retract_local_clauses_impl( self.retract_local_clauses_impl(predicates_compilation_target, *key, &clause_locs);
predicates_compilation_target,
*key,
&clause_locs,
);
if is_dynamic { if is_dynamic {
let clause_clause_compilation_target = match predicates_compilation_target { let clause_clause_compilation_target = match predicates_compilation_target {
@@ -1399,7 +1377,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
impl<'a> MachinePreludeView<'a> { impl<'a> MachinePreludeView<'a> {
#[inline] #[inline]
pub(super) fn composite_op_dir(&self, compilation_target: &CompilationTarget) -> CompositeOpDir { pub(super) fn composite_op_dir(
&self,
compilation_target: &CompilationTarget,
) -> CompositeOpDir {
match compilation_target { match compilation_target {
CompilationTarget::User => CompositeOpDir::new(&self.indices.op_dir, None), CompilationTarget::User => CompositeOpDir::new(&self.indices.op_dir, None),
CompilationTarget::Module(ref module_name) => { CompilationTarget::Module(ref module_name) => {
@@ -1417,7 +1398,10 @@ impl<'a> MachinePreludeView<'a> {
} }
impl MachineState { impl MachineState {
pub(super) fn read_term_from_heap(&mut self, term_addr: HeapCellValue) -> Result<Term, SessionError> { pub(super) fn read_term_from_heap(
&mut self,
term_addr: HeapCellValue,
) -> Result<Term, SessionError> {
let mut term_stack = vec![]; let mut term_stack = vec![];
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term_addr); let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term_addr);
@@ -1436,7 +1420,7 @@ impl MachineState {
term_stack.push(Term::PartialString(Cell::default(), string, tail)); term_stack.push(Term::PartialString(Cell::default(), string, tail));
} }
Ok((string, None)) => { Ok((string, None)) => {
let atom = self.atom_tbl.build_with(&string); let atom = AtomTable::build_with(&self.atom_tbl, &string);
term_stack.push(Term::CompleteString(Cell::default(), atom)); term_stack.push(Term::CompleteString(Cell::default(), atom));
} }
Err(cons_term) => term_stack.push(cons_term), Err(cons_term) => term_stack.push(cons_term),
@@ -1550,9 +1534,9 @@ impl Machine {
} }
pub(crate) fn load_compiled_library(&mut self) -> CallResult { pub(crate) fn load_compiled_library(&mut self) -> CallResult {
let library = cell_as_atom!( let library = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
if let Some(module) = self.indices.modules.get(&library) { if let Some(module) = self.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = module.listing_src { if let ListingSource::DynamicallyGenerated = module.listing_src {
@@ -1583,9 +1567,9 @@ impl Machine {
} }
pub(crate) fn declare_module(&mut self) -> CallResult { pub(crate) fn declare_module(&mut self) -> CallResult {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(3)); let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1652,7 +1636,11 @@ impl Machine {
let arity = self.deref_register(3); let arity = self.deref_register(3);
let arity = match Number::try_from(arity) { let arity = match Number::try_from(arity) {
Ok(Number::Integer(n)) if &*n >= &Integer::from(0) && &*n <= &Integer::from(MAX_ARITY) => Ok(n.to_usize().unwrap()), Ok(Number::Integer(n))
if &*n >= &Integer::from(0) && &*n <= &Integer::from(MAX_ARITY) =>
{
Ok(n.to_usize().unwrap())
}
Ok(Number::Fixnum(n)) if n.get_num() >= 0 && n.get_num() <= MAX_ARITY as i64 => { Ok(Number::Fixnum(n)) if n.get_num() >= 0 && n.get_num() <= MAX_ARITY as i64 => {
Ok(usize::try_from(n.get_num()).unwrap()) Ok(usize::try_from(n.get_num()).unwrap())
} }
@@ -1692,9 +1680,9 @@ impl Machine {
} }
pub(crate) fn add_goal_expansion_clause(&mut self) -> CallResult { pub(crate) fn add_goal_expansion_clause(&mut self) -> CallResult {
let target_module_name = cell_as_atom!( let target_module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(3)); let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1714,7 +1702,8 @@ impl Machine {
if let Some(indexing_term) = indexing_arg { if let Some(indexing_term) = indexing_arg {
if let Some(indexing_name) = indexing_term.name() { if let Some(indexing_name) = indexing_term.name() {
loader.wam_prelude loader
.wam_prelude
.indices .indices
.goal_expansion_indices .goal_expansion_indices
.insert((indexing_name, indexing_term.arity())); .insert((indexing_name, indexing_term.arity()));
@@ -1789,16 +1778,19 @@ impl Machine {
&'a mut self, &'a mut self,
r: RegType, r: RegType,
) -> Loader<'a, LiveLoadAndMachineState<'a>> { ) -> Loader<'a, LiveLoadAndMachineState<'a>> {
let mut load_state = cell_as_load_state_payload!( let mut load_state = cell_as_load_state_payload!(self
self.machine_st.store(self.machine_st.deref(self.machine_st[r])) .machine_st
); .store(self.machine_st.deref(self.machine_st[r])));
load_state.set_tag(ArenaHeaderTag::LiveLoadState); load_state.set_tag(ArenaHeaderTag::LiveLoadState);
let (wam_prelude, machine_st) = self.prelude_view_and_machine_st(); let (wam_prelude, machine_st) = self.prelude_view_and_machine_st();
Loader { Loader {
payload: LiveLoadAndMachineState { load_state, machine_st }, payload: LiveLoadAndMachineState {
load_state,
machine_st,
},
wam_prelude, wam_prelude,
} }
} }
@@ -1806,26 +1798,21 @@ impl Machine {
#[inline] #[inline]
pub(crate) fn push_load_state_payload(&mut self) { pub(crate) fn push_load_state_payload(&mut self) {
let payload = arena_alloc!( let payload = arena_alloc!(
LoadStatePayload::new( LoadStatePayload::new(self.code.len(), LiveTermStream::new(ListingSource::User),),
self.code.len(),
LiveTermStream::new(ListingSource::User),
),
&mut self.machine_st.arena &mut self.machine_st.arena
); );
let var = self.machine_st.deref(self.machine_st.registers[1]); let var = self.machine_st.deref(self.machine_st.registers[1]);
self.machine_st.bind( self.machine_st
var.as_var().unwrap(), .bind(var.as_var().unwrap(), typed_arena_ptr_as_cell!(payload));
typed_arena_ptr_as_cell!(payload),
);
} }
#[inline] #[inline]
pub(crate) fn pop_load_state_payload(&mut self) { pub(crate) fn pop_load_state_payload(&mut self) {
let load_state_payload = self.machine_st.store( let load_state_payload = self
self.machine_st.deref(self.machine_st.registers[1]) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1]));
// unlike in loader_from_heap_evacuable, // unlike in loader_from_heap_evacuable,
// pop_load_state_payload is allowed to fail to find a // pop_load_state_payload is allowed to fail to find a
@@ -1863,11 +1850,12 @@ impl Machine {
2, 2,
)?; )?;
let path = cell_as_atom!( let path = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[2])));
self.load_contexts.push(LoadContext::new(path.as_str(), stream)); self.load_contexts
.push(LoadContext::new(&*path.as_str(), stream));
Ok(()) Ok(())
} }
@@ -1876,9 +1864,7 @@ impl Machine {
result: Result<TypedArenaPtr<LiveLoadState>, SessionError>, result: Result<TypedArenaPtr<LiveLoadState>, SessionError>,
) -> CallResult { ) -> CallResult {
match result { match result {
Ok(_payload) => { Ok(_payload) => Ok(()),
Ok(())
}
Err(e) => { Err(e) => {
let err = self.machine_st.session_error(e); let err = self.machine_st.session_error(e);
let stub = functor_stub(atom!("load"), 1); let stub = functor_stub(atom!("load"), 1);
@@ -1889,9 +1875,9 @@ impl Machine {
} }
pub(crate) fn scoped_clause_to_evacuable(&mut self) -> CallResult { pub(crate) fn scoped_clause_to_evacuable(&mut self) -> CallResult {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let loader = self.loader_from_heap_evacuable(temp_v!(3)); let loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1931,9 +1917,10 @@ impl Machine {
pub(crate) fn load_context_source(&mut self) { pub(crate) fn load_context_source(&mut self) {
if let Some(load_context) = self.load_contexts.last() { if let Some(load_context) = self.load_contexts.last() {
let path_str = load_context.path.to_str().unwrap(); let path_str = load_context.path.to_str().unwrap();
let path_atom = self.machine_st.atom_tbl.build_with(path_str); let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, path_str);
self.machine_st.unify_atom(path_atom, self.machine_st.registers[1]); self.machine_st
.unify_atom(path_atom, self.machine_st.registers[1]);
} else { } else {
self.machine_st.fail = true; self.machine_st.fail = true;
} }
@@ -1944,9 +1931,11 @@ impl Machine {
match load_context.path.file_name() { match load_context.path.file_name() {
Some(file_name) if load_context.path.is_file() => { Some(file_name) if load_context.path.is_file() => {
let file_name_str = file_name.to_str().unwrap(); let file_name_str = file_name.to_str().unwrap();
let file_name_atom = self.machine_st.atom_tbl.build_with(file_name_str); let file_name_atom =
AtomTable::build_with(&self.machine_st.atom_tbl, file_name_str);
self.machine_st.unify_atom(file_name_atom, self.machine_st.registers[1]); self.machine_st
.unify_atom(file_name_atom, self.machine_st.registers[1]);
return; return;
} }
_ => { _ => {
@@ -1962,9 +1951,11 @@ impl Machine {
if let Some(load_context) = self.load_contexts.last() { if let Some(load_context) = self.load_contexts.last() {
if let Some(directory) = load_context.path.parent() { if let Some(directory) = load_context.path.parent() {
let directory_str = directory.to_str().unwrap(); let directory_str = directory.to_str().unwrap();
let directory_atom = self.machine_st.atom_tbl.build_with(directory_str); let directory_atom =
AtomTable::build_with(&self.machine_st.atom_tbl, directory_str);
self.machine_st.unify_atom(directory_atom, self.machine_st.registers[1]); self.machine_st
.unify_atom(directory_atom, self.machine_st.registers[1]);
return; return;
} }
} }
@@ -1999,11 +1990,9 @@ impl Machine {
_ => CompilationTarget::Module(module_name), _ => CompilationTarget::Module(module_name),
}; };
let stub_gen = || { let stub_gen = || match append_or_prepend {
match append_or_prepend {
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1), AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1), AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
}
}; };
let head = self.deref_register(2); let head = self.deref_register(2);
@@ -2019,7 +2008,8 @@ impl Machine {
loader.payload.compilation_target = compilation_target; loader.payload.compilation_target = compilation_target;
let head = LiveLoadAndMachineState::machine_st(&mut loader.payload).read_term_from_heap(head)?; let head = LiveLoadAndMachineState::machine_st(&mut loader.payload)
.read_term_from_heap(head)?;
let name = if let Some(name) = head.name() { let name = if let Some(name) = head.name() {
name name
@@ -2033,21 +2023,13 @@ impl Machine {
let is_dynamic_predicate = loader let is_dynamic_predicate = loader
.wam_prelude .wam_prelude
.indices .indices
.is_dynamic_predicate( .is_dynamic_predicate(module_name, (name, arity));
module_name,
(name, arity),
);
let no_such_predicate = let no_such_predicate = if !is_dynamic_predicate && !is_builtin {
if !is_dynamic_predicate && !is_builtin {
let idx_tag = loader let idx_tag = loader
.wam_prelude .wam_prelude
.indices .indices
.get_predicate_code_index( .get_predicate_code_index(name, arity, module_name)
name,
arity,
module_name,
)
.map(|code_idx| code_idx.get_tag()) .map(|code_idx| code_idx.get_tag())
.unwrap_or(IndexPtrTag::DynamicUndefined); .unwrap_or(IndexPtrTag::DynamicUndefined);
@@ -2098,23 +2080,18 @@ impl Machine {
match compile_assert() { match compile_assert() {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(SessionError::CompilationError( Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead | CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
CompilationError::InadmissibleFact
)) => { )) => {
let err = self.machine_st.type_error( let err = self
ValidType::Callable, .machine_st
self.machine_st.registers[2], .type_error(ValidType::Callable, self.machine_st.registers[2]);
);
Err(self.machine_st.error_form(err, stub_gen())) Err(self.machine_st.error_form(err, stub_gen()))
} }
Err(SessionError::CompilationError( Err(SessionError::CompilationError(CompilationError::InadmissibleQueryTerm)) => {
CompilationError::InadmissibleQueryTerm let err = self
)) => { .machine_st
let err = self.machine_st.type_error( .type_error(ValidType::Callable, self.machine_st.registers[3]);
ValidType::Callable,
self.machine_st.registers[3],
);
Err(self.machine_st.error_form(err, stub_gen())) Err(self.machine_st.error_form(err, stub_gen()))
} }
@@ -2126,9 +2103,9 @@ impl Machine {
} }
pub(crate) fn abolish_clause(&mut self) -> CallResult { pub(crate) fn abolish_clause(&mut self) -> CallResult {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self let key = self
.machine_st .machine_st
@@ -2140,8 +2117,8 @@ impl Machine {
}; };
let mut abolish_clause = || { let mut abolish_clause = || {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
= Loader::new(self, LiveTermStream::new(ListingSource::User)); Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target; loader.payload.compilation_target = compilation_target;
@@ -2161,9 +2138,11 @@ impl Machine {
.remove_predicate_skeleton( .remove_predicate_skeleton(
&clause_clause_compilation_target, &clause_clause_compilation_target,
&(atom!("$clause"), 2), &(atom!("$clause"), 2),
).unwrap(); )
.unwrap();
let result = skeleton.core let result = skeleton
.core
.clause_clause_locs .clause_clause_locs
.iter() .iter()
.map(|clause_clause_loc| { .map(|clause_clause_loc| {
@@ -2173,11 +2152,7 @@ impl Machine {
}) })
.collect(); .collect();
loader.add_extensible_predicate( loader.add_extensible_predicate(key, skeleton, compilation_target);
key,
skeleton,
compilation_target,
);
loader.add_extensible_predicate( loader.add_extensible_predicate(
(atom!("$clause"), 2), (atom!("$clause"), 2),
@@ -2186,14 +2161,15 @@ impl Machine {
); );
result result
}).unwrap(); })
.unwrap();
loader.wam_prelude loader
.wam_prelude
.indices .indices
.remove_predicate_skeleton(&compilation_target, &key); .remove_predicate_skeleton(&compilation_target, &key);
let mut 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());
@@ -2231,9 +2207,9 @@ impl Machine {
_ => unreachable!(), _ => unreachable!(),
}; };
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[4])));
let compilation_target = match module_name { let compilation_target = match module_name {
atom!("user") => CompilationTarget::User, atom!("user") => CompilationTarget::User,
@@ -2286,9 +2262,9 @@ impl Machine {
} }
pub(crate) fn is_consistent_with_term_queue(&mut self) -> CallResult { pub(crate) fn is_consistent_with_term_queue(&mut self) -> CallResult {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self let key = self
.machine_st .machine_st
@@ -2326,9 +2302,9 @@ impl Machine {
} }
pub(crate) fn remove_module_exports(&mut self) -> CallResult { pub(crate) fn remove_module_exports(&mut self) -> CallResult {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(2)); let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
@@ -2354,9 +2330,9 @@ impl Machine {
} }
pub(crate) fn meta_predicate_property(&mut self) { pub(crate) fn meta_predicate_property(&mut self) {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let (predicate_name, arity) = self let (predicate_name, arity) = self
.machine_st .machine_st
@@ -2374,9 +2350,12 @@ impl Machine {
Some(meta_specs) => { Some(meta_specs) => {
let term_loc = self.machine_st.heap.len(); let term_loc = self.machine_st.heap.len();
self.machine_st.heap.push(atom_as_cell!(predicate_name, arity)); self.machine_st
self.machine_st.heap.extend( .heap
meta_specs.iter().map(|meta_spec| match meta_spec { .push(atom_as_cell!(predicate_name, arity));
self.machine_st
.heap
.extend(meta_specs.iter().map(|meta_spec| match meta_spec {
MetaSpec::Minus => atom_as_cell!(atom!("+")), MetaSpec::Minus => atom_as_cell!(atom!("+")),
MetaSpec::Plus => atom_as_cell!(atom!("-")), MetaSpec::Plus => atom_as_cell!(atom!("-")),
MetaSpec::Either => atom_as_cell!(atom!("?")), MetaSpec::Either => atom_as_cell!(atom!("?")),
@@ -2384,15 +2363,20 @@ impl Machine {
MetaSpec::RequiresExpansionWithArgument(ref arg_num) => { MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
fixnum_as_cell!(Fixnum::build_with(*arg_num as i64)) fixnum_as_cell!(Fixnum::build_with(*arg_num as i64))
} }
}) }));
);
let heap_loc = self.machine_st.heap.len(); let heap_loc = self.machine_st.heap.len();
self.machine_st.heap.push(atom_as_cell!(atom!("meta_predicate"), 1)); self.machine_st
.heap
.push(atom_as_cell!(atom!("meta_predicate"), 1));
self.machine_st.heap.push(str_loc_as_cell!(term_loc)); self.machine_st.heap.push(str_loc_as_cell!(term_loc));
unify!(self.machine_st, str_loc_as_cell!(heap_loc), self.machine_st.registers[4]); unify!(
self.machine_st,
str_loc_as_cell!(heap_loc),
self.machine_st.registers[4]
);
} }
None => { None => {
self.machine_st.fail = true; self.machine_st.fail = true;
@@ -2401,9 +2385,9 @@ impl Machine {
} }
pub(crate) fn dynamic_property(&mut self) { pub(crate) fn dynamic_property(&mut self) {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self let key = self
.machine_st .machine_st
@@ -2428,9 +2412,9 @@ impl Machine {
} }
pub(crate) fn multifile_property(&mut self) { pub(crate) fn multifile_property(&mut self) {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self let key = self
.machine_st .machine_st
@@ -2455,9 +2439,9 @@ impl Machine {
} }
pub(crate) fn discontiguous_property(&mut self) { pub(crate) fn discontiguous_property(&mut self) {
let module_name = cell_as_atom!( let module_name = cell_as_atom!(self
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])) .machine_st
); .store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self let key = self
.machine_st .machine_st

View File

@@ -44,7 +44,8 @@ pub(crate) enum ValidType {
InCharacter, InCharacter,
Integer, Integer,
List, List,
#[allow(unused)] Number, #[allow(unused)]
Number,
Pair, Pair,
// PredicateIndicator, // PredicateIndicator,
// Variable // Variable
@@ -254,9 +255,11 @@ pub(super) type FunctorStub = [HeapCellValue; 3];
#[inline(always)] #[inline(always)]
pub(super) fn functor_stub(name: Atom, arity: usize) -> FunctorStub { pub(super) fn functor_stub(name: Atom, arity: usize) -> FunctorStub {
[atom_as_cell!(atom!("/"), 2), [
atom_as_cell!(atom!("/"), 2),
atom_as_cell!(name), atom_as_cell!(name),
fixnum_as_cell!(Fixnum::build_with(arity as i64))] fixnum_as_cell!(Fixnum::build_with(arity as i64)),
]
} }
impl MachineState { impl MachineState {
@@ -444,7 +447,9 @@ impl MachineState {
self.permission_error( self.permission_error(
Permission::Modify, Permission::Modify,
atom!("static_procedure"), atom!("static_procedure"),
functor_stub(key.0, key.1).into_iter().collect::<MachineStub>(), functor_stub(key.0, key.1)
.into_iter()
.collect::<MachineStub>(),
) )
} }
SessionError::ExistenceError(err) => self.existence_error(err), SessionError::ExistenceError(err) => self.existence_error(err),
@@ -471,7 +476,11 @@ impl MachineState {
} }
SessionError::NamelessEntry => { SessionError::NamelessEntry => {
let error_atom = atom!("nameless_procedure"); let error_atom = atom!("nameless_procedure");
self.permission_error(Permission::Create, atom!("static_procedure"), functor!(error_atom)) self.permission_error(
Permission::Create,
atom!("static_procedure"),
functor!(error_atom),
)
} }
SessionError::OpIsInfixAndPostFix(op) => { SessionError::OpIsInfixAndPostFix(op) => {
self.permission_error(Permission::Create, atom!("operator"), functor!(op)) self.permission_error(Permission::Create, atom!("operator"), functor!(op))
@@ -682,10 +691,12 @@ impl CompilationError {
&CompilationError::ExpectedRel => { &CompilationError::ExpectedRel => {
functor!(atom!("expected_relation")) functor!(atom!("expected_relation"))
} }
&CompilationError::InadmissibleFact => { // TODO: type_error(callable, _). &CompilationError::InadmissibleFact => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_fact")) functor!(atom!("inadmissible_fact"))
} }
&CompilationError::InadmissibleQueryTerm => { // TODO: type_error(callable, _). &CompilationError::InadmissibleQueryTerm => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_query_term")) functor!(atom!("inadmissible_query_term"))
} }
&CompilationError::InconsistentEntry => { &CompilationError::InconsistentEntry => {
@@ -838,7 +849,7 @@ impl MachineState {
match BrentAlgState::detect_cycles(&self.heap, list) { match BrentAlgState::detect_cycles(&self.heap, list) {
CycleSearchResult::PartialList(..) => { CycleSearchResult::PartialList(..) => {
let err = self.instantiation_error(); let err = self.instantiation_error();
return Err(self.error_form(err, stub_gen())) return Err(self.error_form(err, stub_gen()));
} }
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => { CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => {
let err = self.type_error(ValidType::List, list); let err = self.type_error(ValidType::List, list);

View File

@@ -3,15 +3,15 @@ use crate::parser::ast::*;
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::*; use crate::forms::*;
use crate::machine::ClauseType;
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 crate::machine::ClauseType;
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use modular_bitfield::{BitfieldSpecifier, bitfield};
use modular_bitfield::specifiers::*; use modular_bitfield::specifiers::*;
use modular_bitfield::{bitfield, BitfieldSpecifier};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::BTreeSet; use std::collections::BTreeSet;
@@ -86,7 +86,8 @@ pub enum IndexPtrTag {
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct IndexPtr { pub struct IndexPtr {
pub p: B56, pub p: B56,
#[allow(unused)] m: bool, #[allow(unused)]
m: bool,
pub tag: IndexPtrTag, pub tag: IndexPtrTag,
} }
@@ -293,7 +294,8 @@ impl IndexStore {
let (name, arity) = key; let (name, arity) = key;
if !ClauseType::is_inbuilt(name, arity) { if !ClauseType::is_inbuilt(name, arity) {
self.modules.get(&(atom!("builtins"))) self.modules
.get(&(atom!("builtins")))
.map(|module| module.code_dir.contains_key(&(name, arity))) .map(|module| module.code_dir.contains_key(&(name, arity)))
.unwrap_or(false) .unwrap_or(false)
} else { } else {
@@ -444,11 +446,7 @@ impl IndexStore {
} }
} }
pub(crate) fn is_dynamic_predicate( pub(crate) fn is_dynamic_predicate(&self, module_name: Atom, key: PredicateKey) -> bool {
&self,
module_name: Atom,
key: PredicateKey,
) -> bool {
match module_name { match module_name {
atom!("user") => self atom!("user") => self
.extensible_predicates .extensible_predicates

View File

@@ -3,7 +3,6 @@ use crate::atom_table::*;
use crate::forms::*; use crate::forms::*;
use crate::heap_iter::*; use crate::heap_iter::*;
use crate::heap_print::*; use crate::heap_print::*;
use crate::machine::Machine;
use crate::machine::attributed_variables::*; use crate::machine::attributed_variables::*;
use crate::machine::copier::*; use crate::machine::copier::*;
use crate::machine::heap::*; use crate::machine::heap::*;
@@ -11,6 +10,7 @@ use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::stack::*; use crate::machine::stack::*;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::machine::Machine;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::read::TermWriteResult; use crate::read::TermWriteResult;
use crate::types::*; use crate::types::*;
@@ -22,6 +22,7 @@ use indexmap::IndexMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::sync::Arc;
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1]; pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
@@ -57,7 +58,7 @@ pub enum OnEOF {
} }
pub struct MachineState { pub struct MachineState {
pub atom_tbl: AtomTable, pub atom_tbl: Arc<AtomTable>,
pub arena: Arena, pub arena: Arena,
pub(super) pdl: Vec<HeapCellValue>, pub(super) pdl: Vec<HeapCellValue>,
pub(super) s: HeapPtr, pub(super) s: HeapPtr,
@@ -203,12 +204,12 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
fn push_var_eq_functors<'a>( fn push_var_eq_functors<'a>(
heap: &mut Heap, heap: &mut Heap,
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>, iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) -> Vec<HeapCellValue> { ) -> Vec<HeapCellValue> {
let mut list_of_var_eqs = vec![]; let mut list_of_var_eqs = vec![];
for (var, binding) in iter { for (var, binding) in iter {
let var_atom = atom_tbl.build_with(&var.to_string()); let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let h = heap.len(); let h = heap.len();
heap.push(atom_as_cell!(atom!("="), 2)); heap.push(atom_as_cell!(atom!("="), 2));
@@ -243,9 +244,11 @@ impl Ball {
pub(super) fn copy_and_align(&self, h: usize) -> Heap { pub(super) fn copy_and_align(&self, h: usize) -> Heap {
let diff = self.boundary as i64 - h as i64; let diff = self.boundary as i64 - h as i64;
self.stub.iter().cloned().map(|heap_value| { self.stub
heap_value - diff .iter()
}).collect() .cloned()
.map(|heap_value| heap_value - diff)
.collect()
} }
} }
@@ -418,9 +421,7 @@ impl MachineState {
if self.cwil.count == *limit { if self.cwil.count == *limit {
self.cwil.inference_limit_exceeded = true; self.cwil.inference_limit_exceeded = true;
return Err( return Err(functor!(atom!("inference_limit_exceeded"), [fixnum(bp)]));
functor!(atom!("inference_limit_exceeded"), [fixnum(bp)])
);
} else { } else {
self.cwil.count += 1; self.cwil.count += 1;
} }
@@ -430,7 +431,10 @@ impl MachineState {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub(super) fn try_char_list(&mut self, addrs: Vec<HeapCellValue>) -> Result<String, MachineError> { pub(super) fn try_char_list(
&mut self,
addrs: Vec<HeapCellValue>,
) -> Result<String, MachineError> {
let mut chars = String::new(); let mut chars = String::new();
for addr in addrs { for addr in addrs {
@@ -519,14 +523,21 @@ impl MachineState {
let list_of_var_eqs = push_var_eq_functors( let list_of_var_eqs = push_var_eq_functors(
&mut self.heap, &mut self.heap,
var_list.iter().filter_map(|(var_name, var,_)| if var_name.is_anon() { None } else { Some((var_name,var)) }), var_list.iter().filter_map(|(var_name, var, _)| {
&mut self.atom_tbl, if var_name.is_anon() {
None
} else {
Some((var_name, var))
}
}),
&self.atom_tbl,
); );
let singleton_addr = self.registers[3]; let singleton_addr = self.registers[3];
let singletons_offset = heap_loc_as_cell!( let singletons_offset = heap_loc_as_cell!(iter_to_heap_list(
iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter()) &mut self.heap,
); singleton_var_list.into_iter()
));
unify_fn!(*self, singletons_offset, singleton_addr); unify_fn!(*self, singletons_offset, singleton_addr);
@@ -535,9 +546,10 @@ impl MachineState {
} }
let vars_addr = self.registers[4]; let vars_addr = self.registers[4];
let vars_offset = heap_loc_as_cell!( let vars_offset = heap_loc_as_cell!(iter_to_heap_list(
iter_to_heap_list(&mut self.heap, var_list.into_iter().map(|(_,cell,_)| cell)) &mut self.heap,
); var_list.into_iter().map(|(_, cell, _)| cell)
));
unify_fn!(*self, vars_offset, vars_addr); unify_fn!(*self, vars_offset, vars_addr);
@@ -546,9 +558,10 @@ impl MachineState {
} }
let var_names_addr = self.registers[5]; let var_names_addr = self.registers[5];
let var_names_offset = heap_loc_as_cell!( let var_names_offset = heap_loc_as_cell!(iter_to_heap_list(
iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter()) &mut self.heap,
); list_of_var_eqs.into_iter()
));
Ok(unify_fn!(*self, var_names_offset, var_names_addr)) Ok(unify_fn!(*self, var_names_offset, var_names_addr))
} }
@@ -589,7 +602,10 @@ impl MachineState {
let singleton_var_list = push_var_eq_functors( let singleton_var_list = push_var_eq_functors(
&mut self.heap, &mut self.heap,
term_write_result.var_dict.iter().filter(|(var_name, binding)| { term_write_result
.var_dict
.iter()
.filter(|(var_name, binding)| {
if var_name.is_anon() { if var_name.is_anon() {
return false; return false;
} }
@@ -600,7 +616,7 @@ impl MachineState {
false false
} }
}), }),
&mut self.atom_tbl, &self.atom_tbl,
); );
for var in term_write_result.var_dict.values_mut() { for var in term_write_result.var_dict.values_mut() {
@@ -620,13 +636,11 @@ impl MachineState {
self.write_read_term_options(var_list, singleton_var_list) self.write_read_term_options(var_list, singleton_var_list)
} }
pub fn read_term_from_user_input_eof_handler(&mut self, stream: Stream) -> Result<OnEOF, MachineStub> { pub fn read_term_from_user_input_eof_handler(
self.eof_action( &mut self,
self.registers[2], stream: Stream,
stream, ) -> Result<OnEOF, MachineStub> {
atom!("read_term"), self.eof_action(self.registers[2], stream, atom!("read_term"), 3)?;
3,
)?;
if stream.options().eof_action() == EOFAction::Reset { if stream.options().eof_action() == EOFAction::Reset {
if self.fail == false { if self.fail == false {
@@ -639,13 +653,15 @@ impl MachineState {
// 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(
let atoms_ptr = (&self.atom_tbl.table) as *const indexmap::IndexSet<Atom>; &mut self,
stream: Stream,
indices: &mut IndexStore,
) -> CallResult {
if let Stream::Readline(ptr) = stream { if let Stream::Readline(ptr) = stream {
unsafe { unsafe {
let readline = ptr.as_ptr().as_mut().unwrap(); let readline = ptr.as_ptr().as_mut().unwrap();
readline.set_atoms_for_completion(atoms_ptr); readline.set_atoms_for_completion(&self.atom_tbl);
return self.read_term( return self.read_term(
stream, stream,
indices, indices,
@@ -663,12 +679,7 @@ impl MachineState {
stream.set_past_end_of_stream(true); stream.set_past_end_of_stream(true);
return Ok(OnEOF::Return); return Ok(OnEOF::Return);
} else if stream.past_end_of_stream() { } else if stream.past_end_of_stream() {
self.eof_action( self.eof_action(self.registers[2], stream, atom!("read_term"), 3)?;
self.registers[2],
stream,
atom!("read_term"),
3,
)?;
if stream.options().eof_action() == EOFAction::Reset { if stream.options().eof_action() == EOFAction::Reset {
if self.fail == false { if self.fail == false {
@@ -709,7 +720,9 @@ impl MachineState {
match &err { match &err {
CompilationError::ParserError(e) if e.is_unexpected_eof() => { CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? { match eof_handler(self, stream)? {
OnEOF::Return => return self.write_read_term_options(vec![], vec![]), OnEOF::Return => {
return self.write_read_term_options(vec![], vec![])
}
OnEOF::Continue => continue, OnEOF::Continue => continue,
} }
} }
@@ -762,14 +775,14 @@ impl MachineState {
} }
(HeapCellValueTag::Atom, (name, _arity)) => { (HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0); debug_assert_eq!(_arity, 0);
var_names.insert(var, VarPtr::from(name.as_str())); var_names.insert(var, VarPtr::from(&*name.as_str()));
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s]) let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity(); .get_name_and_arity();
debug_assert_eq!(arity, 0); debug_assert_eq!(arity, 0);
var_names.insert(var, VarPtr::from(name.as_str())); var_names.insert(var, VarPtr::from(&*name.as_str()));
} }
_ => { _ => {
unreachable!(); unreachable!();
@@ -850,7 +863,7 @@ impl MachineState {
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut self.heap, &mut self.heap,
&mut self.atom_tbl, Arc::clone(&self.atom_tbl),
&mut self.stack, &mut self.stack,
op_dir, op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -896,7 +909,11 @@ impl MachineState {
Ok(Some(printer)) Ok(Some(printer))
} }
pub(super) fn read_predicate_key(&self, name: HeapCellValue, arity: HeapCellValue) -> (Atom, usize) { pub(super) fn read_predicate_key(
&self,
name: HeapCellValue,
arity: HeapCellValue,
) -> (Atom, usize) {
let name = cell_as_atom!(self.store(self.deref(name))); let name = cell_as_atom!(self.store(self.deref(name)));
let arity = cell_as_fixnum!(self.store(self.deref(arity))); let arity = cell_as_fixnum!(self.store(self.deref(arity)));

View File

@@ -1,6 +1,5 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::types::*;
use crate::forms::*; use crate::forms::*;
use crate::heap_iter::*; use crate::heap_iter::*;
use crate::machine::attributed_variables::*; use crate::machine::attributed_variables::*;
@@ -14,6 +13,7 @@ use crate::machine::stack::*;
use crate::machine::unify::*; use crate::machine::unify::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::dashu::{Integer, Rational}; use crate::parser::dashu::{Integer, Rational};
use crate::types::*;
use indexmap::IndexSet; use indexmap::IndexSet;
@@ -59,8 +59,8 @@ impl MachineState {
dynamic_mode: FirstOrNext::First, dynamic_mode: FirstOrNext::First,
unify_fn: MachineState::unify, unify_fn: MachineState::unify,
bind_fn: MachineState::bind, bind_fn: MachineState::bind,
run_cleaners_fn: |_| { false }, run_cleaners_fn: |_| false,
increment_call_count_fn: |_| { Ok(()) }, increment_call_count_fn: |_| Ok(()),
} }
} }
@@ -160,9 +160,8 @@ impl MachineState {
key_atom.index as u64, key_atom.index as u64,
)); ));
self.trail.push(TrailEntry::from_bytes( self.trail
value_cell.into_bytes(), .push(TrailEntry::from_bytes(value_cell.into_bytes()));
));
self.tr += 2; self.tr += 2;
} }
@@ -248,9 +247,7 @@ impl MachineState {
r: Ref, r: Ref,
value: HeapCellValue, value: HeapCellValue,
) { ) {
let mut unifier = CompositeUnifierForOccursCheckWithError::from( let mut unifier = CompositeUnifierForOccursCheckWithError::from(DefaultUnifier::from(self));
DefaultUnifier::from(self),
);
unifier.bind(r, value); unifier.bind(r, value);
} }
@@ -316,9 +313,7 @@ impl MachineState {
} }
pub(super) fn unify_with_occurs_check_with_error(&mut self) { pub(super) fn unify_with_occurs_check_with_error(&mut self) {
let mut unifier = CompositeUnifierForOccursCheckWithError::from( let mut unifier = CompositeUnifierForOccursCheckWithError::from(DefaultUnifier::from(self));
DefaultUnifier::from(self),
);
unifier.unify_internal(); unifier.unify_internal();
} }
@@ -380,8 +375,7 @@ impl MachineState {
} }
) )
} }
&mut HeapPtr::PStrChar(h, ref mut n) | &mut HeapPtr::PStrChar(h, ref mut n) | &mut HeapPtr::PStrLocation(h, ref mut n) => {
&mut HeapPtr::PStrLocation(h, ref mut n) => {
read_heap_cell!(self.heap[h], read_heap_cell!(self.heap[h],
(HeapCellValueTag::PStr, pstr_atom) => { (HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom); let pstr = PartialString::from(pstr_atom);
@@ -509,7 +503,7 @@ impl MachineState {
} else { } else {
self.pdl.clear(); self.pdl.clear();
return Some( return Some(
n1.chars().next().cmp(&Some(c2)) n1.as_str().chars().next().cmp(&Some(c2))
.then(Ordering::Greater) .then(Ordering::Greater)
); );
} }
@@ -539,7 +533,7 @@ impl MachineState {
} else { } else {
self.pdl.clear(); self.pdl.clear();
return Some( return Some(
Some(c1).cmp(&n2.chars().next()) Some(c1).cmp(&n2.as_str().chars().next())
.then(Ordering::Less) .then(Ordering::Less)
); );
} }
@@ -562,7 +556,7 @@ impl MachineState {
} else { } else {
self.pdl.clear(); self.pdl.clear();
return Some( return Some(
Some(c1).cmp(&n2.chars().next()) Some(c1).cmp(&n2.as_str().chars().next())
.then(Ordering::Less) .then(Ordering::Less)
); );
} }
@@ -592,7 +586,7 @@ impl MachineState {
} else { } else {
self.pdl.clear(); self.pdl.clear();
return Some( return Some(
n1.chars().next().cmp(&Some(c2)) n1.as_str().chars().next().cmp(&Some(c2))
.then(Ordering::Greater) .then(Ordering::Greater)
); );
} }
@@ -902,8 +896,12 @@ impl MachineState {
let s = string.as_str(); let s = string.as_str();
match heap_pstr_iter.compare_pstr_to_string(s) { match heap_pstr_iter.compare_pstr_to_string(&*s) {
Some(PStrPrefixCmpResult { focus, offset, prefix_len }) if prefix_len == s.len() => { Some(PStrPrefixCmpResult {
focus,
offset,
prefix_len,
}) if prefix_len == s.len() => {
let focus_addr = self.heap[focus]; let focus_addr = self.heap[focus];
read_heap_cell!(focus_addr, read_heap_cell!(focus_addr,
@@ -950,7 +948,10 @@ impl MachineState {
return; return;
} }
Some(PStrPrefixCmpResult { prefix_len: inner_prefix_len, .. }) => { Some(PStrPrefixCmpResult {
prefix_len: inner_prefix_len,
..
}) => {
prefix_len = inner_prefix_len; prefix_len = inner_prefix_len;
} }
None => { None => {
@@ -1002,9 +1003,9 @@ impl MachineState {
self.s_offset = 0; self.s_offset = 0;
self.mode = MachineMode::Read; self.mode = MachineMode::Read;
put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl) put_partial_string(&mut self.heap, pstr, &self.atom_tbl)
} else { } else {
put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl) put_complete_string(&mut self.heap, pstr, &self.atom_tbl)
} }
} }
@@ -1096,7 +1097,7 @@ impl MachineState {
(name, 0, 0) (name, 0, 0)
} }
(HeapCellValueTag::Char, c) => { (HeapCellValueTag::Char, c) => {
(self.atom_tbl.build_with(&c.to_string()), 0, 0) (AtomTable::build_with(&self.atom_tbl, &c.to_string()), 0, 0)
} }
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let stub = functor_stub(atom!("call"), arity + 1); let stub = functor_stub(atom!("call"), arity + 1);
@@ -1435,7 +1436,7 @@ impl MachineState {
} }
} }
(HeapCellValueTag::Char, c) => { (HeapCellValueTag::Char, c) => {
let c = self.atom_tbl.build_with(&c.to_string()); let c = AtomTable::build_with(&self.atom_tbl, &c.to_string());
self.try_functor_fabricate_struct( self.try_functor_fabricate_struct(
c, c,
@@ -1571,8 +1572,7 @@ impl MachineState {
while let Some(iteratee) = heap_pstr_iter.next() { while let Some(iteratee) = heap_pstr_iter.next() {
match iteratee { match iteratee {
PStrIteratee::Char(_, c) => PStrIteratee::Char(_, c) => chars.push(char_as_cell!(c)),
chars.push(char_as_cell!(c)),
PStrIteratee::PStrSegment(_, pstr_atom, n) => { PStrIteratee::PStrSegment(_, pstr_atom, n) => {
let pstr = PartialString::from(pstr_atom); let pstr = PartialString::from(pstr_atom);
chars.extend(pstr.as_str_from(n).chars().map(|c| char_as_cell!(c))); chars.extend(pstr.as_str_from(n).chars().map(|c| char_as_cell!(c)));
@@ -1634,10 +1634,7 @@ impl MachineState {
let mut value = unmark_cell_bits!(value); let mut value = unmark_cell_bits!(value);
if value.is_var() { if value.is_var() {
value = heap_bound_store( value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value));
iter.heap,
heap_bound_deref(iter.heap, value),
);
if value.is_var() { if value.is_var() {
return true; return true;

View File

@@ -2,15 +2,17 @@ pub use crate::arena::*;
pub use crate::atom_table::*; pub use crate::atom_table::*;
use crate::heap_print::*; use crate::heap_print::*;
pub use crate::machine::heap::*; pub use crate::machine::heap::*;
pub use crate::machine::*;
pub use crate::machine::machine_state::*; pub use crate::machine::machine_state::*;
pub use crate::machine::stack::*; pub use crate::machine::stack::*;
pub use crate::machine::streams::*; pub use crate::machine::streams::*;
pub use crate::machine::*;
pub use crate::macros::*; pub use crate::macros::*;
pub use crate::parser::ast::*; pub use crate::parser::ast::*;
use crate::read::*; use crate::read::*;
pub use crate::types::*; pub use crate::types::*;
use std::sync::Arc;
#[cfg(test)] #[cfg(test)]
use crate::machine::copier::CopierTarget; use crate::machine::copier::CopierTarget;
@@ -61,7 +63,7 @@ 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.atom_tbl, Arc::clone(&self.machine_st.atom_tbl),
&mut self.machine_st.stack, &mut self.machine_st.stack,
&self.op_dir, &self.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -71,11 +73,9 @@ impl MockWAM {
printer.var_names = term_write_result printer.var_names = term_write_result
.var_dict .var_dict
.into_iter() .into_iter()
.map(|(var, cell)| { .map(|(var, cell)| match var {
match var {
VarKey::VarPtr(var) => (cell, var.clone()), VarKey::VarPtr(var) => (cell, var.clone()),
VarKey::AnonVar(_) => (cell, VarPtr::from(var.to_string())) VarKey::AnonVar(_) => (cell, VarPtr::from(var.to_string())),
}
}) })
.collect(); .collect();
@@ -269,10 +269,7 @@ impl Machine {
.unwrap(); .unwrap();
bootstrapping_compile( bootstrapping_compile(
Stream::from_static_string( Stream::from_static_string(LIBRARIES.borrow()["builtins"], &mut wam.machine_st.arena),
LIBRARIES.borrow()["builtins"],
&mut wam.machine_st.arena,
),
&mut wam, &mut wam,
ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()), ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
) )
@@ -346,26 +343,11 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
let mut op_dir = default_op_dir(); let mut op_dir = default_op_dir();
op_dir.insert( op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
(atom!("+"), Fixity::In), op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8));
OpDesc::build_with(500, YFX as u8), op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(500, YFX as u8));
); op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
op_dir.insert( op_dir.insert((atom!("="), Fixity::In), OpDesc::build_with(700, XFX as u8));
(atom!("-"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("/"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert(
(atom!("="), Fixity::In),
OpDesc::build_with(700, XFX as u8),
);
{ {
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
@@ -582,22 +564,10 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
let mut op_dir = default_op_dir(); let mut op_dir = default_op_dir();
op_dir.insert( op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
(atom!("+"), Fixity::In), op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8));
OpDesc::build_with(500, YFX as u8), op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
); op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
op_dir.insert(
(atom!("-"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert(
(atom!("/"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
{ {
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
@@ -688,20 +658,12 @@ mod tests {
wam.heap.push(heap_loc_as_cell!(1)); wam.heap.push(heap_loc_as_cell!(1));
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
wam,
heap_loc_as_cell!(0),
heap_loc_as_cell!(0)
),
Some(Ordering::Equal) Some(Ordering::Equal)
); );
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, heap_loc_as_cell!(0), atom_as_cell!(atom!("a"))),
wam,
heap_loc_as_cell!(0),
atom_as_cell!(atom!("a"))
),
Some(Ordering::Greater) Some(Ordering::Greater)
); );
@@ -724,29 +686,17 @@ mod tests {
wam.heap.push(empty_list_as_cell!()); wam.heap.push(empty_list_as_cell!());
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
wam,
heap_loc_as_cell!(7),
heap_loc_as_cell!(7)
),
Some(Ordering::Equal) Some(Ordering::Equal)
); );
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(7)),
wam,
heap_loc_as_cell!(0),
heap_loc_as_cell!(7)
),
Some(Ordering::Greater) Some(Ordering::Greater)
); );
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, empty_list_as_cell!(), heap_loc_as_cell!(7)),
wam,
empty_list_as_cell!(),
heap_loc_as_cell!(7)
),
Some(Ordering::Less) Some(Ordering::Less)
); );
@@ -769,40 +719,24 @@ mod tests {
); );
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, empty_list_as_cell!(), atom_as_cell!(atom!("atom"))),
wam,
empty_list_as_cell!(),
atom_as_cell!(atom!("atom"))
),
Some(Ordering::Less) Some(Ordering::Less)
); );
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, atom_as_cell!(atom!("atom")), empty_list_as_cell!()),
wam,
atom_as_cell!(atom!("atom")),
empty_list_as_cell!()
),
Some(Ordering::Greater) Some(Ordering::Greater)
); );
let one_p_one = HeapCellValue::from(float_alloc!(1.1, &mut wam.arena)); let one_p_one = HeapCellValue::from(float_alloc!(1.1, &mut wam.arena));
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, one_p_one, fixnum_as_cell!(Fixnum::build_with(1))),
wam,
one_p_one,
fixnum_as_cell!(Fixnum::build_with(1))
),
Some(Ordering::Less) Some(Ordering::Less)
); );
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(wam, fixnum_as_cell!(Fixnum::build_with(1)), one_p_one),
wam,
fixnum_as_cell!(Fixnum::build_with(1)),
one_p_one
),
Some(Ordering::Greater) Some(Ordering::Greater)
); );
} }
@@ -821,7 +755,8 @@ mod tests {
all_cells_unmarked(&wam.heap); all_cells_unmarked(&wam.heap);
wam.heap.clear(); wam.heap.clear();
wam.heap.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))])); wam.heap
.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))]));
assert!(!wam.is_cyclic_term(str_loc_as_cell!(0))); assert!(!wam.is_cyclic_term(str_loc_as_cell!(0)));

View File

@@ -6,6 +6,7 @@ pub mod code_walker;
pub mod loader; pub mod loader;
pub mod compile; pub mod compile;
pub mod copier; pub mod copier;
pub mod disjuncts;
pub mod dispatch; pub mod dispatch;
pub mod gc; pub mod gc;
pub mod heap; pub mod heap;
@@ -16,7 +17,6 @@ pub mod machine_state;
pub mod machine_state_impl; pub mod machine_state_impl;
pub mod mock_wam; pub mod mock_wam;
pub mod partial_string; pub mod partial_string;
pub mod disjuncts;
pub mod preprocessor; pub mod preprocessor;
pub mod stack; pub mod stack;
pub mod streams; pub mod streams;
@@ -27,9 +27,9 @@ pub mod unify;
use crate::arena::*; use crate::arena::*;
use crate::arithmetic::*; use crate::arithmetic::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::*;
#[cfg(feature = "ffi")] #[cfg(feature = "ffi")]
use crate::ffi::ForeignFunctionTable; use crate::ffi::ForeignFunctionTable;
use crate::forms::*;
use crate::instructions::*; use crate::instructions::*;
use crate::machine::args::*; use crate::machine::args::*;
use crate::machine::compile::*; use crate::machine::compile::*;
@@ -163,7 +163,10 @@ pub(crate) fn import_builtin_impls(code_dir: &CodeDir, builtins: &mut Module) {
for key in keys { for key in keys {
let idx = code_dir.get(&key).unwrap(); let idx = code_dir.get(&key).unwrap();
builtins.code_dir.insert(key, idx.clone()); builtins.code_dir.insert(key, idx.clone());
builtins.module_decl.exports.push(ModuleExport::PredicateKey(key)); builtins
.module_decl
.exports
.push(ModuleExport::PredicateKey(key));
} }
} }
@@ -194,7 +197,7 @@ impl Machine {
code: &mut self.code, code: &mut self.code,
load_contexts: &mut self.load_contexts, load_contexts: &mut self.load_contexts,
}, },
&mut self.machine_st &mut self.machine_st,
) )
} }
@@ -206,7 +209,11 @@ impl Machine {
self.machine_st.throw_exception(err); self.machine_st.throw_exception(err);
} }
fn run_module_predicate(&mut self, module_name: Atom, key: PredicateKey) -> std::process::ExitCode { fn run_module_predicate(
&mut self,
module_name: Atom,
key: PredicateKey,
) -> std::process::ExitCode {
if let Some(module) = self.indices.modules.get(&module_name) { if let Some(module) = self.indices.modules.get(&module_name) {
if let Some(ref code_index) = module.code_dir.get(&key) { if let Some(ref code_index) = module.code_dir.get(&key) {
let p = code_index.local().unwrap(); let p = code_index.local().unwrap();
@@ -223,9 +230,8 @@ impl Machine {
pub fn load_file(&mut self, path: &str, stream: Stream) { pub fn load_file(&mut self, path: &str, stream: Stream) {
self.machine_st.registers[1] = stream_as_cell!(stream); self.machine_st.registers[1] = stream_as_cell!(stream);
self.machine_st.registers[2] = atom_as_cell!( self.machine_st.registers[2] =
self.machine_st.atom_tbl.build_with(path) atom_as_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, path));
);
self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2)); self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2));
} }
@@ -236,10 +242,8 @@ impl Machine {
path_buf.push("src/toplevel.pl"); path_buf.push("src/toplevel.pl");
let path = path_buf.to_str().unwrap(); let path = path_buf.to_str().unwrap();
let toplevel_stream = Stream::from_static_string( let toplevel_stream =
include_str!("../toplevel.pl"), Stream::from_static_string(include_str!("../toplevel.pl"), &mut self.machine_st.arena);
&mut self.machine_st.arena,
);
self.load_file(path, toplevel_stream); self.load_file(path, toplevel_stream);
@@ -292,19 +296,24 @@ impl Machine {
arg_pstrs.push(put_complete_string( arg_pstrs.push(put_complete_string(
&mut self.machine_st.heap, &mut self.machine_st.heap,
&arg, &arg,
&mut self.machine_st.atom_tbl, &self.machine_st.atom_tbl,
)); ));
} }
self.machine_st.registers[1] = heap_loc_as_cell!( self.machine_st.registers[1] = heap_loc_as_cell!(iter_to_heap_list(
iter_to_heap_list(&mut self.machine_st.heap, arg_pstrs.into_iter()) &mut self.machine_st.heap,
); arg_pstrs.into_iter()
));
self.run_module_predicate(atom!("$toplevel"), (atom!("$repl"), 1)) self.run_module_predicate(atom!("$toplevel"), (atom!("$repl"), 1))
} }
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, arena: &mut Arena) { 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);
@@ -349,10 +358,18 @@ 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, &mut self.machine_st.arena); 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, &mut self.machine_st.arena); 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 {
@@ -363,7 +380,8 @@ impl Machine {
pub(crate) fn add_impls_to_indices(&mut self) { pub(crate) fn add_impls_to_indices(&mut self) {
let impls_offset = self.code.len() + 3; let impls_offset = self.code.len() + 3;
self.code.extend(vec![ self.code.extend(
vec![
Instruction::BreakFromDispatchLoop, Instruction::BreakFromDispatchLoop,
Instruction::InstallVerifyAttr, Instruction::InstallVerifyAttr,
Instruction::VerifyAttrInterrupt, Instruction::VerifyAttrInterrupt,
@@ -375,7 +393,10 @@ impl Machine {
Instruction::ExecuteTermNotEqual, Instruction::ExecuteTermNotEqual,
Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), Instruction::ExecuteNumberGreaterThanOrEqual(
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
),
Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))), Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
@@ -405,14 +426,19 @@ impl Machine {
Instruction::ExecuteIsRational(temp_v!(1)), Instruction::ExecuteIsRational(temp_v!(1)),
Instruction::ExecuteIsFloat(temp_v!(1)), Instruction::ExecuteIsFloat(temp_v!(1)),
Instruction::ExecuteIsNonVar(temp_v!(1)), Instruction::ExecuteIsNonVar(temp_v!(1)),
Instruction::ExecuteIsVar(temp_v!(1)) Instruction::ExecuteIsVar(temp_v!(1)),
].into_iter()); ]
.into_iter(),
);
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( self.indices.code_dir.insert(
key, key,
CodeIndex::new(IndexPtr::index(p + impls_offset), &mut self.machine_st.arena), CodeIndex::new(
IndexPtr::index(p + impls_offset),
&mut self.machine_st.arena,
),
); );
} }
} }
@@ -428,8 +454,7 @@ impl Machine {
let user_error = Stream::stderr(&mut machine_st.arena); let user_error = Stream::stderr(&mut machine_st.arena);
#[cfg(not(target_os = "wasi"))] #[cfg(not(target_os = "wasi"))]
let runtime = tokio::runtime::Runtime::new() let runtime = tokio::runtime::Runtime::new().unwrap();
.unwrap();
#[cfg(target_os = "wasi")] #[cfg(target_os = "wasi")]
let runtime = tokio::runtime::Builder::new_current_thread() let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all() .enable_all()
@@ -470,10 +495,7 @@ impl Machine {
.unwrap(); .unwrap();
bootstrapping_compile( bootstrapping_compile(
Stream::from_static_string( Stream::from_static_string(LIBRARIES.borrow()["builtins"], &mut wam.machine_st.arena),
LIBRARIES.borrow()["builtins"],
&mut wam.machine_st.arena,
),
&mut wam, &mut wam,
ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()), ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
) )
@@ -526,7 +548,9 @@ impl Machine {
} }
pub(crate) fn configure_streams(&mut self) { pub(crate) fn configure_streams(&mut self) {
self.user_input.options_mut().set_alias_to_atom_opt(Some(atom!("user_input"))); self.user_input
.options_mut()
.set_alias_to_atom_opt(Some(atom!("user_input")));
self.indices self.indices
.stream_aliases .stream_aliases
@@ -534,7 +558,9 @@ impl Machine {
self.indices.streams.insert(self.user_input); self.indices.streams.insert(self.user_input);
self.user_output.options_mut().set_alias_to_atom_opt(Some(atom!("user_output"))); self.user_output
.options_mut()
.set_alias_to_atom_opt(Some(atom!("user_output")));
self.indices self.indices
.stream_aliases .stream_aliases
@@ -564,9 +590,16 @@ impl Machine {
loop { loop {
let indexing_code_ptr = match &indexing_lines[oip] { let indexing_code_ptr = match &indexing_lines[oip] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, v, c, l, s)) => { &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
arg,
v,
c,
l,
s,
)) => {
cell = self.deref_register(arg); cell = self.deref_register(arg);
self.machine_st.select_switch_on_term_index(cell, v, c, l, s) self.machine_st
.select_switch_on_term_index(cell, v, c, l, s)
} }
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
let lit = self.machine_st.constant_to_literal(cell); let lit = self.machine_st.constant_to_literal(cell);
@@ -676,7 +709,12 @@ impl Machine {
} }
); );
} }
&Instruction::GetPartialString(Level::Shallow, string, RegType::Temp(t), has_tail) => { &Instruction::GetPartialString(
Level::Shallow,
string,
RegType::Temp(t),
has_tail,
) => {
let cell = self.deref_register(t); let cell = self.deref_register(t);
read_heap_cell!(cell, read_heap_cell!(cell,
@@ -707,17 +745,17 @@ impl Machine {
} }
); );
} }
Instruction::GetConstant(..) | Instruction::GetConstant(..)
Instruction::GetList(..) | | Instruction::GetList(..)
Instruction::GetStructure(..) | | Instruction::GetStructure(..)
Instruction::GetPartialString(..) | | Instruction::GetPartialString(..)
&Instruction::UnifyVoid(..) | | &Instruction::UnifyVoid(..)
&Instruction::UnifyConstant(..) | | &Instruction::UnifyConstant(..)
&Instruction::GetVariable(..) | | &Instruction::GetVariable(..)
&Instruction::GetValue(..) | | &Instruction::GetValue(..)
&Instruction::UnifyVariable(..) | | &Instruction::UnifyVariable(..)
&Instruction::UnifyValue(..) | | &Instruction::UnifyValue(..)
&Instruction::UnifyLocalValue(..) => { | &Instruction::UnifyLocalValue(..) => {
offset += 1; offset += 1;
} }
_ => { _ => {
@@ -732,9 +770,10 @@ impl Machine {
fn next_applicable_clause(&mut self, mut offset: usize) -> Option<usize> { fn next_applicable_clause(&mut self, mut offset: usize) -> Option<usize> {
while !self.next_clause_applicable(self.machine_st.p + offset + 1) { while !self.next_clause_applicable(self.machine_st.p + offset + 1) {
match &self.code[self.machine_st.p + offset] { match &self.code[self.machine_st.p + offset] {
&Instruction::DefaultRetryMeElse(o) | &Instruction::RetryMeElse(o) | &Instruction::DefaultRetryMeElse(o)
&Instruction::DynamicElse(.., NextOrFail::Next(o)) | | &Instruction::RetryMeElse(o)
&Instruction::DynamicInternalElse(.., NextOrFail::Next(o)) => offset += o, | &Instruction::DynamicElse(.., NextOrFail::Next(o))
| &Instruction::DynamicInternalElse(.., NextOrFail::Next(o)) => offset += o,
_ => { _ => {
return None; return None;
} }
@@ -753,16 +792,16 @@ impl Machine {
match &indexing_lines[self.machine_st.oip as usize] { match &indexing_lines[self.machine_st.oip as usize] {
IndexingLine::IndexedChoice(indexed_choice) => { IndexingLine::IndexedChoice(indexed_choice) => {
match &indexed_choice[(self.machine_st.iip + inner_offset) as usize] { match &indexed_choice[(self.machine_st.iip + inner_offset) as usize] {
&IndexedChoiceInstruction::Retry(o) | &IndexedChoiceInstruction::Retry(o)
&IndexedChoiceInstruction::DefaultRetry(o) => { | &IndexedChoiceInstruction::DefaultRetry(o) => {
if self.next_clause_applicable(self.machine_st.p + o) { if self.next_clause_applicable(self.machine_st.p + o) {
return Some(inner_offset); return Some(inner_offset);
} }
inner_offset += 1; inner_offset += 1;
} }
&IndexedChoiceInstruction::Trust(o) | &IndexedChoiceInstruction::Trust(o)
&IndexedChoiceInstruction::DefaultTrust(o) => { | &IndexedChoiceInstruction::DefaultTrust(o) => {
return if self.next_clause_applicable(self.machine_st.p + o) { return if self.next_clause_applicable(self.machine_st.p + o) {
Some(inner_offset) Some(inner_offset)
} else { } else {
@@ -815,7 +854,8 @@ impl Machine {
or_frame.prelude.tr = self.machine_st.tr; or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len(); or_frame.prelude.h = self.machine_st.heap.len();
or_frame.prelude.b0 = self.machine_st.b0; or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len = self.machine_st.attr_var_init.attr_var_queue.len(); or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
self.machine_st.b = b; self.machine_st.b = b;
@@ -846,7 +886,8 @@ impl Machine {
or_frame.prelude.tr = self.machine_st.tr; or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len(); or_frame.prelude.h = self.machine_st.heap.len();
or_frame.prelude.b0 = self.machine_st.b0; or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len = self.machine_st.attr_var_init.attr_var_queue.len(); or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
self.machine_st.b = b; self.machine_st.b = b;
@@ -1040,15 +1081,17 @@ impl Machine {
#[inline(always)] #[inline(always)]
fn undefined_procedure(&mut self, name: Atom, arity: usize) -> CallResult { fn undefined_procedure(&mut self, name: Atom, arity: usize) -> CallResult {
match self.machine_st.flags.unknown { match self.machine_st.flags.unknown {
Unknown::Error => { Unknown::Error => Err(self.machine_st.throw_undefined_error(name, arity)),
Err(self.machine_st.throw_undefined_error(name, arity))
}
Unknown::Fail => { Unknown::Fail => {
self.machine_st.fail = true; self.machine_st.fail = true;
Ok(()) Ok(())
} }
Unknown::Warn => { Unknown::Warn => {
println!("warning: predicate {}/{} is undefined", name.as_str(), arity); println!(
"warning: predicate {}/{} is undefined",
name.as_str(),
arity
);
self.machine_st.fail = true; self.machine_st.fail = true;
Ok(()) Ok(())
} }
@@ -1093,9 +1136,7 @@ impl Machine {
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);
} }
IndexPtrTag::Index => { IndexPtrTag::Index => self.machine_st.execute_at_index(arity, compiled_tl_index),
self.machine_st.execute_at_index(arity, compiled_tl_index)
}
} }
Ok(()) Ok(())
@@ -1120,7 +1161,9 @@ impl Machine {
} }
} else { } else {
let stub = functor_stub(name, arity); let stub = functor_stub(name, arity);
let err = self.machine_st.module_resolution_error(module_name, name, arity); let err = self
.machine_st
.module_resolution_error(module_name, name, arity);
Err(self.machine_st.error_form(err, stub)) Err(self.machine_st.error_form(err, stub))
} }
@@ -1146,7 +1189,9 @@ impl Machine {
} }
} else { } else {
let stub = functor_stub(name, arity); let stub = functor_stub(name, arity);
let err = self.machine_st.module_resolution_error(module_name, name, arity); let err = self
.machine_st
.module_resolution_error(module_name, name, arity);
Err(self.machine_st.error_form(err, stub)) Err(self.machine_st.error_form(err, stub))
} }
@@ -1180,10 +1225,14 @@ impl Machine {
let r_c_wo_h_atom = atom!("run_cleaners_without_handling"); let r_c_wo_h_atom = atom!("run_cleaners_without_handling");
let iso_ext = atom!("iso_ext"); let iso_ext = atom!("iso_ext");
RCWH = self.indices.get_predicate_code_index(r_c_w_h_atom, 0, iso_ext) RCWH = self
.indices
.get_predicate_code_index(r_c_w_h_atom, 0, iso_ext)
.and_then(|item| item.local()) .and_then(|item| item.local())
.unwrap(); .unwrap();
RCWOH = self.indices.get_predicate_code_index(r_c_wo_h_atom, 1, iso_ext) RCWOH = self
.indices
.get_predicate_code_index(r_c_wo_h_atom, 1, iso_ext)
.and_then(|item| item.local()) .and_then(|item| item.local())
.unwrap(); .unwrap();
}); });
@@ -1196,9 +1245,8 @@ impl Machine {
let (idx, arity) = if self.machine_st.effective_block() > prev_block { let (idx, arity) = if self.machine_st.effective_block() > prev_block {
(r_c_w_h, 0) (r_c_w_h, 0)
} else { } else {
self.machine_st.registers[1] = fixnum_as_cell!( self.machine_st.registers[1] =
Fixnum::build_with(b_cutoff as i64) fixnum_as_cell!(Fixnum::build_with(b_cutoff as i64));
);
(r_c_wo_h, 1) (r_c_wo_h, 1)
}; };
@@ -1265,8 +1313,7 @@ impl Machine {
None => unreachable!(), None => unreachable!(),
} }
} }
TrailEntryTag::TrailedAttachedValue => { TrailEntryTag::TrailedAttachedValue => {}
}
} }
} }
} }

View File

@@ -43,10 +43,9 @@ impl Into<Atom> for PartialString {
impl PartialString { impl PartialString {
#[inline] #[inline]
pub(super) fn new<'a>(src: &'a str, atom_tbl: &mut AtomTable) -> Option<(Self, &'a str)> { pub(super) fn new<'a>(src: &'a str, atom_tbl: &AtomTable) -> Option<(Self, &'a str)> {
let terminator_idx = scan_for_terminator(src.chars()); let terminator_idx = scan_for_terminator(src.chars());
let pstr = PartialString(atom_tbl.build_with(&src[.. terminator_idx])); let pstr = PartialString(AtomTable::build_with(&atom_tbl, &src[..terminator_idx]));
Some(if terminator_idx < src.as_bytes().len() { Some(if terminator_idx < src.as_bytes().len() {
(pstr, &src[terminator_idx + 1..]) (pstr, &src[terminator_idx + 1..])
} else { } else {
@@ -55,8 +54,8 @@ impl PartialString {
} }
#[inline(always)] #[inline(always)]
pub(crate) fn as_str_from(&self, n: usize) -> &str { pub(crate) fn as_str_from(&self, n: usize) -> AtomString {
&self.0.as_str()[n..] self.0.as_str().map(|str| &str[n..])
} }
} }
@@ -124,7 +123,11 @@ impl<'a> HeapPStrIter<'a> {
let mut final_result = None; let mut final_result = None;
while let Some(PStrIterStep { iteratee, next_hare }) = self.step(self.brent_st.hare) { while let Some(PStrIterStep {
iteratee,
next_hare,
}) = self.step(self.brent_st.hare)
{
self.brent_st.hare = next_hare; self.brent_st.hare = next_hare;
self.focus = self.heap[iteratee.focus()]; self.focus = self.heap[iteratee.focus()];
@@ -151,7 +154,7 @@ impl<'a> HeapPStrIter<'a> {
let s = &s[result.prefix_len..]; let s = &s[result.prefix_len..];
if s.len() >= t.len() { if s.len() >= t.len() {
if s.starts_with(t) { if (&*s).starts_with(&*t) {
result.prefix_len += t.len(); result.prefix_len += t.len();
result.offset += t.len(); result.offset += t.len();
} else { } else {
@@ -225,7 +228,7 @@ impl<'a> HeapPStrIter<'a> {
} }
PStrIteratee::PStrSegment(_, pstr_atom, n) => { PStrIteratee::PStrSegment(_, pstr_atom, n) => {
let pstr = PartialString::from(pstr_atom); let pstr = PartialString::from(pstr_atom);
buf += pstr.as_str_from(n); buf += &*pstr.as_str_from(n);
} }
} }
} }
@@ -381,8 +384,10 @@ impl<'a> HeapPStrIter<'a> {
} }
fn pre_cycle_discovery_stepper(&mut self) -> Option<PStrIteratee> { fn pre_cycle_discovery_stepper(&mut self) -> Option<PStrIteratee> {
let PStrIterStep { iteratee, next_hare } = let PStrIterStep {
match self.step(self.brent_st.hare) { iteratee,
next_hare,
} = match self.step(self.brent_st.hare) {
Some(results) => results, Some(results) => results,
None => { None => {
return None; return None;
@@ -421,8 +426,10 @@ impl<'a> HeapPStrIter<'a> {
return None; return None;
} }
let PStrIterStep { iteratee, next_hare } = let PStrIterStep {
match self.step(self.brent_st.hare) { iteratee,
next_hare,
} = match self.step(self.brent_st.hare) {
Some(results) => results, Some(results) => results,
None => { None => {
return None; return None;
@@ -515,11 +522,8 @@ impl<'a> Iterator for PStrCharsIter<'a> {
match pstr.as_str_from(n).chars().next() { match pstr.as_str_from(n).chars().next() {
Some(c) => { Some(c) => {
self.item = Some(PStrIteratee::PStrSegment( self.item =
f1, Some(PStrIteratee::PStrSegment(f1, pstr_atom, n + c.len_utf8()));
pstr_atom,
n + c.len_utf8(),
));
return Some(c); return Some(c);
} }
@@ -684,8 +688,10 @@ pub fn compare_pstr_prefixes<'a>(
} }
} }
} }
(PStrIteratee::PStrSegment(f1, pstr1_atom, n1), (
PStrIteratee::PStrSegment(f2, pstr2_atom, n2)) => { PStrIteratee::PStrSegment(f1, pstr1_atom, n1),
PStrIteratee::PStrSegment(f2, pstr2_atom, n2),
) => {
if pstr1_atom == pstr2_atom && n1 == n2 { if pstr1_atom == pstr2_atom && n1 == n2 {
cycle_detection_step(i1, i2, &step_1); cycle_detection_step(i1, i2, &step_1);
let both_cyclic = cycle_detection_step(i2, i1, &step_2); let both_cyclic = cycle_detection_step(i2, i1, &step_2);
@@ -707,7 +713,7 @@ pub fn compare_pstr_prefixes<'a>(
let str2 = pstr2.as_str_from(n2); let str2 = pstr2.as_str_from(n2);
match str1.len().cmp(&str2.len()) { match str1.len().cmp(&str2.len()) {
Ordering::Equal if str1 == str2 => { Ordering::Equal if &*str1 == &*str2 => {
cycle_detection_step(i1, i2, &step_1); cycle_detection_step(i1, i2, &step_1);
let both_cyclic = cycle_detection_step(i2, i1, &step_2); let both_cyclic = cycle_detection_step(i2, i1, &step_2);
@@ -718,8 +724,9 @@ pub fn compare_pstr_prefixes<'a>(
continue; continue;
} }
} }
Ordering::Less if str2.starts_with(str1) => { Ordering::Less if str2.starts_with(&*str1) => {
step_2.iteratee = PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len()); step_2.iteratee =
PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len());
let c1_result = cycle_detection_step(i1, i2, &step_1); let c1_result = cycle_detection_step(i1, i2, &step_1);
r1 = step(i1, i1.brent_st.hare); r1 = step(i1, i1.brent_st.hare);
@@ -727,8 +734,9 @@ pub fn compare_pstr_prefixes<'a>(
continue; continue;
} }
} }
Ordering::Greater if str1.starts_with(str2) => { Ordering::Greater if str1.starts_with(&*str2) => {
step_1.iteratee = PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len()); step_1.iteratee =
PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len());
let c2_result = cycle_detection_step(i2, i1, &step_2); let c2_result = cycle_detection_step(i2, i1, &step_2);
r2 = step(i2, i2.brent_st.hare); r2 = step(i2, i2.brent_st.hare);
@@ -737,7 +745,7 @@ pub fn compare_pstr_prefixes<'a>(
} }
} }
_ => { _ => {
return PStrCmpResult::Ordered(str1.cmp(str2)); return PStrCmpResult::Ordered(str1.cmp(&*str2));
} }
} }
} }
@@ -796,11 +804,8 @@ mod test {
fn pstr_iter_tests() { fn pstr_iter_tests() {
let mut wam = MockWAM::new(); let mut wam = MockWAM::new();
let pstr_var_cell = put_partial_string( let pstr_var_cell =
&mut wam.machine_st.heap, put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
"abc ",
&mut wam.machine_st.atom_tbl,
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
@@ -819,11 +824,8 @@ mod test {
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string( let pstr_second_var_cell =
&mut wam.machine_st.heap, put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
"def",
&mut wam.machine_st.atom_tbl,
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
@@ -836,7 +838,11 @@ mod test {
); );
assert_eq!( assert_eq!(
iter.next(), iter.next(),
Some(PStrIteratee::PStrSegment(2, cell_as_atom!(pstr_second_cell), 0)) Some(PStrIteratee::PStrSegment(
2,
cell_as_atom!(pstr_second_cell),
0
))
); );
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
@@ -855,7 +861,11 @@ mod test {
); );
assert_eq!( assert_eq!(
iter.next(), iter.next(),
Some(PStrIteratee::PStrSegment(2, cell_as_atom!(pstr_second_cell), 0)) Some(PStrIteratee::PStrSegment(
2,
cell_as_atom!(pstr_second_cell),
0
))
); );
assert_eq!(iter.next(), None); assert_eq!(iter.next(), None);
@@ -863,10 +873,14 @@ mod test {
} }
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1)); wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0)));
{ {
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0); let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
@@ -892,21 +906,13 @@ mod test {
// construct a structurally similar but different cyclic partial string // construct a structurally similar but different cyclic partial string
// matching the one beginning at wam.machine_st.heap[0]. // matching the one beginning at wam.machine_st.heap[0].
put_partial_string( put_partial_string(&mut wam.machine_st.heap, "ab", &wam.machine_st.atom_tbl);
&mut wam.machine_st.heap,
"ab",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2)); wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2));
put_partial_string( put_partial_string(&mut wam.machine_st.heap, "c ", &wam.machine_st.atom_tbl);
&mut wam.machine_st.heap,
"c ",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.pop(); wam.machine_st.heap.pop();
@@ -916,7 +922,9 @@ mod test {
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 6)); wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 6));
wam.machine_st.heap.push(pstr_offset_as_cell!(second_h)); wam.machine_st.heap.push(pstr_offset_as_cell!(second_h));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0)));
let mut iter1 = HeapPStrIter::new(&wam.machine_st.heap, 0); let mut iter1 = HeapPStrIter::new(&wam.machine_st.heap, 0);
let mut iter2 = HeapPStrIter::new(&wam.machine_st.heap, second_h); let mut iter2 = HeapPStrIter::new(&wam.machine_st.heap, second_h);
@@ -929,11 +937,7 @@ mod test {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
put_partial_string( put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
&mut wam.machine_st.heap,
"abc ",
&mut wam.machine_st.atom_tbl,
);
let pstr_cell = wam.machine_st.heap[0]; let pstr_cell = wam.machine_st.heap[0];
@@ -963,11 +967,8 @@ mod test {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string( let cstr_var_cell =
&mut wam.machine_st.heap, put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
"abc",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.push(list_loc_as_cell!(2)); wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(2));
@@ -982,30 +983,18 @@ mod test {
unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1)); unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1));
assert_eq!( assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
wam.machine_st.heap[2],
char_as_cell!('a'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
wam.machine_st.heap[4],
char_as_cell!('b'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
wam.machine_st.heap[6],
char_as_cell!('c'),
);
// test "abc" = [X,Y,Z|D]. // test "abc" = [X,Y,Z|D].
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string( let cstr_var_cell =
&mut wam.machine_st.heap, put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
"abc",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.push(list_loc_as_cell!(2)); wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2)); // X wam.machine_st.heap.push(heap_loc_as_cell!(2)); // X
@@ -1022,35 +1011,20 @@ mod test {
assert_eq!(wam.machine_st.fail, false); assert_eq!(wam.machine_st.fail, false);
assert_eq!( assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
wam.machine_st.heap[2],
char_as_cell!('a'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
wam.machine_st.heap[4],
char_as_cell!('b'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
wam.machine_st.heap[6],
char_as_cell!('c'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[7], empty_list_as_cell!(),);
wam.machine_st.heap[7],
empty_list_as_cell!(),
);
// test "d" = [d]. // test "d" = [d].
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string( let cstr_var_cell =
&mut wam.machine_st.heap, put_complete_string(&mut wam.machine_st.heap, "d", &wam.machine_st.atom_tbl);
"d",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.push(list_loc_as_cell!(2)); wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(char_as_cell!('d')); wam.machine_st.heap.push(char_as_cell!('d'));
@@ -1064,11 +1038,8 @@ mod test {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string( let cstr_var_cell =
&mut wam.machine_st.heap, put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
"abc",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.push(list_loc_as_cell!(2)); wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(2));
@@ -1085,30 +1056,17 @@ mod test {
assert_eq!(wam.machine_st.fail, false); assert_eq!(wam.machine_st.fail, false);
assert_eq!( assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
wam.machine_st.heap[2],
char_as_cell!('a'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
wam.machine_st.heap[4],
char_as_cell!('b'),
);
assert_eq!( assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
wam.machine_st.heap[6],
char_as_cell!('c'),
);
// test "abcdef" = [a,b,c|X]. // test "abcdef" = [a,b,c|X].
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
put_complete_string( put_complete_string(&mut wam.machine_st.heap, "abcdef", &wam.machine_st.atom_tbl);
&mut wam.machine_st.heap,
"abcdef",
&mut wam.machine_st.atom_tbl,
);
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc"))); wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(2));
@@ -1123,7 +1081,10 @@ mod test {
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(1)); assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[4], atom_as_cstr_cell!(atom!("abcdef"))); assert_eq!(wam.machine_st.heap[4], atom_as_cstr_cell!(atom!("abcdef")));
assert_eq!(wam.machine_st.heap[5], pstr_offset_as_cell!(4)); assert_eq!(wam.machine_st.heap[5], pstr_offset_as_cell!(4));
assert_eq!(wam.machine_st.heap[6], fixnum_as_cell!(Fixnum::build_with("abc".len() as i64))); assert_eq!(
wam.machine_st.heap[6],
fixnum_as_cell!(Fixnum::build_with("abc".len() as i64))
);
// test iteration on X = [b,c,b,c,b,c,b,c|...] as an offset. // test iteration on X = [b,c,b,c,b,c,b,c|...] as an offset.
@@ -1132,7 +1093,9 @@ mod test {
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc"))); wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_loc_as_cell!(2));
wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1))); wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1)));
{ {
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 2); let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 2);

View File

@@ -12,11 +12,7 @@ use indexmap::IndexSet;
use std::cell::Cell; use std::cell::Cell;
use std::convert::TryFrom; use std::convert::TryFrom;
pub(crate) fn to_op_decl( pub(crate) fn to_op_decl(prec: u16, spec: Atom, name: Atom) -> Result<OpDecl, CompilationError> {
prec: u16,
spec: Atom,
name: Atom,
) -> Result<OpDecl, CompilationError> {
match spec { match spec {
atom!("xfx") => Ok(OpDecl::new(OpDesc::build_with(prec, XFX as u8), name)), atom!("xfx") => Ok(OpDecl::new(OpDesc::build_with(prec, XFX as u8), name)),
atom!("xfy") => Ok(OpDecl::new(OpDesc::build_with(prec, XFY as u8), name)), atom!("xfy") => Ok(OpDecl::new(OpDesc::build_with(prec, XFY as u8), name)),
@@ -29,19 +25,16 @@ pub(crate) fn to_op_decl(
} }
} }
fn setup_op_decl( fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, CompilationError> {
mut terms: Vec<Term>,
atom_tbl: &mut AtomTable,
) -> Result<OpDecl, CompilationError> {
let name = match terms.pop().unwrap() { let name = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name, Term::Literal(_, Literal::Atom(name)) => name,
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()), Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
_ => return Err(CompilationError::InconsistentEntry), _ => return Err(CompilationError::InconsistentEntry),
}; };
let spec = match terms.pop().unwrap() { let spec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name, Term::Literal(_, Literal::Atom(name)) => name,
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()), Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
_ => return Err(CompilationError::InconsistentEntry), _ => return Err(CompilationError::InconsistentEntry),
}; };
@@ -68,12 +61,14 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
Term::Literal(_, Literal::Integer(n)) => n.to_usize(), Term::Literal(_, Literal::Integer(n)) => n.to_usize(),
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(), Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
_ => None, _ => None,
}.ok_or(CompilationError::InvalidModuleExport)?; }
.ok_or(CompilationError::InvalidModuleExport)?;
let name = match name { let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name), Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None, _ => None,
}.ok_or(CompilationError::InvalidModuleExport)?; }
.ok_or(CompilationError::InvalidModuleExport)?;
if *slash == atom!("/") { if *slash == atom!("/") {
Ok((name, arity)) Ok((name, arity))
@@ -87,7 +82,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
fn setup_module_export( fn setup_module_export(
mut term: Term, mut term: Term,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) -> Result<ModuleExport, CompilationError> { ) -> Result<ModuleExport, CompilationError> {
setup_predicate_indicator(&mut term) setup_predicate_indicator(&mut term)
.map(ModuleExport::PredicateKey) .map(ModuleExport::PredicateKey)
@@ -113,7 +108,7 @@ pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
pub(super) fn setup_module_export_list( pub(super) fn setup_module_export_list(
mut export_list: Term, mut export_list: Term,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) -> Result<Vec<ModuleExport>, CompilationError> { ) -> Result<Vec<ModuleExport>, CompilationError> {
let mut exports = vec![]; let mut exports = vec![];
@@ -133,7 +128,7 @@ pub(super) fn setup_module_export_list(
fn setup_module_decl( fn setup_module_decl(
mut terms: Vec<Term>, mut terms: Vec<Term>,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) -> Result<ModuleDecl, CompilationError> { ) -> Result<ModuleDecl, CompilationError> {
let export_list = terms.pop().unwrap(); let export_list = terms.pop().unwrap();
let name = terms.pop().unwrap(); let name = terms.pop().unwrap();
@@ -141,7 +136,8 @@ fn setup_module_decl(
let name = match name { let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name), Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None, _ => None,
}.ok_or(CompilationError::InvalidModuleDecl)?; }
.ok_or(CompilationError::InvalidModuleDecl)?;
let exports = setup_module_export_list(export_list, atom_tbl)?; let exports = setup_module_export_list(export_list, atom_tbl)?;
@@ -150,9 +146,7 @@ fn setup_module_decl(
fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> { fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> {
match terms.pop().unwrap() { match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
if name == atom!("library") && terms.len() == 1 =>
{
match terms.pop().unwrap() { match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)), Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl), _ => Err(CompilationError::InvalidModuleDecl),
@@ -167,13 +161,11 @@ type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
fn setup_qualified_import( fn setup_qualified_import(
mut terms: Vec<Term>, mut terms: Vec<Term>,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) -> Result<UseModuleExport, CompilationError> { ) -> Result<UseModuleExport, CompilationError> {
let mut export_list = terms.pop().unwrap(); let mut export_list = terms.pop().unwrap();
let module_src = match terms.pop().unwrap() { let module_src = match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
if name == atom!("library") && terms.len() == 1 =>
{
match terms.pop().unwrap() { match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)), Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl), _ => Err(CompilationError::InvalidModuleDecl),
@@ -318,11 +310,11 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
} }
(atom!("module"), 2) => { (atom!("module"), 2) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl; let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?)) Ok(Declaration::Module(setup_module_decl(terms, &atom_tbl)?))
} }
(atom!("op"), 3) => { (atom!("op"), 3) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl; let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?)) Ok(Declaration::Op(setup_op_decl(terms, &atom_tbl)?))
} }
(atom!("non_counted_backtracking"), 1) => { (atom!("non_counted_backtracking"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?; let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
@@ -331,7 +323,7 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)), (atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
(atom!("use_module"), 2) => { (atom!("use_module"), 2) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl; let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
let (name, exports) = setup_qualified_import(terms, atom_tbl)?; let (name, exports) = setup_qualified_import(terms, &atom_tbl)?;
Ok(Declaration::UseQualifiedModule(name, exports)) Ok(Declaration::UseQualifiedModule(name, exports))
} }
@@ -381,19 +373,28 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
} }
fn tag_with_module_name(module_name: Atom, term: Term) -> Term { fn tag_with_module_name(module_name: Atom, term: Term) -> Term {
Term::Clause(Cell::default(), atom!(":"), vec![ Term::Clause(
Cell::default(),
atom!(":"),
vec![
Term::Literal(Cell::default(), Literal::Atom(module_name)), Term::Literal(Cell::default(), Literal::Atom(module_name)),
term term,
]) ],
)
} }
let process_term: fn(Atom, Term) -> Term; let process_term: fn(Atom, Term) -> Term;
let (module_name, key, term) = match term { let (module_name, key, term) = match term {
Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => { Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => {
if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1]) { if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1])
{
process_term = tag_with_module_name; process_term = tag_with_module_name;
(module_name, (name, terms[1].arity() + supp_args), terms.pop().unwrap()) (
module_name,
(name, terms[1].arity() + supp_args),
terms.pop().unwrap(),
)
} else { } else {
arg_terms.push(Term::Clause(cell, atom!(":"), terms)); arg_terms.push(Term::Clause(cell, atom!(":"), terms));
continue; continue;
@@ -408,10 +409,8 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
let term = match term { let term = match term {
Term::Clause(cell, name, mut terms) => { Term::Clause(cell, name, mut terms) => {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() { if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
arg_terms.push(process_term( arg_terms
module_name, .push(process_term(module_name, Term::Clause(cell, name, terms)));
Term::Clause(cell, name, terms),
));
continue; continue;
} }
@@ -424,11 +423,14 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
Term::Literal(cell, Literal::Atom(name)) => { Term::Literal(cell, Literal::Atom(name)) => {
let idx = loader.get_or_insert_qualified_code_index(module_name, key); let idx = loader.get_or_insert_qualified_code_index(module_name, key);
process_term(module_name, Term::Clause( process_term(
module_name,
Term::Clause(
cell, cell,
name, name,
vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))], vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
)) ),
)
} }
term => term, term => term,
}; };
@@ -462,12 +464,7 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
if let ClauseType::Named(arity, name, idx) = ct { if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() { if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name(); let module_name = loader.payload.compilation_target.module_name();
let terms = build_meta_predicate_clause( let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
loader,
module_name,
terms,
meta_specs,
);
return QueryTerm::Clause( return QueryTerm::Clause(
Cell::default(), Cell::default(),
@@ -501,12 +498,7 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
if let ClauseType::Named(arity, name, idx) = ct { if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() { if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let terms = build_meta_predicate_clause( let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
loader,
module_name,
terms,
meta_specs,
);
return QueryTerm::Clause( return QueryTerm::Clause(
Cell::default(), Cell::default(),
@@ -529,17 +521,13 @@ pub(crate) struct Preprocessor {
impl Preprocessor { impl Preprocessor {
pub(super) fn new(settings: CodeGenSettings) -> Self { pub(super) fn new(settings: CodeGenSettings) -> Self {
Preprocessor { Preprocessor { settings }
settings,
}
} }
fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> { fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
match term { match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => { Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
let classifier = VariableClassifier::new( let classifier = VariableClassifier::new(self.settings.default_call_policy());
self.settings.default_call_policy(),
);
let (head, var_data) = classifier.classify_fact(term)?; let (head, var_data) = classifier.classify_fact(term)?;
Ok((Fact { head }, var_data)) Ok((Fact { head }, var_data))
@@ -554,21 +542,25 @@ impl Preprocessor {
head: Term, head: Term,
body: Term, body: Term,
) -> Result<(Rule, VarData), CompilationError> { ) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new( let classifier = VariableClassifier::new(self.settings.default_call_policy());
self.settings.default_call_policy(),
);
let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?; let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
match head { match head {
Term::Clause(_, name, terms) => Ok((Rule { Term::Clause(_, name, terms) => Ok((
Rule {
head: (name, terms), head: (name, terms),
clauses, clauses,
}, var_data)), },
Term::Literal(_, Literal::Atom(name)) => Ok((Rule { var_data,
)),
Term::Literal(_, Literal::Atom(name)) => Ok((
Rule {
head: (name, vec![]), head: (name, vec![]),
clauses, clauses,
}, var_data)), },
var_data,
)),
_ => Err(CompilationError::InvalidRuleHead), _ => Err(CompilationError::InvalidRuleHead),
} }
} }

View File

@@ -30,12 +30,6 @@ pub struct Stack {
_marker: PhantomData<HeapCellValue>, _marker: PhantomData<HeapCellValue>,
} }
impl Drop for Stack {
fn drop(&mut self) {
self.buf.deallocate();
}
}
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct AndFramePrelude { pub(crate) struct AndFramePrelude {
pub(crate) num_cells: usize, pub(crate) num_cells: usize,
@@ -189,7 +183,7 @@ impl Stack {
let frame_size = AndFrame::size_of(num_cells); let frame_size = AndFrame::size_of(num_cells);
unsafe { unsafe {
let e = self.buf.ptr as usize - self.buf.base as usize; let e = (*self.buf.ptr.get_mut()) as usize - self.buf.base as usize;
let new_ptr = self.alloc(frame_size); let new_ptr = self.alloc(frame_size);
let mut offset = prelude_size::<AndFramePrelude>(); let mut offset = prelude_size::<AndFramePrelude>();
@@ -213,7 +207,7 @@ impl Stack {
let frame_size = OrFrame::size_of(num_cells); let frame_size = OrFrame::size_of(num_cells);
unsafe { unsafe {
let b = self.buf.ptr as usize - self.buf.base as usize; let b = (*self.buf.ptr.get_mut()) as usize - self.buf.base as usize;
let new_ptr = self.alloc(frame_size); let new_ptr = self.alloc(frame_size);
let mut offset = prelude_size::<OrFramePrelude>(); let mut offset = prelude_size::<OrFramePrelude>();
@@ -269,8 +263,8 @@ impl Stack {
pub(crate) fn truncate(&mut self, b: usize) { pub(crate) fn truncate(&mut self, b: usize) {
let base = self.buf.base as usize + b; let base = self.buf.base as usize + b;
if base < self.buf.ptr as usize { if base < (*self.buf.ptr.get_mut()) as usize {
self.buf.ptr = base as *mut _; *self.buf.ptr.get_mut() = base as *mut _;
} }
} }
} }
@@ -315,7 +309,10 @@ mod tests {
let and_frame = wam.machine_st.stack.index_and_frame_mut(next_e); let and_frame = wam.machine_st.stack.index_and_frame_mut(next_e);
for idx in 0..9 { for idx in 0..9 {
assert_eq!(and_frame[idx + 1], stack_loc_as_cell!(AndFrame, next_e, idx + 1)); assert_eq!(
and_frame[idx + 1],
stack_loc_as_cell!(AndFrame, next_e, idx + 1)
);
} }
let and_frame = wam.machine_st.stack.index_and_frame(e); let and_frame = wam.machine_st.stack.index_and_frame(e);

View File

@@ -4,13 +4,13 @@ use crate::parser::ast::*;
use crate::parser::char_reader::*; use crate::parser::char_reader::*;
use crate::read::*; use crate::read::*;
#[cfg(feature = "http")]
use crate::http::HttpResponse;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::machine_state::*; use crate::machine::machine_state::*;
use crate::types::*; use crate::types::*;
#[cfg(feature = "http")]
use crate::http::HttpResponse;
pub use modular_bitfield::prelude::*; pub use modular_bitfield::prelude::*;
@@ -19,11 +19,11 @@ use std::error::Error;
use std::fmt; use std::fmt;
use std::fmt::Debug; use std::fmt::Debug;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::hash::{Hash}; use std::hash::Hash;
use std::io; use std::io;
use std::io::{BufRead, Cursor, ErrorKind, Read, Seek, SeekFrom, Write}; use std::io::{BufRead, Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
use std::mem; use std::mem;
use std::net::{TcpStream, Shutdown}; use std::net::{Shutdown, TcpStream};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
@@ -154,7 +154,9 @@ impl StreamLayout<CharReader<InputFileStream>> {
fn position(&mut self) -> Option<u64> { fn position(&mut self) -> Option<u64> {
// stream is the internal CharReader. subtract // stream is the internal CharReader. subtract
// its pending buffer length from position. // its pending buffer length from position.
self.get_mut().file.seek(SeekFrom::Current(0)) self.get_mut()
.file
.seek(SeekFrom::Current(0))
.map(|pos| pos - self.stream.rem_buf_len() as u64) .map(|pos| pos - self.stream.rem_buf_len() as u64)
.ok() .ok()
} }
@@ -205,7 +207,9 @@ impl CharRead for StaticStringStream {
#[inline(always)] #[inline(always)]
fn put_back_char(&mut self, c: char) { fn put_back_char(&mut self, c: char) {
self.stream.seek(SeekFrom::Current(- (c.len_utf8() as i64))).unwrap(); self.stream
.seek(SeekFrom::Current(-(c.len_utf8() as i64)))
.unwrap();
} }
} }
@@ -315,8 +319,7 @@ impl Write for HttpWriteStream {
let mut response = response.lock().unwrap(); let mut response = response.lock().unwrap();
let bytes = bytes::Bytes::copy_from_slice(&self.buffer); let bytes = bytes::Bytes::copy_from_slice(&self.buffer);
let mut response_ = hyper::Response::builder() let mut response_ = hyper::Response::builder().status(self.status_code);
.status(self.status_code);
*response_.headers_mut().unwrap() = self.headers.clone(); *response_.headers_mut().unwrap() = self.headers.clone();
*response = Some(response_.body(http_body_util::Full::new(bytes)).unwrap()); *response = Some(response_.body(http_body_util::Full::new(bytes)).unwrap());
} }
@@ -510,7 +513,9 @@ impl Stream {
#[inline] #[inline]
pub fn from_owned_string(string: String, arena: &mut Arena) -> Stream { pub fn from_owned_string(string: String, arena: &mut Arena) -> Stream {
Stream::Byte(arena_alloc!( Stream::Byte(arena_alloc!(
StreamLayout::new(CharReader::new(ByteStream(Cursor::new(string.into_bytes())))), StreamLayout::new(CharReader::new(ByteStream(Cursor::new(
string.into_bytes()
)))),
arena arena
)) ))
} }
@@ -732,10 +737,10 @@ impl CharRead for Stream {
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream, StreamError::ReadFromOutputStream,
))), ))),
Stream::OutputFile(_) | Stream::OutputFile(_)
Stream::StandardError(_) | | Stream::StandardError(_)
Stream::StandardOutput(_) | | Stream::StandardOutput(_)
Stream::Null(_) => Some(Err(std::io::Error::new( | Stream::Null(_) => Some(Err(std::io::Error::new(
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream, StreamError::ReadFromOutputStream,
))), ))),
@@ -758,10 +763,10 @@ impl CharRead for Stream {
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream, StreamError::ReadFromOutputStream,
))), ))),
Stream::OutputFile(_) | Stream::OutputFile(_)
Stream::StandardError(_) | | Stream::StandardError(_)
Stream::StandardOutput(_) | | Stream::StandardOutput(_)
Stream::Null(_) => Some(Err(std::io::Error::new( | Stream::Null(_) => Some(Err(std::io::Error::new(
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream, StreamError::ReadFromOutputStream,
))), ))),
@@ -781,10 +786,10 @@ impl CharRead for Stream {
Stream::Byte(cursor) => cursor.put_back_char(c), Stream::Byte(cursor) => cursor.put_back_char(c),
#[cfg(feature = "http")] #[cfg(feature = "http")]
Stream::HttpWrite(_) => {} Stream::HttpWrite(_) => {}
Stream::OutputFile(_) | Stream::OutputFile(_)
Stream::StandardError(_) | | Stream::StandardError(_)
Stream::StandardOutput(_) | | Stream::StandardOutput(_)
Stream::Null(_) => {} | Stream::Null(_) => {}
} }
} }
@@ -801,10 +806,10 @@ impl CharRead for Stream {
Stream::Byte(ref mut cursor) => cursor.consume(nread), Stream::Byte(ref mut cursor) => cursor.consume(nread),
#[cfg(feature = "http")] #[cfg(feature = "http")]
Stream::HttpWrite(_) => {} Stream::HttpWrite(_) => {}
Stream::OutputFile(_) | Stream::OutputFile(_)
Stream::StandardError(_) | | Stream::StandardError(_)
Stream::StandardOutput(_) | | Stream::StandardOutput(_)
Stream::Null(_) => {} | Stream::Null(_) => {}
} }
} }
} }
@@ -857,10 +862,10 @@ impl Write for Stream {
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::WriteToInputStream, StreamError::WriteToInputStream,
)), )),
Stream::StaticString(_) | Stream::StaticString(_)
Stream::Readline(_) | | Stream::Readline(_)
Stream::InputFile(..) | | Stream::InputFile(..)
Stream::Null(_) => Err(std::io::Error::new( | Stream::Null(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::WriteToInputStream, StreamError::WriteToInputStream,
)), )),
@@ -883,10 +888,10 @@ impl Write for Stream {
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::FlushToInputStream, StreamError::FlushToInputStream,
)), )),
Stream::StaticString(_) | Stream::StaticString(_)
Stream::Readline(_) | | Stream::Readline(_)
Stream::InputFile(_) | | Stream::InputFile(_)
Stream::Null(_) => Err(std::io::Error::new( | Stream::Null(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied, ErrorKind::PermissionDenied,
StreamError::FlushToInputStream, StreamError::FlushToInputStream,
)), )),
@@ -898,8 +903,10 @@ impl Write for Stream {
enum StreamError { enum StreamError {
PeekByteFailed, PeekByteFailed,
PeekByteFromNonPeekableStream, PeekByteFromNonPeekableStream,
#[allow(unused)] PeekCharFailed, #[allow(unused)]
#[allow(unused)] PeekCharFromNonPeekableStream, PeekCharFailed,
#[allow(unused)]
PeekCharFromNonPeekableStream,
ReadFromOutputStream, ReadFromOutputStream,
WriteToInputStream, WriteToInputStream,
FlushToInputStream, FlushToInputStream,
@@ -958,7 +965,11 @@ impl PartialEq for Stream {
impl Eq for Stream {} impl Eq for Stream {}
fn cursor_position<T>(past_end_of_stream: &mut bool, cursor: &Cursor<T>, cursor_len: u64) -> AtEndOfStream { fn cursor_position<T>(
past_end_of_stream: &mut bool,
cursor: &Cursor<T>,
cursor_len: u64,
) -> AtEndOfStream {
let position = cursor.position(); let position = cursor.position();
let at_end_of_stream = match position.cmp(&cursor_len) { let at_end_of_stream = match position.cmp(&cursor_len) {
@@ -984,17 +995,10 @@ impl Stream {
Stream::StaticString(string_stream_layout) => { Stream::StaticString(string_stream_layout) => {
Some(string_stream_layout.stream.stream.position()) Some(string_stream_layout.stream.stream.position())
} }
Stream::InputFile(file_stream) => { Stream::InputFile(file_stream) => file_stream.position(),
file_stream.position()
}
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
Stream::NamedTls(..) => { Stream::NamedTls(..) => Some(0),
Some(0) Stream::NamedTcp(..) | Stream::Readline(..) => Some(0),
}
Stream::NamedTcp(..)
| Stream::Readline(..) => {
Some(0)
}
_ => None, _ => None,
}; };
@@ -1011,7 +1015,11 @@ impl Stream {
.. ..
} = &mut **stream_layout; } = &mut **stream_layout;
stream.get_mut().file.seek(SeekFrom::Start(position)).unwrap(); stream
.get_mut()
.file
.seek(SeekFrom::Start(position))
.unwrap();
stream.reset_buffer(); // flush the internal buffer. stream.reset_buffer(); // flush the internal buffer.
if let Ok(metadata) = stream.get_ref().file.metadata() { if let Ok(metadata) = stream.get_ref().file.metadata() {
@@ -1127,9 +1135,7 @@ impl Stream {
} }
} }
} }
_ => { _ => AtEndOfStream::Not,
AtEndOfStream::Not
}
} }
} }
@@ -1160,7 +1166,9 @@ impl Stream {
Stream::OutputFile(file) if file.is_append => atom!("append"), Stream::OutputFile(file) if file.is_append => atom!("append"),
#[cfg(feature = "http")] #[cfg(feature = "http")]
Stream::HttpWrite(_) => atom!("write"), Stream::HttpWrite(_) => atom!("write"),
Stream::OutputFile(_) | Stream::StandardError(_) | Stream::StandardOutput(_) => atom!("write"), Stream::OutputFile(_) | Stream::StandardError(_) | Stream::StandardOutput(_) => {
atom!("write")
}
Stream::Null(_) => atom!(""), Stream::Null(_) => atom!(""),
} }
} }
@@ -1182,11 +1190,7 @@ impl Stream {
} }
#[inline] #[inline]
pub(crate) fn from_tcp_stream( pub(crate) fn from_tcp_stream(address: Atom, tcp_stream: TcpStream, arena: &mut Arena) -> Self {
address: Atom,
tcp_stream: TcpStream,
arena: &mut Arena,
) -> Self {
tcp_stream.set_read_timeout(None).unwrap(); tcp_stream.set_read_timeout(None).unwrap();
tcp_stream.set_write_timeout(None).unwrap(); tcp_stream.set_write_timeout(None).unwrap();
@@ -1282,11 +1286,9 @@ impl Stream {
match stream { match stream {
Stream::NamedTcp(ref mut tcp_stream) => { Stream::NamedTcp(ref mut tcp_stream) => {
tcp_stream.inner_mut().tcp_stream.shutdown(Shutdown::Both) tcp_stream.inner_mut().tcp_stream.shutdown(Shutdown::Both)
},
#[cfg(feature = "tls")]
Stream::NamedTls(ref mut tls_stream) => {
tls_stream.inner_mut().tls_stream.shutdown()
} }
#[cfg(feature = "tls")]
Stream::NamedTls(ref mut tls_stream) => tls_stream.inner_mut().tls_stream.shutdown(),
#[cfg(feature = "http")] #[cfg(feature = "http")]
Stream::HttpRead(ref mut http_stream) => { Stream::HttpRead(ref mut http_stream) => {
unsafe { unsafe {
@@ -1323,7 +1325,7 @@ impl Stream {
Ok(()) Ok(())
} }
_ => Ok(()) _ => Ok(()),
} }
} }
@@ -1381,7 +1383,12 @@ impl Stream {
return true; return true;
} }
Stream::InputFile(ref mut file_stream) => { Stream::InputFile(ref mut file_stream) => {
file_stream.stream.get_mut().file.seek(SeekFrom::Start(0)).unwrap(); file_stream
.stream
.get_mut()
.file
.seek(SeekFrom::Start(0))
.unwrap();
return true; return true;
} }
Stream::Readline(ref mut readline_stream) => { Stream::Readline(ref mut readline_stream) => {
@@ -1410,17 +1417,13 @@ impl Stream {
_ => Err(std::io::Error::new(ErrorKind::UnexpectedEof, "end of file")), _ => Err(std::io::Error::new(ErrorKind::UnexpectedEof, "end of file")),
} }
} }
Stream::InputFile(ref mut file) => { Stream::InputFile(ref mut file) => match file.peek_byte() {
match file.peek_byte() { Some(result) => Ok(result?),
Some(result) => {
Ok(result?)
}
_ => Err(std::io::Error::new( _ => Err(std::io::Error::new(
ErrorKind::UnexpectedEof, ErrorKind::UnexpectedEof,
StreamError::PeekByteFailed, StreamError::PeekByteFailed,
)), )),
} },
}
Stream::Readline(ref mut stream) => stream.stream.peek_byte(), Stream::Readline(ref mut stream) => stream.stream.peek_byte(),
Stream::NamedTcp(ref mut stream) => { Stream::NamedTcp(ref mut stream) => {
let mut b = [0u8; 1]; let mut b = [0u8; 1];
@@ -1663,7 +1666,10 @@ impl MachineState {
} }
} }
pub(crate) fn open_parsing_stream(&mut self, mut stream: Stream) -> Result<Stream, ParserError> { pub(crate) fn open_parsing_stream(
&mut self,
mut stream: Stream,
) -> Result<Stream, ParserError> {
match stream.peek_char() { match stream.peek_char() {
None => Ok(stream), // empty stream is handled gracefully by Lexer::eof None => Ok(stream), // empty stream is handled gracefully by Lexer::eof
Some(Err(e)) => Err(ParserError::IO(e)), Some(Err(e)) => Err(ParserError::IO(e)),
@@ -1847,7 +1853,7 @@ impl MachineState {
} }
}; };
let file = match open_options.open(file_spec.as_str()) { let file = match open_options.open(&*file_spec.as_str()) {
Ok(file) => file, Ok(file) => file,
Err(err) => { Err(err) => {
match err.kind() { match err.kind() {
@@ -1855,15 +1861,18 @@ impl MachineState {
// 8.11.5.3j) // 8.11.5.3j)
let stub = functor_stub(atom!("open"), 4); let stub = functor_stub(atom!("open"), 4);
let err = self.existence_error( let err =
ExistenceError::SourceSink(self[temp_v!(1)]), self.existence_error(ExistenceError::SourceSink(self[temp_v!(1)]));
);
return Err(self.error_form(err, stub)); return Err(self.error_form(err, stub));
} }
ErrorKind::PermissionDenied => { ErrorKind::PermissionDenied => {
// 8.11.5.3k) // 8.11.5.3k)
return Err(self.open_permission_error(self.registers[1], atom!("open"), 4)); return Err(self.open_permission_error(
self.registers[1],
atom!("open"),
4,
));
} }
_ => { _ => {
let stub = functor_stub(atom!("open"), 4); let stub = functor_stub(atom!("open"), 4);

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
use crate::forms::*; use crate::forms::*;
use crate::machine::*;
use crate::machine::load_state::*; use crate::machine::load_state::*;
use crate::machine::loader::*; use crate::machine::loader::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::parser::*; use crate::parser::parser::*;
use crate::read::devour_whitespace; use crate::read::devour_whitespace;
@@ -45,7 +45,10 @@ impl<'a> BootstrappingTermStream<'a> {
listing_src: ListingSource, listing_src: ListingSource,
) -> Self { ) -> Self {
let parser = Parser::new(stream, machine_st); let parser = Parser::new(stream, machine_st);
Self { parser, listing_src } Self {
parser,
listing_src,
}
} }
} }
@@ -122,8 +125,7 @@ impl TermStream for LiveTermStream {
} }
} }
pub struct InlineTermStream { pub struct InlineTermStream {}
}
impl TermStream for InlineTermStream { impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> { fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
@@ -138,4 +140,3 @@ impl TermStream for InlineTermStream {
&ListingSource::User &ListingSource::User
} }
} }

View File

@@ -1,9 +1,9 @@
use crate::arena::*; use crate::arena::*;
use crate::forms::*; use crate::forms::*;
use crate::heap_iter::stackful_preorder_iter; use crate::heap_iter::stackful_preorder_iter;
use crate::machine::*;
use crate::machine::machine_state::*; use crate::machine::machine_state::*;
use crate::machine::partial_string::*; use crate::machine::partial_string::*;
use crate::machine::*;
use crate::types::*; use crate::types::*;
use std::cmp::Ordering; use std::cmp::Ordering;
@@ -190,8 +190,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
machine_st.pdl.push(pstr_iter1.focus); machine_st.pdl.push(pstr_iter1.focus);
} }
} }
continuable @ PStrCmpResult::FirstIterContinuable(iteratee) | continuable @ PStrCmpResult::FirstIterContinuable(iteratee)
continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => { | continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
if continuable.is_second_iter() { if continuable.is_second_iter() {
std::mem::swap(&mut pstr_iter1, &mut pstr_iter2); std::mem::swap(&mut pstr_iter1, &mut pstr_iter2);
} }
@@ -439,10 +439,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
} }
fn unify_big_num<N>(&mut self, n1: TypedArenaPtr<N>, value: HeapCellValue) fn unify_big_num<N>(&mut self, n1: TypedArenaPtr<N>, value: HeapCellValue)
where N: PartialEq<Rational> where
+ PartialEq<Integer> N: PartialEq<Rational> + PartialEq<Integer> + PartialEq<i64> + ArenaAllocated,
+ PartialEq<i64>
+ ArenaAllocated
{ {
if let Some(r) = value.as_var() { if let Some(r) = value.as_var() {
Self::bind(self, r, typed_arena_ptr_as_cell!(n1)); Self::bind(self, r, typed_arena_ptr_as_cell!(n1));

View File

@@ -88,7 +88,7 @@ macro_rules! cell_as_atom_cell {
macro_rules! cell_as_f64_ptr { macro_rules! cell_as_f64_ptr {
($cell:expr) => {{ ($cell:expr) => {{
let offset = $cell.get_value() as usize; let offset = $cell.get_value() as usize;
F64Ptr::from_offset(offset) F64Ptr::from_offset(F64Offset::new(offset))
}}; }};
} }
@@ -236,12 +236,14 @@ macro_rules! cell_as_stream {
} }
macro_rules! cell_as_load_state_payload { macro_rules! cell_as_load_state_payload {
($cell:expr) => { unsafe { ($cell:expr) => {
unsafe {
let ptr = cell_as_untyped_arena_ptr!($cell); let ptr = cell_as_untyped_arena_ptr!($cell);
let ptr = std::mem::transmute::<_, *mut LiveLoadState>(ptr.payload_offset()); let ptr = std::mem::transmute::<_, *mut LiveLoadState>(ptr.payload_offset());
TypedArenaPtr::new(ptr) TypedArenaPtr::new(ptr)
}}; }
};
} }
macro_rules! match_untyped_arena_ptr_pat_body { macro_rules! match_untyped_arena_ptr_pat_body {
@@ -258,13 +260,15 @@ macro_rules! match_untyped_arena_ptr_pat_body {
$code $code
}}; }};
($ptr:ident, OssifiedOpDir, $n:ident, $code:expr) => {{ ($ptr:ident, OssifiedOpDir, $n:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut OssifiedOpDir>($ptr.payload_offset()) }; let payload_ptr =
unsafe { std::mem::transmute::<_, *mut OssifiedOpDir>($ptr.payload_offset()) };
let $n = TypedArenaPtr::new(payload_ptr); let $n = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}}; }};
($ptr:ident, LiveLoadState, $n:ident, $code:expr) => {{ ($ptr:ident, LiveLoadState, $n:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut LiveLoadState>($ptr.payload_offset()) }; let payload_ptr =
unsafe { std::mem::transmute::<_, *mut LiveLoadState>($ptr.payload_offset()) };
let $n = TypedArenaPtr::new(payload_ptr); let $n = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
@@ -275,21 +279,24 @@ macro_rules! match_untyped_arena_ptr_pat_body {
$code $code
}}; }};
($ptr:ident, TcpListener, $listener:ident, $code:expr) => {{ ($ptr:ident, TcpListener, $listener:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut TcpListener>($ptr.payload_offset()) }; let payload_ptr =
unsafe { std::mem::transmute::<_, *mut TcpListener>($ptr.payload_offset()) };
#[allow(unused_mut)] #[allow(unused_mut)]
let mut $listener = TypedArenaPtr::new(payload_ptr); let mut $listener = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}}; }};
($ptr:ident, HttpListener, $listener:ident, $code:expr) => {{ ($ptr:ident, HttpListener, $listener:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut HttpListener>($ptr.payload_offset()) }; let payload_ptr =
unsafe { std::mem::transmute::<_, *mut HttpListener>($ptr.payload_offset()) };
#[allow(unused_mut)] #[allow(unused_mut)]
let mut $listener = TypedArenaPtr::new(payload_ptr); let mut $listener = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}}; }};
($ptr:ident, HttpResponse, $listener:ident, $code:expr) => {{ ($ptr:ident, HttpResponse, $listener:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut HttpResponse>($ptr.payload_offset()) }; let payload_ptr =
unsafe { std::mem::transmute::<_, *mut HttpResponse>($ptr.payload_offset()) };
#[allow(unused_mut)] #[allow(unused_mut)]
let mut $listener = TypedArenaPtr::new(payload_ptr); let mut $listener = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)] #[allow(unused_braces)]
@@ -297,7 +304,8 @@ macro_rules! match_untyped_arena_ptr_pat_body {
}}; }};
($ptr:ident, IndexPtr, $ip:ident, $code:expr) => {{ ($ptr:ident, IndexPtr, $ip:ident, $code:expr) => {{
#[allow(unused_mut)] #[allow(unused_mut)]
let mut $ip = TypedArenaPtr::new(unsafe { std::mem::transmute::<_, *mut IndexPtr>($ptr.get_ptr()) }); let mut $ip =
TypedArenaPtr::new(unsafe { std::mem::transmute::<_, *mut IndexPtr>($ptr.get_ptr()) });
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}}; }};
@@ -323,10 +331,10 @@ macro_rules! match_untyped_arena_ptr_pat {
| ArenaHeaderTag::StandardErrorStream | ArenaHeaderTag::StandardErrorStream
}; };
(IndexPtr) => { (IndexPtr) => {
ArenaHeaderTag::IndexPtrUndefined | ArenaHeaderTag::IndexPtrUndefined
ArenaHeaderTag::IndexPtrDynamicUndefined | | ArenaHeaderTag::IndexPtrDynamicUndefined
ArenaHeaderTag::IndexPtrDynamicIndex | | ArenaHeaderTag::IndexPtrDynamicIndex
ArenaHeaderTag::IndexPtrIndex | ArenaHeaderTag::IndexPtrIndex
}; };
($tag:ident) => { ($tag:ident) => {
ArenaHeaderTag::$tag ArenaHeaderTag::$tag
@@ -347,71 +355,71 @@ macro_rules! match_untyped_arena_ptr {
} }
macro_rules! read_heap_cell_pat_body { macro_rules! read_heap_cell_pat_body {
($cell:ident, Cons, $n:ident, $code:expr) => ({ ($cell:ident, Cons, $n:ident, $code:expr) => {{
let $n = cell_as_untyped_arena_ptr!($cell); let $n = cell_as_untyped_arena_ptr!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, F64, $n:ident, $code:expr) => ({ ($cell:ident, F64, $n:ident, $code:expr) => {{
let $n = cell_as_f64_ptr!($cell); let $n = cell_as_f64_ptr!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => ({ ($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => {{
let ($name, $arity) = cell_as_atom_cell!($cell).get_name_and_arity(); let ($name, $arity) = cell_as_atom_cell!($cell).get_name_and_arity();
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, PStr, $atom:ident, $code:expr) => ({ ($cell:ident, PStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell); let $atom = cell_as_atom!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, CStr, $atom:ident, $code:expr) => ({ ($cell:ident, CStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell); let $atom = cell_as_atom!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, CStr | PStr, $atom:ident, $code:expr) => ({ ($cell:ident, CStr | PStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell); let $atom = cell_as_atom!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, PStr | CStr, $atom:ident, $code:expr) => ({ ($cell:ident, PStr | CStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell); let $atom = cell_as_atom!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, Fixnum, $value:ident, $code:expr) => ({ ($cell:ident, Fixnum, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes()); let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, CutPoint, $value:ident, $code:expr) => ({ ($cell:ident, CutPoint, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes()); let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, Fixnum | CutPoint, $value:ident, $code:expr) => ({ ($cell:ident, Fixnum | CutPoint, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes()); let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, CutPoint | Fixnum, $value:ident, $code:expr) => ({ ($cell:ident, CutPoint | Fixnum, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes()); let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, Char, $value:ident, $code:expr) => ({ ($cell:ident, Char, $value:ident, $code:expr) => {{
let $value = unsafe { char::from_u32_unchecked($cell.get_value() as u32) }; let $value = unsafe { char::from_u32_unchecked($cell.get_value() as u32) };
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => ({ ($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => {{
let $value = $cell.get_value() as usize; let $value = $cell.get_value() as usize;
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}); }};
} }
macro_rules! read_heap_cell_pat { macro_rules! read_heap_cell_pat {
@@ -596,7 +604,9 @@ macro_rules! index_store {
IndexStore { IndexStore {
code_dir: $code_dir, code_dir: $code_dir,
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()), extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()), local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
FxBuildHasher::default(),
),
global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()), global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()),
goal_expansion_indices: GoalExpansionIndices::with_hasher(FxBuildHasher::default()), goal_expansion_indices: GoalExpansionIndices::with_hasher(FxBuildHasher::default()),
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()), meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),

View File

@@ -10,6 +10,7 @@ use std::hash::{Hash, Hasher};
use std::io::{Error as IOError, ErrorKind}; use std::io::{Error as IOError, ErrorKind};
use std::ops::{Deref, Neg}; use std::ops::{Deref, Neg};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use std::vec::Vec; use std::vec::Vec;
use crate::parser::dashu::{Integer, Rational}; use crate::parser::dashu::{Integer, Rational};
@@ -258,7 +259,8 @@ impl GenContext {
pub struct OpDesc { pub struct OpDesc {
prec: B11, prec: B11,
spec: B8, spec: B8,
#[allow(unused)] padding: B13, #[allow(unused)]
padding: B13,
} }
impl OpDesc { impl OpDesc {
@@ -417,13 +419,13 @@ pub enum ParserError {
impl ParserError { impl ParserError {
pub fn line_and_col_num(&self) -> Option<(usize, usize)> { pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
match self { match self {
&ParserError::BackQuotedString(line_num, col_num) | &ParserError::BackQuotedString(line_num, col_num)
&ParserError::IncompleteReduction(line_num, col_num) | | &ParserError::IncompleteReduction(line_num, col_num)
&ParserError::MissingQuote(line_num, col_num) | | &ParserError::MissingQuote(line_num, col_num)
&ParserError::NonPrologChar(line_num, col_num) | | &ParserError::NonPrologChar(line_num, col_num)
&ParserError::ParseBigInt(line_num, col_num) | | &ParserError::ParseBigInt(line_num, col_num)
&ParserError::UnexpectedChar(_, line_num, col_num) | | &ParserError::UnexpectedChar(_, line_num, col_num)
&ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)), | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
_ => None, _ => None,
} }
} }
@@ -432,8 +434,12 @@ impl ParserError {
match self { match self {
ParserError::BackQuotedString(..) => atom!("back_quoted_string"), ParserError::BackQuotedString(..) => atom!("back_quoted_string"),
ParserError::IncompleteReduction(..) => atom!("incomplete_reduction"), ParserError::IncompleteReduction(..) => atom!("incomplete_reduction"),
ParserError::InvalidSingleQuotedCharacter(..) => atom!("invalid_single_quoted_character"), ParserError::InvalidSingleQuotedCharacter(..) => {
ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => atom!("unexpected_end_of_file"), atom!("invalid_single_quoted_character")
}
ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => {
atom!("unexpected_end_of_file")
}
ParserError::IO(_) => atom!("input_output_error"), ParserError::IO(_) => atom!("input_output_error"),
ParserError::LexicalError(_) => atom!("lexical_error"), ParserError::LexicalError(_) => atom!("lexical_error"),
ParserError::MissingQuote(..) => atom!("missing_quote"), ParserError::MissingQuote(..) => atom!("missing_quote"),
@@ -522,9 +528,12 @@ pub enum Fixity {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct Fixnum { pub struct Fixnum {
num: B56, num: B56,
#[allow(unused)] f: bool, #[allow(unused)]
#[allow(unused)] m: bool, f: bool,
#[allow(unused)] tag: B6, #[allow(unused)]
m: bool,
#[allow(unused)]
tag: B6,
} }
impl Fixnum { impl Fixnum {
@@ -623,7 +632,7 @@ impl fmt::Display for Literal {
} }
impl Literal { impl Literal {
pub fn to_atom(&self, atom_tbl: &mut AtomTable) -> Option<Atom> { pub fn to_atom(&self, atom_tbl: &Arc<AtomTable>) -> Option<Atom> {
match self { match self {
Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)), Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)),
_ => None, _ => None,
@@ -631,7 +640,6 @@ impl Literal {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct VarPtr(Rc<RefCell<Var>>); pub struct VarPtr(Rc<RefCell<Var>>);

View File

@@ -78,7 +78,7 @@ pub trait CharRead {
self.consume(c.len_utf8()); self.consume(c.len_utf8());
Some(Ok(c)) Some(Ok(c))
} }
result => result result => result,
} }
} }
@@ -161,9 +161,7 @@ impl<R: Read> CharRead for CharReader<R> {
return Some(Ok(c)); return Some(Ok(c));
} }
Err(e) => { Err(e) => e,
e
}
}; };
if buf.len() - e.valid_up_to() >= 4 { if buf.len() - e.valid_up_to() >= 4 {
@@ -192,8 +190,10 @@ impl<R: Read> CharRead for CharReader<R> {
// the buffer, it will be returned on the next // the buffer, it will be returned on the next
// loop. // loop.
return Some(Err(io::Error::new(io::ErrorKind::InvalidData, return Some(Err(io::Error::new(
BadUtf8Error { bytes: badbytes }))); io::ErrorKind::InvalidData,
BadUtf8Error { bytes: badbytes },
)));
} else { } else {
if self.pos >= self.buf.len() { if self.pos >= self.buf.len() {
return None; return None;
@@ -208,8 +208,10 @@ impl<R: Read> CharRead for CharReader<R> {
Err(e) => { Err(e) => {
let badbytes = self.buf[self.pos..e.valid_up_to()].to_vec(); let badbytes = self.buf[self.pos..e.valid_up_to()].to_vec();
Some(Err(io::Error::new(io::ErrorKind::InvalidData, Some(Err(io::Error::new(
BadUtf8Error { bytes: badbytes }))) io::ErrorKind::InvalidData,
BadUtf8Error { bytes: badbytes },
)))
} }
}; };
} else { } else {
@@ -311,7 +313,10 @@ impl<R: Read> Read for CharReader<R> {
} }
if !buf.is_empty() { if !buf.is_empty() {
Err(io::Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) Err(io::Error::new(
ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else { } else {
Ok(()) Ok(())
} }
@@ -364,12 +369,14 @@ where
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("CharReader") fmt.debug_struct("CharReader")
.field("reader", &self.inner) .field("reader", &self.inner)
.field("buf", &format_args!("{}/{}", self.buf.capacity() - self.pos, self.buf.len())) .field(
"buf",
&format_args!("{}/{}", self.buf.capacity() - self.pos, self.buf.len()),
)
.finish() .finish()
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::parser::char_reader::*; use crate::parser::char_reader::*;

View File

@@ -86,14 +86,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
pub fn lookahead_char(&mut self) -> Result<char, ParserError> { pub fn lookahead_char(&mut self) -> Result<char, ParserError> {
match self.reader.peek_char() { match self.reader.peek_char() {
Some(Ok(c)) => Ok(c), Some(Ok(c)) => Ok(c),
_ => Err(ParserError::unexpected_eof()) _ => Err(ParserError::unexpected_eof()),
} }
} }
pub fn read_char(&mut self) -> Result<char, ParserError> { pub fn read_char(&mut self) -> Result<char, ParserError> {
match self.reader.read_char() { match self.reader.read_char() {
Some(Ok(c)) => Ok(c), Some(Ok(c)) => Ok(c),
_ => Err(ParserError::unexpected_eof()) _ => Err(ParserError::unexpected_eof()),
} }
} }
@@ -168,13 +168,15 @@ impl<'a, R: CharRead> Lexer<'a, R> {
match comment_loop() { match comment_loop() {
Err(e) if e.is_unexpected_eof() => { Err(e) if e.is_unexpected_eof() => {
return Err(ParserError::IncompleteReduction(self.line_num, self.col_num)); return Err(ParserError::IncompleteReduction(
self.line_num,
self.col_num,
));
} }
Err(e) => { Err(e) => {
return Err(e); return Err(e);
} }
Ok(_) => { Ok(_) => {}
}
} }
if prolog_char!(c) { if prolog_char!(c) {
@@ -362,7 +364,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if hexadecimal_digit_char!(c) { if hexadecimal_digit_char!(c) {
self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16) self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16)
} else { } else {
Err(ParserError::IncompleteReduction(self.line_num, self.col_num)) Err(ParserError::IncompleteReduction(
self.line_num,
self.col_num,
))
} }
} }
@@ -395,7 +400,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
}, },
) )
} else { } else {
Err(ParserError::IncompleteReduction(self.line_num, self.col_num)) Err(ParserError::IncompleteReduction(
self.line_num,
self.col_num,
))
} }
} }
@@ -463,9 +471,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| { .or_else(|_| {
Integer::from_str_radix(&token, 16) Integer::from_str_radix(&token, 16)
.map(|n| Token::Literal(Literal::Integer( .map(|n| {
arena_alloc!(n, &mut self.machine_st.arena) Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
))) )))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
}) })
} else { } else {
@@ -495,9 +506,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| { .or_else(|_| {
Integer::from_str_radix(&token, 8) Integer::from_str_radix(&token, 8)
.map(|n| Token::Literal(Literal::Integer( .map(|n| {
arena_alloc!(n, &mut self.machine_st.arena) Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
))) )))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
}) })
} else { } else {
@@ -527,9 +541,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| { .or_else(|_| {
Integer::from_str_radix(&token, 2) Integer::from_str_radix(&token, 2)
.map(|n| Token::Literal(Literal::Integer( .map(|n| {
arena_alloc!(n, &mut self.machine_st.arena) Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
))) )))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
}) })
} else { } else {
@@ -620,16 +637,20 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if token.as_str() == "[]" { if token.as_str() == "[]" {
Ok(Token::Literal(Literal::Atom(atom!("[]")))) Ok(Token::Literal(Literal::Atom(atom!("[]"))))
} else { } else {
Ok(Token::Literal(Literal::Atom( Ok(Token::Literal(Literal::Atom(AtomTable::build_with(
self.machine_st.atom_tbl.build_with(&token), &self.machine_st.atom_tbl,
))) &token,
))))
} }
} }
fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> { fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
let n = parse_lossy::<f64, _>(token.as_bytes())?; let n = parse_lossy::<f64, _>(token.as_bytes())?;
Ok(Token::Literal(Literal::from(float_alloc!(n, self.machine_st.arena)))) Ok(Token::Literal(Literal::from(float_alloc!(
n,
self.machine_st.arena
))))
} }
fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> { fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
@@ -675,7 +696,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token token
.parse::<Integer>() .parse::<Integer>()
.map(|n| { .map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(n, &mut self.machine_st.arena))) Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
}) })
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
}) })
@@ -740,17 +764,19 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
let n = parse_lossy::<f64, _>(token.as_bytes())?; let n = parse_lossy::<f64, _>(token.as_bytes())?;
Ok(Token::Literal(Literal::from( Ok(Token::Literal(Literal::from(float_alloc!(
float_alloc!(n, self.machine_st.arena) n,
))) self.machine_st.arena
))))
} else { } else {
return Ok(self.vacate_with_float(token)?); return Ok(self.vacate_with_float(token)?);
} }
} else { } else {
let n = parse_lossy::<f64, _>(token.as_bytes())?; let n = parse_lossy::<f64, _>(token.as_bytes())?;
Ok(Token::Literal(Literal::from( Ok(Token::Literal(Literal::from(float_alloc!(
float_alloc!(n, self.machine_st.arena) n,
))) self.machine_st.arena
))))
} }
} else { } else {
self.return_char('.'); self.return_char('.');
@@ -761,7 +787,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token token
.parse::<Integer>() .parse::<Integer>()
.map(|n| { .map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(n, &mut self.machine_st.arena))) Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
}) })
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
}) })
@@ -772,7 +801,9 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.hexadecimal_constant(c).or_else(|e| { self.hexadecimal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
i64::from_str_radix(&token, 10) i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| { .or_else(|_| {
token token
.parse::<Integer>() .parse::<Integer>()
@@ -794,7 +825,9 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.octal_constant(c).or_else(|e| { self.octal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
i64::from_str_radix(&token, 10) i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| { .or_else(|_| {
token token
.parse::<Integer>() .parse::<Integer>()
@@ -816,7 +849,9 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.binary_constant(c).or_else(|e| { self.binary_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
i64::from_str_radix(&token, 10) i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| { .or_else(|_| {
token token
.parse::<Integer>() .parse::<Integer>()
@@ -856,15 +891,16 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|c| Token::Literal(Literal::Fixnum(Fixnum::build_with(c as i64)))) .map(|c| Token::Literal(Literal::Fixnum(Fixnum::build_with(c as i64))))
.or_else(|err| { .or_else(|err| {
match err { match err {
ParserError::UnexpectedChar('\'', ..) => { ParserError::UnexpectedChar('\'', ..) => {}
}
err => return Err(err), err => return Err(err),
} }
self.return_char(c); self.return_char(c);
i64::from_str_radix(&token, 10) i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| { .or_else(|_| {
token token
.parse::<Integer>() .parse::<Integer>()
@@ -901,7 +937,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token token
.parse::<Integer>() .parse::<Integer>()
.map(|n| { .map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(n, &mut self.machine_st.arena))) Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
}) })
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
}) })
@@ -940,11 +979,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
pub fn scan_for_layout(&mut self) -> Result<bool, ParserError> { pub fn scan_for_layout(&mut self) -> Result<bool, ParserError> {
match self.lookahead_char() { match self.lookahead_char() {
Err(e) => { Err(e) => Err(e),
Err(e)
}
Ok(c) => { Ok(c) => {
let mut layout_info = LayoutInfo { inserted: false, more: true }; let mut layout_info = LayoutInfo {
inserted: false,
more: true,
};
let mut cr = Some(c); let mut cr = Some(c);
loop { loop {
@@ -1044,7 +1084,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if c == '"' { if c == '"' {
let s = self.char_code_list_token(c)?; let s = self.char_code_list_token(c)?;
let atom = self.machine_st.atom_tbl.build_with(&s); let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &s);
return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes { return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes {
Ok(Token::Literal(Literal::Atom(atom))) Ok(Token::Literal(Literal::Atom(atom)))
@@ -1054,7 +1094,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
if c == '\u{0}' { if c == '\u{0}' {
return Err(ParserError::unexpected_eof()) return Err(ParserError::unexpected_eof());
} }
self.name_token(c) self.name_token(c)

View File

@@ -7,13 +7,14 @@ macro_rules! char_class {
#[macro_export] #[macro_export]
macro_rules! alpha_char { macro_rules! alpha_char {
($c: expr) => { ($c: expr) => {
(!$c.is_numeric() && (!$c.is_numeric()
!$c.is_whitespace() && && !$c.is_whitespace()
!$c.is_control() && && !$c.is_control()
!$crate::graphic_token_char!($c) && && !$crate::graphic_token_char!($c)
!$crate::layout_char!($c) && && !$crate::layout_char!($c)
!$crate::meta_char!($c) && && !$crate::meta_char!($c)
!$crate::solo_char!($c)) || $c == '_' && !$crate::solo_char!($c))
|| $c == '_'
}; };
} }

View File

@@ -7,7 +7,6 @@ use crate::parser::ast::*;
use crate::parser::char_reader::*; use crate::parser::char_reader::*;
use crate::parser::lexer::*; use crate::parser::lexer::*;
use std::cell::Cell; use std::cell::Cell;
use std::mem; use std::mem;
use std::ops::Neg; use std::ops::Neg;
@@ -108,7 +107,7 @@ pub(crate) fn as_partial_string(
tail_ref = tail; tail_ref = tail;
} }
Term::CompleteString(_, cstr) => { Term::CompleteString(_, cstr) => {
string += cstr.as_str(); string += &*cstr.as_str();
tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))); tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
break; break;
} }
@@ -120,26 +119,17 @@ pub(crate) fn as_partial_string(
} }
match &tail { match &tail {
Term::AnonVar | Term::Var(..) => { Term::AnonVar | Term::Var(..) => Ok((string, Some(Box::new(tail)))),
Ok((string, Some(Box::new(tail)))) Term::Literal(_, Literal::Atom(atom!("[]"))) => Ok((string, None)),
}
Term::Literal(_, Literal::Atom(atom!("[]"))) => {
Ok((string, None))
}
Term::Literal(_, Literal::String(tail)) => { Term::Literal(_, Literal::String(tail)) => {
string += tail.as_str(); string += &*tail.as_str();
Ok((string, None)) Ok((string, None))
} }
_ => { _ => Ok((string, Some(Box::new(tail)))),
Ok((string, Some(Box::new(tail))))
}
} }
} }
pub fn get_op_desc( pub fn get_op_desc(name: Atom, op_dir: &CompositeOpDir) -> Option<CompositeOpDesc> {
name: Atom,
op_dir: &CompositeOpDir,
) -> Option<CompositeOpDesc> {
let mut op_desc = CompositeOpDesc { let mut op_desc = CompositeOpDesc {
pre: 0, pre: 0,
inf: 0, inf: 0,
@@ -295,17 +285,17 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
Ok(tokens) Ok(tokens)
} }
fn atomize_term(atom_tbl: &mut AtomTable, term: &Term) -> Option<Atom> { fn atomize_term(atom_tbl: &AtomTable, term: &Term) -> Option<Atom> {
match term { match term {
Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c), Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
_ => None, _ => None,
} }
} }
fn atomize_constant(atom_tbl: &mut AtomTable, c: Literal) -> Option<Atom> { fn atomize_constant(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
match c { match c {
Literal::Atom(ref name) => Some(*name), Literal::Atom(ref name) => Some(*name),
Literal::Char(c) => Some(atom_tbl.build_with(&c.to_string())), Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
_ => None, _ => None,
} }
} }
@@ -409,7 +399,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) { fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
self.terms.push(Term::Literal(Cell::default(), Literal::Atom(atom))); self.terms
.push(Term::Literal(Cell::default(), Literal::Atom(atom)));
self.stack.push(TokenDesc { self.stack.push(TokenDesc {
tt: TokenType::Term, tt: TokenType::Term,
priority, priority,
@@ -419,7 +410,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
fn shift(&mut self, token: Token, priority: usize, spec: Specifier) { fn shift(&mut self, token: Token, priority: usize, spec: Specifier) {
let tt = match token { let tt = match token {
Token::Literal(Literal::String(s)) if self.lexer.machine_st.flags.double_quotes.is_codes() => { Token::Literal(Literal::String(s))
if self.lexer.machine_st.flags.double_quotes.is_codes() =>
{
let mut list = Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))); let mut list = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
for c in s.as_str().chars().rev() { for c in s.as_str().chars().rev() {
@@ -436,7 +429,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
self.terms.push(list); self.terms.push(list);
TokenType::Term TokenType::Term
} }
Token::Literal(Literal::String(s)) if self.lexer.machine_st.flags.double_quotes.is_chars() => { Token::Literal(Literal::String(s))
if self.lexer.machine_st.flags.double_quotes.is_chars() =>
{
self.terms.push(Term::CompleteString(Cell::default(), s)); self.terms.push(Term::CompleteString(Cell::default(), s));
TokenType::Term TokenType::Term
} }
@@ -573,7 +568,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
let idx = self.terms.len() - arity; let idx = self.terms.len() - arity;
if TokenType::Term == self.stack[stack_len].tt { if TokenType::Term == self.stack[stack_len].tt {
if atomize_term(&mut self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() { if atomize_term(&self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() {
self.stack.truncate(stack_len + 1); self.stack.truncate(stack_len + 1);
let mut subterms: Vec<_> = self.terms.drain(idx..).collect(); let mut subterms: Vec<_> = self.terms.drain(idx..).collect();
@@ -581,27 +576,29 @@ impl<'a, R: CharRead> Parser<'a, R> {
if let Some(name) = self if let Some(name) = self
.terms .terms
.pop() .pop()
.and_then(|t| atomize_term(&mut self.lexer.machine_st.atom_tbl, &t)) .and_then(|t| atomize_term(&self.lexer.machine_st.atom_tbl, &t))
{ {
// reduce the '.' functor to a cons cell if it applies. // reduce the '.' functor to a cons cell if it applies.
if name == atom!(".") && subterms.len() == 2 { if name == atom!(".") && subterms.len() == 2 {
let tail = subterms.pop().unwrap(); let tail = subterms.pop().unwrap();
let head = subterms.pop().unwrap(); let head = subterms.pop().unwrap();
self.terms.push( self.terms.push(match as_partial_string(head, tail) {
match as_partial_string(head, tail) {
Ok((string_buf, Some(tail))) => { Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail) Term::PartialString(Cell::default(), string_buf, tail)
} }
Ok((string_buf, None)) => { Ok((string_buf, None)) => {
let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf); let atom = AtomTable::build_with(
&self.lexer.machine_st.atom_tbl,
&string_buf,
);
Term::CompleteString(Cell::default(), atom) Term::CompleteString(Cell::default(), atom)
} }
Err(term) => term, Err(term) => term,
}, });
);
} else { } else {
self.terms.push(Term::Clause(Cell::default(), name, subterms)); self.terms
.push(Term::Clause(Cell::default(), name, subterms));
} }
if let Some(&mut TokenDesc { if let Some(&mut TokenDesc {
@@ -695,7 +692,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
td.tt = TokenType::Term; td.tt = TokenType::Term;
td.priority = 0; td.priority = 0;
self.terms.push(Term::Literal(Cell::default(), Literal::Atom(atom!("[]")))); self.terms
.push(Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))));
return Ok(true); return Ok(true);
} }
} }
@@ -736,8 +734,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
if arity > self.terms.len() { if arity > self.terms.len() {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.line_num, self.lexer.line_num,
self.lexer.col_num self.lexer.col_num,
)) ));
} }
let idx = self.terms.len() - arity; let idx = self.terms.len() - arity;
@@ -755,18 +753,16 @@ impl<'a, R: CharRead> Parser<'a, R> {
}); });
self.terms.push(match list { self.terms.push(match list {
Term::Cons(_, head, tail) => { Term::Cons(_, head, tail) => match as_partial_string(*head, *tail) {
match as_partial_string(*head, *tail) {
Ok((string_buf, Some(tail))) => { Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail) Term::PartialString(Cell::default(), string_buf, tail)
} }
Ok((string_buf, None)) => { Ok((string_buf, None)) => {
let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf); let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
Term::CompleteString(Cell::default(), atom) Term::CompleteString(Cell::default(), atom)
} }
Err(term) => term, Err(term) => term,
} },
}
term => term, term => term,
}); });
@@ -784,10 +780,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
td.priority = 0; td.priority = 0;
td.spec = TERM; td.spec = TERM;
let term = Term::Literal( let term = Term::Literal(Cell::default(), Literal::Atom(atom!("{}")));
Cell::default(),
Literal::Atom(atom!("{}")),
);
self.terms.push(term); self.terms.push(term);
return Ok(true); return Ok(true);
@@ -818,11 +811,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
}; };
self.terms.push(Term::Clause( self.terms
Cell::default(), .push(Term::Clause(Cell::default(), atom!("{}"), vec![term]));
atom!("{}"),
vec![term],
));
return Ok(true); return Ok(true);
} }
@@ -933,7 +923,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
if let Some(term) = self.terms.last().cloned() { if let Some(term) = self.terms.last().cloned() {
match term { match term {
Term::Literal(_, Literal::Atom(name)) Term::Literal(_, Literal::Atom(name))
if name == atom!("-") && (is_prefix!(desc.spec) || is_negate!(desc.spec)) => if name == atom!("-")
&& (is_prefix!(desc.spec) || is_negate!(desc.spec)) =>
{ {
self.stack.pop(); self.stack.pop();
self.terms.pop(); self.terms.pop();
@@ -983,7 +974,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
|n, arena| Literal::from(float_alloc!(n, arena)), |n, arena| Literal::from(float_alloc!(n, arena)),
), ),
Token::Literal(c) => { Token::Literal(c) => {
if let Some(name) = atomize_constant(&mut self.lexer.machine_st.atom_tbl, c) { let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
if let Some(name) = atomized {
if !self.shift_op(name, op_dir)? { if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM); self.shift(Token::Literal(c), 0, TERM);
} }
@@ -1069,7 +1061,11 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
// on success, returns the parsed term and the number of lines read. // on success, returns the parsed term and the number of lines read.
pub fn read_term(&mut self, op_dir: &CompositeOpDir, tokens: Tokens) -> Result<Term, ParserError> { pub fn read_term(
&mut self,
op_dir: &CompositeOpDir,
tokens: Tokens,
) -> Result<Term, ParserError> {
self.tokens = match tokens { self.tokens = match tokens {
Tokens::Default => read_tokens(&mut self.lexer)?, Tokens::Default => read_tokens(&mut self.lexer)?,
Tokens::Provided(tokens) => tokens, Tokens::Provided(tokens) => tokens,

View File

@@ -1,6 +1,7 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use std::alloc; use std::alloc;
use std::cell::UnsafeCell;
use std::ptr; use std::ptr;
pub trait RawBlockTraits { pub trait RawBlockTraits {
@@ -12,7 +13,7 @@ pub trait RawBlockTraits {
pub struct RawBlock<T: RawBlockTraits> { pub struct RawBlock<T: RawBlockTraits> {
pub base: *const u8, pub base: *const u8,
pub top: *const u8, pub top: *const u8,
pub ptr: *mut u8, pub ptr: UnsafeCell<*mut u8>,
_marker: PhantomData<T>, _marker: PhantomData<T>,
} }
@@ -22,7 +23,7 @@ impl<T: RawBlockTraits> RawBlock<T> {
RawBlock { RawBlock {
base: ptr::null(), base: ptr::null(),
top: ptr::null(), top: ptr::null(),
ptr: ptr::null_mut(), ptr: UnsafeCell::new(ptr::null_mut()),
_marker: PhantomData, _marker: PhantomData,
} }
} }
@@ -42,7 +43,7 @@ impl<T: RawBlockTraits> RawBlock<T> {
self.base = alloc::alloc(layout) as *const _; self.base = alloc::alloc(layout) as *const _;
self.top = (self.base as usize + cap) as *const _; self.top = (self.base as usize + cap) as *const _;
self.ptr = self.base as *mut _; *self.ptr.get_mut() = self.base as *mut _;
} }
pub unsafe fn grow(&mut self) { pub unsafe fn grow(&mut self) {
@@ -54,7 +55,25 @@ impl<T: RawBlockTraits> RawBlock<T> {
self.base = alloc::realloc(self.base as *mut _, layout, size * 2) as *const _; self.base = alloc::realloc(self.base as *mut _, layout, size * 2) as *const _;
self.top = (self.base as usize + size * 2) as *const _; self.top = (self.base as usize + size * 2) as *const _;
self.ptr = (self.base as usize + size) as *mut _; *self.ptr.get_mut() = (self.base as usize + size) as *mut _;
}
}
pub unsafe fn grow_new(&self) -> Option<Self> {
if self.base.is_null() {
Some(Self::new())
} else {
let mut new_block = Self::empty_block();
new_block.init_at_size(self.size() * 2);
if new_block.base.is_null() {
// allocation failed
None
} else {
let allocated = (*self.ptr.get()) as usize - self.base as usize;
self.base.copy_to(new_block.base.cast_mut(), allocated);
*new_block.ptr.get_mut() = new_block.base.offset(allocated as isize).cast_mut();
Some(new_block)
}
} }
} }
@@ -64,35 +83,39 @@ impl<T: RawBlockTraits> RawBlock<T> {
} }
#[inline(always)] #[inline(always)]
fn free_space(&self) -> usize { unsafe fn free_space(&self) -> usize {
debug_assert!( debug_assert!(
self.ptr as *const _ >= self.base, *self.ptr.get() as *const _ >= self.base,
"self.ptr = {:?} < {:?} = self.base", "self.ptr = {:?} < {:?} = self.base",
self.ptr, *self.ptr.get(),
self.base self.base
); );
self.top as usize - self.ptr as usize self.top as usize - (*self.ptr.get()) as usize
} }
pub unsafe fn alloc(&mut self, size: usize) -> *mut u8 { pub unsafe fn alloc(&self, size: usize) -> *mut u8 {
if self.free_space() >= size { if self.free_space() >= size {
let ptr = self.ptr; let ptr = *self.ptr.get();
self.ptr = (self.ptr as usize + size) as *mut _; *self.ptr.get() = (ptr as usize + size) as *mut _;
ptr ptr
} else { } else {
ptr::null_mut() ptr::null_mut()
} }
} }
}
pub fn deallocate(&mut self) { impl<T: RawBlockTraits> Drop for RawBlock<T> {
fn drop(&mut self) {
if !self.base.is_null() {
unsafe { unsafe {
let layout = alloc::Layout::from_size_align_unchecked(self.size(), T::align()); let layout = alloc::Layout::from_size_align_unchecked(self.size(), T::align());
alloc::dealloc(self.base as *mut _, layout); alloc::dealloc(self.base as *mut _, layout);
}
self.top = ptr::null(); self.top = ptr::null();
self.base = ptr::null(); self.base = ptr::null();
self.ptr = ptr::null_mut(); *self.ptr.get_mut() = ptr::null_mut();
} }
} }
} }

221
src/rcu.rs Normal file
View File

@@ -0,0 +1,221 @@
use std::{
cell::OnceCell,
fmt::Debug,
mem::ManuallyDrop,
ops::Deref,
ptr::NonNull,
sync::{
atomic::{AtomicPtr, AtomicU8},
Arc, Weak,
},
};
use tokio::sync::RwLock;
// the epoch counters of all threads that have ever accessed an Rcu
// threads that have finished will have a dangling Weak reference and can be cleand up
// having this be shared between all Rcu's is a tradeof,
// writes will be slower as more epoch counters need to be waited for
// reads should be faster as a thread only needs to register itself once on the first read
//
static EPOCH_COUNTERS: RwLock<Vec<Weak<AtomicU8>>> = RwLock::const_new(Vec::new());
thread_local! {
// odd value means the current thread is about to access the active_epoch of an Rcu
// a thread has a single epoch counter for all Rcu it accesses,
// as a thread can only access one Rcu at a time
static THREAD_EPOCH_COUNTER: OnceCell<Arc<AtomicU8>> = OnceCell::new();
}
pub struct Rcu<T> {
active_value: AtomicPtr<T>,
}
impl<T: std::fmt::Debug> std::fmt::Debug for Rcu<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let active_epoch = self.active_epoch();
f.debug_struct("Rcu")
.field("active_value", &active_epoch)
.finish()
}
}
impl<T> Rcu<T> {
pub fn new(initial_value: T) -> Self {
Rcu {
active_value: AtomicPtr::new(Arc::into_raw(Arc::new(initial_value)).cast_mut()),
}
}
pub fn active_epoch(&self) -> RcuRef<T, T> {
THREAD_EPOCH_COUNTER.with(|epoch_counter| {
let epoch_counter = epoch_counter.get_or_init(|| {
let epoch_counter = Arc::new(AtomicU8::new(0));
// register the current threads epoch counter on init
EPOCH_COUNTERS
.blocking_write()
.push(Arc::downgrade(&epoch_counter));
epoch_counter
});
let old = epoch_counter.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
assert!(old % 2 == 0, "Old Epoch counter value should be even!");
});
let arc_ptr = self.active_value.load(std::sync::atomic::Ordering::Acquire);
let arc = unsafe {
// Safety:
// - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
// - the Rcu is responsible for of the arc's strong refrences
// - the Rcu is alive as this function takes a reference to the Rcu
// - replace will wait with decrementing the old values strong count until our epoich counter is even again
Arc::increment_strong_count(arc_ptr);
// Safety:
// - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
// - we have just ensured an additional strong count by incrementing the count
Arc::from_raw(arc_ptr)
};
THREAD_EPOCH_COUNTER.with(|epoch_counter| {
let old = epoch_counter
.get().expect("we initialized the OnceCell when we incremented the epoch counter the fist time")
.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
assert!(old % 2 != 0, "Old Epoch counter value should be odd!");
});
RcuRef {
data: arc.deref().into(),
arc,
}
}
/*
* replace the Rcu'S content with a new value
*
* This does not syncronize write and last to update the active_value pointer wins,
* all writes that do not win will be lost, though not leaked.
* This will block untill the old value can be reclaimed,
* i.e. all threads whitnest to be in the read critical sections
* have been witnest to have left the critical section at least once
*/
pub fn replace(&self, new_value: T) {
let arc_ptr = self.active_value.swap(
Arc::into_raw(Arc::new(new_value)).cast_mut(),
std::sync::atomic::Ordering::AcqRel,
);
// maually drop as we need to ensure not to drop the arc while
// we have not witnest all threads to be or have been outside the read critical section
// i.e. even epoch counter or different odd epoch counter
// Safety:
// - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
// - the Rcu itself holds one strong count
let arc = unsafe { ManuallyDrop::new(Arc::from_raw(arc_ptr)) };
let epochs = EPOCH_COUNTERS.blocking_read().clone();
let mut epochs = epochs
.into_iter()
.flat_map(|elem| {
let arc = elem.upgrade()?;
let init_val = arc.load(std::sync::atomic::Ordering::Acquire);
if init_val % 2 == 0 {
// already even can be ignored
return None;
}
// odd initial value thread is in read critical section
// need to wait for the value to change before we can drop the arc
Some((init_val, elem))
})
.collect::<Vec<_>>();
while !epochs.is_empty() {
epochs.retain(|elem| {
let Some(arc) = elem.1.upgrade() else {
// as the thread is dead it can't have a ref to old arc
return false;
};
// the epoch counter has not changed so the thread is still in the same instance of the critical section
// any different value is ok as
// - even values indicate the thread is outside the critical section
// - a diffrent odd value indicates the thread has left the critical section and can subsequently only read the new active_value
arc.load(std::sync::atomic::Ordering::Acquire) == elem.0
})
}
// Safety:
// - we have not dropped the arc another way
// - we witnessed all threads either with an even epoch count or with a new odd count
// as such they must have left the critical section at some point
ManuallyDrop::into_inner(arc);
}
}
pub struct RcuRef<T, M>
where
T: ?Sized,
M: ?Sized,
{
arc: Arc<T>,
data: NonNull<M>,
}
impl<T: ?Sized, M: ?Sized + Debug> Debug for RcuRef<T, M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RcuRef")
.field("data", &self.deref())
.finish()
}
}
// use assoiated functions rather than methods so that we don't overlap
// with functions of the Deref Target type
impl<T: ?Sized, M: ?Sized> RcuRef<T, M> {
pub fn map<N: ?Sized, F: for<'a> FnOnce(&'a M) -> &'a N>(referece: Self, f: F) -> RcuRef<T, N> {
RcuRef {
arc: referece.arc,
data: f(unsafe { referece.data.as_ref() }).into(),
}
}
pub fn try_map<N: ?Sized, F: for<'a> FnOnce(&'a M) -> Option<&'a N>>(
referece: Self,
f: F,
) -> Option<RcuRef<T, N>> {
let val = f(unsafe { referece.data.as_ref() })?;
Some(RcuRef {
arc: Arc::clone(&referece.arc),
data: val.into(),
})
}
pub fn same_epoch<M2>(this: &Self, other: &RcuRef<T, M2>) -> bool {
Arc::ptr_eq(&this.arc, &other.arc)
}
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.data == other.data
}
pub fn clone(this: &Self) -> Self {
Self {
arc: Arc::clone(&this.arc),
data: this.data,
}
}
pub fn get_root(this: &Self) -> &T {
&this.arc
}
}
impl<T: ?Sized, M: ?Sized> Deref for RcuRef<T, M> {
type Target = M;
fn deref(&self) -> &Self::Target {
// Safety: The pointer points into the arc we are holding
// while we are alive so is the target
// as the content is in an Rcu no mutable acess is given out
unsafe { self.data.as_ref() }
}
}

View File

@@ -16,8 +16,6 @@ use crate::types::*;
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
use indexmap::IndexSet;
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
@@ -27,18 +25,17 @@ use rustyline::{Config, Editor};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::io::{Cursor, Error, ErrorKind, Read}; use std::io::{Cursor, Error, ErrorKind, Read};
use std::sync::Arc;
type SubtermDeque = VecDeque<(usize, usize)>; type SubtermDeque = VecDeque<(usize, usize)>;
pub(crate) fn devour_whitespace<'a, R: CharRead>(parser: &mut Parser<'a, R>) -> Result<bool, ParserError> { pub(crate) fn devour_whitespace<'a, R: CharRead>(
parser: &mut Parser<'a, R>,
) -> Result<bool, ParserError> {
match parser.lexer.scan_for_layout() { match parser.lexer.scan_for_layout() {
Err(e) if e.is_unexpected_eof() => { Err(e) if e.is_unexpected_eof() => Ok(true),
Ok(true)
}
Err(e) => Err(e), Err(e) => Err(e),
Ok(_) => { Ok(_) => Ok(false),
Ok(false)
}
} }
} }
@@ -60,7 +57,6 @@ pub(crate) fn error_after_read_term<R>(
CompilationError::from(err) CompilationError::from(err)
} }
impl MachineState { impl MachineState {
pub(crate) fn read( pub(crate) fn read(
&mut self, &mut self,
@@ -74,14 +70,15 @@ impl MachineState {
parser.add_lines_read(prior_num_lines_read); parser.add_lines_read(prior_num_lines_read);
let term = parser.read_term(&op_dir, Tokens::Default) let term = parser
.read_term(&op_dir, Tokens::Default)
.map_err(|err| error_after_read_term(err, prior_num_lines_read, &parser))?; // CompilationError::from .map_err(|err| error_after_read_term(err, prior_num_lines_read, &parser))?; // CompilationError::from
(term, parser.lines_read() - prior_num_lines_read) (term, parser.lines_read() - prior_num_lines_read)
}; };
inner.add_lines_read(num_lines_read); inner.add_lines_read(num_lines_read);
write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl) write_term_to_heap(&term, &mut self.heap, &self.atom_tbl)
} }
} }
@@ -114,12 +111,11 @@ pub struct ReadlineStream {
} }
impl ReadlineStream { impl ReadlineStream {
#[cfg(feature = "repl")]
#[inline] #[inline]
pub fn new(pending_input: &str, add_history: bool) -> Self { pub fn new(pending_input: &str, add_history: bool) -> Self {
let config = Config::builder() #[cfg(feature = "repl")]
.check_cursor_position(true) {
.build(); let config = Config::builder().check_cursor_position(true).build();
let helper = Helper::new(); let helper = Helper::new();
@@ -141,22 +137,20 @@ impl ReadlineStream {
} }
#[cfg(not(feature = "repl"))] #[cfg(not(feature = "repl"))]
#[inline] {
pub fn new(pending_input: &str, add_history: bool) -> Self {
ReadlineStream { ReadlineStream {
pending_input: CharReader::new(Cursor::new(pending_input.to_owned())), pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
add_history: add_history, add_history: add_history,
} }
} }
#[cfg(feature = "repl")]
pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet<Atom>) {
let helper = self.rl.helper_mut().unwrap();
helper.atoms = atoms;
} }
#[cfg(not(feature = "repl"))] pub fn set_atoms_for_completion(&mut self, atoms: &Arc<AtomTable>) {
pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet<Atom>) { #[cfg(feature = "repl")]
{
let helper = self.rl.helper_mut().unwrap();
helper.atoms = Arc::downgrade(atoms);
}
} }
#[inline] #[inline]
@@ -180,7 +174,9 @@ impl ReadlineStream {
unsafe { unsafe {
if PROMPT { if PROMPT {
self.rl.add_history_entry(self.pending_input.get_ref().get_ref()).unwrap(); self.rl
.add_history_entry(self.pending_input.get_ref().get_ref())
.unwrap();
self.save_history(); self.save_history();
PROMPT = false; PROMPT = false;
} }
@@ -220,8 +216,7 @@ impl ReadlineStream {
} }
#[cfg(not(feature = "repl"))] #[cfg(not(feature = "repl"))]
fn save_history(&mut self) { fn save_history(&mut self) {}
}
#[inline] #[inline]
pub(crate) fn peek_byte(&mut self) -> std::io::Result<u8> { pub(crate) fn peek_byte(&mut self) -> std::io::Result<u8> {
@@ -253,7 +248,7 @@ impl Read for ReadlineStream {
self.call_readline()?; self.call_readline()?;
self.pending_input.read(buf) self.pending_input.read(buf)
} }
result => result result => result,
} }
} }
} }
@@ -266,16 +261,14 @@ impl CharRead for ReadlineStream {
Some(Ok(c)) => { Some(Ok(c)) => {
return Some(Ok(c)); return Some(Ok(c));
} }
_ => { _ => match self.call_readline() {
match self.call_readline() {
Err(e) => { Err(e) => {
return Some(Err(e)); return Some(Err(e));
} }
_ => { _ => {
set_prompt(false); set_prompt(false);
} }
} },
}
} }
} }
} }
@@ -295,7 +288,7 @@ impl CharRead for ReadlineStream {
pub(crate) fn write_term_to_heap<'a, 'b>( pub(crate) fn write_term_to_heap<'a, 'b>(
term: &'a Term, term: &'a Term,
heap: &'b mut Heap, heap: &'b mut Heap,
atom_tbl: &mut AtomTable, atom_tbl: &AtomTable,
) -> Result<TermWriteResult, CompilationError> { ) -> Result<TermWriteResult, CompilationError> {
let term_writer = TermWriter::new(heap, atom_tbl); let term_writer = TermWriter::new(heap, atom_tbl);
term_writer.write_term_to_heap(term) term_writer.write_term_to_heap(term)
@@ -304,7 +297,7 @@ pub(crate) fn write_term_to_heap<'a, 'b>(
#[derive(Debug)] #[derive(Debug)]
struct TermWriter<'a, 'b> { struct TermWriter<'a, 'b> {
heap: &'a mut Heap, heap: &'a mut Heap,
atom_tbl: &'b mut AtomTable, atom_tbl: &'b AtomTable,
queue: SubtermDeque, queue: SubtermDeque,
var_dict: HeapVarDict, var_dict: HeapVarDict,
} }
@@ -317,7 +310,7 @@ pub struct TermWriteResult {
impl<'a, 'b> TermWriter<'a, 'b> { impl<'a, 'b> TermWriter<'a, 'b> {
#[inline] #[inline]
fn new(heap: &'a mut Heap, atom_tbl: &'b mut AtomTable) -> Self { fn new(heap: &'a mut Heap, atom_tbl: &'b AtomTable) -> Self {
TermWriter { TermWriter {
heap, heap,
atom_tbl, atom_tbl,
@@ -347,14 +340,15 @@ impl<'a, 'b> TermWriter<'a, 'b> {
match term { match term {
&TermRef::Cons(..) => list_loc_as_cell!(h), &TermRef::Cons(..) => list_loc_as_cell!(h),
&TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h), &TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h),
&TermRef::CompleteString(_, _, ref src) => &TermRef::CompleteString(_, _, ref src) => {
if src.as_str().is_empty() { if src.as_str().is_empty() {
empty_list_as_cell!() empty_list_as_cell!()
} else if self.heap[h].get_tag() == HeapCellValueTag::CStr { } else if self.heap[h].get_tag() == HeapCellValueTag::CStr {
heap_loc_as_cell!(h) heap_loc_as_cell!(h)
} else { } else {
pstr_loc_as_cell!(h) pstr_loc_as_cell!(h)
}, }
}
&TermRef::PartialString(..) => pstr_loc_as_cell!(h), &TermRef::PartialString(..) => pstr_loc_as_cell!(h),
&TermRef::Literal(_, _, literal) => HeapCellValue::from(*literal), &TermRef::Literal(_, _, literal) => HeapCellValue::from(*literal),
&TermRef::Clause(_, _, _, subterms) if subterms.len() == 0 => heap_loc_as_cell!(h), &TermRef::Clause(_, _, _, subterms) if subterms.len() == 0 => heap_loc_as_cell!(h),
@@ -427,7 +421,8 @@ impl<'a, 'b> TermWriter<'a, 'b> {
} }
&TermRef::AnonVar(_) => { &TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = self.queue.pop_front() { if let Some((arity, site_h)) = self.queue.pop_front() {
self.var_dict.insert(VarKey::AnonVar(h), heap_loc_as_cell!(site_h)); self.var_dict
.insert(VarKey::AnonVar(h), heap_loc_as_cell!(site_h));
if arity > 1 { if arity > 1 {
self.queue.push_front((arity - 1, site_h + 1)); self.queue.push_front((arity - 1, site_h + 1));
@@ -437,7 +432,8 @@ impl<'a, 'b> TermWriter<'a, 'b> {
continue; continue;
} }
&TermRef::CompleteString(_, _, ref src) => { &TermRef::CompleteString(_, _, ref src) => {
put_complete_string(self.heap, src.as_str(), self.atom_tbl); let src = src.as_str().to_owned();
put_complete_string(self.heap, &src, self.atom_tbl);
} }
&TermRef::PartialString(lvl, _, ref src, _) => { &TermRef::PartialString(lvl, _, ref src, _) => {
if let Level::Root = lvl { if let Level::Root = lvl {

View File

@@ -1,23 +1,24 @@
use indexmap::IndexSet; use rustyline::completion::Completer;
use rustyline::completion::{Completer, Candidate}; use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::Hinter; use rustyline::hint::Hinter;
use rustyline::validate::Validator; use rustyline::validate::Validator;
use rustyline::highlight::{MatchingBracketHighlighter, Highlighter}; use rustyline::{Context, Helper as RlHelper, Result};
use rustyline::{Helper as RlHelper, Result, Context};
use crate::atom_table::{Atom, STATIC_ATOMS_MAP}; use std::sync::Weak;
use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP};
// TODO: Maybe add validation to the helper // TODO: Maybe add validation to the helper
pub struct Helper { pub struct Helper {
highligher: MatchingBracketHighlighter, highligher: MatchingBracketHighlighter,
pub atoms: *const IndexSet<Atom>, pub atoms: Weak<AtomTable>,
} }
impl Helper { impl Helper {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
highligher: MatchingBracketHighlighter::new(), highligher: MatchingBracketHighlighter::new(),
atoms: std::ptr::null(), atoms: Weak::new(),
} }
} }
} }
@@ -43,7 +44,7 @@ fn get_prefix(line: &str, pos: usize) -> Option<usize> {
} }
if i == pos { if i == pos {
break break;
} }
} }
@@ -54,39 +55,33 @@ fn get_prefix(line: &str, pos: usize) -> Option<usize> {
start_of_atom start_of_atom
} }
pub struct StrPtr(*const str);
impl Candidate for StrPtr {
fn display(&self) -> &str {
unsafe {
self.0.as_ref().unwrap()
}
}
fn replacement(&self) -> &str {
unsafe {
self.0.as_ref().unwrap()
}
}
}
impl Completer for Helper { impl Completer for Helper {
type Candidate = StrPtr; type Candidate = AtomString<'static>;
fn complete(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Result<(usize, Vec<Self::Candidate>)> { fn complete(
&self,
line: &str,
pos: usize,
_ctx: &Context<'_>,
) -> Result<(usize, Vec<Self::Candidate>)> {
let start_of_prefix = get_prefix(line, pos); let start_of_prefix = get_prefix(line, pos);
if let Some(idx) = start_of_prefix { if let Some(idx) = start_of_prefix {
let sub_str = line.get(idx..pos).unwrap(); let sub_str = line.get(idx..pos).unwrap();
Ok((idx, unsafe {
let mut matching = (*self.atoms).iter() let atom_table = self.atoms.upgrade().unwrap();
let index_set = atom_table.active_table();
let mut matching = index_set
.iter()
.chain(STATIC_ATOMS_MAP.values()) .chain(STATIC_ATOMS_MAP.values())
.filter(|a| a.as_str().starts_with(sub_str)) .map(|a| a.as_str())
.map(|s| StrPtr(s.as_str())) .filter(|a| a.starts_with(sub_str))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
matching.sort_unstable_by(|a, b| Ord::cmp(&(*a.0).len(), &(*b.0).len())); matching.sort_unstable_by(|a, b| Ord::cmp(&a.len(), &b.len()));
matching
})) Ok((idx, matching))
} else { } else {
Ok((0, vec![])) Ok((0, vec![]))
} }

View File

@@ -121,28 +121,24 @@ pub(crate) enum RefTag {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct Ref { pub struct Ref {
val: B56, val: B56,
#[allow(unused)] m: bool, #[allow(unused)]
#[allow(unused)] f: bool, m: bool,
#[allow(unused)]
f: bool,
tag: RefTag, tag: RefTag,
} }
impl Ord for Ref { impl Ord for Ref {
fn cmp(&self, rhs: &Ref) -> Ordering { fn cmp(&self, rhs: &Ref) -> Ordering {
match self.get_tag() { match self.get_tag() {
RefTag::HeapCell | RefTag::AttrVar => { RefTag::HeapCell | RefTag::AttrVar => match rhs.get_tag() {
match rhs.get_tag() {
RefTag::StackCell => Ordering::Less, RefTag::StackCell => Ordering::Less,
_ => self.get_value().cmp(&rhs.get_value()), _ => self.get_value().cmp(&rhs.get_value()),
} },
} RefTag::StackCell => match rhs.get_tag() {
RefTag::StackCell => { RefTag::StackCell => self.get_value().cmp(&rhs.get_value()),
match rhs.get_tag() { _ => Ordering::Greater,
RefTag::StackCell => },
self.get_value().cmp(&rhs.get_value()),
_ =>
Ordering::Greater,
}
}
} }
} }
} }
@@ -215,9 +211,12 @@ pub(crate) enum TrailEntryTag {
#[repr(u64)] #[repr(u64)]
pub(crate) struct TrailEntry { pub(crate) struct TrailEntry {
val: B56, val: B56,
#[allow(unused)] f: bool, #[allow(unused)]
#[allow(unused)] m: bool, f: bool,
#[allow(unused)] tag: TrailEntryTag, #[allow(unused)]
m: bool,
#[allow(unused)]
tag: TrailEntryTag,
} }
impl TrailEntry { impl TrailEntry {
@@ -257,14 +256,13 @@ pub struct HeapCellValue {
impl fmt::Debug for HeapCellValue { impl fmt::Debug for HeapCellValue {
fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::F64 => { HeapCellValueTag::F64 => f
f.debug_struct("HeapCellValue") .debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::F64) .field("tag", &HeapCellValueTag::F64)
.field("offset", &self.get_value()) .field("offset", &self.get_value())
.field("m", &self.m()) .field("m", &self.m())
.field("f", &self.f()) .field("f", &self.f())
.finish() .finish(),
}
HeapCellValueTag::Cons => { HeapCellValueTag::Cons => {
let cons_ptr = ConsPtr::from_bytes(self.into_bytes()); let cons_ptr = ConsPtr::from_bytes(self.into_bytes());
@@ -276,8 +274,7 @@ impl fmt::Debug for HeapCellValue {
.finish() .finish()
} }
HeapCellValueTag::Atom => { HeapCellValueTag::Atom => {
let (name, arity) = cell_as_atom_cell!(self) let (name, arity) = cell_as_atom_cell!(self).get_name_and_arity();
.get_name_and_arity();
f.debug_struct("HeapCellValue") f.debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::Atom) .field("tag", &HeapCellValueTag::Atom)
@@ -288,8 +285,7 @@ impl fmt::Debug for HeapCellValue {
.finish() .finish()
} }
HeapCellValueTag::PStr => { HeapCellValueTag::PStr => {
let (name, _) = cell_as_atom_cell!(self) let (name, _) = cell_as_atom_cell!(self).get_name_and_arity();
.get_name_and_arity();
f.debug_struct("HeapCellValue") f.debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::PStr) .field("tag", &HeapCellValueTag::PStr)
@@ -298,14 +294,13 @@ impl fmt::Debug for HeapCellValue {
.field("f", &self.f()) .field("f", &self.f())
.finish() .finish()
} }
tag => { tag => f
f.debug_struct("HeapCellValue") .debug_struct("HeapCellValue")
.field("tag", &tag) .field("tag", &tag)
.field("value", &self.get_value()) .field("value", &self.get_value())
.field("m", &self.get_mark_bit()) .field("m", &self.get_mark_bit())
.field("f", &self.get_forwarding_bit()) .field("f", &self.get_forwarding_bit())
.finish() .finish(),
}
} }
} }
} }
@@ -320,10 +315,7 @@ impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue {
impl From<F64Ptr> for HeapCellValue { impl From<F64Ptr> for HeapCellValue {
#[inline] #[inline]
fn from(f64_ptr: F64Ptr) -> HeapCellValue { fn from(f64_ptr: F64Ptr) -> HeapCellValue {
HeapCellValue::build_with( HeapCellValue::build_with(HeapCellValueTag::F64, f64_ptr.as_offset().to_u64())
HeapCellValueTag::F64,
f64_ptr.as_offset().to_u64(),
)
} }
} }
@@ -402,9 +394,13 @@ impl HeapCellValue {
#[inline] #[inline]
pub fn is_ref(self) -> bool { pub fn is_ref(self) -> bool {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::Var | HeapCellValueTag::Str
HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar | HeapCellValueTag::PStrLoc | | HeapCellValueTag::Lis
HeapCellValueTag::PStrOffset => true, | HeapCellValueTag::Var
| HeapCellValueTag::StackVar
| HeapCellValueTag::AttrVar
| HeapCellValueTag::PStrLoc
| HeapCellValueTag::PStrOffset => true,
_ => false, _ => false,
} }
} }
@@ -431,16 +427,13 @@ impl HeapCellValue {
#[inline] #[inline]
pub fn is_constant(self) -> bool { pub fn is_constant(self) -> bool {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::Cons | HeapCellValueTag::F64 | HeapCellValueTag::Fixnum | HeapCellValueTag::Cons
HeapCellValueTag::Char | HeapCellValueTag::CStr => { | HeapCellValueTag::F64
true | HeapCellValueTag::Fixnum
} | HeapCellValueTag::Char
HeapCellValueTag::Atom => { | HeapCellValueTag::CStr => true,
cell_as_atom_cell!(self).get_arity() == 0 HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0,
} _ => false,
_ => {
false
}
} }
} }
@@ -455,17 +448,13 @@ impl HeapCellValue {
HeapCellValueTag::Str => { HeapCellValueTag::Str => {
cell_as_atom_cell!(heap[self.get_value() as usize]).get_arity() > 0 cell_as_atom_cell!(heap[self.get_value() as usize]).get_arity() > 0
} }
HeapCellValueTag::Lis | HeapCellValueTag::Lis
HeapCellValueTag::CStr | | HeapCellValueTag::CStr
HeapCellValueTag::PStr | | HeapCellValueTag::PStr
HeapCellValueTag::PStrLoc | | HeapCellValueTag::PStrLoc
HeapCellValueTag::PStrOffset => { | HeapCellValueTag::PStrOffset => true,
true HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() > 0,
} _ => false,
HeapCellValueTag::Atom => {
cell_as_atom_cell!(self).get_arity() > 0
}
_ => { false }
} }
} }
@@ -530,9 +519,7 @@ impl HeapCellValue {
#[inline] #[inline]
pub fn to_pstr(self) -> Option<PartialString> { pub fn to_pstr(self) -> Option<PartialString> {
match self.tag() { match self.tag() {
HeapCellValueTag::PStr => { HeapCellValueTag::PStr => Some(PartialString::from(Atom::from(self.val() << 3))),
Some(PartialString::from(Atom::from(self.val() << 3)))
}
_ => None, _ => None,
} }
} }
@@ -548,7 +535,16 @@ impl HeapCellValue {
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
#[inline] #[inline]
pub fn from_raw_ptr_bytes(ptr_bytes: [u8; 4]) -> Self { pub fn from_raw_ptr_bytes(ptr_bytes: [u8; 4]) -> Self {
HeapCellValue::from_bytes([ptr_bytes[0], ptr_bytes[1], ptr_bytes[2], ptr_bytes[3], 0, 0, 0, 0]) HeapCellValue::from_bytes([
ptr_bytes[0],
ptr_bytes[1],
ptr_bytes[2],
ptr_bytes[3],
0,
0,
0,
0,
])
} }
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
#[inline] #[inline]
@@ -577,7 +573,9 @@ impl HeapCellValue {
#[inline] #[inline]
pub fn to_untyped_arena_ptr(self) -> Option<UntypedArenaPtr> { pub fn to_untyped_arena_ptr(self) -> Option<UntypedArenaPtr> {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::Cons => Some(UntypedArenaPtr::from_bytes(self.to_untyped_arena_ptr_bytes())), HeapCellValueTag::Cons => Some(UntypedArenaPtr::from_bytes(
self.to_untyped_arena_ptr_bytes(),
)),
_ => None, _ => None,
} }
} }
@@ -586,7 +584,7 @@ impl HeapCellValue {
pub fn get_forwarding_bit(self) -> bool { pub fn get_forwarding_bit(self) -> bool {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::Cons => ConsPtr::from_bytes(self.into_bytes()).f(), HeapCellValueTag::Cons => ConsPtr::from_bytes(self.into_bytes()).f(),
_ => self.f() _ => self.f(),
} }
} }
@@ -604,9 +602,7 @@ impl HeapCellValue {
#[inline(always)] #[inline(always)]
pub fn get_mark_bit(self) -> bool { pub fn get_mark_bit(self) -> bool {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::Cons => { HeapCellValueTag::Cons => ConsPtr::from_bytes(self.into_bytes()).m(),
ConsPtr::from_bytes(self.into_bytes()).m()
}
_ => self.m(), _ => self.m(),
} }
} }
@@ -633,15 +629,12 @@ impl HeapCellValue {
Some(TermOrderCategory::Variable) Some(TermOrderCategory::Variable)
} }
HeapCellValueTag::Char => Some(TermOrderCategory::Atom), HeapCellValueTag::Char => Some(TermOrderCategory::Atom),
HeapCellValueTag::Atom => { HeapCellValueTag::Atom => Some(if cell_as_atom_cell!(self).get_arity() > 0 {
Some(if cell_as_atom_cell!(self).get_arity() > 0 {
TermOrderCategory::Compound TermOrderCategory::Compound
} else { } else {
TermOrderCategory::Atom TermOrderCategory::Atom
}) }),
} HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr => {
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc |
HeapCellValueTag::CStr => {
Some(TermOrderCategory::Compound) Some(TermOrderCategory::Compound)
} }
HeapCellValueTag::Str => { HeapCellValueTag::Str => {
@@ -654,9 +647,7 @@ impl HeapCellValue {
Some(TermOrderCategory::Compound) Some(TermOrderCategory::Compound)
} }
} }
_ => { _ => None,
None
}
}, },
} }
} }
@@ -680,16 +671,17 @@ const_assert!(mem::size_of::<HeapCellValue>() == 8);
#[repr(u64)] #[repr(u64)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct UntypedArenaPtr { pub struct UntypedArenaPtr {
#[allow(unused)] ptr: B61, #[allow(unused)]
ptr: B61,
m: bool, m: bool,
#[allow(unused)] padding: B2, #[allow(unused)]
padding: B2,
} }
impl UntypedArenaPtr { impl UntypedArenaPtr {
#[inline(always)] #[inline(always)]
pub fn build_with(ptr: usize) -> Self { pub fn build_with(ptr: usize) -> Self {
UntypedArenaPtr::new() UntypedArenaPtr::new().with_ptr(ptr as u64)
.with_ptr(ptr as u64)
} }
} }
@@ -763,17 +755,15 @@ impl Add<usize> for HeapCellValue {
fn add(self, rhs: usize) -> Self::Output { fn add(self, rhs: usize) -> Self::Output {
match self.get_tag() { match self.get_tag() {
tag @ HeapCellValueTag::Str | tag @ HeapCellValueTag::Str
tag @ HeapCellValueTag::Lis | | tag @ HeapCellValueTag::Lis
tag @ HeapCellValueTag::PStrOffset | | tag @ HeapCellValueTag::PStrOffset
tag @ HeapCellValueTag::PStrLoc | | tag @ HeapCellValueTag::PStrLoc
tag @ HeapCellValueTag::Var | | tag @ HeapCellValueTag::Var
tag @ HeapCellValueTag::AttrVar => { | tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, (self.get_value() as usize + rhs) as u64) HeapCellValue::build_with(tag, (self.get_value() as usize + rhs) as u64)
} }
_ => { _ => self,
self
}
} }
} }
} }
@@ -783,17 +773,15 @@ impl Sub<usize> for HeapCellValue {
fn sub(self, rhs: usize) -> Self::Output { fn sub(self, rhs: usize) -> Self::Output {
match self.get_tag() { match self.get_tag() {
tag @ HeapCellValueTag::Str | tag @ HeapCellValueTag::Str
tag @ HeapCellValueTag::Lis | | tag @ HeapCellValueTag::Lis
tag @ HeapCellValueTag::PStrOffset | | tag @ HeapCellValueTag::PStrOffset
tag @ HeapCellValueTag::PStrLoc | | tag @ HeapCellValueTag::PStrLoc
tag @ HeapCellValueTag::Var | | tag @ HeapCellValueTag::Var
tag @ HeapCellValueTag::AttrVar => { | tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, (self.get_value() as usize - rhs) as u64) HeapCellValue::build_with(tag, (self.get_value() as usize - rhs) as u64)
} }
_ => { _ => self,
self
}
} }
} }
} }
@@ -811,21 +799,18 @@ impl Sub<i64> for HeapCellValue {
fn sub(self, rhs: i64) -> Self::Output { fn sub(self, rhs: i64) -> Self::Output {
if rhs < 0 { if rhs < 0 {
match self.get_tag() { match self.get_tag() {
tag @ HeapCellValueTag::Str | tag @ HeapCellValueTag::Str
tag @ HeapCellValueTag::Lis | | tag @ HeapCellValueTag::Lis
tag @ HeapCellValueTag::PStrOffset | | tag @ HeapCellValueTag::PStrOffset
tag @ HeapCellValueTag::PStrLoc | | tag @ HeapCellValueTag::PStrLoc
tag @ HeapCellValueTag::Var | | tag @ HeapCellValueTag::Var
tag @ HeapCellValueTag::AttrVar => { | tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, self.get_value() + rhs.abs() as u64) HeapCellValue::build_with(tag, self.get_value() + rhs.abs() as u64)
} }
_ => { _ => self,
self
}
} }
} else { } else {
self.sub(rhs as usize) self.sub(rhs as usize)
} }
} }
} }

View File

@@ -56,8 +56,10 @@ impl VarSafetyStatus {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum PermVarAllocation { pub enum PermVarAllocation {
Done { shallow_safety: VarSafetyStatus, Done {
deep_safety: VarSafetyStatus }, shallow_safety: VarSafetyStatus,
deep_safety: VarSafetyStatus,
},
Pending, Pending,
} }
@@ -81,11 +83,13 @@ impl PermVarAllocation {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum VarAlloc { pub enum VarAlloc {
Temp { term_loc: GenContext, Temp {
term_loc: GenContext,
temp_reg: usize, temp_reg: usize,
temp_var_data: TempVarData, temp_var_data: TempVarData,
safety: VarSafetyStatus, safety: VarSafetyStatus,
to_perm_var_num: Option<usize> }, to_perm_var_num: Option<usize>,
},
Perm(usize, PermVarAllocation), // stack offset, allocation info Perm(usize, PermVarAllocation), // stack offset, allocation info
} }
@@ -102,7 +106,9 @@ impl VarAlloc {
pub(crate) fn set_register(&mut self, reg_num: usize) { pub(crate) fn set_register(&mut self, reg_num: usize) {
match self { match self {
VarAlloc::Perm(ref mut p, _) => *p = reg_num, VarAlloc::Perm(ref mut p, _) => *p = reg_num,
VarAlloc::Temp { ref mut temp_reg, .. } => *temp_reg = reg_num, VarAlloc::Temp {
ref mut temp_reg, ..
} => *temp_reg = reg_num,
}; };
} }
} }
@@ -191,7 +197,8 @@ impl VariableRecords {
// Compute the conflict set of u. // Compute the conflict set of u.
// 1. // 1.
let mut use_sets: IndexMap<usize, IndexSet<(GenContext, usize), FxBuildHasher>> = IndexMap::new(); let mut use_sets: IndexMap<usize, IndexSet<(GenContext, usize), FxBuildHasher>> =
IndexMap::new();
for (var_gen_index, record) in self.0.iter_mut().enumerate() { for (var_gen_index, record) in self.0.iter_mut().enumerate() {
match &mut record.allocation { match &mut record.allocation {
@@ -203,8 +210,7 @@ impl VariableRecords {
use_sets.insert(var_gen_index, use_set); use_sets.insert(var_gen_index, use_set);
} }
_ => { _ => {}
}
} }
} }
@@ -214,7 +220,11 @@ impl VariableRecords {
if let GenContext::Last(cn_u) = term_loc { if let GenContext::Last(cn_u) = term_loc {
for (var_gen_index, record) in self.0.iter_mut().enumerate() { for (var_gen_index, record) in self.0.iter_mut().enumerate() {
match &mut record.allocation { match &mut record.allocation {
VarAlloc::Temp { term_loc, temp_var_data, .. } => { VarAlloc::Temp {
term_loc,
temp_var_data,
..
} => {
if cn_u == term_loc.chunk_num() && u != var_gen_index { if cn_u == term_loc.chunk_num() && u != var_gen_index {
if !temp_var_data.uses_reg(reg) { if !temp_var_data.uses_reg(reg) {
temp_var_data.no_use_set.insert(reg); temp_var_data.no_use_set.insert(reg);

View File

@@ -1,5 +1,4 @@
use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args}; use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args};
use scryer_prolog::machine::Machine;
use serial_test::serial; use serial_test::serial;
// issue #857 // issue #857
@@ -171,16 +170,3 @@ fn call_0() {
" error(existence_error(procedure,call/0),call/0).\n", " error(existence_error(procedure,call/0),call/0).\n",
); );
} }
// issue #1206
#[serial]
#[test]
#[should_panic(expected = "Overwriting atom table base pointer")]
fn atomtable_is_not_concurrency_safe() {
// this is basically the same test as scryer_prolog::atom_table::atomtable_is_not_concurrency_safe
// but for this integration test scryer_prolog is compiled with cfg!(not(test)) while for the unit test it is compiled with cfg!(test)
// as the atom table implementation differ between cfg!(test) and cfg!(not(test)) both test serve a pourpose
// Note: this integration test itself is compiled with cfg!(test) independent of scryer_prolog itself
let _machine_a = Machine::with_test_streams();
let _machine_b = Machine::with_test_streams();
}

View File

@@ -73,8 +73,5 @@ fn clpz_load() {
#[serial] #[serial]
#[test] #[test]
fn iso_conformity_tests() { fn iso_conformity_tests() {
load_module_test( load_module_test("tests-pl/iso-conformity-tests.pl", "All tests passed");
"tests-pl/iso-conformity-tests.pl",
"All tests passed",
);
} }