move to a predicate-based module system, move to loader.[rs|pl]-based compilation, add support for incremental clause compilation
This commit is contained in:
551
Cargo.lock
generated
551
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ libc = "0.2.62"
|
|||||||
nix = "0.15.0"
|
nix = "0.15.0"
|
||||||
num-rug-adapter = { optional = true, version = "0.1.4" }
|
num-rug-adapter = { optional = true, version = "0.1.4" }
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = { version = "0.8.68", default-features = false }
|
prolog_parser = { version = "0.8.63", path = "../prolog_parser", default-features = false }
|
||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
rug = { version = "1.4.0", optional = true }
|
rug = { version = "1.4.0", optional = true }
|
||||||
rustyline = "7.0.0"
|
rustyline = "7.0.0"
|
||||||
@@ -48,3 +48,4 @@ select = "0.4.3"
|
|||||||
roxmltree = "0.11.0"
|
roxmltree = "0.11.0"
|
||||||
base64 = "0.12.3"
|
base64 = "0.12.3"
|
||||||
sodiumoxide = "0.2.6"
|
sodiumoxide = "0.2.6"
|
||||||
|
slice-deque = "0.3.0"
|
||||||
2
build.rs
2
build.rs
@@ -11,6 +11,7 @@ fn find_prolog_files(libraries: &mut File, prefix: &str, current_dir: &Path) {
|
|||||||
Ok(entries) => entries,
|
Ok(entries) => entries,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
for entry in entries.filter_map(Result::ok).map(|e| e.path()) {
|
for entry in entries.filter_map(Result::ok).map(|e| e.path()) {
|
||||||
if entry.is_dir() {
|
if entry.is_dir() {
|
||||||
if let Some(file_name) = entry.file_name() {
|
if let Some(file_name) = entry.file_name() {
|
||||||
@@ -24,6 +25,7 @@ fn find_prolog_files(libraries: &mut File, prefix: &str, current_dir: &Path) {
|
|||||||
let contain =
|
let contain =
|
||||||
String::from_utf8(fs::read(&entry).unwrap()).unwrap();
|
String::from_utf8(fs::read(&entry).unwrap()).unwrap();
|
||||||
let name = entry.file_stem().unwrap().to_str().unwrap();
|
let name = entry.file_stem().unwrap().to_str().unwrap();
|
||||||
|
|
||||||
let line = format!(
|
let line = format!(
|
||||||
" m.insert(\"{}\",\n{:?});\n",
|
" m.insert(\"{}\",\n{:?});\n",
|
||||||
prefix.to_owned() + name,
|
prefix.to_owned() + name,
|
||||||
|
|||||||
@@ -150,11 +150,11 @@ impl InlinedClauseType {
|
|||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum SystemClauseType {
|
pub enum SystemClauseType {
|
||||||
AbolishClause,
|
// AbolishClause,
|
||||||
AbolishModuleClause,
|
// AbolishModuleClause,
|
||||||
AssertDynamicPredicateToBack,
|
// AssertDynamicPredicateToBack,
|
||||||
AssertDynamicPredicateToFront,
|
// AssertDynamicPredicateToFront,
|
||||||
AtEndOfExpansion,
|
// AtEndOfExpansion,
|
||||||
AtomChars,
|
AtomChars,
|
||||||
AtomCodes,
|
AtomCodes,
|
||||||
AtomLength,
|
AtomLength,
|
||||||
@@ -189,8 +189,8 @@ pub enum SystemClauseType {
|
|||||||
DynamicModuleResolution(usize),
|
DynamicModuleResolution(usize),
|
||||||
EnqueueAttributeGoal,
|
EnqueueAttributeGoal,
|
||||||
EnqueueAttributedVar,
|
EnqueueAttributedVar,
|
||||||
ExpandGoal,
|
// ExpandGoal,
|
||||||
ExpandTerm,
|
// ExpandTerm,
|
||||||
FetchGlobalVar,
|
FetchGlobalVar,
|
||||||
FetchGlobalVarWithOffset,
|
FetchGlobalVarWithOffset,
|
||||||
FirstStream,
|
FirstStream,
|
||||||
@@ -207,16 +207,16 @@ pub enum SystemClauseType {
|
|||||||
GetAttrVarQueueDelimiter,
|
GetAttrVarQueueDelimiter,
|
||||||
GetAttrVarQueueBeyond,
|
GetAttrVarQueueBeyond,
|
||||||
GetBValue,
|
GetBValue,
|
||||||
GetClause,
|
// GetClause,
|
||||||
GetContinuationChunk,
|
GetContinuationChunk,
|
||||||
GetModuleClause,
|
// GetModuleClause,
|
||||||
GetNextDBRef,
|
GetNextDBRef,
|
||||||
GetNextOpDBRef,
|
GetNextOpDBRef,
|
||||||
IsPartialString,
|
IsPartialString,
|
||||||
LookupDBRef,
|
LookupDBRef,
|
||||||
LookupOpDBRef,
|
LookupOpDBRef,
|
||||||
Halt,
|
Halt,
|
||||||
ModuleHeadIsDynamic,
|
// ModuleHeadIsDynamic,
|
||||||
GetLiftedHeapFromOffset,
|
GetLiftedHeapFromOffset,
|
||||||
GetLiftedHeapFromOffsetDiff,
|
GetLiftedHeapFromOffsetDiff,
|
||||||
GetSCCCleaner,
|
GetSCCCleaner,
|
||||||
@@ -224,11 +224,11 @@ pub enum SystemClauseType {
|
|||||||
InstallSCCCleaner,
|
InstallSCCCleaner,
|
||||||
InstallInferenceCounter,
|
InstallInferenceCounter,
|
||||||
LiftedHeapLength,
|
LiftedHeapLength,
|
||||||
ModuleAssertDynamicPredicateToFront,
|
LoadLibraryAsStream,
|
||||||
ModuleAssertDynamicPredicateToBack,
|
// ModuleAssertDynamicPredicateToFront,
|
||||||
|
// ModuleAssertDynamicPredicateToBack,
|
||||||
ModuleExists,
|
ModuleExists,
|
||||||
ModuleOf,
|
// ModuleRetractClause,
|
||||||
ModuleRetractClause,
|
|
||||||
NextEP,
|
NextEP,
|
||||||
NoSuchPredicate,
|
NoSuchPredicate,
|
||||||
NumberToChars,
|
NumberToChars,
|
||||||
@@ -254,7 +254,7 @@ pub enum SystemClauseType {
|
|||||||
ResetContinuationMarker,
|
ResetContinuationMarker,
|
||||||
ResetGlobalVarAtKey,
|
ResetGlobalVarAtKey,
|
||||||
ResetGlobalVarAtOffset,
|
ResetGlobalVarAtOffset,
|
||||||
RetractClause,
|
// RetractClause,
|
||||||
RestoreCutPolicy,
|
RestoreCutPolicy,
|
||||||
SetCutPoint(RegType),
|
SetCutPoint(RegType),
|
||||||
SetInput,
|
SetInput,
|
||||||
@@ -324,11 +324,11 @@ pub enum SystemClauseType {
|
|||||||
impl SystemClauseType {
|
impl SystemClauseType {
|
||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
&SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
|
// &SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
|
||||||
&SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
|
// &SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
|
||||||
&SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
|
// &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
|
||||||
&SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
|
// &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
|
||||||
&SystemClauseType::AtEndOfExpansion => clause_name!("$at_end_of_expansion"),
|
// &SystemClauseType::AtEndOfExpansion => clause_name!("$at_end_of_expansion"),
|
||||||
&SystemClauseType::AtomChars => clause_name!("$atom_chars"),
|
&SystemClauseType::AtomChars => clause_name!("$atom_chars"),
|
||||||
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
|
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
|
||||||
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
||||||
@@ -356,17 +356,50 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
|
&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
|
||||||
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
|
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
|
||||||
&SystemClauseType::FileTime => clause_name!("$file_time"),
|
&SystemClauseType::FileTime => clause_name!("$file_time"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
&SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) =>
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
clause_name!("$add_dynamic_predicate"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
|
&SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) =>
|
||||||
clause_name!("$use_qualified_module")
|
clause_name!("$add_goal_expansion_clause"),
|
||||||
}
|
&SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause) =>
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile) => {
|
clause_name!("$add_term_expansion_clause"),
|
||||||
clause_name!("$use_module_from_file")
|
&SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable) =>
|
||||||
}
|
clause_name!("$clause_to_evacuable"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
|
&SystemClauseType::REPL(REPLCodePtr::ConcludeLoad) =>
|
||||||
clause_name!("$use_qualified_module_from_file")
|
clause_name!("$conclude_load"),
|
||||||
}
|
&SystemClauseType::REPL(REPLCodePtr::DeclareModule) =>
|
||||||
|
clause_name!("$declare_module"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary) =>
|
||||||
|
clause_name!("$load_compiled_library"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload) =>
|
||||||
|
clause_name!("$push_load_state_payload"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::UserAsserta) =>
|
||||||
|
clause_name!("$asserta"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::UserAssertz) =>
|
||||||
|
clause_name!("$assertz"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::UserRetract) =>
|
||||||
|
clause_name!("$retract_clause"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::UseModule) =>
|
||||||
|
clause_name!("$use_module"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::PushLoadContext) =>
|
||||||
|
clause_name!("$push_load_context"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::PopLoadContext) =>
|
||||||
|
clause_name!("$pop_load_context"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload) =>
|
||||||
|
clause_name!("$pop_load_state_payload"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::LoadContextSource) =>
|
||||||
|
clause_name!("$prolog_lc_source"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::LoadContextFile) =>
|
||||||
|
clause_name!("$prolog_lc_file"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory) =>
|
||||||
|
clause_name!("$prolog_lc_dir"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::LoadContextModule) =>
|
||||||
|
clause_name!("$prolog_lc_module"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::LoadContextStream) =>
|
||||||
|
clause_name!("$prolog_lc_stream"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty) =>
|
||||||
|
clause_name!("$cpp_meta_predicate_property"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates) =>
|
||||||
|
clause_name!("$compile_pending_predicates"),
|
||||||
&SystemClauseType::Close => clause_name!("$close"),
|
&SystemClauseType::Close => clause_name!("$close"),
|
||||||
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
@@ -374,12 +407,9 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::DynamicModuleResolution(_) => clause_name!("$module_call"),
|
&SystemClauseType::DynamicModuleResolution(_) => clause_name!("$module_call"),
|
||||||
&SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"),
|
&SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"),
|
||||||
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
|
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
|
||||||
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
|
||||||
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
|
||||||
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
|
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
|
||||||
&SystemClauseType::FetchGlobalVarWithOffset => {
|
&SystemClauseType::FetchGlobalVarWithOffset =>
|
||||||
clause_name!("$fetch_global_var_with_offset")
|
clause_name!("$fetch_global_var_with_offset"),
|
||||||
}
|
|
||||||
&SystemClauseType::FirstStream => clause_name!("$first_stream"),
|
&SystemClauseType::FirstStream => clause_name!("$first_stream"),
|
||||||
&SystemClauseType::FlushOutput => clause_name!("$flush_output"),
|
&SystemClauseType::FlushOutput => clause_name!("$flush_output"),
|
||||||
&SystemClauseType::GetByte => clause_name!("$get_byte"),
|
&SystemClauseType::GetByte => clause_name!("$get_byte"),
|
||||||
@@ -405,13 +435,13 @@ impl SystemClauseType {
|
|||||||
clause_name!("$get_lh_from_offset_diff")
|
clause_name!("$get_lh_from_offset_diff")
|
||||||
}
|
}
|
||||||
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
||||||
&SystemClauseType::GetClause => clause_name!("$get_clause"),
|
// &SystemClauseType::GetClause => clause_name!("$get_clause"),
|
||||||
&SystemClauseType::GetNextDBRef => clause_name!("$get_next_db_ref"),
|
&SystemClauseType::GetNextDBRef => clause_name!("$get_next_db_ref"),
|
||||||
&SystemClauseType::GetNextOpDBRef => clause_name!("$get_next_op_db_ref"),
|
&SystemClauseType::GetNextOpDBRef => clause_name!("$get_next_op_db_ref"),
|
||||||
&SystemClauseType::LookupDBRef => clause_name!("$lookup_db_ref"),
|
&SystemClauseType::LookupDBRef => clause_name!("$lookup_db_ref"),
|
||||||
&SystemClauseType::LookupOpDBRef => clause_name!("$lookup_op_db_ref"),
|
&SystemClauseType::LookupOpDBRef => clause_name!("$lookup_op_db_ref"),
|
||||||
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
||||||
&SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
|
// &SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
|
||||||
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
||||||
&SystemClauseType::Halt => clause_name!("$halt"),
|
&SystemClauseType::Halt => clause_name!("$halt"),
|
||||||
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
||||||
@@ -430,15 +460,14 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::Maybe => clause_name!("maybe"),
|
&SystemClauseType::Maybe => clause_name!("maybe"),
|
||||||
&SystemClauseType::CpuNow => clause_name!("$cpu_now"),
|
&SystemClauseType::CpuNow => clause_name!("$cpu_now"),
|
||||||
&SystemClauseType::CurrentTime => clause_name!("$current_time"),
|
&SystemClauseType::CurrentTime => clause_name!("$current_time"),
|
||||||
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
|
// &SystemClauseType::ModuleAssertDynamicPredicateToFront => {
|
||||||
clause_name!("$module_asserta")
|
// clause_name!("$module_asserta")
|
||||||
}
|
// }
|
||||||
&SystemClauseType::ModuleAssertDynamicPredicateToBack => {
|
// &SystemClauseType::ModuleAssertDynamicPredicateToBack => {
|
||||||
clause_name!("$module_assertz")
|
// clause_name!("$module_assertz")
|
||||||
}
|
// }
|
||||||
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
|
// &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
|
||||||
&SystemClauseType::ModuleExists => clause_name!("$module_exists"),
|
&SystemClauseType::ModuleExists => clause_name!("$module_exists"),
|
||||||
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
|
||||||
&SystemClauseType::NextStream => clause_name!("$next_stream"),
|
&SystemClauseType::NextStream => clause_name!("$next_stream"),
|
||||||
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
|
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
|
||||||
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
|
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
|
||||||
@@ -483,14 +512,13 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::GetCutPoint => clause_name!("$get_cp"),
|
&SystemClauseType::GetCutPoint => clause_name!("$get_cp"),
|
||||||
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
|
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
|
||||||
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
|
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
|
||||||
&SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
|
// &SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
|
||||||
&SystemClauseType::NextEP => clause_name!("$nextEP"),
|
&SystemClauseType::NextEP => clause_name!("$nextEP"),
|
||||||
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
|
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
|
||||||
&SystemClauseType::ReadTerm => clause_name!("$read_term"),
|
&SystemClauseType::ReadTerm => clause_name!("$read_term"),
|
||||||
&SystemClauseType::ReadTermFromChars => clause_name!("$read_term_from_chars"),
|
&SystemClauseType::ReadTermFromChars => clause_name!("$read_term_from_chars"),
|
||||||
&SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
|
&SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
|
||||||
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
|
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
|
||||||
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
|
||||||
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
|
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
|
||||||
&SystemClauseType::ResetContinuationMarker => clause_name!("$reset_cont_marker"),
|
&SystemClauseType::ResetContinuationMarker => clause_name!("$reset_cont_marker"),
|
||||||
&SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"),
|
&SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"),
|
||||||
@@ -533,22 +561,27 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::SetEnv => clause_name!("$setenv"),
|
&SystemClauseType::SetEnv => clause_name!("$setenv"),
|
||||||
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
|
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
|
||||||
&SystemClauseType::CharsBase64 => clause_name!("$chars_base64"),
|
&SystemClauseType::CharsBase64 => clause_name!("$chars_base64"),
|
||||||
|
&SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
// ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
||||||
("$at_end_of_expansion", 0) => Some(SystemClauseType::AtEndOfExpansion),
|
("$add_dynamic_predicate", 3) =>
|
||||||
|
Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate)),
|
||||||
|
("$add_goal_expansion_clause", 4) =>
|
||||||
|
Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause)),
|
||||||
|
("$add_term_expansion_clause", 3) =>
|
||||||
|
Some(SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause)),
|
||||||
|
// ("$at_end_of_expansion", 0) => Some(SystemClauseType::AtEndOfExpansion),
|
||||||
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
|
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
|
||||||
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
|
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
|
||||||
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
|
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
|
||||||
("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
|
// ("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
|
||||||
("$bind_from_register", 2) => Some(SystemClauseType::BindFromRegister),
|
("$bind_from_register", 2) => Some(SystemClauseType::BindFromRegister),
|
||||||
("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
|
// ("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
|
||||||
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
// ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
||||||
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
|
||||||
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
|
||||||
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
|
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
|
||||||
("$char_code", 2) => Some(SystemClauseType::CharCode),
|
("$char_code", 2) => Some(SystemClauseType::CharCode),
|
||||||
("$char_type", 2) => Some(SystemClauseType::CharType),
|
("$char_type", 2) => Some(SystemClauseType::CharType),
|
||||||
@@ -559,7 +592,6 @@ impl SystemClauseType {
|
|||||||
("$copy_term_without_attr_vars", 2) => Some(SystemClauseType::CopyTermWithoutAttrVars),
|
("$copy_term_without_attr_vars", 2) => Some(SystemClauseType::CopyTermWithoutAttrVars),
|
||||||
("$create_partial_string", 3) => Some(SystemClauseType::CreatePartialString),
|
("$create_partial_string", 3) => Some(SystemClauseType::CreatePartialString),
|
||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
|
|
||||||
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
||||||
("$close", 2) => Some(SystemClauseType::Close),
|
("$close", 2) => Some(SystemClauseType::Close),
|
||||||
("$current_hostname", 1) => Some(SystemClauseType::CurrentHostname),
|
("$current_hostname", 1) => Some(SystemClauseType::CurrentHostname),
|
||||||
@@ -582,8 +614,8 @@ impl SystemClauseType {
|
|||||||
("$peek_char", 2) => Some(SystemClauseType::PeekChar),
|
("$peek_char", 2) => Some(SystemClauseType::PeekChar),
|
||||||
("$peek_code", 2) => Some(SystemClauseType::PeekCode),
|
("$peek_code", 2) => Some(SystemClauseType::PeekCode),
|
||||||
("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
|
("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
|
||||||
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
// ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
||||||
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
// ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
||||||
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
||||||
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
|
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
|
||||||
("$get_byte", 2) => Some(SystemClauseType::GetByte),
|
("$get_byte", 2) => Some(SystemClauseType::GetByte),
|
||||||
@@ -615,14 +647,14 @@ impl SystemClauseType {
|
|||||||
}
|
}
|
||||||
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
||||||
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
||||||
("$get_clause", 2) => Some(SystemClauseType::GetClause),
|
// ("$get_clause", 2) => Some(SystemClauseType::GetClause),
|
||||||
("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
|
// ("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
|
||||||
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
|
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
|
||||||
("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
|
("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
|
||||||
("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
|
("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
|
||||||
("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
|
("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
|
||||||
("$halt", 1) => Some(SystemClauseType::Halt),
|
("$halt", 1) => Some(SystemClauseType::Halt),
|
||||||
("$head_is_dynamic", 1) => Some(SystemClauseType::HeadIsDynamic),
|
("$head_is_dynamic", 2) => Some(SystemClauseType::HeadIsDynamic),
|
||||||
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
|
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
|
||||||
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
||||||
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
||||||
@@ -630,10 +662,9 @@ impl SystemClauseType {
|
|||||||
("$cpu_now", 1) => Some(SystemClauseType::CpuNow),
|
("$cpu_now", 1) => Some(SystemClauseType::CpuNow),
|
||||||
("$current_time", 1) => Some(SystemClauseType::CurrentTime),
|
("$current_time", 1) => Some(SystemClauseType::CurrentTime),
|
||||||
("$module_exists", 1) => Some(SystemClauseType::ModuleExists),
|
("$module_exists", 1) => Some(SystemClauseType::ModuleExists),
|
||||||
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
// ("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
||||||
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
// ("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
|
||||||
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
|
("$no_such_predicate", 2) => Some(SystemClauseType::NoSuchPredicate),
|
||||||
("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
|
|
||||||
("$number_to_chars", 2) => Some(SystemClauseType::NumberToChars),
|
("$number_to_chars", 2) => Some(SystemClauseType::NumberToChars),
|
||||||
("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
|
("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
|
||||||
("$op", 3) => Some(SystemClauseType::OpDeclaration),
|
("$op", 3) => Some(SystemClauseType::OpDeclaration),
|
||||||
@@ -667,7 +698,7 @@ impl SystemClauseType {
|
|||||||
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
||||||
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
|
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
|
||||||
("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset),
|
("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset),
|
||||||
("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
|
// ("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
|
||||||
("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
|
("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
|
||||||
("$set_ball", 1) => Some(SystemClauseType::SetBall),
|
("$set_ball", 1) => Some(SystemClauseType::SetBall),
|
||||||
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
|
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
|
||||||
@@ -697,15 +728,17 @@ impl SystemClauseType {
|
|||||||
("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory),
|
("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory),
|
||||||
("$path_canonical", 2) => Some(SystemClauseType::PathCanonical),
|
("$path_canonical", 2) => Some(SystemClauseType::PathCanonical),
|
||||||
("$file_time", 3) => Some(SystemClauseType::FileTime),
|
("$file_time", 3) => Some(SystemClauseType::FileTime),
|
||||||
("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
|
("$clause_to_evacuable", 3) => Some(SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable)),
|
||||||
("$use_module_from_file", 1) =>
|
("$conclude_load", 1) => Some(SystemClauseType::REPL(REPLCodePtr::ConcludeLoad)),
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),
|
("$use_module", 3) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
|
||||||
("$use_qualified_module", 2) =>
|
("$declare_module", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DeclareModule)),
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule)),
|
("$load_compiled_library", 2) => Some(SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary)),
|
||||||
("$use_qualified_module_from_file", 2) =>
|
("$push_load_state_payload", 1) => Some(SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload)),
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
("$asserta", 4) => Some(SystemClauseType::REPL(REPLCodePtr::UserAsserta)),
|
||||||
|
("$assertz", 4) => Some(SystemClauseType::REPL(REPLCodePtr::UserAssertz)),
|
||||||
|
("$retract_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::UserRetract)),
|
||||||
("$variant", 2) => Some(SystemClauseType::Variant),
|
("$variant", 2) => Some(SystemClauseType::Variant),
|
||||||
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions),
|
||||||
("$write_term", 7) => Some(SystemClauseType::WriteTerm),
|
("$write_term", 7) => Some(SystemClauseType::WriteTerm),
|
||||||
("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars),
|
("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars),
|
||||||
("$scryer_prolog_version", 1) => Some(SystemClauseType::ScryerPrologVersion),
|
("$scryer_prolog_version", 1) => Some(SystemClauseType::ScryerPrologVersion),
|
||||||
@@ -727,6 +760,17 @@ impl SystemClauseType {
|
|||||||
("$setenv", 2) => Some(SystemClauseType::SetEnv),
|
("$setenv", 2) => Some(SystemClauseType::SetEnv),
|
||||||
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
|
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
|
||||||
("$chars_base64", 4) => Some(SystemClauseType::CharsBase64),
|
("$chars_base64", 4) => Some(SystemClauseType::CharsBase64),
|
||||||
|
("$load_library_as_stream", 3) => Some(SystemClauseType::LoadLibraryAsStream),
|
||||||
|
("$push_load_context", 2) => Some(SystemClauseType::REPL(REPLCodePtr::PushLoadContext)),
|
||||||
|
("$pop_load_state_payload", 1) => Some(SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload)),
|
||||||
|
("$pop_load_context", 0) => Some(SystemClauseType::REPL(REPLCodePtr::PopLoadContext)),
|
||||||
|
("$prolog_lc_source", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextSource)),
|
||||||
|
("$prolog_lc_file", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextFile)),
|
||||||
|
("$prolog_lc_dir", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory)),
|
||||||
|
("$prolog_lc_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextModule)),
|
||||||
|
("$prolog_lc_stream", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextStream)),
|
||||||
|
("$cpp_meta_predicate_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)),
|
||||||
|
("$compile_pending_predicates", 1) => Some(SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -754,7 +798,6 @@ pub enum BuiltInClauseType {
|
|||||||
pub enum ClauseType {
|
pub enum ClauseType {
|
||||||
BuiltIn(BuiltInClauseType),
|
BuiltIn(BuiltInClauseType),
|
||||||
CallN,
|
CallN,
|
||||||
Hook(CompileTimeHook),
|
|
||||||
Inlined(InlinedClauseType),
|
Inlined(InlinedClauseType),
|
||||||
Named(ClauseName, usize, CodeIndex), // name, arity, index.
|
Named(ClauseName, usize, CodeIndex), // name, arity, index.
|
||||||
Op(ClauseName, SharedOpDesc, CodeIndex),
|
Op(ClauseName, SharedOpDesc, CodeIndex),
|
||||||
@@ -818,7 +861,6 @@ impl ClauseType {
|
|||||||
match self {
|
match self {
|
||||||
&ClauseType::BuiltIn(ref built_in) => built_in.name(),
|
&ClauseType::BuiltIn(ref built_in) => built_in.name(),
|
||||||
&ClauseType::CallN => clause_name!("call"),
|
&ClauseType::CallN => clause_name!("call"),
|
||||||
&ClauseType::Hook(ref hook) => hook.name(),
|
|
||||||
&ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
|
&ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
|
||||||
&ClauseType::Op(ref name, ..) => name.clone(),
|
&ClauseType::Op(ref name, ..) => name.clone(),
|
||||||
&ClauseType::Named(ref name, ..) => name.clone(),
|
&ClauseType::Named(ref name, ..) => name.clone(),
|
||||||
|
|||||||
280
src/codegen.rs
280
src/codegen.rs
@@ -1,5 +1,6 @@
|
|||||||
/// Code generation to WAM-like instructions.
|
/// Code generation to WAM-like instructions.
|
||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::*;
|
||||||
|
use crate::prolog_parser::tabled_rc::TabledData;
|
||||||
|
|
||||||
use crate::allocator::*;
|
use crate::allocator::*;
|
||||||
use crate::arithmetic::*;
|
use crate::arithmetic::*;
|
||||||
@@ -9,20 +10,32 @@ use crate::forms::*;
|
|||||||
use crate::indexing::*;
|
use crate::indexing::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::iterators::*;
|
use crate::iterators::*;
|
||||||
use crate::machine::machine_indices::*;
|
|
||||||
use crate::targets::*;
|
use crate::targets::*;
|
||||||
|
|
||||||
|
use crate::machine::machine_errors::*;
|
||||||
|
|
||||||
use crate::indexmap::{IndexMap, IndexSet};
|
use crate::indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::collections::VecDeque;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::vec::Vec;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[inline]
|
||||||
pub struct CodeGenerator<TermMarker> {
|
pub fn trust_me(non_counted_bt: bool) -> ChoiceInstruction {
|
||||||
marker: TermMarker,
|
if non_counted_bt {
|
||||||
pub var_count: IndexMap<Rc<Var>, usize>,
|
ChoiceInstruction::DefaultTrustMe(0)
|
||||||
non_counted_bt: bool,
|
} else {
|
||||||
|
ChoiceInstruction::TrustMe(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn retry_me_else(offset: usize, non_counted_bt: bool) -> ChoiceInstruction {
|
||||||
|
if non_counted_bt {
|
||||||
|
ChoiceInstruction::DefaultRetryMeElse(offset)
|
||||||
|
} else {
|
||||||
|
ChoiceInstruction::RetryMeElse(offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -97,17 +110,46 @@ impl<'a> ConjunctInfo<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub fn new(non_counted_bt: bool) -> Self {
|
pub struct CodeGenSettings {
|
||||||
CodeGenerator {
|
pub is_extensible: bool,
|
||||||
marker: Allocator::new(),
|
pub non_counted_bt: bool,
|
||||||
var_count: IndexMap::new(),
|
}
|
||||||
|
|
||||||
|
impl CodeGenSettings {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(is_extensible: bool, non_counted_bt: bool) -> Self {
|
||||||
|
CodeGenSettings {
|
||||||
|
is_extensible,
|
||||||
non_counted_bt,
|
non_counted_bt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn take_vars(self) -> AllocVarDict {
|
#[derive(Debug)]
|
||||||
self.marker.take_bindings()
|
pub struct CodeGenerator<TermMarker> {
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
marker: TermMarker,
|
||||||
|
pub var_count: IndexMap<Rc<Var>, usize>,
|
||||||
|
non_counted_bt: bool,
|
||||||
|
is_extensible: bool,
|
||||||
|
pub skeleton: PredicateSkeleton,
|
||||||
|
pub jmp_by_locs: Vec<usize>,
|
||||||
|
global_jmp_by_locs_offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
||||||
|
pub fn new(atom_tbl: TabledData<Atom>, settings: CodeGenSettings) -> Self {
|
||||||
|
CodeGenerator {
|
||||||
|
atom_tbl,
|
||||||
|
marker: Allocator::new(),
|
||||||
|
var_count: IndexMap::new(),
|
||||||
|
non_counted_bt: settings.non_counted_bt,
|
||||||
|
is_extensible: settings.is_extensible,
|
||||||
|
skeleton: PredicateSkeleton::new(),
|
||||||
|
jmp_by_locs: vec![],
|
||||||
|
global_jmp_by_locs_offset: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_var_count<Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
|
fn update_var_count<Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
|
||||||
@@ -337,16 +379,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
|
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) {
|
fn add_conditional_call(&mut self, code: &mut Code, qt: &QueryTerm, pvs: usize) {
|
||||||
match qt {
|
match qt {
|
||||||
&QueryTerm::Jump(ref vars) => code.push(jmp_call!(vars.len(), 0, pvs)),
|
&QueryTerm::Jump(ref vars) => {
|
||||||
|
self.jmp_by_locs.push(code.len());
|
||||||
|
code.push(jmp_call!(vars.len(), 0, pvs));
|
||||||
|
}
|
||||||
&QueryTerm::Clause(_, ref ct, ref terms, true) => {
|
&QueryTerm::Clause(_, ref ct, ref terms, true) => {
|
||||||
code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs))
|
code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs));
|
||||||
}
|
}
|
||||||
&QueryTerm::Clause(_, ref ct, ref terms, false) => {
|
&QueryTerm::Clause(_, ref ct, ref terms, false) => {
|
||||||
code.push(call_clause!(ct.clone(), terms.len(), pvs))
|
code.push(call_clause!(ct.clone(), terms.len(), pvs));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,16 +402,22 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
match code.last_mut() {
|
match code.last_mut() {
|
||||||
Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
|
Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
|
||||||
&mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
|
&mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
|
||||||
*last_call = true
|
*last_call = true;
|
||||||
}
|
}
|
||||||
&mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => {
|
&mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => {
|
||||||
*last_call = true
|
*last_call = true;
|
||||||
|
}
|
||||||
|
&mut ControlInstruction::Proceed => {
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
dealloc_index += 1;
|
||||||
}
|
}
|
||||||
&mut ControlInstruction::Proceed => {}
|
|
||||||
_ => dealloc_index += 1,
|
|
||||||
},
|
},
|
||||||
Some(&mut Line::Cut(CutInstruction::Cut(_))) => dealloc_index += 1,
|
Some(&mut Line::Cut(CutInstruction::Cut(_))) => {
|
||||||
_ => {}
|
dealloc_index += 1;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dealloc_index
|
dealloc_index
|
||||||
@@ -377,7 +429,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
terms: &'a Vec<Box<Term>>,
|
terms: &'a Vec<Box<Term>>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
) -> Result<(), ParserError> {
|
) -> Result<(), CompilationError> {
|
||||||
match ct {
|
match ct {
|
||||||
&InlinedClauseType::CompareNumber(cmp, ..) => {
|
&InlinedClauseType::CompareNumber(cmp, ..) => {
|
||||||
self.marker.reset_arg(2);
|
self.marker.reset_arg(2);
|
||||||
@@ -553,7 +605,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
use_default_call_policy: bool,
|
use_default_call_policy: bool,
|
||||||
) -> Result<(), ParserError> {
|
) -> Result<(), CompilationError> {
|
||||||
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
|
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
|
||||||
code.append(&mut acode);
|
code.append(&mut acode);
|
||||||
|
|
||||||
@@ -656,7 +708,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
conjunct_info: &ConjunctInfo<'a>,
|
conjunct_info: &ConjunctInfo<'a>,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
is_exposed: bool,
|
is_exposed: bool,
|
||||||
) -> Result<(), ParserError> {
|
) -> Result<(), CompilationError> {
|
||||||
for (chunk_num, _, terms) in iter.rule_body_iter() {
|
for (chunk_num, _, terms) in iter.rule_body_iter() {
|
||||||
for (i, term) in terms.iter().enumerate() {
|
for (i, term) in terms.iter().enumerate() {
|
||||||
let term_loc = if i + 1 < terms.len() {
|
let term_loc = if i + 1 < terms.len() {
|
||||||
@@ -669,18 +721,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
|
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
|
||||||
self.compile_get_level_and_unify(code, cell, var.clone(), term_loc)
|
self.compile_get_level_and_unify(code, cell, var.clone(), term_loc)
|
||||||
}
|
}
|
||||||
&QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
|
&QueryTerm::UnblockedCut(ref cell) => {
|
||||||
&QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
|
self.compile_unblocked_cut(code, cell)
|
||||||
Line::Cut(CutInstruction::NeckCut)
|
}
|
||||||
} else {
|
&QueryTerm::BlockedCut => {
|
||||||
Line::Cut(CutInstruction::Cut(perm_v!(1)))
|
code.push(if chunk_num == 0 {
|
||||||
}),
|
Line::Cut(CutInstruction::NeckCut)
|
||||||
|
} else {
|
||||||
|
Line::Cut(CutInstruction::Cut(perm_v!(1)))
|
||||||
|
})
|
||||||
|
}
|
||||||
&QueryTerm::Clause(
|
&QueryTerm::Clause(
|
||||||
_,
|
_,
|
||||||
ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
|
ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
|
||||||
ref terms,
|
ref terms,
|
||||||
use_default_call_policy,
|
use_default_call_policy,
|
||||||
) => self.compile_is_call(terms, code, term_loc, use_default_call_policy)?,
|
) => {
|
||||||
|
self.compile_is_call(terms, code, term_loc, use_default_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, code)?
|
self.compile_inlined(ct, terms, term_loc, code)?
|
||||||
}
|
}
|
||||||
@@ -714,7 +772,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) {
|
fn compile_cleanup(&mut self, code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) {
|
||||||
// add a proceed to bookend any trailing cuts.
|
// add a proceed to bookend any trailing cuts.
|
||||||
match toc {
|
match toc {
|
||||||
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
|
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
|
||||||
@@ -726,11 +784,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
let dealloc_index = Self::lco(code);
|
let dealloc_index = Self::lco(code);
|
||||||
|
|
||||||
if conjunct_info.allocates() {
|
if conjunct_info.allocates() {
|
||||||
|
let offset = self.global_jmp_by_locs_offset;
|
||||||
|
|
||||||
|
if let Some(jmp_by_offset) = self.jmp_by_locs[offset ..].last_mut() {
|
||||||
|
if *jmp_by_offset == dealloc_index {
|
||||||
|
*jmp_by_offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
|
code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, ParserError> {
|
pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, CompilationError> {
|
||||||
let iter = ChunkedIterator::from_rule(rule);
|
let iter = ChunkedIterator::from_rule(rule);
|
||||||
let conjunct_info = self.collect_var_data(iter);
|
let conjunct_info = self.collect_var_data(iter);
|
||||||
|
|
||||||
@@ -739,7 +805,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
ref clauses,
|
ref clauses,
|
||||||
} = rule;
|
} = rule;
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Code::new();
|
||||||
|
|
||||||
self.marker.reset_at_head(args);
|
self.marker.reset_at_head(args);
|
||||||
self.compile_seq_prelude(&conjunct_info, &mut code);
|
self.compile_seq_prelude(&conjunct_info, &mut code);
|
||||||
@@ -761,8 +827,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
self.compile_seq(iter, &conjunct_info, &mut code, false)?;
|
self.compile_seq(iter, &conjunct_info, &mut code, false)?;
|
||||||
|
|
||||||
conjunct_info.mark_unsafe_vars(unsafe_var_marker, &mut code);
|
conjunct_info.mark_unsafe_vars(unsafe_var_marker, &mut code);
|
||||||
|
self.compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
|
||||||
|
|
||||||
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
|
|
||||||
Ok(code)
|
Ok(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,10 +902,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::add_conditional_call(code, term, num_perm_vars_left);
|
self.add_conditional_call(code, term, num_perm_vars_left);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_query(&mut self, query: &'a Vec<QueryTerm>) -> Result<Code, ParserError> {
|
/*
|
||||||
|
pub fn compile_query(&mut self, query: &'a Vec<QueryTerm>) -> Result<Code, CompilationError> {
|
||||||
let iter = ChunkedIterator::from_term_sequence(query);
|
let iter = ChunkedIterator::from_term_sequence(query);
|
||||||
let conjunct_info = self.collect_var_data(iter);
|
let conjunct_info = self.collect_var_data(iter);
|
||||||
|
|
||||||
@@ -857,6 +924,16 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
|
|
||||||
Ok(code)
|
Ok(code)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn increment_jmp_by_locs_by(&mut self, incr: usize) {
|
||||||
|
let offset = self.global_jmp_by_locs_offset;
|
||||||
|
|
||||||
|
for loc in &mut self.jmp_by_locs[offset ..] {
|
||||||
|
*loc += incr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the index of the first instantiated argument.
|
/// Returns the index of the first instantiated argument.
|
||||||
fn first_instantiated_index(clauses: &[PredicateClause]) -> Option<usize> {
|
fn first_instantiated_index(clauses: &[PredicateClause]) -> Option<usize> {
|
||||||
@@ -925,48 +1002,50 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
subseqs
|
subseqs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trust_me(&self) -> ChoiceInstruction {
|
|
||||||
if self.non_counted_bt {
|
|
||||||
ChoiceInstruction::DefaultTrustMe
|
|
||||||
} else {
|
|
||||||
ChoiceInstruction::TrustMe
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn retry_me_else(&self, offset: usize) -> ChoiceInstruction {
|
|
||||||
if self.non_counted_bt {
|
|
||||||
ChoiceInstruction::DefaultRetryMeElse(offset)
|
|
||||||
} else {
|
|
||||||
ChoiceInstruction::RetryMeElse(offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compile_pred_subseq<'b: 'a>(
|
fn compile_pred_subseq<'b: 'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
clauses: &'b [PredicateClause],
|
clauses: &'b [PredicateClause],
|
||||||
optimal_index: usize,
|
optimal_index: usize,
|
||||||
) -> Result<Code, ParserError> {
|
) -> Result<Code, CompilationError> {
|
||||||
let mut code_body = Vec::new();
|
let mut code = VecDeque::new();
|
||||||
let mut code_offsets = CodeOffsets::new();
|
let mut code_offsets = CodeOffsets::new(self.atom_tbl.clone(), optimal_index + 1);
|
||||||
|
let mut skip_stub_try_me_else = false;
|
||||||
|
|
||||||
let num_clauses = clauses.len();
|
let jmp_by_locs_len = self.jmp_by_locs.len();
|
||||||
|
|
||||||
for (i, clause) in clauses.iter().enumerate() {
|
for (i, clause) in clauses.iter().enumerate() {
|
||||||
self.marker.reset();
|
self.marker.reset();
|
||||||
|
|
||||||
let mut clause_code = match *clause {
|
let mut clause_index_info = ClauseIndexInfo::new(code.len());
|
||||||
PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
|
self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
|
||||||
PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
|
|
||||||
|
let clause_code = match clause {
|
||||||
|
&PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
|
||||||
|
&PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
if num_clauses > 1 {
|
if clauses.len() > 1 {
|
||||||
let choice = match i {
|
let choice = match i {
|
||||||
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
|
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
|
||||||
_ if i == num_clauses - 1 => self.trust_me(),
|
_ if i == clauses.len() - 1 => trust_me(self.non_counted_bt),
|
||||||
_ => self.retry_me_else(clause_code.len() + 1),
|
_ => retry_me_else(clause_code.len() + 1, self.non_counted_bt),
|
||||||
};
|
};
|
||||||
|
|
||||||
code_body.push(Line::Choice(choice));
|
code.push_back(Line::Choice(choice));
|
||||||
|
} else if self.is_extensible {
|
||||||
|
/*
|
||||||
|
generate stub choice instructions for extensible
|
||||||
|
predicates. if predicates are added to either the
|
||||||
|
inner or outer thread of choice instructions,
|
||||||
|
these stubs will be used, and surrounding indexing
|
||||||
|
instructions modified accordingly.
|
||||||
|
|
||||||
|
until then, the v offset of SwitchOnTerm will skip
|
||||||
|
over them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code.push_front(Line::Choice(ChoiceInstruction::TryMeElse(0)));
|
||||||
|
skip_stub_try_me_else = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg = match clause.args() {
|
let arg = match clause.args() {
|
||||||
@@ -976,47 +1055,86 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(arg) = arg {
|
if let Some(arg) = arg {
|
||||||
let index = code_body.len();
|
let index = code.len();
|
||||||
code_offsets.index_term(arg, index);
|
code_offsets.index_term(arg, index, &mut clause_index_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
code_body.append(&mut clause_code);
|
if !skip_stub_try_me_else {
|
||||||
|
self.increment_jmp_by_locs_by(code.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.skeleton.clauses.push_back(clause_index_info);
|
||||||
|
code.extend(clause_code.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let index_code = code_offsets.compute_indices(skip_stub_try_me_else);
|
||||||
code_offsets.add_indices(&mut code, code_body, optimal_index + 1);
|
self.global_jmp_by_locs_offset = jmp_by_locs_len;
|
||||||
|
|
||||||
Ok(code)
|
if !index_code.is_empty() {
|
||||||
|
code.push_front(Line::IndexingCode(index_code));
|
||||||
|
|
||||||
|
if skip_stub_try_me_else {
|
||||||
|
// skip the TryMeElse(0) also.
|
||||||
|
self.increment_jmp_by_locs_by(2);
|
||||||
|
} else {
|
||||||
|
self.increment_jmp_by_locs_by(1);
|
||||||
|
}
|
||||||
|
} else if skip_stub_try_me_else {
|
||||||
|
// remove the TryMeElse(0).
|
||||||
|
code.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Vec::from(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_predicate<'b: 'a>(
|
pub fn compile_predicate<'b: 'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
clauses: &'b Vec<PredicateClause>,
|
clauses: &'b Vec<PredicateClause>,
|
||||||
) -> Result<Code, ParserError> {
|
) -> Result<Code, CompilationError> {
|
||||||
let mut code = Vec::new();
|
let mut code = Code::new();
|
||||||
|
|
||||||
let optimal_index = match Self::first_instantiated_index(&clauses) {
|
let optimal_index = match Self::first_instantiated_index(&clauses) {
|
||||||
Some(index) => index,
|
Some(index) => index,
|
||||||
None => 0, // Default to first argument indexing.
|
None => 0, // Default to first argument indexing.
|
||||||
};
|
};
|
||||||
|
|
||||||
let split_pred = Self::split_predicate(&clauses, optimal_index);
|
let split_pred = Self::split_predicate(&clauses, optimal_index);
|
||||||
let multi_seq = split_pred.len() > 1;
|
let multi_seq = split_pred.len() > 1;
|
||||||
|
|
||||||
for (l, r) in split_pred {
|
for (l, r) in split_pred {
|
||||||
let mut code_segment =
|
let skel_lower_bound = self.skeleton.clauses.len();
|
||||||
self.compile_pred_subseq(&clauses[l..r], optimal_index)?;
|
let code_segment = self.compile_pred_subseq(&clauses[l .. r], optimal_index)?;
|
||||||
|
let clause_start_offset = code.len();
|
||||||
|
|
||||||
if multi_seq {
|
if multi_seq {
|
||||||
let choice = match l {
|
let choice = match l {
|
||||||
0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1),
|
0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1),
|
||||||
_ if r == clauses.len() => self.trust_me(),
|
_ if r == clauses.len() => trust_me(self.non_counted_bt),
|
||||||
_ => self.retry_me_else(code_segment.len() + 1),
|
_ => retry_me_else(code_segment.len() + 1, self.non_counted_bt),
|
||||||
};
|
};
|
||||||
|
|
||||||
code.push(Line::Choice(choice));
|
code.push(Line::Choice(choice));
|
||||||
|
} else if self.is_extensible {
|
||||||
|
code.push(Line::Choice(ChoiceInstruction::TryMeElse(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
code.append(&mut code_segment);
|
if self.is_extensible {
|
||||||
|
let segment_is_indexed = to_indexing_line(&code_segment[0]).is_some();
|
||||||
|
|
||||||
|
for clause_index_info in self.skeleton.clauses[skel_lower_bound ..].iter_mut() {
|
||||||
|
clause_index_info.clause_start +=
|
||||||
|
clause_start_offset + 2 * (segment_is_indexed as usize);
|
||||||
|
clause_index_info.opt_arg_index_key +=
|
||||||
|
clause_start_offset + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.increment_jmp_by_locs_by(code.len());
|
||||||
|
self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
|
||||||
|
|
||||||
|
code.extend(code_segment.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(code)
|
Ok(code)
|
||||||
|
|||||||
483
src/forms.rs
483
src/forms.rs
@@ -1,6 +1,5 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::*;
|
||||||
use crate::prolog_parser::parser::OpDesc;
|
use crate::prolog_parser::parser::OpDesc;
|
||||||
use crate::prolog_parser::tabled_rc::*;
|
|
||||||
|
|
||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::machine::machine_errors::*;
|
use crate::machine::machine_errors::*;
|
||||||
@@ -8,15 +7,19 @@ use crate::machine::machine_indices::*;
|
|||||||
use crate::ordered_float::OrderedFloat;
|
use crate::ordered_float::OrderedFloat;
|
||||||
use crate::rug::{Integer, Rational};
|
use crate::rug::{Integer, Rational};
|
||||||
|
|
||||||
use crate::indexmap::IndexMap;
|
use crate::indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
|
use slice_deque::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::ops::AddAssign;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub type PredicateKey = (ClauseName, usize); // name, arity.
|
pub type PredicateKey = (ClauseName, usize); // name, arity.
|
||||||
|
|
||||||
|
pub type Predicate = Vec<PredicateClause>;
|
||||||
|
|
||||||
// vars of predicate, toplevel offset. Vec<Term> is always a vector
|
// vars of predicate, toplevel offset. Vec<Term> is always a vector
|
||||||
// of vars (we get their adjoining cells this way).
|
// of vars (we get their adjoining cells this way).
|
||||||
pub type JumpStub = Vec<Term>;
|
pub type JumpStub = Vec<Term>;
|
||||||
@@ -24,19 +27,24 @@ pub type JumpStub = Vec<Term>;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TopLevel {
|
pub enum TopLevel {
|
||||||
Declaration(Declaration),
|
Declaration(Declaration),
|
||||||
Fact(Term, usize, usize), // Term, line_num, col_num
|
Fact(Term), // Term, line_num, col_num
|
||||||
Predicate(Predicate),
|
Predicate(Predicate),
|
||||||
Query(Vec<QueryTerm>),
|
Query(Vec<QueryTerm>),
|
||||||
Rule(Rule, usize, usize), // Rule, line_num, col_num
|
Rule(Rule), // Rule, line_num, col_num
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopLevel {
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub fn is_end_of_file_atom(&self) -> bool {
|
pub enum AppendOrPrepend {
|
||||||
|
Append,
|
||||||
|
Prepend
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppendOrPrepend {
|
||||||
|
#[inline]
|
||||||
|
pub fn is_append(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _)), ..) => {
|
AppendOrPrepend::Append => true,
|
||||||
return name.as_str() == "end_of_file"
|
AppendOrPrepend::Prepend => false,
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,30 +99,9 @@ pub struct Rule {
|
|||||||
pub clauses: Vec<QueryTerm>,
|
pub clauses: Vec<QueryTerm>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug, Hash)]
|
||||||
pub struct Predicate(pub Vec<PredicateClause>);
|
|
||||||
|
|
||||||
impl Predicate {
|
|
||||||
#[inline]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Predicate(vec![])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn clauses(self) -> Vec<PredicateClause> {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> {
|
|
||||||
self.0
|
|
||||||
.first()
|
|
||||||
.and_then(|clause| clause.name().map(|name| (name, clause.arity())))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ListingSource {
|
pub enum ListingSource {
|
||||||
|
DynamicallyGenerated,
|
||||||
File(ClauseName, PathBuf), // filename, path
|
File(ClauseName, PathBuf), // filename, path
|
||||||
User,
|
User,
|
||||||
}
|
}
|
||||||
@@ -123,98 +110,13 @@ impl ListingSource {
|
|||||||
pub fn from_file_and_path(filename: ClauseName, path_buf: PathBuf) -> Self {
|
pub fn from_file_and_path(filename: ClauseName, path_buf: PathBuf) -> Self {
|
||||||
ListingSource::File(filename, path_buf)
|
ListingSource::File(filename, path_buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> ClauseName {
|
|
||||||
match self {
|
|
||||||
ListingSource::File(ref filename, _) => filename.clone(),
|
|
||||||
ListingSource::User => clause_name!("[user]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path(&self) -> PathBuf {
|
|
||||||
match self {
|
|
||||||
ListingSource::File(_, ref path) => path.clone(),
|
|
||||||
ListingSource::User => std::env::current_dir().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolved_term_and_module(term: &Term) -> Option<(ClauseName, ClauseName)>
|
pub trait ClauseInfo {
|
||||||
{
|
|
||||||
match term {
|
|
||||||
Term::Clause(_, ref name, ref terms, _) => {
|
|
||||||
if name.as_str() == ":" && terms.len() == 2 {
|
|
||||||
let module_name = match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::Atom(ref module_name, _)) => {
|
|
||||||
module_name.clone()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Some((name.owning_module(), name.clone()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match terms[1].as_ref() {
|
|
||||||
Term::Clause(_, ref name, ..)
|
|
||||||
| Term::Constant(_, Constant::Atom(ref name, ..)) => {
|
|
||||||
return Some((module_name, name.clone()));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((name.owning_module(), name.clone()))
|
|
||||||
} else {
|
|
||||||
Some((name.owning_module(), name.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Term::Constant(_, Constant::Atom(ref name, _)) => {
|
|
||||||
Some((name.owning_module(), name.clone()))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolved_term_arity(term: &Term) -> usize
|
|
||||||
{
|
|
||||||
match term {
|
|
||||||
Term::Clause(_, ref name, ref terms, _) => {
|
|
||||||
if name.as_str() == ":" && terms.len() == 2 {
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::Atom(..)) => {
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match terms[1].as_ref() {
|
|
||||||
Term::Clause(_, _, ref terms, _) => {
|
|
||||||
terms.len()
|
|
||||||
}
|
|
||||||
Term::Constant(_, Constant::Atom(..)) => {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
terms.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ClauseConsistency {
|
|
||||||
fn is_consistent(&self, clauses: &Vec<PredicateClause>) -> bool {
|
fn is_consistent(&self, clauses: &Vec<PredicateClause>) -> bool {
|
||||||
match clauses.first() {
|
match clauses.first() {
|
||||||
Some(ref cl) => {
|
Some(cl) => {
|
||||||
self.name_and_module() == cl.name_and_module() && self.arity() == cl.arity()
|
self.name() == cl.name() && self.arity() == cl.arity()
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
true
|
true
|
||||||
@@ -222,33 +124,29 @@ pub trait ClauseConsistency {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_and_module(&self) -> Option<(ClauseName, ClauseName)>;
|
fn name(&self) -> Option<ClauseName>;
|
||||||
fn arity(&self) -> usize;
|
fn arity(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Of course '$current_module$' isn't the name of the current
|
impl ClauseInfo for Term {
|
||||||
* module. It'll do if no module is explicitly specified through
|
fn name(&self) -> Option<ClauseName> {
|
||||||
* (:)/2.
|
|
||||||
*/
|
|
||||||
impl ClauseConsistency for Term {
|
|
||||||
fn name_and_module(&self) -> Option<(ClauseName, ClauseName)>
|
|
||||||
{
|
|
||||||
match self {
|
match self {
|
||||||
Term::Clause(_, ref name, ref terms, _) =>
|
Term::Clause(_, ref name, ref terms, _) => {
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
":-" => {
|
":-" => {
|
||||||
match terms.len() {
|
match terms.len() {
|
||||||
1 => None, // a declaration.
|
1 => None, // a declaration.
|
||||||
2 => resolved_term_and_module(&terms[0]),
|
2 => terms[0].name(),
|
||||||
_ => Some((name.owning_module(), clause_name!(":-"))),
|
_ => Some(clause_name!(":-")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
resolved_term_and_module(self)
|
Some(name.clone())
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Term::Constant(_, Constant::Atom(ref name, _)) => {
|
Term::Constant(_, Constant::Atom(ref name, _)) => {
|
||||||
Some((name.owning_module(), name.clone()))
|
Some(name.clone())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
None
|
None
|
||||||
@@ -263,12 +161,12 @@ impl ClauseConsistency for Term {
|
|||||||
":-" => {
|
":-" => {
|
||||||
match terms.len() {
|
match terms.len() {
|
||||||
1 => 0,
|
1 => 0,
|
||||||
2 => resolved_term_arity(&terms[0]),
|
2 => terms[0].arity(),
|
||||||
_ => terms.len(),
|
_ => terms.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
resolved_term_arity(self)
|
terms.len()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@@ -278,9 +176,9 @@ impl ClauseConsistency for Term {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClauseConsistency for Rule {
|
impl ClauseInfo for Rule {
|
||||||
fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
|
fn name(&self) -> Option<ClauseName> {
|
||||||
Some((self.head.0.owning_module(), self.head.0.clone()))
|
Some(self.head.0.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arity(&self) -> usize {
|
fn arity(&self) -> usize {
|
||||||
@@ -288,15 +186,14 @@ impl ClauseConsistency for Rule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClauseConsistency for PredicateClause {
|
impl ClauseInfo for PredicateClause {
|
||||||
fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
|
fn name(&self) -> Option<ClauseName> {
|
||||||
match self {
|
match self {
|
||||||
&PredicateClause::Fact(ref term, ..) => {
|
&PredicateClause::Fact(ref term, ..) => {
|
||||||
term.name_and_module()
|
term.name()
|
||||||
.map(|(_, name)| (name.owning_module(), name))
|
|
||||||
}
|
}
|
||||||
&PredicateClause::Rule(ref rule, ..) => {
|
&PredicateClause::Rule(ref rule, ..) => {
|
||||||
rule.name_and_module()
|
rule.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,22 +210,12 @@ impl ClauseConsistency for PredicateClause {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClauseConsistency for Predicate {
|
// pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
|
||||||
fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
|
|
||||||
self.0.first().and_then(|clause| clause.name_and_module())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arity(&self) -> usize {
|
|
||||||
self.0.first().map(|clause| clause.arity()).unwrap_or(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum PredicateClause {
|
pub enum PredicateClause {
|
||||||
Fact(Term, usize, usize), // Term, line number, column number.
|
Fact(Term),
|
||||||
Rule(Rule, usize, usize), // Term, line number, column number.
|
Rule(Rule),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PredicateClause {
|
impl PredicateClause {
|
||||||
@@ -395,66 +282,61 @@ impl ModuleSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator.
|
// pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator.
|
||||||
|
|
||||||
|
/*
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MultiFileIndicator {
|
pub enum MultiFileIndicator {
|
||||||
LocalScoped(ClauseName, usize), // name, arity
|
LocalScoped(ClauseName, usize), // name, arity
|
||||||
ModuleScoped(ScopedPredicateKey),
|
ModuleScoped(ScopedPredicateKey),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Hash, Debug)]
|
||||||
|
pub enum MetaSpec {
|
||||||
|
Minus,
|
||||||
|
Plus,
|
||||||
|
Either,
|
||||||
|
RequiresExpansion,
|
||||||
|
RequiresExpansionWithArgument(usize),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Declaration {
|
pub enum Declaration {
|
||||||
Dynamic(ClauseName, usize), // name, arity
|
Dynamic(ClauseName, usize),
|
||||||
EndOfFile,
|
MetaPredicate(ClauseName, ClauseName, Vec<MetaSpec>), // module name, name, meta-specs
|
||||||
Hook(CompileTimeHook, PredicateClause, VecDeque<TopLevel>),
|
|
||||||
ModuleInitialization(Vec<QueryTerm>, VecDeque<TopLevel>), // goal
|
|
||||||
Module(ModuleDecl),
|
Module(ModuleDecl),
|
||||||
MultiFile(MultiFileIndicator),
|
|
||||||
NonCountedBacktracking(ClauseName, usize), // name, arity
|
NonCountedBacktracking(ClauseName, usize), // name, arity
|
||||||
Op(OpDecl),
|
Op(OpDecl),
|
||||||
SetPrologFlag(DoubleQuotes),
|
|
||||||
UseModule(ModuleSource),
|
UseModule(ModuleSource),
|
||||||
UseQualifiedModule(ModuleSource, Vec<ModuleExport>),
|
UseQualifiedModule(ModuleSource, IndexSet<ModuleExport>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Declaration {
|
#[derive(Debug, Clone, Eq, Hash, PartialEq, Ord, PartialOrd)]
|
||||||
#[inline]
|
pub struct OpDecl {
|
||||||
pub fn is_module_decl(&self) -> bool {
|
pub prec: usize,
|
||||||
if let &Declaration::Module(_) = self {
|
pub spec: Specifier,
|
||||||
true
|
pub name: ClauseName
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn is_end_of_file(&self) -> bool {
|
|
||||||
if let &Declaration::EndOfFile = self {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
|
|
||||||
|
|
||||||
impl OpDecl {
|
impl OpDecl {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn name(&self) -> ClauseName {
|
pub fn new(prec: usize, spec: Specifier, name: ClauseName) -> Self {
|
||||||
self.2.clone()
|
Self { prec, spec, name }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn remove(&self, op_dir: &mut OpDir) {
|
pub fn remove(&mut self, op_dir: &mut OpDir) {
|
||||||
self.insert_into_op_dir(clause_name!(""), op_dir, 0);
|
let prec = self.prec;
|
||||||
|
self.prec = 0;
|
||||||
|
|
||||||
|
self.insert_into_op_dir(op_dir);
|
||||||
|
self.prec = prec;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fixity(&self) -> Fixity {
|
pub fn fixity(&self) -> Fixity {
|
||||||
match self.1 {
|
match self.spec {
|
||||||
XFY | XFX | YFX => Fixity::In,
|
XFY | XFX | YFX => Fixity::In,
|
||||||
XF | YF => Fixity::Post,
|
XF | YF => Fixity::Post,
|
||||||
FX | FY => Fixity::Pre,
|
FX | FY => Fixity::Pre,
|
||||||
@@ -462,29 +344,27 @@ impl OpDecl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) {
|
pub fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<(usize, Specifier)> {
|
||||||
let (spec, name) = (self.1, self.2.clone());
|
let key = (self.name.clone(), self.fixity());
|
||||||
|
|
||||||
let fixity = self.fixity();
|
match op_dir.get(&key) {
|
||||||
|
|
||||||
match op_dir.get(&(name.clone(), fixity)) {
|
|
||||||
Some(cell) => {
|
Some(cell) => {
|
||||||
cell.shared_op_desc().set(prec, spec);
|
return Some(cell.shared_op_desc().replace((self.prec, self.spec)));
|
||||||
return;
|
}
|
||||||
|
None => {
|
||||||
}
|
}
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
op_dir.insert((name, fixity), OpDirValue::new(spec, prec, module));
|
op_dir.insert(key, OpDirValue::new(self.spec, self.prec))
|
||||||
|
.map(|op_dir_value| op_dir_value.shared_op_desc().get())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submit(
|
pub fn submit(
|
||||||
&self,
|
&self,
|
||||||
module: ClauseName,
|
|
||||||
existing_desc: Option<OpDesc>,
|
existing_desc: Option<OpDesc>,
|
||||||
op_dir: &mut OpDir,
|
op_dir: &mut OpDir,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
let (prec, spec, name) = (self.0, self.1, self.2.clone());
|
let (spec, name) = (self.spec, self.name.clone());
|
||||||
|
|
||||||
if is_infix!(spec) {
|
if is_infix!(spec) {
|
||||||
if let Some(desc) = existing_desc {
|
if let Some(desc) = existing_desc {
|
||||||
@@ -502,7 +382,8 @@ impl OpDecl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.insert_into_op_dir(module, op_dir, prec))
|
self.insert_into_op_dir(op_dir);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,7 +422,7 @@ pub fn fetch_op_spec(
|
|||||||
match arity {
|
match arity {
|
||||||
2 => op_dir
|
2 => op_dir
|
||||||
.get(&(name, Fixity::In))
|
.get(&(name, Fixity::In))
|
||||||
.and_then(|OpDirValue(spec, _)| {
|
.and_then(|OpDirValue(spec)| {
|
||||||
if spec.prec() > 0 {
|
if spec.prec() > 0 {
|
||||||
Some(spec.clone())
|
Some(spec.clone())
|
||||||
} else {
|
} else {
|
||||||
@@ -549,15 +430,15 @@ pub fn fetch_op_spec(
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
1 => {
|
1 => {
|
||||||
if let Some(OpDirValue(spec, _)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
|
if let Some(OpDirValue(spec)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
|
||||||
if spec.prec() > 0 {
|
if spec.prec() > 0 {
|
||||||
return Some(spec.clone());
|
return Some(spec.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op_dir
|
op_dir
|
||||||
.get(&(name, Fixity::Post))
|
.get(&(name.clone(), Fixity::Post))
|
||||||
.and_then(|OpDirValue(spec, _)| {
|
.and_then(|OpDirValue(spec)| {
|
||||||
if spec.prec() > 0 {
|
if spec.prec() > 0 {
|
||||||
Some(spec.clone())
|
Some(spec.clone())
|
||||||
} else {
|
} else {
|
||||||
@@ -573,7 +454,7 @@ pub fn fetch_op_spec(
|
|||||||
|
|
||||||
pub type ModuleDir = IndexMap<ClauseName, Module>;
|
pub type ModuleDir = IndexMap<ClauseName, Module>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||||
pub enum ModuleExport {
|
pub enum ModuleExport {
|
||||||
OpDecl(OpDecl),
|
OpDecl(OpDecl),
|
||||||
PredicateKey(PredicateKey),
|
PredicateKey(PredicateKey),
|
||||||
@@ -587,21 +468,32 @@ pub struct ModuleDecl {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub atom_tbl: TabledData<Atom>,
|
|
||||||
pub module_decl: ModuleDecl,
|
pub module_decl: ModuleDecl,
|
||||||
pub code_dir: CodeDir,
|
pub code_dir: CodeDir,
|
||||||
pub op_dir: OpDir,
|
pub op_dir: OpDir,
|
||||||
pub term_dir: TermDir, // this contains multifile predicates.
|
pub meta_predicates: MetaPredicateDir,
|
||||||
pub term_expansions: (Predicate, VecDeque<TopLevel>),
|
pub extensible_predicates: IndexMap<PredicateKey, PredicateSkeleton>,
|
||||||
pub goal_expansions: (Predicate, VecDeque<TopLevel>),
|
|
||||||
pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope.
|
|
||||||
pub user_goal_expansions: (Predicate, VecDeque<TopLevel>), // same for goal_expansions.
|
|
||||||
pub local_term_expansions: (Predicate, VecDeque<TopLevel>), // expansions local to the module.
|
|
||||||
pub local_goal_expansions: (Predicate, VecDeque<TopLevel>),
|
|
||||||
pub inserted_expansions: bool, // has the module been successfully inserted into toplevel??
|
|
||||||
pub is_impromptu_module: bool,
|
pub is_impromptu_module: bool,
|
||||||
pub listing_src: ListingSource,
|
pub listing_src: ListingSource,
|
||||||
}
|
pub clause_assert_margin: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module's and related types are defined in forms.
|
||||||
|
impl Module {
|
||||||
|
pub fn new(module_decl: ModuleDecl, listing_src: ListingSource) -> Self {
|
||||||
|
Module {
|
||||||
|
module_decl,
|
||||||
|
code_dir: CodeDir::new(),
|
||||||
|
op_dir: default_op_dir(),
|
||||||
|
meta_predicates: MetaPredicateDir::new(),
|
||||||
|
is_impromptu_module: false,
|
||||||
|
extensible_predicates: IndexMap::new(),
|
||||||
|
listing_src,
|
||||||
|
clause_assert_margin: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Number {
|
pub enum Number {
|
||||||
@@ -709,3 +601,154 @@ impl Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum OptArgIndexKey {
|
||||||
|
Constant(usize, usize, Constant, Vec<Constant>), // index, IndexingCode location, opt arg, alternatives
|
||||||
|
List(usize, usize), // index, IndexingCode location
|
||||||
|
None,
|
||||||
|
Structure(usize, usize, ClauseName, usize), // index, IndexingCode location, name, arity
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptArgIndexKey {
|
||||||
|
#[inline]
|
||||||
|
pub fn take(&mut self) -> OptArgIndexKey {
|
||||||
|
std::mem::replace(self, OptArgIndexKey::None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn arg_num(&self) -> usize {
|
||||||
|
match &self {
|
||||||
|
OptArgIndexKey::Constant(arg_num, ..) |
|
||||||
|
OptArgIndexKey::Structure(arg_num, ..) |
|
||||||
|
OptArgIndexKey::List(arg_num, _) => {
|
||||||
|
// these are always at least 1.
|
||||||
|
*arg_num
|
||||||
|
}
|
||||||
|
OptArgIndexKey::None => {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_some(&self) -> bool {
|
||||||
|
self.switch_on_term_loc().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn switch_on_term_loc(&self) -> Option<usize> {
|
||||||
|
match &self {
|
||||||
|
OptArgIndexKey::Constant(_, loc, ..) |
|
||||||
|
OptArgIndexKey::Structure(_, loc, ..) |
|
||||||
|
OptArgIndexKey::List(_, loc) => {
|
||||||
|
Some(*loc)
|
||||||
|
}
|
||||||
|
OptArgIndexKey::None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_switch_on_term_loc(&mut self, value: usize) {
|
||||||
|
match self {
|
||||||
|
OptArgIndexKey::Constant(_, ref mut loc, ..) |
|
||||||
|
OptArgIndexKey::Structure(_, ref mut loc, ..) |
|
||||||
|
OptArgIndexKey::List(_, ref mut loc) => {
|
||||||
|
*loc = value;
|
||||||
|
}
|
||||||
|
OptArgIndexKey::None => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<usize> for OptArgIndexKey {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, n: usize) {
|
||||||
|
match self {
|
||||||
|
OptArgIndexKey::Constant(_, ref mut o, ..) |
|
||||||
|
OptArgIndexKey::List(_, ref mut o) |
|
||||||
|
OptArgIndexKey::Structure(_, ref mut o, ..) => {
|
||||||
|
*o += n;
|
||||||
|
}
|
||||||
|
OptArgIndexKey::None => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ClauseIndexInfo {
|
||||||
|
pub clause_start: usize,
|
||||||
|
pub opt_arg_index_key: OptArgIndexKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClauseIndexInfo {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(clause_start: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
clause_start,
|
||||||
|
opt_arg_index_key: OptArgIndexKey::None,
|
||||||
|
// index_locs: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PredicateSkeleton {
|
||||||
|
pub is_discontiguous: bool,
|
||||||
|
pub is_dynamic: bool,
|
||||||
|
pub is_multifile: bool,
|
||||||
|
pub clauses: SliceDeque<ClauseIndexInfo>,
|
||||||
|
pub clause_clause_locs: SliceDeque<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PredicateSkeleton {
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
PredicateSkeleton {
|
||||||
|
is_discontiguous: false,
|
||||||
|
is_dynamic: false,
|
||||||
|
is_multifile: false,
|
||||||
|
clauses: sdeq![],
|
||||||
|
clause_clause_locs: sdeq![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[inline]
|
||||||
|
pub fn set_discontiguous(self, is_discontiguous: bool) -> Self {
|
||||||
|
PredicateSkeleton {
|
||||||
|
is_discontiguous,
|
||||||
|
is_dynamic: self.is_dynamic,
|
||||||
|
is_multifile: self.is_multifile,
|
||||||
|
clauses: self.clauses,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_dynamic(self, is_dynamic: bool) -> Self {
|
||||||
|
PredicateSkeleton {
|
||||||
|
is_discontiguous: self.is_discontiguous,
|
||||||
|
is_dynamic,
|
||||||
|
is_multifile: self.is_multifile,
|
||||||
|
clauses: self.clauses,
|
||||||
|
clause_clause_locs: self.clause_clause_locs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[inline]
|
||||||
|
pub fn set_multifile(self, is_multifile: bool) -> Self {
|
||||||
|
PredicateSkeleton {
|
||||||
|
is_discontiguous: self.is_discontiguous,
|
||||||
|
is_dynamic: self.is_dynamic,
|
||||||
|
is_multifile,
|
||||||
|
clauses: self.clauses,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,10 +45,13 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
| HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
|
| HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
|
||||||
Addr::Con(h)
|
Addr::Con(h)
|
||||||
}
|
}
|
||||||
|
HeapCellValue::LoadStatePayload(_) => {
|
||||||
|
Addr::LoadStatePayload(h)
|
||||||
|
}
|
||||||
HeapCellValue::Stream(_) => {
|
HeapCellValue::Stream(_) => {
|
||||||
Addr::Stream(h)
|
Addr::Stream(h)
|
||||||
}
|
}
|
||||||
&HeapCellValue::TcpListener(_) => {
|
HeapCellValue::TcpListener(_) => {
|
||||||
Addr::TcpListener(h)
|
Addr::TcpListener(h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,13 +178,17 @@ impl<'a> Iterator for HCPostOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
||||||
match &self.machine_st.heap[h] {
|
match &self.machine_st.heap[h] {
|
||||||
&HeapCellValue::PartialString(ref pstr, _) => {
|
&HeapCellValue::PartialString(..) => {// ref pstr, _) => {
|
||||||
|
/*
|
||||||
let c = pstr.range_from(n ..).next().unwrap();
|
let c = pstr.range_from(n ..).next().unwrap();
|
||||||
let next_n = n + c.len_utf8();
|
let next_n = n + c.len_utf8();
|
||||||
|
|
||||||
if !pstr.at_end(next_n) {
|
if !pstr.at_end(next_n) {
|
||||||
self.parent_stack.push((2, Addr::PStrLocation(h, next_n)));
|
*/
|
||||||
}
|
// self.parent_stack.push((2, Addr::PStrLocation(h, next_n)));
|
||||||
|
// }
|
||||||
|
|
||||||
|
self.parent_stack.push((2, Addr::PStrLocation(h, n)));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|||||||
@@ -402,6 +402,7 @@ pub fn requires_space(atom: &str, op: &str) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict {
|
fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict {
|
||||||
machine_st
|
machine_st
|
||||||
.heap_locs
|
.heap_locs
|
||||||
@@ -414,6 +415,7 @@ fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict {
|
|||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn non_quoted_graphic_token<Iter: Iterator<Item = char>>(mut iter: Iter, c: char) -> bool {
|
fn non_quoted_graphic_token<Iter: Iterator<Item = char>>(mut iter: Iter, c: char) -> bool {
|
||||||
if c == '/' {
|
if c == '/' {
|
||||||
@@ -503,7 +505,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
max_depth: 0,
|
max_depth: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
pub fn from_heap_locs(
|
pub fn from_heap_locs(
|
||||||
machine_st: &'a MachineState,
|
machine_st: &'a MachineState,
|
||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
@@ -520,17 +522,20 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
printer
|
printer
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
pub fn drop_toplevel_spec(&mut self) {
|
pub fn drop_toplevel_spec(&mut self) {
|
||||||
self.toplevel_spec = None;
|
self.toplevel_spec = None;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn see_all_locs(&mut self) {
|
pub fn see_all_locs(&mut self) {
|
||||||
for key in self.heap_locs.keys().cloned() {
|
for key in self.heap_locs.keys().cloned() {
|
||||||
self.printed_vars.insert(key);
|
self.printed_vars.insert(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ambiguity_check(&self, atom: &str) -> bool {
|
fn ambiguity_check(&self, atom: &str) -> bool {
|
||||||
@@ -1024,7 +1029,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
fn print_rational(&mut self, r: &Rational, add_brackets: bool) {
|
fn print_rational(&mut self, r: &Rational, add_brackets: bool) {
|
||||||
match self.op_dir.get(&(clause_name!("rdiv"), Fixity::In)) {
|
match self.op_dir.get(&(clause_name!("rdiv"), Fixity::In)) {
|
||||||
Some(OpDirValue(ref spec, _)) => {
|
Some(OpDirValue(ref spec)) => {
|
||||||
if add_brackets {
|
if add_brackets {
|
||||||
self.state_stack.push(TokenOrRedirect::Close);
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
}
|
}
|
||||||
|
|||||||
1391
src/indexing.rs
1391
src/indexing.rs
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ use crate::prolog_parser::ast::*;
|
|||||||
|
|
||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
|
use crate::indexing::IndexingCodePtr;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
use crate::machine::machine_errors::MachineStub;
|
use crate::machine::machine_errors::MachineStub;
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
@@ -9,7 +10,8 @@ use crate::rug::Integer;
|
|||||||
|
|
||||||
use crate::indexmap::IndexMap;
|
use crate::indexmap::IndexMap;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use slice_deque::SliceDeque;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
||||||
@@ -48,9 +50,9 @@ impl ArithmeticTerm {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ChoiceInstruction {
|
pub enum ChoiceInstruction {
|
||||||
DefaultRetryMeElse(usize),
|
DefaultRetryMeElse(usize),
|
||||||
DefaultTrustMe,
|
DefaultTrustMe(usize),
|
||||||
RetryMeElse(usize),
|
RetryMeElse(usize),
|
||||||
TrustMe,
|
TrustMe(usize),
|
||||||
TryMeElse(usize),
|
TryMeElse(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,14 +65,14 @@ impl ChoiceInstruction {
|
|||||||
&ChoiceInstruction::RetryMeElse(offset) => {
|
&ChoiceInstruction::RetryMeElse(offset) => {
|
||||||
functor!("retry_me_else", [integer(offset)])
|
functor!("retry_me_else", [integer(offset)])
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::TrustMe => {
|
&ChoiceInstruction::TrustMe(offset) => {
|
||||||
functor!("trust_me")
|
functor!("trust_me", [integer(offset)])
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
||||||
functor!("default_retry_me_else", [integer(offset)])
|
functor!("default_retry_me_else", [integer(offset)])
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::DefaultTrustMe => {
|
&ChoiceInstruction::DefaultTrustMe(offset) => {
|
||||||
functor!("default_trust_me")
|
functor!("default_trust_me", [integer(offset)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,19 +108,13 @@ impl CutInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum IndexedChoiceInstruction {
|
pub enum IndexedChoiceInstruction {
|
||||||
Retry(usize),
|
Retry(usize),
|
||||||
Trust(usize),
|
Trust(usize),
|
||||||
Try(usize),
|
Try(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IndexedChoiceInstruction> for Line {
|
|
||||||
fn from(i: IndexedChoiceInstruction) -> Self {
|
|
||||||
Line::IndexedChoice(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IndexedChoiceInstruction {
|
impl IndexedChoiceInstruction {
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
@@ -144,6 +140,26 @@ impl IndexedChoiceInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A `Line` is an instruction (cf. page 98 of wambook).
|
/// A `Line` is an instruction (cf. page 98 of wambook).
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum IndexingLine {
|
||||||
|
Indexing(IndexingInstruction),
|
||||||
|
IndexedChoice(SliceDeque<IndexedChoiceInstruction>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IndexingInstruction> for IndexingLine {
|
||||||
|
#[inline]
|
||||||
|
fn from(instr: IndexingInstruction) -> Self {
|
||||||
|
IndexingLine::Indexing(instr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SliceDeque<IndexedChoiceInstruction>> for IndexingLine {
|
||||||
|
#[inline]
|
||||||
|
fn from(instrs: SliceDeque<IndexedChoiceInstruction>) -> Self {
|
||||||
|
IndexingLine::IndexedChoice(instrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Line {
|
pub enum Line {
|
||||||
Arithmetic(ArithmeticInstruction),
|
Arithmetic(ArithmeticInstruction),
|
||||||
@@ -151,12 +167,13 @@ pub enum Line {
|
|||||||
Control(ControlInstruction),
|
Control(ControlInstruction),
|
||||||
Cut(CutInstruction),
|
Cut(CutInstruction),
|
||||||
Fact(FactInstruction),
|
Fact(FactInstruction),
|
||||||
Indexing(IndexingInstruction),
|
IndexingCode(Vec<IndexingLine>),
|
||||||
IndexedChoice(IndexedChoiceInstruction),
|
IndexedChoice(IndexedChoiceInstruction),
|
||||||
Query(QueryInstruction),
|
Query(QueryInstruction),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Line {
|
impl Line {
|
||||||
|
#[inline]
|
||||||
pub fn is_head_instr(&self) -> bool {
|
pub fn is_head_instr(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Line::Cut(_) => true,
|
&Line::Cut(_) => true,
|
||||||
@@ -166,16 +183,64 @@ impl Line {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
pub fn enqueue_functors(&self, mut h: usize, functors: &mut Vec<MachineStub>) {
|
||||||
match self {
|
match self {
|
||||||
&Line::Arithmetic(ref arith_instr) => arith_instr.to_functor(h),
|
&Line::Arithmetic(ref arith_instr) =>
|
||||||
&Line::Choice(ref choice_instr) => choice_instr.to_functor(),
|
functors.push(arith_instr.to_functor(h)),
|
||||||
&Line::Control(ref control_instr) => control_instr.to_functor(),
|
&Line::Choice(ref choice_instr) =>
|
||||||
&Line::Cut(ref cut_instr) => cut_instr.to_functor(h),
|
functors.push(choice_instr.to_functor()),
|
||||||
&Line::Fact(ref fact_instr) => fact_instr.to_functor(h),
|
&Line::Control(ref control_instr) =>
|
||||||
&Line::Indexing(ref indexing_instr) => indexing_instr.to_functor(),
|
functors.push(control_instr.to_functor()),
|
||||||
&Line::IndexedChoice(ref indexed_choice_instr) => indexed_choice_instr.to_functor(),
|
&Line::Cut(ref cut_instr) =>
|
||||||
&Line::Query(ref query_instr) => query_instr.to_functor(h),
|
functors.push(cut_instr.to_functor(h)),
|
||||||
|
&Line::Fact(ref fact_instr) =>
|
||||||
|
functors.push(fact_instr.to_functor(h)),
|
||||||
|
&Line::IndexingCode(ref indexing_instrs) => {
|
||||||
|
for indexing_instr in indexing_instrs {
|
||||||
|
match indexing_instr {
|
||||||
|
IndexingLine::Indexing(indexing_instr) => {
|
||||||
|
let section = indexing_instr.to_functor(h);
|
||||||
|
h += section.len();
|
||||||
|
functors.push(section);
|
||||||
|
}
|
||||||
|
IndexingLine::IndexedChoice(indexed_choice_instrs) => {
|
||||||
|
for indexed_choice_instr in indexed_choice_instrs {
|
||||||
|
let section = indexed_choice_instr.to_functor();
|
||||||
|
h += section.len();
|
||||||
|
functors.push(section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Line::IndexedChoice(ref indexed_choice_instr) =>
|
||||||
|
functors.push(indexed_choice_instr.to_functor()),
|
||||||
|
&Line::Query(ref query_instr) =>
|
||||||
|
functors.push(query_instr.to_functor(h)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec<IndexingLine>> {
|
||||||
|
match line {
|
||||||
|
Line::IndexingCode(ref mut indexing_code) => {
|
||||||
|
Some(indexing_code)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn to_indexing_line(line: &Line) -> Option<&Vec<IndexingLine>> {
|
||||||
|
match line {
|
||||||
|
Line::IndexingCode(ref indexing_code) => {
|
||||||
|
Some(indexing_code)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,6 +451,9 @@ pub enum ControlInstruction {
|
|||||||
CallClause(ClauseType, usize, usize, bool, bool),
|
CallClause(ClauseType, usize, usize, bool, bool),
|
||||||
Deallocate,
|
Deallocate,
|
||||||
JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
|
JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
|
||||||
|
RevJmpBy(usize), // notice the lack of context change as in
|
||||||
|
// JmpBy. RevJmpBy is used only to patch extensible
|
||||||
|
// predicates together.
|
||||||
Proceed,
|
Proceed,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +486,9 @@ impl ControlInstruction {
|
|||||||
&ControlInstruction::JmpBy(_, offset, ..) => {
|
&ControlInstruction::JmpBy(_, offset, ..) => {
|
||||||
functor!("jmp_by", [integer(offset)])
|
functor!("jmp_by", [integer(offset)])
|
||||||
}
|
}
|
||||||
|
&ControlInstruction::RevJmpBy(offset) => {
|
||||||
|
functor!("rev_jmp_by", [integer(offset)])
|
||||||
|
}
|
||||||
&ControlInstruction::Proceed => {
|
&ControlInstruction::Proceed => {
|
||||||
functor!("proceed")
|
functor!("proceed")
|
||||||
}
|
}
|
||||||
@@ -429,40 +500,94 @@ impl ControlInstruction {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IndexingInstruction {
|
pub enum IndexingInstruction {
|
||||||
// The first index is the optimal argument being indexed.
|
// The first index is the optimal argument being indexed.
|
||||||
SwitchOnTerm(usize, usize, usize, usize, usize),
|
SwitchOnTerm(usize, usize, IndexingCodePtr, IndexingCodePtr, IndexingCodePtr),
|
||||||
SwitchOnConstant(usize, usize, IndexMap<Constant, usize>),
|
SwitchOnConstant(IndexMap<Constant, IndexingCodePtr>),
|
||||||
SwitchOnStructure(usize, usize, IndexMap<(ClauseName, usize), usize>),
|
SwitchOnStructure(IndexMap<(ClauseName, usize), IndexingCodePtr>),
|
||||||
}
|
|
||||||
|
|
||||||
impl From<IndexingInstruction> for Line {
|
|
||||||
fn from(i: IndexingInstruction) -> Self {
|
|
||||||
Line::Indexing(i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexingInstruction {
|
impl IndexingInstruction {
|
||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self, mut h: usize) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
|
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
|
||||||
functor!(
|
functor!(
|
||||||
"switch_on_term",
|
"switch_on_term",
|
||||||
[integer(arg),
|
[integer(arg),
|
||||||
integer(vars),
|
integer(vars),
|
||||||
integer(constants),
|
indexing_code_ptr(h, constants),
|
||||||
integer(lists),
|
indexing_code_ptr(h, lists),
|
||||||
integer(structures)]
|
indexing_code_ptr(h, structures)]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnConstant(arg, constants, _) => {
|
&IndexingInstruction::SwitchOnConstant(ref constants) => {
|
||||||
|
let mut key_value_list_stub = vec![];
|
||||||
|
let orig_h = h;
|
||||||
|
|
||||||
|
h += 2; // skip the 2-cell "switch_on_constant" functor.
|
||||||
|
|
||||||
|
for (c, ptr) in constants.iter() {
|
||||||
|
let key_value_pair = functor!(
|
||||||
|
":",
|
||||||
|
SharedOpDesc::new(600, XFY),
|
||||||
|
[constant(c),
|
||||||
|
indexing_code_ptr(h + 3, *ptr)]
|
||||||
|
);
|
||||||
|
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(Addr::Str(h + 3)));
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(
|
||||||
|
Addr::HeapCell(h + 3 + key_value_pair.len())
|
||||||
|
));
|
||||||
|
|
||||||
|
h += key_value_pair.len() + 3;
|
||||||
|
key_value_list_stub.extend(key_value_pair.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
|
||||||
functor!(
|
functor!(
|
||||||
"switch_on_constant",
|
"switch_on_constant",
|
||||||
[integer(arg), integer(constants)]
|
[aux(orig_h, 0)],
|
||||||
|
[key_value_list_stub]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(arg, structures, _) => {
|
&IndexingInstruction::SwitchOnStructure(ref structures) => {
|
||||||
|
let mut key_value_list_stub = vec![];
|
||||||
|
let orig_h = h;
|
||||||
|
|
||||||
|
h += 2; // skip the 2-cell "switch_on_constant" functor.
|
||||||
|
|
||||||
|
for ((name, arity), ptr) in structures.iter() {
|
||||||
|
let predicate_indicator_stub = functor!(
|
||||||
|
"/",
|
||||||
|
SharedOpDesc::new(400, YFX),
|
||||||
|
[clause_name(name.clone()),
|
||||||
|
integer(*arity)]
|
||||||
|
);
|
||||||
|
|
||||||
|
let key_value_pair = functor!(
|
||||||
|
":",
|
||||||
|
SharedOpDesc::new(600, XFY),
|
||||||
|
[aux(h + 3, 0),
|
||||||
|
indexing_code_ptr(h + 3, *ptr)],
|
||||||
|
[predicate_indicator_stub]
|
||||||
|
);
|
||||||
|
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(Addr::Str(h + 3)));
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(
|
||||||
|
Addr::HeapCell(h + 3 + key_value_pair.len())
|
||||||
|
));
|
||||||
|
|
||||||
|
h += key_value_pair.len() + 3;
|
||||||
|
key_value_list_stub.extend(key_value_pair.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
key_value_list_stub.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
|
||||||
functor!(
|
functor!(
|
||||||
"switch_on_structure",
|
"switch_on_structure",
|
||||||
[integer(arg), integer(structures)]
|
[aux(orig_h, 0)],
|
||||||
|
[key_value_list_stub]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -710,8 +835,4 @@ impl QueryInstruction {
|
|||||||
|
|
||||||
pub type CompiledFact = Vec<FactInstruction>;
|
pub type CompiledFact = Vec<FactInstruction>;
|
||||||
|
|
||||||
pub type ThirdLevelIndex = Vec<IndexedChoiceInstruction>;
|
|
||||||
|
|
||||||
pub type Code = Vec<Line>;
|
pub type Code = Vec<Line>;
|
||||||
|
|
||||||
pub type CodeDeque = VecDeque<Line>;
|
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ impl<'a> ChunkedIterator<'a> {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self {
|
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self {
|
||||||
ChunkedIterator {
|
ChunkedIterator {
|
||||||
chunk_num: 0,
|
chunk_num: 0,
|
||||||
@@ -490,7 +490,7 @@ impl<'a> ChunkedIterator<'a> {
|
|||||||
cut_var_in_head: false,
|
cut_var_in_head: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
|
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
|
||||||
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
|
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
|
||||||
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
|
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
:- module(atts, [op(1199, fx, attribute), call_residue_vars/2,
|
:- module(atts, [op(1199, fx, attribute),
|
||||||
|
call_residue_vars/2,
|
||||||
term_attributed_variables/2,
|
term_attributed_variables/2,
|
||||||
'$absent_attr'/2, '$copy_attr_list'/2, '$get_attr'/2,
|
'$absent_attr'/2, '$copy_attr_list'/2, '$get_attr'/2,
|
||||||
'$put_attr'/2, '$absent_from_list'/2,
|
'$put_attr'/2, '$absent_from_list'/2,
|
||||||
@@ -19,9 +20,7 @@
|
|||||||
).
|
).
|
||||||
|
|
||||||
'$default_attr_list'([PG | PGs], Module, AttrVar) -->
|
'$default_attr_list'([PG | PGs], Module, AttrVar) -->
|
||||||
( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)]
|
[Module:put_atts(AttrVar, PG)],
|
||||||
; { true }
|
|
||||||
),
|
|
||||||
'$default_attr_list'(PGs, Module, AttrVar).
|
'$default_attr_list'(PGs, Module, AttrVar).
|
||||||
'$default_attr_list'([], _, _) --> [].
|
'$default_attr_list'([], _, _) --> [].
|
||||||
|
|
||||||
@@ -66,7 +65,8 @@
|
|||||||
|
|
||||||
'$del_attr_step'(Ls1, V, Attr) :-
|
'$del_attr_step'(Ls1, V, Attr) :-
|
||||||
( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
|
( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
|
||||||
; true ).
|
; true
|
||||||
|
).
|
||||||
|
|
||||||
%% assumptions: Ls0 is a list, Ls1 is its tail;
|
%% assumptions: Ls0 is a list, Ls1 is its tail;
|
||||||
%% the head of Ls0 can be ignored.
|
%% the head of Ls0 can be ignored.
|
||||||
@@ -75,8 +75,8 @@
|
|||||||
; Ls1 = [Att | Ls2] ->
|
; Ls1 = [Att | Ls2] ->
|
||||||
( Att \= Attr -> '$del_attr_buried'(Ls1, Ls2, V, Attr)
|
( Att \= Attr -> '$del_attr_buried'(Ls1, Ls2, V, Attr)
|
||||||
; '$enqueue_attr_var'(V),
|
; '$enqueue_attr_var'(V),
|
||||||
'$del_attr_non_head'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
|
'$del_attr_non_head'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
|
||||||
'$del_attr_step'(Ls1, V, Attr)
|
'$del_attr_step'(Ls1, V, Attr)
|
||||||
)
|
)
|
||||||
).
|
).
|
||||||
|
|
||||||
@@ -88,66 +88,66 @@ user:term_expansion(Term0, Terms) :-
|
|||||||
nonvar(Term0),
|
nonvar(Term0),
|
||||||
Term0 = (:- attribute Atts),
|
Term0 = (:- attribute Atts),
|
||||||
nonvar(Atts),
|
nonvar(Atts),
|
||||||
phrase(expand_terms(Atts), Terms).
|
loader:prolog_load_context(module, Module),
|
||||||
|
phrase(expand_terms(Atts, Module), Terms).
|
||||||
|
|
||||||
expand_terms(Atts) -->
|
expand_terms(Atts, Module) -->
|
||||||
put_attrs_var_check,
|
put_attrs_var_check,
|
||||||
put_attrs(Atts),
|
put_attrs(Atts, Module),
|
||||||
get_attrs_var_check,
|
get_attrs_var_check,
|
||||||
get_attrs(Atts).
|
get_attrs(Atts, Module).
|
||||||
|
|
||||||
put_attrs_var_check -->
|
put_attrs_var_check -->
|
||||||
{ numbervars([Var, Attr], 0, _) },
|
|
||||||
[(put_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), put_atts/2))),
|
[(put_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), put_atts/2))),
|
||||||
(put_atts(Var, Attr) :- var(Attr), throw(error(instantiation_error, put_atts/2)))].
|
(put_atts(Var, Attr) :- var(Attr), throw(error(instantiation_error, put_atts/2)))].
|
||||||
|
|
||||||
get_attrs_var_check -->
|
get_attrs_var_check -->
|
||||||
{ numbervars([Var, Ls, Attr], 0, _) },
|
|
||||||
[(get_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), get_atts/2))),
|
[(get_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), get_atts/2))),
|
||||||
(get_atts(Var, Attr) :- var(Attr), !, '$get_attr_list'(Var, Ls), nonvar(Ls),
|
(get_atts(Var, Attr) :- var(Attr), !, '$get_attr_list'(Var, Ls), nonvar(Ls),
|
||||||
'$copy_attr_list'(Ls, Attr))].
|
'$copy_attr_list'(Ls, Attr))].
|
||||||
|
|
||||||
put_attrs(Name/Arity) -->
|
put_attrs(Name/Arity, Module) -->
|
||||||
put_attr(Name, Arity),
|
put_attr(Name, Arity, Module),
|
||||||
{ numbervars([Var, Attr], 0, _) },
|
|
||||||
[(put_atts(Var, Attr) :- lists:maplist(put_atts(Var), Attr), !)].
|
[(put_atts(Var, Attr) :- lists:maplist(put_atts(Var), Attr), !)].
|
||||||
put_attrs((Name/Arity, Atts)) -->
|
put_attrs((Name/Arity, Atts), Module) -->
|
||||||
{ nonvar(Atts) },
|
{ nonvar(Atts) },
|
||||||
put_attr(Name, Arity),
|
put_attr(Name, Arity, Module),
|
||||||
put_attrs(Atts).
|
put_attrs(Atts, Module).
|
||||||
|
|
||||||
get_attrs(Name/Arity) -->
|
get_attrs(Name/Arity, Module) -->
|
||||||
get_attr(Name, Arity).
|
get_attr(Name, Arity, Module).
|
||||||
get_attrs((Name/Arity, Atts)) -->
|
get_attrs((Name/Arity, Atts), Module) -->
|
||||||
{ nonvar(Atts) },
|
{ nonvar(Atts) },
|
||||||
get_attr(Name, Arity),
|
get_attr(Name, Arity, Module),
|
||||||
get_attrs(Atts).
|
get_attrs(Atts, Module).
|
||||||
|
|
||||||
put_attr(Name, Arity) -->
|
put_attr(Name, Arity, Module) -->
|
||||||
{ functor(Attr, Name, Arity),
|
{ functor(Attr, Name, Arity) },
|
||||||
numbervars(Attr, 0, Arity),
|
[(put_atts(V, +Attr) :-
|
||||||
V = '$VAR'(Arity) },
|
!,
|
||||||
[(put_atts(V, +Attr) :- !, functor(Attr, Head, Arity),
|
functor(Attr, Head, Arity),
|
||||||
functor(AttrForm, Head, Arity),
|
functor(AttrForm, Head, Arity),
|
||||||
'$get_attr_list'(V, Ls),
|
'$get_attr_list'(V, Ls),
|
||||||
'$del_attr'(Ls, V, AttrForm),
|
'$del_attr'(Ls, V, Module:AttrForm),
|
||||||
'$put_attr'(V, Attr)),
|
'$put_attr'(V, Module:Attr)),
|
||||||
(put_atts(V, Attr) :- !, functor(Attr, Head, Arity),
|
(put_atts(V, Attr) :-
|
||||||
functor(AttrForm, Head, Arity),
|
!,
|
||||||
'$get_attr_list'(V, Ls),
|
functor(Attr, Head, Arity),
|
||||||
'$del_attr'(Ls, V, AttrForm),
|
functor(AttrForm, Head, Arity),
|
||||||
'$put_attr'(V, Attr)),
|
'$get_attr_list'(V, Ls),
|
||||||
(put_atts(V, -Attr) :- !, functor(Attr, _, _),
|
'$del_attr'(Ls, V, Module:AttrForm),
|
||||||
'$get_attr_list'(V, Ls),
|
'$put_attr'(V, Module:Attr)),
|
||||||
'$del_attr'(Ls, V, Attr))].
|
(put_atts(V, -Attr) :-
|
||||||
|
!,
|
||||||
|
functor(Attr, _, _),
|
||||||
|
'$get_attr_list'(V, Ls),
|
||||||
|
'$del_attr'(Ls, V, Module:Attr))].
|
||||||
|
|
||||||
get_attr(Name, Arity) -->
|
get_attr(Name, Arity, Module) -->
|
||||||
{ functor(Attr, Name, Arity),
|
{ functor(Attr, Name, Arity) },
|
||||||
numbervars(Attr, 0, Arity),
|
[(get_atts(V, +Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Module:Attr)),
|
||||||
V = '$VAR'(Arity) },
|
(get_atts(V, Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Module:Attr)),
|
||||||
[(get_atts(V, +Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Attr)),
|
(get_atts(V, -Attr) :- !, functor(Attr, _, _), '$absent_attr'(V, Module:Attr))].
|
||||||
(get_atts(V, Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Attr)),
|
|
||||||
(get_atts(V, -Attr) :- !, functor(Attr, _, _), '$absent_attr'(V, Attr))].
|
|
||||||
|
|
||||||
user:goal_expansion(Term, M:put_atts(Var, Attr)) :-
|
user:goal_expansion(Term, M:put_atts(Var, Attr)) :-
|
||||||
nonvar(Term),
|
nonvar(Term),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,8 @@
|
|||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
:- module(clpb, [op(300, fy, ~),
|
:- module(clpb, [op(300, fy, ~),
|
||||||
op(500, yfx, #),
|
op(500, yfx, #),
|
||||||
sat/1,
|
sat/1,
|
||||||
taut/2,
|
taut/2,
|
||||||
labeling/1,
|
labeling/1,
|
||||||
sat_count/2,
|
sat_count/2,
|
||||||
|
|||||||
@@ -5,13 +5,21 @@
|
|||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
:- use_module(library(lists), [append/3]).
|
:- use_module(library(lists), [append/3]).
|
||||||
|
:- use_module(library(loader), [strip_module/3]).
|
||||||
|
|
||||||
|
:- meta_predicate phrase(2, ?).
|
||||||
|
|
||||||
|
:- meta_predicate phrase(2, ?, ?).
|
||||||
|
|
||||||
phrase(GRBody, S0) :-
|
phrase(GRBody, S0) :-
|
||||||
phrase(GRBody, S0, []).
|
phrase(GRBody, S0, []).
|
||||||
|
|
||||||
|
|
||||||
phrase(GRBody, S0, S) :-
|
phrase(GRBody, S0, S) :-
|
||||||
( var(GRBody) -> throw(error(instantiation_error, phrase/3))
|
( var(GRBody) -> throw(error(instantiation_error, phrase/3))
|
||||||
; dcg_constr(GRBody) -> phrase_(GRBody, S0, S)
|
; strip_module(GRBody, _, GRBody0),
|
||||||
|
dcg_constr(GRBody0) ->
|
||||||
|
phrase_(GRBody0, S0, S)
|
||||||
; functor(GRBody, _, _) -> call(GRBody, S0, S)
|
; functor(GRBody, _, _) -> call(GRBody, S0, S)
|
||||||
; throw(error(type_error(callable, GRBody), phrase/3))
|
; throw(error(type_error(callable, GRBody), phrase/3))
|
||||||
).
|
).
|
||||||
|
|||||||
@@ -2,13 +2,23 @@
|
|||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
|
|
||||||
|
|
||||||
wam_instructions(Clause, Listing) :-
|
wam_instructions(Clause, Listing) :-
|
||||||
( nonvar(Clause) ->
|
( nonvar(Clause) ->
|
||||||
Clause = Name / Arity,
|
( Clause = Name / Arity ->
|
||||||
must_be(atom, Name),
|
fetch_instructions(user, Name, Arity, Listing)
|
||||||
must_be(integer, Arity),
|
; Clause = Module : (Name / Arity) ->
|
||||||
( Arity >= 0 -> '$wam_instructions'(Name, Arity, Listing)
|
fetch_instructions(Module, Name, Arity, Listing)
|
||||||
; throw(error(domain_error(not_less_than_zero, Arity), wam_instructions/2))
|
|
||||||
)
|
)
|
||||||
; throw(error(instantiation_error, wam_instructions/2))
|
; throw(error(instantiation_error, wam_instructions/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
|
fetch_instructions(Module, Name, Arity, Listing) :-
|
||||||
|
must_be(atom, Module),
|
||||||
|
must_be(atom, Name),
|
||||||
|
must_be(integer, Arity),
|
||||||
|
( Arity >= 0 ->
|
||||||
|
'$wam_instructions'(Module, Name, Arity, Listing)
|
||||||
|
; throw(error(domain_error(not_less_than_zero, Arity), wam_instructions/2))
|
||||||
|
).
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
put_dif_att(Var, X, Y) :-
|
put_dif_att(Var, X, Y) :-
|
||||||
( get_atts(Var, +dif(Z)) ->
|
( get_atts(Var, +dif(Z)) ->
|
||||||
sort([X \== Y | Z], NewZ),
|
sort([X \== Y | Z], NewZ),
|
||||||
put_atts(Var, +dif(NewZ))
|
put_atts(Var, +dif(NewZ))
|
||||||
; put_atts(Var, +dif([X \== Y]))
|
; put_atts(Var, +dif([X \== Y]))
|
||||||
).
|
).
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ dif_set_variables([Var|Vars], X, Y) :-
|
|||||||
append_goals([], _).
|
append_goals([], _).
|
||||||
append_goals([Var|Vars], Goals) :-
|
append_goals([Var|Vars], Goals) :-
|
||||||
( get_atts(Var, +dif(VarGoals)) ->
|
( get_atts(Var, +dif(VarGoals)) ->
|
||||||
append(Goals, VarGoals, NewGoals0),
|
append(Goals, VarGoals, NewGoals0),
|
||||||
sort(NewGoals0, NewGoals)
|
sort(NewGoals0, NewGoals)
|
||||||
; NewGoals = Goals
|
; NewGoals = Goals
|
||||||
),
|
),
|
||||||
put_atts(Var, +dif(NewGoals)),
|
put_atts(Var, +dif(NewGoals)),
|
||||||
@@ -30,8 +30,8 @@ append_goals([Var|Vars], Goals) :-
|
|||||||
|
|
||||||
verify_attributes(Var, Value, Goals) :-
|
verify_attributes(Var, Value, Goals) :-
|
||||||
( get_atts(Var, +dif(Goals)) ->
|
( get_atts(Var, +dif(Goals)) ->
|
||||||
term_variables(Value, ValueVars),
|
term_variables(Value, ValueVars),
|
||||||
append_goals(ValueVars, Goals)
|
append_goals(ValueVars, Goals)
|
||||||
; Goals = []
|
; Goals = []
|
||||||
).
|
).
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ dif(X, Y) :-
|
|||||||
gather_dif_goals([]) --> [].
|
gather_dif_goals([]) --> [].
|
||||||
gather_dif_goals([(X \== Y) | Goals]) -->
|
gather_dif_goals([(X \== Y) | Goals]) -->
|
||||||
( { X \= Y } -> []
|
( { X \= Y } -> []
|
||||||
; [dif(X, Y)]
|
; [dif:dif(X, Y)]
|
||||||
),
|
),
|
||||||
gather_dif_goals(Goals).
|
gather_dif_goals(Goals).
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ must_be_(var, Term) :-
|
|||||||
).
|
).
|
||||||
must_be_(integer, Term) :- check_(integer, integer, Term).
|
must_be_(integer, Term) :- check_(integer, integer, Term).
|
||||||
must_be_(atom, Term) :- check_(atom, atom, Term).
|
must_be_(atom, Term) :- check_(atom, atom, Term).
|
||||||
must_be_(character, T) :- check_(character, character, T).
|
must_be_(character, T) :- check_(error:character, character, T).
|
||||||
must_be_(list, Term) :- check_(ilist, list, Term).
|
must_be_(list, Term) :- check_(error:ilist, list, Term).
|
||||||
must_be_(type, Term) :- check_(type, type, Term).
|
must_be_(type, Term) :- check_(error:type, type, Term).
|
||||||
must_be_(boolean, Term) :- check_(boolean, boolean, Term).
|
must_be_(boolean, Term) :- check_(error:boolean, boolean, Term).
|
||||||
|
|
||||||
check_(Pred, Type, Term) :-
|
check_(Pred, Type, Term) :-
|
||||||
( var(Term) -> instantiation_error(must_be/2)
|
( var(Term) -> instantiation_error(must_be/2)
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)).
|
|||||||
|
|
||||||
bb_b_put(Key, NewValue) :-
|
bb_b_put(Key, NewValue) :-
|
||||||
( '$bb_get_with_offset'(Key, OldValue, OldOffset) ->
|
( '$bb_get_with_offset'(Key, OldValue, OldOffset) ->
|
||||||
call_cleanup((store_global_var_with_offset(Key, NewValue) ; false),
|
call_cleanup((iso_ext:store_global_var_with_offset(Key, NewValue) ; false),
|
||||||
reset_global_var_at_offset(Key, OldValue, OldOffset))
|
reset_global_var_at_offset(Key, OldValue, OldOffset))
|
||||||
; call_cleanup((store_global_var_with_offset(Key, NewValue) ; false),
|
; call_cleanup((iso_ext:store_global_var_with_offset(Key, NewValue) ; false),
|
||||||
reset_global_var_at_key(Key))
|
reset_global_var_at_key(Key))
|
||||||
).
|
).
|
||||||
|
|
||||||
@@ -45,11 +45,16 @@ reset_global_var_at_offset(Key, Value, Offset) :- '$reset_global_var_at_offset'(
|
|||||||
bb_get(Key, Value) :- atom(Key), !, '$fetch_global_var'(Key, Value).
|
bb_get(Key, Value) :- atom(Key), !, '$fetch_global_var'(Key, Value).
|
||||||
bb_get(Key, _) :- throw(error(type_error(atom, Key), bb_get/2)).
|
bb_get(Key, _) :- throw(error(type_error(atom, Key), bb_get/2)).
|
||||||
|
|
||||||
|
|
||||||
|
:- meta_predicate call_cleanup(:, :).
|
||||||
|
|
||||||
call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
|
call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
|
||||||
|
|
||||||
|
|
||||||
% setup_call_cleanup.
|
% setup_call_cleanup.
|
||||||
|
|
||||||
|
:- meta_predicate setup_call_cleanup(:, :, :).
|
||||||
|
|
||||||
setup_call_cleanup(S, G, C) :-
|
setup_call_cleanup(S, G, C) :-
|
||||||
'$get_b_value'(B),
|
'$get_b_value'(B),
|
||||||
call(S),
|
call(S),
|
||||||
@@ -117,6 +122,8 @@ handle_ile(B, E, _) :-
|
|||||||
'$remove_call_policy_check'(B),
|
'$remove_call_policy_check'(B),
|
||||||
'$call_with_default_policy'(throw(E)).
|
'$call_with_default_policy'(throw(E)).
|
||||||
|
|
||||||
|
:- meta_predicate call_with_inference_limit(:, ?, ?).
|
||||||
|
|
||||||
call_with_inference_limit(G, L, R) :-
|
call_with_inference_limit(G, L, R) :-
|
||||||
'$get_current_block'(Bb),
|
'$get_current_block'(Bb),
|
||||||
'$get_b_value'(B),
|
'$get_b_value'(B),
|
||||||
|
|||||||
@@ -1,15 +1,29 @@
|
|||||||
:- module(lists, [member/2, select/3, append/2, append/3, foldl/4, foldl/5,
|
:- module(lists, [member/2, select/3, append/2, append/3, foldl/4, foldl/5,
|
||||||
memberchk/2, reverse/2, length/2, maplist/2,
|
memberchk/2, reverse/2, length/2, maplist/2,
|
||||||
maplist/3, maplist/4, maplist/5, maplist/6,
|
maplist/3, maplist/4, maplist/5, maplist/6,
|
||||||
maplist/7, maplist/8, maplist/9, same_length/2, nth0/3,
|
maplist/7, maplist/8, maplist/9, same_length/2, nth0/3,
|
||||||
sum_list/2, transpose/2, list_to_set/2, list_max/2, list_min/2]).
|
sum_list/2, transpose/2, list_to_set/2, list_max/2, list_min/2]).
|
||||||
|
|
||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
|
|
||||||
|
|
||||||
|
:- meta_predicate maplist(1, ?).
|
||||||
|
:- meta_predicate maplist(2, ?, ?).
|
||||||
|
:- meta_predicate maplist(3, ?, ?, ?).
|
||||||
|
:- meta_predicate maplist(4, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate maplist(5, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate maplist(6, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate maplist(7, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate maplist(8, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
|
||||||
|
:- meta_predicate foldl(3, ?, ?, ?).
|
||||||
|
:- meta_predicate foldl(4, ?, ?, ?, ?).
|
||||||
|
|
||||||
|
|
||||||
length(Xs, N) :-
|
length(Xs, N) :-
|
||||||
var(N), !,
|
var(N),
|
||||||
|
!,
|
||||||
'$skip_max_list'(M, -1, Xs, Xs0),
|
'$skip_max_list'(M, -1, Xs, Xs0),
|
||||||
( Xs0 == [] -> N = M
|
( Xs0 == [] -> N = M
|
||||||
; var(Xs0) -> length_addendum(Xs0, N, M)).
|
; var(Xs0) -> length_addendum(Xs0, N, M)).
|
||||||
@@ -66,7 +80,6 @@ reverse([], [], YsRev, YsRev).
|
|||||||
reverse([_|Xs], [Y1|Ys], YsPreludeRev, Xss) :-
|
reverse([_|Xs], [Y1|Ys], YsPreludeRev, Xss) :-
|
||||||
reverse(Xs, Ys, [Y1|YsPreludeRev], Xss).
|
reverse(Xs, Ys, [Y1|YsPreludeRev], Xss).
|
||||||
|
|
||||||
|
|
||||||
maplist(_, []).
|
maplist(_, []).
|
||||||
maplist(Cont1, [E1|E1s]) :-
|
maplist(Cont1, [E1|E1s]) :-
|
||||||
call(Cont1, E1),
|
call(Cont1, E1),
|
||||||
@@ -87,21 +100,25 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :-
|
|||||||
call(Cont, E1, E2, E3, E4),
|
call(Cont, E1, E2, E3, E4),
|
||||||
maplist(Cont, E1s, E2s, E3s, E4s).
|
maplist(Cont, E1s, E2s, E3s, E4s).
|
||||||
|
|
||||||
|
|
||||||
maplist(_, [], [], [], [], []).
|
maplist(_, [], [], [], [], []).
|
||||||
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
|
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
|
||||||
call(Cont, E1, E2, E3, E4, E5),
|
call(Cont, E1, E2, E3, E4, E5),
|
||||||
maplist(Cont, E1s, E2s, E3s, E4s, E5s).
|
maplist(Cont, E1s, E2s, E3s, E4s, E5s).
|
||||||
|
|
||||||
|
|
||||||
maplist(_, [], [], [], [], [], []).
|
maplist(_, [], [], [], [], [], []).
|
||||||
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
|
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
|
||||||
call(Cont, E1, E2, E3, E4, E5, E6),
|
call(Cont, E1, E2, E3, E4, E5, E6),
|
||||||
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
|
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
|
||||||
|
|
||||||
|
|
||||||
maplist(_, [], [], [], [], [], [], []).
|
maplist(_, [], [], [], [], [], [], []).
|
||||||
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
|
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
|
||||||
call(Cont, E1, E2, E3, E4, E5, E6, E7),
|
call(Cont, E1, E2, E3, E4, E5, E6, E7),
|
||||||
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
|
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
|
||||||
|
|
||||||
|
|
||||||
maplist(_, [], [], [], [], [], [], [], []).
|
maplist(_, [], [], [], [], [], [], [], []).
|
||||||
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
|
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
|
||||||
call(Cont, E1, E2, E3, E4, E5, E6, E7, E8),
|
call(Cont, E1, E2, E3, E4, E5, E6, E7, E8),
|
||||||
@@ -111,7 +128,7 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7
|
|||||||
sum_list(Ls, S) :-
|
sum_list(Ls, S) :-
|
||||||
foldl(sum_, Ls, 0, S).
|
foldl(sum_, Ls, 0, S).
|
||||||
|
|
||||||
sum_(L, S0, S) :- S is S0 + L.
|
sum_(L, S0, S) :- is(S, +(S0, L)).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -132,6 +149,7 @@ foldl_([L|Ls], G_3, A0, A) :-
|
|||||||
foldl(Goal_4, Xs, Ys, A0, A) :-
|
foldl(Goal_4, Xs, Ys, A0, A) :-
|
||||||
foldl_(Xs, Ys, Goal_4, A0, A).
|
foldl_(Xs, Ys, Goal_4, A0, A).
|
||||||
|
|
||||||
|
|
||||||
foldl_([], [], _, A, A).
|
foldl_([], [], _, A, A).
|
||||||
foldl_([X|Xs], [Y|Ys], G_4, A0, A) :-
|
foldl_([X|Xs], [Y|Ys], G_4, A0, A) :-
|
||||||
call(G_4, X, Y, A0, A1),
|
call(G_4, X, Y, A0, A1),
|
||||||
|
|||||||
127
src/lib/ops_and_meta_predicates.pl
Normal file
127
src/lib/ops_and_meta_predicates.pl
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
:- op(400, yfx, /).
|
||||||
|
|
||||||
|
% module resolution operator.
|
||||||
|
:- op(600, xfy, :).
|
||||||
|
|
||||||
|
:- op(1199, fx, meta_predicate).
|
||||||
|
|
||||||
|
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
|
||||||
|
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
|
||||||
|
instructions are unchanged. */
|
||||||
|
:- op(700, fx, non_counted_backtracking).
|
||||||
|
|
||||||
|
% arithmetic operators.
|
||||||
|
:- op(700, xfx, is).
|
||||||
|
:- op(500, yfx, +).
|
||||||
|
:- op(500, yfx, -).
|
||||||
|
:- op(400, yfx, *).
|
||||||
|
:- op(200, xfy, **).
|
||||||
|
:- op(200, xfy, ^).
|
||||||
|
:- op(500, yfx, /\).
|
||||||
|
:- op(500, yfx, \/).
|
||||||
|
:- op(500, yfx, xor).
|
||||||
|
:- op(400, yfx, div).
|
||||||
|
:- op(400, yfx, //).
|
||||||
|
:- op(400, yfx, rdiv).
|
||||||
|
:- op(400, yfx, <<).
|
||||||
|
:- op(400, yfx, >>).
|
||||||
|
:- op(400, yfx, mod).
|
||||||
|
:- op(400, yfx, rem).
|
||||||
|
:- op(200, fy, +).
|
||||||
|
:- op(200, fy, -).
|
||||||
|
:- op(200, fy, \).
|
||||||
|
|
||||||
|
% arithmetic comparison operators.
|
||||||
|
:- op(700, xfx, >).
|
||||||
|
:- op(700, xfx, <).
|
||||||
|
:- op(700, xfx, =\=).
|
||||||
|
:- op(700, xfx, =:=).
|
||||||
|
:- op(700, xfx, >=).
|
||||||
|
:- op(700, xfx, =<).
|
||||||
|
|
||||||
|
% term comparison.
|
||||||
|
:- op(700, xfx, ==).
|
||||||
|
:- op(700, xfx, \==).
|
||||||
|
:- op(700, xfx, @=<).
|
||||||
|
:- op(700, xfx, @>=).
|
||||||
|
:- op(700, xfx, @<).
|
||||||
|
:- op(700, xfx, @>).
|
||||||
|
|
||||||
|
% conditional operators.
|
||||||
|
:- op(1050, xfy, ->).
|
||||||
|
:- op(1100, xfy, ;).
|
||||||
|
|
||||||
|
% control.
|
||||||
|
:- op(700, xfx, =).
|
||||||
|
:- op(700, xfx, =..).
|
||||||
|
:- op(700, xfx, \=).
|
||||||
|
:- op(900, fy, \+).
|
||||||
|
|
||||||
|
:- op(1200, xfx, -->).
|
||||||
|
|
||||||
|
% meta_predicate declarations for call/{0, 64}.
|
||||||
|
:- meta_predicate call(:).
|
||||||
|
:- meta_predicate call(:, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
|
:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
map_list_to_pairs/3]).
|
map_list_to_pairs/3]).
|
||||||
|
|
||||||
|
|
||||||
|
:- meta_predicate map_list_to_pairs(:, ?, ?).
|
||||||
|
|
||||||
pairs_keys_values([], [], []).
|
pairs_keys_values([], [], []).
|
||||||
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
|
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
|
||||||
pairs_keys_values(ABs, As, Bs).
|
pairs_keys_values(ABs, As, Bs).
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ wrappers(Name/Arity) -->
|
|||||||
atom_concat(Name, ' tabled', WrapName),
|
atom_concat(Name, ' tabled', WrapName),
|
||||||
Head =.. [Name|Args],
|
Head =.. [Name|Args],
|
||||||
WrappedHead =.. [WrapName|Args],
|
WrappedHead =.. [WrapName|Args],
|
||||||
'$module_of'(Module, Name) %prolog_load_context(module, Module)
|
prolog_load_context(module, Module)
|
||||||
},
|
},
|
||||||
[ ( Head :-
|
[ ( Head :-
|
||||||
start_tabling(Module:Head, WrappedHead)
|
start_tabling(Module:Head, WrappedHead)
|
||||||
@@ -109,10 +109,10 @@ rename_term(Name, WrapName) :-
|
|||||||
|
|
||||||
|
|
||||||
user:term_expansion(Term0, Clauses) :-
|
user:term_expansion(Term0, Clauses) :-
|
||||||
nonvar(Term0),
|
nonvar(Term0),
|
||||||
Term0 = (:- table Preds),
|
Term0 = (:- table Preds),
|
||||||
phrase(wrappers(Preds), Clauses).
|
phrase(wrappers(Preds), Clauses).
|
||||||
user:term_expansion(Clause, NewClause) :-
|
user:term_expansion(Clause, NewClause) :-
|
||||||
nonvar(Clause),
|
nonvar(Clause),
|
||||||
'$module_of'(Module, Clause),
|
prolog_load_context(module, Module),
|
||||||
rename(Clause, NewClause, Module).
|
rename(Clause, NewClause, Module).
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ sleep(T) :-
|
|||||||
|
|
||||||
% '$cpu_now' can be replaced by statistics/2 once that is implemented.
|
% '$cpu_now' can be replaced by statistics/2 once that is implemented.
|
||||||
|
|
||||||
|
:- meta_predicate time(:).
|
||||||
|
|
||||||
time(Goal) :-
|
time(Goal) :-
|
||||||
'$cpu_now'(T0),
|
'$cpu_now'(T0),
|
||||||
setup_call_cleanup(true,
|
setup_call_cleanup(true,
|
||||||
|
|||||||
433
src/loader.pl
Normal file
433
src/loader.pl
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
|
||||||
|
:- module(loader, [consult/1,
|
||||||
|
expand_goal/3,
|
||||||
|
expand_term/2,
|
||||||
|
file_load/2,
|
||||||
|
load/1,
|
||||||
|
predicate_property/2,
|
||||||
|
prolog_load_context/2,
|
||||||
|
strip_module/3,
|
||||||
|
use_module/1,
|
||||||
|
use_module/2
|
||||||
|
]).
|
||||||
|
|
||||||
|
|
||||||
|
:- use_module(library(error)).
|
||||||
|
:- use_module(library(lists)).
|
||||||
|
:- use_module(library(pairs)).
|
||||||
|
|
||||||
|
|
||||||
|
create_file_load_context(Stream, Path, Evacuable) :-
|
||||||
|
'$push_load_context'(Stream, Path),
|
||||||
|
'$push_load_state_payload'(Evacuable).
|
||||||
|
|
||||||
|
create_load_context(Stream, Evacuable) :-
|
||||||
|
'$push_load_context'(Stream, ''),
|
||||||
|
'$push_load_state_payload'(Evacuable).
|
||||||
|
|
||||||
|
unload_evacuable(Evacuable) :-
|
||||||
|
'$pop_load_state_payload'(Evacuable),
|
||||||
|
'$pop_load_context'.
|
||||||
|
|
||||||
|
|
||||||
|
file_load(Stream, Path) :-
|
||||||
|
file_load(Stream, Path, _).
|
||||||
|
|
||||||
|
file_load(Stream, Path, Evacuable) :-
|
||||||
|
create_file_load_context(Stream, Path, Evacuable),
|
||||||
|
catch(loader:load_loop(Stream, Evacuable),
|
||||||
|
E,
|
||||||
|
(loader:unload_evacuable(Evacuable), throw(E))),
|
||||||
|
'$pop_load_context'.
|
||||||
|
|
||||||
|
|
||||||
|
load(Stream) :-
|
||||||
|
create_load_context(Stream, Evacuable),
|
||||||
|
catch(loader:load_loop(Stream, Evacuable),
|
||||||
|
E,
|
||||||
|
(loader:unload_evacuable(Evacuable), throw(E))),
|
||||||
|
'$pop_load_context'.
|
||||||
|
|
||||||
|
load_loop(Stream, Evacuable) :-
|
||||||
|
read_term(Stream, Term, [variable_names(VNs), singletons(Singletons)]),
|
||||||
|
( Term == end_of_file ->
|
||||||
|
close(Stream),
|
||||||
|
'$conclude_load'(Evacuable)
|
||||||
|
; var(Term) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; expand_terms_and_goals(Term, Terms),
|
||||||
|
!,
|
||||||
|
( var(Terms) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; Terms = [_|_] ->
|
||||||
|
compile_dispatch_or_clause_on_list(Terms, Evacuable, VNs)
|
||||||
|
; compile_dispatch_or_clause(Terms, Evacuable, VNs)
|
||||||
|
),
|
||||||
|
load_loop(Stream, Evacuable)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
inner_meta_specs((:), HeadArg, InnerHeadArgs, InnerMetaSpecs) :-
|
||||||
|
!,
|
||||||
|
predicate_property(HeadArg, meta_predicate(InnerMetaSpecs)),
|
||||||
|
HeadArg =.. [_ | InnerHeadArgs].
|
||||||
|
|
||||||
|
inner_meta_specs(N, HeadArg, InnerHeadArgs, InnerMetaSpecs) :-
|
||||||
|
integer(N),
|
||||||
|
N >= 0,
|
||||||
|
HeadArg =.. [Functor | InnerHeadArgs],
|
||||||
|
length(InnerHeadArgs1, N),
|
||||||
|
append(InnerHeadArgs, InnerHeadArgs1, InnerHeadArgs0),
|
||||||
|
CompleteHeadArg =.. [Functor | InnerHeadArgs0],
|
||||||
|
predicate_property(CompleteHeadArg, meta_predicate(InnerMetaSpecs)).
|
||||||
|
|
||||||
|
|
||||||
|
module_expanded_head_variables_([], _, HeadVars, HeadVars).
|
||||||
|
module_expanded_head_variables_([HeadArg | HeadArgs], [MetaSpec | MetaSpecs], HeadVars, HeadVars0) :-
|
||||||
|
( ( MetaSpec == (:)
|
||||||
|
; integer(MetaSpec),
|
||||||
|
MetaSpec >= 0
|
||||||
|
) ->
|
||||||
|
( var(HeadArg) ->
|
||||||
|
HeadVars = [HeadArg-HeadArg | HeadVars1],
|
||||||
|
module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars1, HeadVars0)
|
||||||
|
; inner_meta_specs(MetaSpec, HeadArg, InnerHeadArgs, InnerMetaSpecs) ->
|
||||||
|
module_expanded_head_variables_(InnerHeadArgs, InnerMetaSpecs, HeadVars, HeadVars1),
|
||||||
|
module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars1, HeadVars0)
|
||||||
|
; module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, HeadVars0)
|
||||||
|
)
|
||||||
|
; module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, HeadVars0)
|
||||||
|
).
|
||||||
|
|
||||||
|
module_expanded_head_variables(Head, MetaSpecs, HeadVars) :-
|
||||||
|
( var(Head) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; predicate_property(Head, meta_predicate(MetaSpecs)),
|
||||||
|
Head =.. [_ | HeadArgs] ->
|
||||||
|
module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, [])
|
||||||
|
; HeadVars = []
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
expand_terms_and_goals(Term, Terms) :-
|
||||||
|
expand_term(Term, Terms0),
|
||||||
|
( var(Terms0) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; Terms0 = (Head1 :- Body0) ->
|
||||||
|
( var(Head1) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; prolog_load_context(module, Target),
|
||||||
|
module_expanded_head_variables(Head1, MetaSpecs, HeadVars),
|
||||||
|
expand_goal(Body0, Target, Body1, HeadVars)
|
||||||
|
),
|
||||||
|
Terms = (Head1 :- Body1)
|
||||||
|
; Terms = Terms0
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
expand_term(UnexpandedTerm, ExpandedTerm) :-
|
||||||
|
user:term_expansion(UnexpandedTerm, ExpandedTerm).
|
||||||
|
|
||||||
|
|
||||||
|
compile_dispatch_or_clause_on_list([], Evacuable, VNs).
|
||||||
|
compile_dispatch_or_clause_on_list([Term | Terms], Evacuable, VNs) :-
|
||||||
|
compile_dispatch_or_clause(Term, Evacuable, VNs),
|
||||||
|
compile_dispatch_or_clause_on_list(Terms, Evacuable, VNs).
|
||||||
|
|
||||||
|
|
||||||
|
compile_dispatch_or_clause(Term, Evacuable, VNs) :-
|
||||||
|
( var(Term) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; compile_dispatch(Term, Evacuable, VNs) ->
|
||||||
|
true
|
||||||
|
;
|
||||||
|
compile_clause(Term, Evacuable, VNs)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
compile_dispatch((:- Declaration), Evacuable, _VNs) :-
|
||||||
|
( var(Declaration) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
;
|
||||||
|
compile_declaration(Declaration, Evacuable)
|
||||||
|
).
|
||||||
|
compile_dispatch(term_expansion(Term, Terms), Evacuable, VNs) :-
|
||||||
|
'$add_term_expansion_clause'('$term_expansion'(Term, Terms), Evacuable, VNs).
|
||||||
|
compile_dispatch((term_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
|
||||||
|
'$add_term_expansion_clause'(('$term_expansion'(Term, Terms) :- Body), Evacuable, VNs).
|
||||||
|
compile_dispatch(user:term_expansion(Term, Terms), Evacuable, VNs) :-
|
||||||
|
'$add_term_expansion_clause'('$term_expansion'(Term, Terms), Evacuable, VNs).
|
||||||
|
compile_dispatch((user:term_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
|
||||||
|
'$add_term_expansion_clause'(('$term_expansion'(Term, Terms) :- Body), Evacuable, VNs).
|
||||||
|
compile_dispatch(goal_expansion(Term, Terms), Evacuable, VNs) :-
|
||||||
|
prolog_load_context(module, Target),
|
||||||
|
'$add_goal_expansion_clause'(Target, goal_expansion(Term, Terms), Evacuable, VNs).
|
||||||
|
compile_dispatch((goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
|
||||||
|
prolog_load_context(module, Target),
|
||||||
|
'$add_goal_expansion_clause'(Target, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs).
|
||||||
|
compile_dispatch(Target:goal_expansion(Term, Terms), Evacuable, VNs) :-
|
||||||
|
'$add_goal_expansion_clause'(Target, goal_expansion(Term, Terms), Evacuable, VNs).
|
||||||
|
compile_dispatch((Target:goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
|
||||||
|
'$add_goal_expansion_clause'(Target, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs).
|
||||||
|
|
||||||
|
|
||||||
|
compile_declaration(use_module(Module), Evacuable) :-
|
||||||
|
use_module(Module, [], Evacuable).
|
||||||
|
compile_declaration(use_module(Module, Exports), Evacuable) :-
|
||||||
|
( Exports == [] ->
|
||||||
|
'$remove_module_exports'(Module, Evacuable) % TODO: implement this.
|
||||||
|
;
|
||||||
|
use_module(Module, Exports, Evacuable)
|
||||||
|
).
|
||||||
|
compile_declaration(module(Module, Exports), Evacuable) :-
|
||||||
|
( atom(Module) ->
|
||||||
|
'$declare_module'(Module, Exports, Evacuable)
|
||||||
|
;
|
||||||
|
type_error(atom, Module, load/1)
|
||||||
|
).
|
||||||
|
compile_declaration(dynamic(Name/Arity), Evacuable) :-
|
||||||
|
must_be(atom, Name),
|
||||||
|
must_be(integer, Arity),
|
||||||
|
'$add_dynamic_predicate'(Name, Arity, Evacuable).
|
||||||
|
compile_declaration(initialization(Goal), Evacuable) :-
|
||||||
|
prolog_load_context(module, Module),
|
||||||
|
'$compile_pending_predicates'(Evacuable),
|
||||||
|
expand_goal(call(Goal), Module, call(ExpandedGoal)),
|
||||||
|
call(ExpandedGoal).
|
||||||
|
|
||||||
|
|
||||||
|
compile_clause(Clause, Evacuable, VNs) :-
|
||||||
|
'$clause_to_evacuable'(Clause, Evacuable, VNs).
|
||||||
|
|
||||||
|
|
||||||
|
prolog_load_context(source, Source) :-
|
||||||
|
%% The absolute path name of the file being compiled. During
|
||||||
|
%% loading of a PO file, the corresponding source file name is
|
||||||
|
%% returned.
|
||||||
|
'$prolog_lc_source'(Source).
|
||||||
|
prolog_load_context(file, File) :-
|
||||||
|
%% Outside included files (see Include Declarations) this is the
|
||||||
|
%% same as the source key. In included files this is the absolute
|
||||||
|
%% path name of the file being included.
|
||||||
|
'$prolog_lc_file'(File).
|
||||||
|
prolog_load_context(directory, Dir) :-
|
||||||
|
%% The absolute path name of the directory of the file being
|
||||||
|
%% compiled/loaded. In included files this is the directory of the
|
||||||
|
%% file being included.
|
||||||
|
'$prolog_lc_dir'(Dir).
|
||||||
|
prolog_load_context(module, Module) :-
|
||||||
|
%% The source module (see ref-mod-mne). This is useful for example
|
||||||
|
%% if you are defining clauses for user:term_expansion/6 and need
|
||||||
|
%% to access the source module at compile time.
|
||||||
|
'$prolog_lc_module'(Module).
|
||||||
|
prolog_load_context(stream, Stream) :-
|
||||||
|
%% The stream being compiled or loaded from.
|
||||||
|
'$prolog_lc_stream'(Stream).
|
||||||
|
prolog_load_context(term_position, TermPosition) :-
|
||||||
|
%% TermPosition represents the stream position of the last term read.
|
||||||
|
'$prolog_lc_stream'(Stream),
|
||||||
|
stream_property(Stream, position(TermPosition)).
|
||||||
|
|
||||||
|
|
||||||
|
consult(Item) :-
|
||||||
|
( atom(Item) -> use_module(Item)
|
||||||
|
; type_error(atom, Item, consult/1)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
use_module(Module) :-
|
||||||
|
'$push_load_state_payload'(Evacuable),
|
||||||
|
use_module(Module, [], Evacuable).
|
||||||
|
|
||||||
|
use_module(Module, Exports) :-
|
||||||
|
'$push_load_state_payload'(Evacuable),
|
||||||
|
( Exports == [] ->
|
||||||
|
'$remove_module_exports'(Module, Evacuable)
|
||||||
|
;
|
||||||
|
use_module(Module, Exports, Evacuable)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
%% If use_module is invoked in an existing load context, use its
|
||||||
|
%% directory. Otherwise, use the relative path of Path.
|
||||||
|
load_context_path(Module, Path) :-
|
||||||
|
( prolog_load_context(directory, CurrentDir) ->
|
||||||
|
atom_concat(CurrentDir, Path, Module)
|
||||||
|
;
|
||||||
|
Module = Path
|
||||||
|
).
|
||||||
|
|
||||||
|
use_module(Module, Exports, Evacuable) :-
|
||||||
|
( var(Module) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; Module = library(Library) ->
|
||||||
|
( atom(Library) ->
|
||||||
|
( '$load_compiled_library'(Library, Evacuable) -> %% TODO: What about Exports?
|
||||||
|
true
|
||||||
|
;
|
||||||
|
'$load_library_as_stream'(Library, Stream, Path),
|
||||||
|
file_load(Stream, Path, Subevacuable),
|
||||||
|
'$use_module'(Evacuable, Subevacuable, Exports)
|
||||||
|
)
|
||||||
|
; var(Library) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
;
|
||||||
|
type_error(atom, Library, load/1)
|
||||||
|
)
|
||||||
|
; atom(Module) ->
|
||||||
|
load_context_path(Module, Path),
|
||||||
|
open(Path, read, Stream),
|
||||||
|
file_load(Stream, Path, Subevacuable),
|
||||||
|
'$use_module'(Evacuable, Subevacuable, Exports)
|
||||||
|
;
|
||||||
|
type_error(atom, Library, load/1)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
check_predicate_property(meta_predicate, Name, Arity, MetaPredicateTerm) :-
|
||||||
|
must_be(atom, Name),
|
||||||
|
must_be(integer, Arity),
|
||||||
|
'$cpp_meta_predicate_property'(Name, Arity, MetaPredicateTerm).
|
||||||
|
|
||||||
|
|
||||||
|
predicate_property(Callable, Property) :-
|
||||||
|
( var(Callable) ->
|
||||||
|
instantiation_error(load/1)
|
||||||
|
; functor(Callable, Name, Arity),
|
||||||
|
( var(Property) ->
|
||||||
|
true
|
||||||
|
; functor(Property, PropertyType, _)
|
||||||
|
),
|
||||||
|
check_predicate_property(PropertyType, Name, Arity, Property)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
strip_module_(M0, G0, M1, G1) :-
|
||||||
|
( nonvar(G0),
|
||||||
|
G0 = (MG1:G2) ->
|
||||||
|
strip_module_(MG1, G2, M1, G1)
|
||||||
|
; M0 = M1,
|
||||||
|
G0 = G1
|
||||||
|
).
|
||||||
|
|
||||||
|
strip_module(Goal, M, G) :-
|
||||||
|
strip_module_(_, Goal, M, G).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
expand_subgoal(UnexpandedGoals, MS, Module, ExpandedGoals, HeadVars) :-
|
||||||
|
( var(UnexpandedGoals) ->
|
||||||
|
UnexpandedGoals = ExpandedGoals
|
||||||
|
; user:goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
|
||||||
|
( Module \== user ->
|
||||||
|
user:goal_expansion(UnexpandedGoals1, user, Goals)
|
||||||
|
; Goals = UnexpandedGoals1
|
||||||
|
),
|
||||||
|
( inner_meta_specs(MS, Goals, _, MetaSpecs) ->
|
||||||
|
expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars)
|
||||||
|
; Goals = ExpandedGoals
|
||||||
|
)
|
||||||
|
; UnexpandedGoals = ExpandedGoals
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
expand_module_name(ESG0, M, ESG) :-
|
||||||
|
( var(ESG0) ->
|
||||||
|
ESG = M:ESG0
|
||||||
|
; ESG0 = _:ESG1 ->
|
||||||
|
ESG = ESG0
|
||||||
|
; ESG = M:ESG0
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars) :-
|
||||||
|
( ( MS == (:)
|
||||||
|
; integer(MS),
|
||||||
|
MS >= 0
|
||||||
|
) ->
|
||||||
|
( var(SG),
|
||||||
|
pairs:same_key(SG, HeadVars, [_|_], _) ->
|
||||||
|
expand_subgoal(SG, MS, M, ESG, HeadVars)
|
||||||
|
; expand_subgoal(SG, MS, M, ESG0, HeadVars),
|
||||||
|
expand_module_name(ESG0, M, ESG)
|
||||||
|
),
|
||||||
|
expand_meta_predicate_subgoals(SGs, MSs, M, ESGs, HeadVars)
|
||||||
|
; ESG = SG,
|
||||||
|
expand_meta_predicate_subgoals(SGs, MSs, M, ESGs, HeadVars)
|
||||||
|
).
|
||||||
|
|
||||||
|
expand_meta_predicate_subgoals([], _, _, [], _).
|
||||||
|
|
||||||
|
|
||||||
|
expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :-
|
||||||
|
Goals =.. [GoalFunctor | SubGoals],
|
||||||
|
( GoalFunctor == (:) ->
|
||||||
|
false
|
||||||
|
; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars),
|
||||||
|
ExpandedGoals =.. [GoalFunctor | ExpandedGoalList]
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
expand_goal(UnexpandedGoals, Module, ExpandedGoals) :-
|
||||||
|
expand_goal(UnexpandedGoals, Module, ExpandedGoals, []),
|
||||||
|
!.
|
||||||
|
|
||||||
|
expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :-
|
||||||
|
( var(UnexpandedGoals) ->
|
||||||
|
UnexpandedGoals = ExpandedGoals
|
||||||
|
; user:goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
|
||||||
|
( Module \== user ->
|
||||||
|
user:goal_expansion(UnexpandedGoals1, user, Goals)
|
||||||
|
; Goals = UnexpandedGoals1
|
||||||
|
),
|
||||||
|
( Goals = (Goal0, Goals0) ->
|
||||||
|
( expand_goal(Goal0, Module, Goal1, HeadVars) ->
|
||||||
|
expand_goal(Goals0, Module, Goals1, HeadVars),
|
||||||
|
thread_goals(Goal1, ExpandedGoals, Goals1, (','))
|
||||||
|
; expand_goal(Goals0, Module, Goals1, HeadVars),
|
||||||
|
ExpandedGoals = (Goal0, Goals1)
|
||||||
|
)
|
||||||
|
; Goals = (Goals0 -> Goals1) ->
|
||||||
|
expand_goal(Goals0, Module, ExpandedGoals0, HeadVars),
|
||||||
|
expand_goal(Goals1, Module, ExpandedGoals1, HeadVars),
|
||||||
|
ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1)
|
||||||
|
; Goals = (Goals0 ; Goals1) ->
|
||||||
|
expand_goal(Goals0, Module, ExpandedGoals0, HeadVars),
|
||||||
|
expand_goal(Goals1, Module, ExpandedGoals1, HeadVars),
|
||||||
|
ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
|
||||||
|
; Goals = (\+ Goals0) ->
|
||||||
|
expand_goal(Goals0, Module, Goals1, HeadVars),
|
||||||
|
ExpandedGoals = (\+ Goals1)
|
||||||
|
; predicate_property(Goals, meta_predicate(MetaSpecs)) ->
|
||||||
|
expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars)
|
||||||
|
; thread_goals(Goals, ExpandedGoals, (','))
|
||||||
|
; Goals = ExpandedGoals
|
||||||
|
)
|
||||||
|
).
|
||||||
|
|
||||||
|
thread_goals(Goals0, Goals1, Functor) :-
|
||||||
|
( var(Goals0) ->
|
||||||
|
Goals0 = Goals1
|
||||||
|
; ( Goals0 = [G | Gs] ->
|
||||||
|
( Gs = [] ->
|
||||||
|
Goals1 = G
|
||||||
|
; Goals1 =.. [Functor, G, Goals2],
|
||||||
|
thread_goals(Gs, Goals2, Functor)
|
||||||
|
)
|
||||||
|
; Goals1 = Goals0
|
||||||
|
)
|
||||||
|
).
|
||||||
|
|
||||||
|
thread_goals(Goals0, Goals1, Hole, Functor) :-
|
||||||
|
( var(Goals0) ->
|
||||||
|
Goals0 = Goals1
|
||||||
|
; ( Goals0 = [G | Gs] ->
|
||||||
|
( Gs == [] ->
|
||||||
|
Goals1 =.. [Functor, G, Hole]
|
||||||
|
; Goals1 =.. [Functor, G, Goals2],
|
||||||
|
thread_goals(Gs, Goals2, Hole, Functor)
|
||||||
|
)
|
||||||
|
; Goals1 =.. [Functor, Goals0, Hole]
|
||||||
|
)
|
||||||
|
).
|
||||||
@@ -13,10 +13,16 @@ iterate([Var|VarBindings], [Value|ValueBindings], [ListOfGoalLists | ListsCubed]
|
|||||||
iterate(VarBindings, ValueBindings, ListsCubed).
|
iterate(VarBindings, ValueBindings, ListsCubed).
|
||||||
iterate([], [], []).
|
iterate([], [], []).
|
||||||
|
|
||||||
|
/*
|
||||||
gather_modules(Attrs, []) :- var(Attrs), !.
|
gather_modules(Attrs, []) :- var(Attrs), !.
|
||||||
gather_modules([Attr|Attrs], [Module|Modules]) :-
|
gather_modules([Attr|Attrs], [Module|Modules]) :-
|
||||||
'$module_of'(Module, Attr), % write the owning module of Attr to Module.
|
'$module_of'(Module, Attr), % write the owning module of Attr to Module.
|
||||||
gather_modules(Attrs, Modules).
|
gather_modules(Attrs, Modules).
|
||||||
|
*/
|
||||||
|
|
||||||
|
gather_modules(Attrs, []) :- var(Attrs), !.
|
||||||
|
gather_modules([Module:_|Attrs], [Module|Modules]) :-
|
||||||
|
gather_modules(Attrs, Modules).
|
||||||
|
|
||||||
call_verify_attributes(Attrs, _, _, []) :-
|
call_verify_attributes(Attrs, _, _, []) :-
|
||||||
var(Attrs), !.
|
var(Attrs), !.
|
||||||
@@ -24,7 +30,7 @@ call_verify_attributes([], _, _, []).
|
|||||||
call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
|
call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
|
||||||
gather_modules([Attr|Attrs], Modules0),
|
gather_modules([Attr|Attrs], Modules0),
|
||||||
sort(Modules0, Modules),
|
sort(Modules0, Modules),
|
||||||
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
verify_attrs(Modules, Var, Value, ListOfGoalLists). % verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
|
|
||||||
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
|
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
|
||||||
catch(Module:verify_attributes(Var, Value, Goals),
|
catch(Module:verify_attributes(Var, Value, Goals),
|
||||||
@@ -33,6 +39,15 @@ verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
|
|||||||
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
verify_attrs([], _, _, []).
|
verify_attrs([], _, _, []).
|
||||||
|
|
||||||
|
/*
|
||||||
|
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
|
||||||
|
catch(Module:verify_attributes(Var, Value, Goals),
|
||||||
|
error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
|
||||||
|
Goals = []),
|
||||||
|
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
|
verify_attrs([], _, _, []).
|
||||||
|
*/
|
||||||
|
|
||||||
call_goals([ListOfGoalLists | ListsCubed]) :-
|
call_goals([ListOfGoalLists | ListsCubed]) :-
|
||||||
call_goals_0(ListOfGoalLists),
|
call_goals_0(ListOfGoalLists),
|
||||||
call_goals(ListsCubed).
|
call_goals(ListsCubed).
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ use crate::indexmap::IndexSet;
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
|
||||||
pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
|
|
||||||
|
|
||||||
pub(super) type Bindings = Vec<(usize, Addr)>;
|
pub(super) type Bindings = Vec<(usize, Addr)>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -126,7 +123,7 @@ impl MachineState {
|
|||||||
self.stack.index_and_frame_mut(e).prelude.interrupt_cp = self.attr_var_init.cp;
|
self.stack.index_and_frame_mut(e).prelude.interrupt_cp = self.attr_var_init.cp;
|
||||||
|
|
||||||
for i in 1 .. self.num_of_args + 1 {
|
for i in 1 .. self.num_of_args + 1 {
|
||||||
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)].clone();
|
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
||||||
|
|||||||
@@ -1,127 +1,52 @@
|
|||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::codegen::*;
|
|
||||||
use crate::debray_allocator::*;
|
|
||||||
use crate::forms::*;
|
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::compile::*;
|
|
||||||
use crate::machine::machine_errors::*;
|
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
|
|
||||||
use crate::indexmap::IndexSet;
|
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CodeRepo {
|
pub struct CodeRepo {
|
||||||
pub(super) cached_query: Code,
|
|
||||||
pub(super) goal_expanders: Code,
|
|
||||||
pub(super) term_expanders: Code,
|
|
||||||
pub(super) code: Code,
|
pub(super) code: Code,
|
||||||
pub(super) in_situ_code: Code,
|
|
||||||
pub(super) term_dir: TermDir,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodeRepo {
|
impl CodeRepo {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new() -> Self {
|
pub(super)
|
||||||
|
fn new() -> Self {
|
||||||
CodeRepo {
|
CodeRepo {
|
||||||
cached_query: vec![],
|
|
||||||
goal_expanders: Code::new(),
|
|
||||||
term_expanders: Code::new(),
|
|
||||||
code: Code::new(),
|
code: Code::new(),
|
||||||
in_situ_code: Code::new(),
|
|
||||||
term_dir: TermDir::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
|
pub(super)
|
||||||
self.term_dir
|
fn lookup_local_instr<'a>(
|
||||||
.get(&key)
|
&'a self,
|
||||||
.map(|entry| ((entry.0).0.len(), entry.1.len()))
|
p: LocalCodePtr,
|
||||||
.unwrap_or((0, 0))
|
) -> RefOrOwned<'a, Line> {
|
||||||
}
|
match p {
|
||||||
|
LocalCodePtr::Halt => {
|
||||||
#[inline]
|
unreachable!()
|
||||||
pub fn truncate_terms(
|
|
||||||
&mut self,
|
|
||||||
key: PredicateKey,
|
|
||||||
len: usize,
|
|
||||||
queue_len: usize,
|
|
||||||
) -> (Predicate, VecDeque<TopLevel>) {
|
|
||||||
self.term_dir
|
|
||||||
.get_mut(&key)
|
|
||||||
.map(|entry| {
|
|
||||||
let terms =
|
|
||||||
if len < (entry.0).0.len() {
|
|
||||||
(entry.0).0.drain(len ..).collect()
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
};
|
|
||||||
|
|
||||||
let queue =
|
|
||||||
if queue_len < entry.1.len() {
|
|
||||||
entry.1.drain(queue_len ..).collect()
|
|
||||||
} else {
|
|
||||||
VecDeque::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
(Predicate(terms), queue)
|
|
||||||
})
|
|
||||||
.unwrap_or((Predicate::new(), VecDeque::new()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate)
|
|
||||||
fn add_in_situ_result(
|
|
||||||
&mut self,
|
|
||||||
result: &CompiledResult,
|
|
||||||
in_situ_code_dir: &mut InSituCodeDir,
|
|
||||||
in_situ_module_dir: &mut ModuleStubDir,
|
|
||||||
non_counted_bt_preds: &IndexSet<PredicateKey>,
|
|
||||||
) -> Result<(), SessionError> {
|
|
||||||
let (ref decl, ref queue) = result;
|
|
||||||
let (name, arity) = decl
|
|
||||||
.0
|
|
||||||
.first()
|
|
||||||
.and_then(|cl| {
|
|
||||||
let arity = cl.arity();
|
|
||||||
cl.name().map(|name| (name, arity))
|
|
||||||
})
|
|
||||||
.ok_or(SessionError::NamelessEntry)?;
|
|
||||||
|
|
||||||
let non_counted_bt = non_counted_bt_preds.contains(&(name.clone(), arity));
|
|
||||||
let module_name = name.owning_module();
|
|
||||||
|
|
||||||
let p = self.in_situ_code.len();
|
|
||||||
|
|
||||||
match in_situ_module_dir.get_mut(&module_name) {
|
|
||||||
Some(ref mut module_stub) if name.has_table(&module_stub.atom_tbl) => {
|
|
||||||
module_stub.in_situ_code_dir.insert((name, arity), p);
|
|
||||||
}
|
}
|
||||||
_ => {
|
LocalCodePtr::DirEntry(p) => {
|
||||||
in_situ_code_dir.insert((name, arity), p);
|
RefOrOwned::Borrowed(&self.code[p as usize])
|
||||||
|
}
|
||||||
|
LocalCodePtr::IndexingBuf(p, o, i) => {
|
||||||
|
match &self.code[p] {
|
||||||
|
&Line::IndexingCode(ref indexing_lines) => {
|
||||||
|
match &indexing_lines[o] {
|
||||||
|
&IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
|
||||||
|
RefOrOwned::Owned(Line::IndexedChoice(indexed_choice_instrs[i]))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
|
|
||||||
let mut decl_code = cg.compile_predicate(&decl.0)?;
|
|
||||||
|
|
||||||
compile_appendix(&mut decl_code, queue, non_counted_bt)?;
|
|
||||||
|
|
||||||
Ok(self.in_situ_code.extend(decl_code.into_iter()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(super)
|
|
||||||
fn size_of_cached_query(&self) -> usize {
|
|
||||||
self.cached_query.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(super)
|
|
||||||
fn take_in_situ_code(&mut self) -> Code {
|
|
||||||
mem::replace(&mut self.in_situ_code, Code::new())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
@@ -131,32 +56,12 @@ impl CodeRepo {
|
|||||||
p: &CodePtr,
|
p: &CodePtr,
|
||||||
) -> Option<RefOrOwned<'a, Line>> {
|
) -> Option<RefOrOwned<'a, Line>> {
|
||||||
match p {
|
match p {
|
||||||
&CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => {
|
&CodePtr::Local(local) => {
|
||||||
if p < self.goal_expanders.len() {
|
return Some(self.lookup_local_instr(local));
|
||||||
Some(RefOrOwned::Borrowed(&self.goal_expanders[p]))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => {
|
&CodePtr::REPL(..) => {
|
||||||
if p < self.term_expanders.len() {
|
None
|
||||||
Some(RefOrOwned::Borrowed(&self.term_expanders[p]))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&CodePtr::Local(LocalCodePtr::TopLevel(_, p)) => {
|
|
||||||
if p < self.cached_query.len() {
|
|
||||||
Some(RefOrOwned::Borrowed(&self.cached_query[p]))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) => {
|
|
||||||
Some(RefOrOwned::Borrowed(&self.in_situ_code[p]))
|
|
||||||
}
|
|
||||||
&CodePtr::Local(LocalCodePtr::DirEntry(p)) => Some(RefOrOwned::Borrowed(&self.code[p])),
|
|
||||||
&CodePtr::REPL(..) => None,
|
|
||||||
&CodePtr::BuiltInClause(ref built_in, _) => {
|
&CodePtr::BuiltInClause(ref built_in, _) => {
|
||||||
let call_clause = call_clause!(
|
let call_clause = call_clause!(
|
||||||
ClauseType::BuiltIn(built_in.clone()),
|
ClauseType::BuiltIn(built_in.clone()),
|
||||||
@@ -164,14 +69,27 @@ impl CodeRepo {
|
|||||||
0,
|
0,
|
||||||
last_call
|
last_call
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(RefOrOwned::Owned(call_clause))
|
Some(RefOrOwned::Owned(call_clause))
|
||||||
}
|
}
|
||||||
&CodePtr::CallN(arity, _, last_call) => {
|
&CodePtr::CallN(arity, _, last_call) => {
|
||||||
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
|
let call_clause = call_clause!(
|
||||||
|
ClauseType::CallN,
|
||||||
|
arity,
|
||||||
|
0,
|
||||||
|
last_call
|
||||||
|
);
|
||||||
|
|
||||||
Some(RefOrOwned::Owned(call_clause))
|
Some(RefOrOwned::Owned(call_clause))
|
||||||
}
|
}
|
||||||
&CodePtr::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])),
|
&CodePtr::VerifyAttrInterrupt(p) => {
|
||||||
&CodePtr::DynamicTransaction(..) => None,
|
Some(RefOrOwned::Borrowed(&self.code[p]))
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
&CodePtr::DynamicTransaction(..) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +1,39 @@
|
|||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
fn scan_for_trust_me(
|
fn capture_offset(line: &Line, index: usize, stack: &mut Vec<usize>) -> bool {
|
||||||
code: &Code,
|
match line {
|
||||||
jmp_offsets: &mut VecDeque<usize>,
|
&Line::Choice(ChoiceInstruction::TryMeElse(offset)) if offset > 0 => {
|
||||||
before_idx: usize,
|
stack.push(index + offset);
|
||||||
after_idx: &mut usize,
|
}
|
||||||
) {
|
&Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) |
|
||||||
// record the location of the line after the TrustMe capping the
|
&Line::Choice(ChoiceInstruction::RetryMeElse(offset)) if offset > 0 => {
|
||||||
// choice instruction sequence to after_idx.
|
stack.push(index + offset);
|
||||||
loop {
|
}
|
||||||
match &code[*after_idx] {
|
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
|
||||||
&Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) |
|
stack.push(index + offset);
|
||||||
&Line::Choice(ChoiceInstruction::RetryMeElse(offset)) |
|
}
|
||||||
&Line::IndexedChoice(IndexedChoiceInstruction::Retry(offset)) => {
|
&Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
|
||||||
*after_idx += offset;
|
stack.push(index + offset);
|
||||||
}
|
return true;
|
||||||
&Line::Choice(ChoiceInstruction::DefaultTrustMe) |
|
}
|
||||||
&Line::Choice(ChoiceInstruction::TrustMe) |
|
&Line::Control(ControlInstruction::Proceed) |
|
||||||
&Line::IndexedChoice(IndexedChoiceInstruction::Trust(..)) => {
|
&Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) => {
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
_ => {
|
&Line::Control(ControlInstruction::RevJmpBy(offset)) => {
|
||||||
*after_idx += 1;
|
if offset > 0 {
|
||||||
|
stack.push(index - offset);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => {
|
||||||
|
|
||||||
// search the code in the range for JmpBy instructions and record their
|
|
||||||
// offsets for future scanning.
|
|
||||||
for (idx, instr) in code[before_idx .. *after_idx].iter().enumerate() {
|
|
||||||
match instr {
|
|
||||||
&Line::Control(ControlInstruction::JmpBy(_, offset, ..)) => {
|
|
||||||
jmp_offsets.push_back(before_idx + idx + offset)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
*after_idx += 1;
|
false
|
||||||
}
|
|
||||||
|
|
||||||
fn capture_next_range(code: &Code, queue: &mut VecDeque<usize>, last_idx: &mut usize) {
|
|
||||||
loop {
|
|
||||||
match &code[*last_idx] {
|
|
||||||
&Line::Choice(ChoiceInstruction::TryMeElse(offset)) |
|
|
||||||
&Line::IndexedChoice(IndexedChoiceInstruction::Try(offset)) => {
|
|
||||||
let before_idx = *last_idx;
|
|
||||||
*last_idx += offset;
|
|
||||||
|
|
||||||
scan_for_trust_me(code, queue, before_idx, last_idx);
|
|
||||||
}
|
|
||||||
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
|
|
||||||
queue.push_back(*last_idx + offset);
|
|
||||||
*last_idx += 1;
|
|
||||||
}
|
|
||||||
&Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
|
|
||||||
queue.push_back(*last_idx + offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
&Line::Control(ControlInstruction::Proceed) |
|
|
||||||
&Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) =>
|
|
||||||
break,
|
|
||||||
_ =>
|
|
||||||
*last_idx += 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function walks the code of a single predicate, supposed to
|
/* This function walks the code of a single predicate, supposed to
|
||||||
@@ -76,15 +42,22 @@ fn capture_next_range(code: &Code, queue: &mut VecDeque<usize>, last_idx: &mut u
|
|||||||
*/
|
*/
|
||||||
pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line))
|
pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line))
|
||||||
{
|
{
|
||||||
let mut queue = VecDeque::from(vec![p]);
|
let mut stack = vec![p];
|
||||||
|
let mut visited_indices = IndexSet::new();
|
||||||
|
|
||||||
while let Some(first_idx) = queue.pop_front() {
|
while let Some(first_index) = stack.pop() {
|
||||||
let mut last_idx = first_idx;
|
if visited_indices.contains(&first_index) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
visited_indices.insert(first_index);
|
||||||
|
}
|
||||||
|
|
||||||
capture_next_range(code, &mut queue, &mut last_idx);
|
for (index, instr) in code[first_index ..].iter().enumerate() {
|
||||||
|
|
||||||
for instr in &code[first_idx .. last_idx + 1] {
|
|
||||||
walker(instr);
|
walker(instr);
|
||||||
|
|
||||||
|
if capture_offset(instr, first_index + index, &mut stack) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,6 +65,7 @@ pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line))
|
|||||||
/* A function for code walking that might result in modification to
|
/* A function for code walking that might result in modification to
|
||||||
* the code. Otherwise identical to walk_code.
|
* the code. Otherwise identical to walk_code.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
pub fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line))
|
pub fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line))
|
||||||
{
|
{
|
||||||
let mut queue = VecDeque::from(vec![p]);
|
let mut queue = VecDeque::from(vec![p]);
|
||||||
@@ -106,3 +80,4 @@ pub fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,396 +0,0 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
|
||||||
|
|
||||||
use crate::heap_print::*;
|
|
||||||
use crate::machine::*;
|
|
||||||
use crate::machine::compile::*;
|
|
||||||
use crate::machine::machine_errors::*;
|
|
||||||
use crate::machine::streams::*;
|
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
impl Machine {
|
|
||||||
pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
|
|
||||||
match name {
|
|
||||||
&ClauseName::User(ref rc) => rc.table.clone(),
|
|
||||||
_ => self.indices.atom_tbl(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compile_into_machine(
|
|
||||||
&mut self,
|
|
||||||
src: Stream,
|
|
||||||
name: ClauseName,
|
|
||||||
arity: usize,
|
|
||||||
) -> EvalSession {
|
|
||||||
match name.owning_module().as_str() {
|
|
||||||
"user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() {
|
|
||||||
Some(idx) => {
|
|
||||||
let module = idx.0.borrow().1.clone();
|
|
||||||
|
|
||||||
match module.as_str() {
|
|
||||||
"user" => compile_user_module(self, src, true, ListingSource::User),
|
|
||||||
_ => compile_into_module(self, module, src, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => compile_user_module(self, src, true, ListingSource::User),
|
|
||||||
},
|
|
||||||
_ => compile_into_module(self, name.owning_module(), src, name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_predicate_key(&self, name: RegType, arity: RegType) -> PredicateKey {
|
|
||||||
let name = self.machine_st[name].clone();
|
|
||||||
let arity = self.machine_st[arity].clone();
|
|
||||||
|
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
|
||||||
Addr::Con(h) =>
|
|
||||||
if let HeapCellValue::Atom(ref name, _) = &self.machine_st.heap[h] {
|
|
||||||
name.clone()
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
|
||||||
Addr::Con(h) => {
|
|
||||||
match &self.machine_st.heap[h] {
|
|
||||||
HeapCellValue::Integer(ref arity) => {
|
|
||||||
arity.to_usize().unwrap()
|
|
||||||
}
|
|
||||||
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
|
||||||
usize::try_from(*arity).unwrap()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Fixnum(arity) => {
|
|
||||||
usize::try_from(arity).unwrap()
|
|
||||||
}
|
|
||||||
Addr::Usize(n) => {
|
|
||||||
n
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(name, arity)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_new_dynamic_clause(
|
|
||||||
&self,
|
|
||||||
addrs: VecDeque<Addr>,
|
|
||||||
name: ClauseName,
|
|
||||||
arity: usize,
|
|
||||||
) -> String {
|
|
||||||
let mut output = PrinterOutputter::new();
|
|
||||||
output.append(format!(":- dynamic({}/{}). ", name.as_str(), arity).as_str());
|
|
||||||
|
|
||||||
for addr in addrs {
|
|
||||||
let mut printer = HCPrinter::new(&self.machine_st, &self.indices.op_dir, output);
|
|
||||||
printer.quoted = true;
|
|
||||||
|
|
||||||
output = printer.print(addr);
|
|
||||||
output.append(". ");
|
|
||||||
}
|
|
||||||
|
|
||||||
output.result()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_undefined(&mut self, name: ClauseName, arity: usize) {
|
|
||||||
let module_name = name.owning_module();
|
|
||||||
|
|
||||||
match self.indices.modules.get(&module_name) {
|
|
||||||
Some(ref module) => {
|
|
||||||
if let Some(idx) = module.code_dir.get(&(name.clone(), arity)) {
|
|
||||||
set_code_index!(idx, IndexPtr::DynamicUndefined, module_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(idx) = self.indices.code_dir.get(&(name, arity)) {
|
|
||||||
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_undefined_in_module(&mut self, module_name: ClauseName, name: ClauseName, arity: usize) {
|
|
||||||
if let Some(idx) = self.indices.code_dir.get(&(name, arity)) {
|
|
||||||
if idx.module_name() == module_name {
|
|
||||||
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
|
|
||||||
let (name, arity) = self.get_predicate_key(name, arity);
|
|
||||||
|
|
||||||
self.make_undefined(name.clone(), arity);
|
|
||||||
|
|
||||||
self.indices.remove_code_index((name.clone(), arity));
|
|
||||||
self.indices.remove_clause_subsection(name.owning_module(), name, arity);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) {
|
|
||||||
let (name, arity) = self.get_predicate_key(name, arity);
|
|
||||||
let module_addr = self.machine_st[module].clone();
|
|
||||||
|
|
||||||
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
|
||||||
Addr::Con(h) =>
|
|
||||||
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
|
||||||
match self.indices.modules.get_mut(module) {
|
|
||||||
Some(ref mut module) => {
|
|
||||||
module.code_dir.remove(&(name.clone(), arity));
|
|
||||||
module.module_decl.name.clone()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.machine_st.fail = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.make_undefined_in_module(module_name.clone(), name.clone(), arity);
|
|
||||||
|
|
||||||
self.indices.remove_code_index((name.clone(), arity));
|
|
||||||
self.indices.remove_clause_subsection(module_name, name, arity);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_eval_result_from_dynamic_compile(
|
|
||||||
&mut self,
|
|
||||||
pred_str: String,
|
|
||||||
name: ClauseName,
|
|
||||||
arity: usize,
|
|
||||||
src: ClauseName,
|
|
||||||
) {
|
|
||||||
let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
|
|
||||||
|
|
||||||
let result = self.compile_into_machine(
|
|
||||||
Stream::from(pred_str),
|
|
||||||
name,
|
|
||||||
arity,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st = machine_st;
|
|
||||||
|
|
||||||
if let EvalSession::Error(err) = result {
|
|
||||||
let h = self.machine_st.heap.h();
|
|
||||||
let stub = MachineError::functor_stub(src, 1);
|
|
||||||
let err = MachineError::session_error(h, err);
|
|
||||||
let err = self.machine_st.error_form(err, stub);
|
|
||||||
|
|
||||||
self.machine_st.throw_exception(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recompile_dynamic_predicate_impl(
|
|
||||||
&mut self,
|
|
||||||
place: DynamicAssertPlace,
|
|
||||||
name: ClauseName,
|
|
||||||
arity: usize,
|
|
||||||
) {
|
|
||||||
let stub = MachineError::functor_stub(place.predicate_name(), 1);
|
|
||||||
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
|
|
||||||
Ok(addrs) => {
|
|
||||||
let mut addrs = VecDeque::from(addrs);
|
|
||||||
let added_clause = self.machine_st[temp_v!(1)].clone();
|
|
||||||
|
|
||||||
place.push_to_queue(&mut addrs, added_clause);
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
return self.machine_st.throw_exception(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
|
||||||
pred_str,
|
|
||||||
name,
|
|
||||||
arity,
|
|
||||||
place.predicate_name(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
|
|
||||||
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
|
||||||
Addr::Con(h) =>
|
|
||||||
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
|
||||||
match self.indices.modules.get(module) {
|
|
||||||
Some(ref module) => module.atom_tbl.clone(),
|
|
||||||
None => {
|
|
||||||
self.machine_st.fail = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.machine_st.fail = true;
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let &mut ClauseName::User(ref mut rc) = name {
|
|
||||||
rc.table = atom_tbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace) {
|
|
||||||
let (mut name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
|
||||||
let module_addr = self.machine_st[temp_v!(5)].clone();
|
|
||||||
|
|
||||||
if self.set_module_atom_tbl(module_addr, &mut name) {
|
|
||||||
self.recompile_dynamic_predicate_impl(place, name, arity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace) {
|
|
||||||
let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
|
||||||
self.recompile_dynamic_predicate_impl(place, name, arity);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
|
||||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
|
||||||
Addr::Con(h) =>
|
|
||||||
match &self.machine_st.heap[h] {
|
|
||||||
HeapCellValue::Integer(ref arity) => {
|
|
||||||
arity.to_usize().unwrap()
|
|
||||||
}
|
|
||||||
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
|
||||||
usize::try_from(*arity).unwrap()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Fixnum(arity) => {
|
|
||||||
usize::try_from(arity).unwrap()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (mut name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
|
||||||
let module_addr = self.machine_st[temp_v!(5)].clone();
|
|
||||||
|
|
||||||
if self.set_module_atom_tbl(module_addr, &mut name) {
|
|
||||||
let stub = MachineError::functor_stub(clause_name!("retract"), 1);
|
|
||||||
let pred_str = match self.machine_st.try_from_list(temp_v!(4), stub) {
|
|
||||||
Ok(addrs) => {
|
|
||||||
let mut addrs = VecDeque::from(addrs);
|
|
||||||
addrs.remove(index);
|
|
||||||
|
|
||||||
if addrs.is_empty() {
|
|
||||||
self.make_undefined(name.clone(), arity);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
return self.machine_st.throw_exception(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
|
||||||
pred_str,
|
|
||||||
name,
|
|
||||||
arity,
|
|
||||||
clause_name!("retract"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn retract_from_dynamic_predicate(&mut self) {
|
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
|
||||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
|
||||||
Addr::Con(h) => {
|
|
||||||
match &self.machine_st.heap[h] {
|
|
||||||
HeapCellValue::Integer(ref arity) => {
|
|
||||||
arity.to_usize().unwrap()
|
|
||||||
}
|
|
||||||
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
|
||||||
usize::try_from(*arity).unwrap()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Usize(n) => {
|
|
||||||
n
|
|
||||||
}
|
|
||||||
Addr::Fixnum(n) => {
|
|
||||||
usize::try_from(n).unwrap()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
|
||||||
|
|
||||||
let stub = MachineError::functor_stub(clause_name!("retract"), 1);
|
|
||||||
let pred_str = match self.machine_st.try_from_list(temp_v!(4), stub) {
|
|
||||||
Ok(addrs) => {
|
|
||||||
let mut addrs = VecDeque::from(addrs);
|
|
||||||
addrs.remove(index);
|
|
||||||
|
|
||||||
if addrs.is_empty() {
|
|
||||||
self.make_undefined(name.clone(), arity);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
return self.machine_st.throw_exception(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
|
||||||
pred_str,
|
|
||||||
name,
|
|
||||||
arity,
|
|
||||||
clause_name!("retract"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn dynamic_transaction(
|
|
||||||
&mut self,
|
|
||||||
trans_type: DynamicTransactionType,
|
|
||||||
p: LocalCodePtr,
|
|
||||||
) {
|
|
||||||
match trans_type {
|
|
||||||
DynamicTransactionType::Abolish => {
|
|
||||||
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2))
|
|
||||||
}
|
|
||||||
DynamicTransactionType::Assert(place) => {
|
|
||||||
self.recompile_dynamic_predicate(place)
|
|
||||||
}
|
|
||||||
DynamicTransactionType::ModuleAbolish => {
|
|
||||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3))
|
|
||||||
}
|
|
||||||
DynamicTransactionType::ModuleAssert(place) => {
|
|
||||||
self.recompile_dynamic_predicate_in_module(place)
|
|
||||||
}
|
|
||||||
DynamicTransactionType::ModuleRetract => {
|
|
||||||
self.retract_from_dynamic_predicate_in_module()
|
|
||||||
}
|
|
||||||
DynamicTransactionType::Retract => {
|
|
||||||
self.retract_from_dynamic_predicate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.machine_st.p = CodePtr::Local(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -168,6 +168,9 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
&HeapCellValue::Integer(ref n) => {
|
&HeapCellValue::Integer(ref n) => {
|
||||||
HeapCellValue::Integer(n.clone())
|
HeapCellValue::Integer(n.clone())
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::LoadStatePayload(_) => {
|
||||||
|
HeapCellValue::Addr(Addr::LoadStatePayload(h))
|
||||||
|
}
|
||||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
}
|
}
|
||||||
@@ -295,6 +298,9 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
val @ HeapCellValue::Rational(_) => {
|
val @ HeapCellValue::Rational(_) => {
|
||||||
Addr::Con(self.push(val))
|
Addr::Con(self.push(val))
|
||||||
}
|
}
|
||||||
|
val @ HeapCellValue::LoadStatePayload(_) => {
|
||||||
|
Addr::LoadStatePayload(self.push(val))
|
||||||
|
}
|
||||||
val @ HeapCellValue::NamedStr(..) => {
|
val @ HeapCellValue::NamedStr(..) => {
|
||||||
Addr::Str(self.push(val))
|
Addr::Str(self.push(val))
|
||||||
}
|
}
|
||||||
@@ -371,15 +377,6 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate)
|
|
||||||
fn take(&mut self) -> Self {
|
|
||||||
HeapTemplate {
|
|
||||||
buf: self.buf.take(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn truncate(&mut self, h: usize) {
|
fn truncate(&mut self, h: usize) {
|
||||||
@@ -479,9 +476,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
("dir_entry", 1) => {
|
("dir_entry", 1) => {
|
||||||
extract_integer(s+1).map(LocalCodePtr::DirEntry)
|
extract_integer(s+1).map(LocalCodePtr::DirEntry)
|
||||||
}
|
}
|
||||||
("in_situ_dir_entry", 1) => {
|
/*
|
||||||
extract_integer(s+1).map(LocalCodePtr::InSituDirEntry)
|
|
||||||
}
|
|
||||||
("top_level", 2) => {
|
("top_level", 2) => {
|
||||||
if let Some(chunk_num) = extract_integer(s+1) {
|
if let Some(chunk_num) = extract_integer(s+1) {
|
||||||
if let Some(p) = extract_integer(s+2) {
|
if let Some(p) = extract_integer(s+2) {
|
||||||
@@ -491,13 +486,10 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
("user_goal_expansion", 1) => {
|
*/
|
||||||
extract_integer(s+1).map(LocalCodePtr::UserGoalExpansion)
|
_ => {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
("user_term_expansion", 1) => {
|
|
||||||
extract_integer(s+1).map(LocalCodePtr::UserTermExpansion)
|
|
||||||
}
|
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
@@ -508,8 +500,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub
|
pub fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
||||||
fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
|
||||||
match addr {
|
match addr {
|
||||||
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => {
|
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => {
|
||||||
RefOrOwned::Borrowed(&self[h])
|
RefOrOwned::Borrowed(&self[h])
|
||||||
|
|||||||
918
src/machine/load_state.rs
Normal file
918
src/machine/load_state.rs
Normal file
@@ -0,0 +1,918 @@
|
|||||||
|
use crate::machine::*;
|
||||||
|
use crate::machine::machine_indices::*;
|
||||||
|
use crate::machine::term_stream::*;
|
||||||
|
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
|
use crate::ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
|
type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We will want to borrow these fields from Loader separately, without
|
||||||
|
* restricting access to other fields by borrowing them mutably.
|
||||||
|
*/
|
||||||
|
pub(super) struct LoadState<'a> {
|
||||||
|
pub(super) compilation_target: CompilationTarget,
|
||||||
|
pub(super) module_op_exports: ModuleOpExports,
|
||||||
|
pub(super) retraction_info: RetractionInfo,
|
||||||
|
pub(super) wam: &'a mut Machine,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn set_code_index(
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
key: PredicateKey,
|
||||||
|
code_index: &CodeIndex,
|
||||||
|
code_ptr: IndexPtr,
|
||||||
|
) {
|
||||||
|
let record =
|
||||||
|
match compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
if IndexPtr::Undefined == code_index.get() {
|
||||||
|
code_index.set(code_ptr);
|
||||||
|
RetractionRecord::AddedUserPredicate(key)
|
||||||
|
} else {
|
||||||
|
// TODO: emit warning about overwriting previous record
|
||||||
|
let replaced = code_index.replace(code_ptr);
|
||||||
|
RetractionRecord::ReplacedUserPredicate(key, replaced)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
if IndexPtr::Undefined == code_index.get() {
|
||||||
|
code_index.set(code_ptr);
|
||||||
|
RetractionRecord::AddedModulePredicate(module_name.clone(), key)
|
||||||
|
} else {
|
||||||
|
// TODO: emit warning about overwriting previous record
|
||||||
|
let replaced = code_index.replace(code_ptr);
|
||||||
|
RetractionRecord::ReplacedModulePredicate(module_name.clone(), key, replaced)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
retraction_info.push_record(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_op_decl_as_module_export(
|
||||||
|
module_op_dir: &mut OpDir,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
wam_op_dir: &mut OpDir,
|
||||||
|
module_op_exports: &mut ModuleOpExports,
|
||||||
|
op_decl: &OpDecl,
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
insert the operator at top-level so it can
|
||||||
|
inform the parser. it will be retracted
|
||||||
|
from the user-level op_dir when the load
|
||||||
|
succeeds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
match op_decl.insert_into_op_dir(wam_op_dir) {
|
||||||
|
Some((prec, spec)) => {
|
||||||
|
retraction_info.push_record(
|
||||||
|
RetractionRecord::ReplacedUserOp(op_decl.clone(), prec, spec)
|
||||||
|
);
|
||||||
|
|
||||||
|
module_op_exports.push((op_decl.clone(), Some((prec, spec))));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedUserOp(op_decl.clone())
|
||||||
|
);
|
||||||
|
|
||||||
|
module_op_exports.push((op_decl.clone(), None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_op_decl(retraction_info, compilation_target, module_op_dir, op_decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn add_op_decl(
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
op_dir: &mut OpDir,
|
||||||
|
op_decl: &OpDecl,
|
||||||
|
) {
|
||||||
|
match op_decl.insert_into_op_dir(op_dir) {
|
||||||
|
Some((prec, spec)) => {
|
||||||
|
match &compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
retraction_info.push_record(
|
||||||
|
RetractionRecord::ReplacedUserOp(op_decl.clone(), prec, spec),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
retraction_info.push_record(
|
||||||
|
RetractionRecord::ReplacedModuleOp(
|
||||||
|
module_name.clone(), op_decl.clone(), prec, spec,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
match &compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedUserOp(op_decl.clone()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedModuleOp(module_name.clone(), op_decl.clone()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn import_module_exports(
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
imported_module: &Module,
|
||||||
|
code_dir: &mut CodeDir,
|
||||||
|
op_dir: &mut OpDir,
|
||||||
|
meta_predicates: &mut MetaPredicateDir,
|
||||||
|
) {
|
||||||
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
|
match export {
|
||||||
|
ModuleExport::PredicateKey((ref name, arity)) => {
|
||||||
|
let key = (name.clone(), *arity);
|
||||||
|
|
||||||
|
if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
|
||||||
|
meta_predicates.insert(key.clone(), meta_specs.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let target_code_index = code_dir
|
||||||
|
.entry(key.clone())
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
set_code_index(
|
||||||
|
retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
key,
|
||||||
|
&target_code_index,
|
||||||
|
src_code_index.get(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
|
add_op_decl(
|
||||||
|
retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
op_dir,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_module_exports_into_module(
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
imported_module: &Module,
|
||||||
|
code_dir: &mut CodeDir,
|
||||||
|
op_dir: &mut OpDir,
|
||||||
|
meta_predicates: &mut MetaPredicateDir,
|
||||||
|
wam_op_dir: &mut OpDir,
|
||||||
|
module_op_exports: &mut ModuleOpExports
|
||||||
|
) {
|
||||||
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
|
match export {
|
||||||
|
ModuleExport::PredicateKey((ref name, arity)) => {
|
||||||
|
let key = (name.clone(), *arity);
|
||||||
|
|
||||||
|
if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
|
||||||
|
meta_predicates.insert(key.clone(), meta_specs.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let target_code_index = code_dir
|
||||||
|
.entry(key.clone())
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
set_code_index(
|
||||||
|
retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
key,
|
||||||
|
&target_code_index,
|
||||||
|
src_code_index.get(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
|
add_op_decl_as_module_export(
|
||||||
|
op_dir,
|
||||||
|
compilation_target,
|
||||||
|
retraction_info,
|
||||||
|
wam_op_dir,
|
||||||
|
module_op_exports,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn import_qualified_module_exports(
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
imported_module: &Module,
|
||||||
|
exports: &IndexSet<ModuleExport>,
|
||||||
|
code_dir: &mut CodeDir,
|
||||||
|
op_dir: &mut OpDir,
|
||||||
|
) {
|
||||||
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
|
if !exports.contains(export) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match export {
|
||||||
|
ModuleExport::PredicateKey((ref name, arity)) => {
|
||||||
|
let key = (name.clone(), *arity);
|
||||||
|
|
||||||
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let target_code_index = code_dir
|
||||||
|
.entry(key.clone())
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
set_code_index(
|
||||||
|
retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
key,
|
||||||
|
&target_code_index,
|
||||||
|
src_code_index.get(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
|
add_op_decl(
|
||||||
|
retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
op_dir,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_qualified_module_exports_into_module(
|
||||||
|
retraction_info: &mut RetractionInfo,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
imported_module: &Module,
|
||||||
|
exports: &IndexSet<ModuleExport>,
|
||||||
|
code_dir: &mut CodeDir,
|
||||||
|
op_dir: &mut OpDir,
|
||||||
|
wam_op_dir: &mut OpDir,
|
||||||
|
module_op_exports: &mut ModuleOpExports,
|
||||||
|
) {
|
||||||
|
for export in imported_module.module_decl.exports.iter() {
|
||||||
|
if !exports.contains(export) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match export {
|
||||||
|
ModuleExport::PredicateKey((ref name, arity)) => {
|
||||||
|
let key = (name.clone(), *arity);
|
||||||
|
|
||||||
|
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
|
||||||
|
let target_code_index = code_dir
|
||||||
|
.entry(key.clone())
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
set_code_index(
|
||||||
|
retraction_info,
|
||||||
|
compilation_target,
|
||||||
|
key,
|
||||||
|
&target_code_index,
|
||||||
|
src_code_index.get(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModuleExport::OpDecl(ref op_decl) => {
|
||||||
|
add_op_decl_as_module_export(
|
||||||
|
op_dir,
|
||||||
|
compilation_target,
|
||||||
|
retraction_info,
|
||||||
|
wam_op_dir,
|
||||||
|
module_op_exports,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LoadState<'a> {
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn increment_clause_assert_margin(&mut self, incr: usize) {
|
||||||
|
match &self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::IncreasedClauseAssertMargin(
|
||||||
|
module_name.clone(),
|
||||||
|
incr,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.wam.indices.modules.get_mut(module_name)
|
||||||
|
.map(|module| module.clause_assert_margin += incr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn remove_module_op_exports(&mut self) {
|
||||||
|
for (mut op_decl, record) in self.module_op_exports.drain(0 ..) {
|
||||||
|
op_decl.remove(&mut self.wam.indices.op_dir);
|
||||||
|
|
||||||
|
if let Some((prec, spec)) = record {
|
||||||
|
op_decl.prec = prec;
|
||||||
|
op_decl.spec = spec;
|
||||||
|
op_decl.insert_into_op_dir(&mut self.wam.indices.op_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_or_insert_local_code_index(
|
||||||
|
&mut self,
|
||||||
|
module_name: ClauseName,
|
||||||
|
key: PredicateKey,
|
||||||
|
) -> CodeIndex {
|
||||||
|
match self.wam.indices.modules.get_mut(&module_name) {
|
||||||
|
Some(ref mut module) => {
|
||||||
|
module.code_dir
|
||||||
|
.entry(key)
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut module = Module::new(
|
||||||
|
ModuleDecl { name: module_name.clone(), exports: vec![] },
|
||||||
|
ListingSource::DynamicallyGenerated,
|
||||||
|
);
|
||||||
|
|
||||||
|
let code_index = module.code_dir
|
||||||
|
.entry(key)
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedModule(module_name.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.wam.indices.modules.insert(module_name, module);
|
||||||
|
code_index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn get_or_insert_code_index(&mut self, key: PredicateKey) -> CodeIndex {
|
||||||
|
match self.compilation_target.clone() {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
self.wam.indices.code_dir
|
||||||
|
.entry(key)
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(module_name) => {
|
||||||
|
self.get_or_insert_local_code_index(module_name, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn get_or_insert_qualified_code_index(
|
||||||
|
&mut self,
|
||||||
|
module_name: ClauseName,
|
||||||
|
key: PredicateKey,
|
||||||
|
) -> CodeIndex {
|
||||||
|
if module_name.as_str() == "user" {
|
||||||
|
return self.wam.indices.code_dir
|
||||||
|
.entry(key)
|
||||||
|
.or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
|
||||||
|
.clone();
|
||||||
|
} else {
|
||||||
|
self.get_or_insert_local_code_index(module_name, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn add_extensible_predicate(&mut self, key: PredicateKey, skeleton: PredicateSkeleton) {
|
||||||
|
match &self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
self.wam.indices.extensible_predicates.insert(key.clone(), skeleton);
|
||||||
|
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedUserExtensiblePredicate(key),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
if let Some(module) = self.wam.indices.modules.get_mut(module_name) {
|
||||||
|
module.extensible_predicates.insert(key.clone(), skeleton);
|
||||||
|
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedModuleExtensiblePredicate(module_name.clone(), key),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn add_op_decl(&mut self, op_decl: &OpDecl) {
|
||||||
|
match &self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
add_op_decl(
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&self.compilation_target,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
match self.wam.indices.modules.get_mut(module_name) {
|
||||||
|
Some(ref mut module) => {
|
||||||
|
add_op_decl_as_module_export(
|
||||||
|
&mut module.op_dir,
|
||||||
|
&self.compilation_target,
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
&mut self.module_op_exports,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn get_clause_type(
|
||||||
|
&mut self,
|
||||||
|
name: ClauseName,
|
||||||
|
arity: usize,
|
||||||
|
fixity: Option<SharedOpDesc>,
|
||||||
|
) -> ClauseType {
|
||||||
|
match ClauseType::from(name, arity, fixity) {
|
||||||
|
ClauseType::Named(name, arity, _) => {
|
||||||
|
let idx = self.get_or_insert_code_index((name.clone(), arity));
|
||||||
|
ClauseType::Named(name, arity, idx)
|
||||||
|
}
|
||||||
|
ClauseType::Op(name, fixity, _) => {
|
||||||
|
let idx = self.get_or_insert_code_index((name.clone(), arity));
|
||||||
|
ClauseType::Op(name, fixity, idx)
|
||||||
|
}
|
||||||
|
ct => {
|
||||||
|
ct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn get_qualified_clause_type(
|
||||||
|
&mut self,
|
||||||
|
module_name: ClauseName,
|
||||||
|
name: ClauseName,
|
||||||
|
arity: usize,
|
||||||
|
fixity: Option<SharedOpDesc>,
|
||||||
|
) -> ClauseType {
|
||||||
|
match ClauseType::from(name, arity, fixity) {
|
||||||
|
ClauseType::Named(name, arity, _) => {
|
||||||
|
let key = (name.clone(), arity);
|
||||||
|
let idx = self.get_or_insert_qualified_code_index(module_name, key);
|
||||||
|
|
||||||
|
ClauseType::Named(name, arity, idx)
|
||||||
|
}
|
||||||
|
ClauseType::Op(name, fixity, _) => {
|
||||||
|
let key = (name.clone(), arity);
|
||||||
|
let idx = self.get_or_insert_qualified_code_index(module_name, key);
|
||||||
|
|
||||||
|
ClauseType::Op(name, fixity, idx)
|
||||||
|
}
|
||||||
|
ct => {
|
||||||
|
ct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn module_name(&self) -> ClauseName {
|
||||||
|
match self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
clause_name!("user")
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
module_name.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn add_meta_predicate_record(
|
||||||
|
&mut self,
|
||||||
|
module_name: ClauseName,
|
||||||
|
name: ClauseName,
|
||||||
|
meta_specs: Vec<MetaSpec>,
|
||||||
|
) {
|
||||||
|
let arity = meta_specs.len();
|
||||||
|
let key = (name, arity);
|
||||||
|
|
||||||
|
match module_name.as_str() {
|
||||||
|
"user" => {
|
||||||
|
match self.wam.indices.meta_predicates.insert(key.clone(), meta_specs) {
|
||||||
|
Some(old_meta_specs) => {
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::ReplacedMetaPredicate(
|
||||||
|
module_name.clone(), key.0, old_meta_specs,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedMetaPredicate(
|
||||||
|
module_name.clone(), key,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
match self.wam.indices.modules.get_mut(&module_name) {
|
||||||
|
Some(ref mut module) => {
|
||||||
|
match module.meta_predicates.insert(key.clone(), meta_specs) {
|
||||||
|
Some(old_meta_specs) => {
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::ReplacedMetaPredicate(
|
||||||
|
module_name.clone(), key.0, old_meta_specs,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedMetaPredicate(
|
||||||
|
module_name.clone(), key,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let module_decl = ModuleDecl {
|
||||||
|
name: module_name.clone(),
|
||||||
|
exports: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let listing_src = ListingSource::DynamicallyGenerated;
|
||||||
|
let mut module = Module::new(module_decl, listing_src);
|
||||||
|
|
||||||
|
module.meta_predicates.insert(key.clone(), meta_specs);
|
||||||
|
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedMetaPredicate(
|
||||||
|
module_name.clone(), key,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedModule(module_name.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.wam.indices.modules.insert(module_name, module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_builtins_in_module(
|
||||||
|
&mut self,
|
||||||
|
code_dir: &mut CodeDir,
|
||||||
|
op_dir: &mut OpDir,
|
||||||
|
meta_predicates: &mut MetaPredicateDir,
|
||||||
|
) {
|
||||||
|
if let Some(builtins) = self.wam.indices.modules.get(&clause_name!("builtins")) {
|
||||||
|
import_module_exports(
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&self.compilation_target,
|
||||||
|
builtins,
|
||||||
|
code_dir,
|
||||||
|
op_dir,
|
||||||
|
meta_predicates,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
|
||||||
|
let module_name = module_decl.name.clone();
|
||||||
|
|
||||||
|
let mut module =
|
||||||
|
match self.wam.indices.modules.remove(&module_name) {
|
||||||
|
Some(mut module) => {
|
||||||
|
let old_module_decl = mem::replace(&mut module.module_decl, module_decl);
|
||||||
|
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::ReplacedModule(
|
||||||
|
old_module_decl, listing_src.clone(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
module.listing_src = listing_src;
|
||||||
|
module
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.retraction_info.push_record(
|
||||||
|
RetractionRecord::AddedModule(module_name.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Module::new(module_decl, listing_src)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.import_builtins_in_module(
|
||||||
|
&mut module.code_dir,
|
||||||
|
&mut module.op_dir,
|
||||||
|
&mut module.meta_predicates,
|
||||||
|
);
|
||||||
|
|
||||||
|
for export in &module.module_decl.exports {
|
||||||
|
if let ModuleExport::OpDecl(ref op_decl) = export {
|
||||||
|
add_op_decl_as_module_export(
|
||||||
|
&mut module.op_dir,
|
||||||
|
&self.compilation_target, // this is a Module.
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
&mut self.module_op_exports,
|
||||||
|
op_decl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(load_context) = self.wam.load_contexts.last_mut() {
|
||||||
|
load_context.module = module_name.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.wam.indices.modules.insert(module_name, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn import_module(&mut self, module_name: ClauseName) -> Result<(), SessionError> {
|
||||||
|
if let Some(module) = self.wam.indices.modules.remove(&module_name) {
|
||||||
|
match &self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
import_module_exports(
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&self.compilation_target,
|
||||||
|
&module,
|
||||||
|
&mut self.wam.indices.code_dir,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
&mut self.wam.indices.meta_predicates,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref defining_module_name) => {
|
||||||
|
match self.wam.indices.modules.get_mut(defining_module_name) {
|
||||||
|
Some(ref mut target_module) => {
|
||||||
|
import_module_exports_into_module(
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&self.compilation_target,
|
||||||
|
&module,
|
||||||
|
&mut target_module.code_dir,
|
||||||
|
&mut target_module.op_dir,
|
||||||
|
&mut target_module.meta_predicates,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
&mut self.module_op_exports,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// we find ourselves here because we're trying to import
|
||||||
|
// a module into itself as it is being defined.
|
||||||
|
self.wam.indices.modules.insert(module_name.clone(), module);
|
||||||
|
return Err(SessionError::ModuleCannotImportSelf(module_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.wam.indices.modules.insert(module_name, module);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_qualified_module(
|
||||||
|
&mut self,
|
||||||
|
module_name: ClauseName,
|
||||||
|
exports: IndexSet<ModuleExport>,
|
||||||
|
) -> Result<(), SessionError> {
|
||||||
|
if let Some(module) = self.wam.indices.modules.remove(&module_name) {
|
||||||
|
match &self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
import_qualified_module_exports(
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&self.compilation_target,
|
||||||
|
&module,
|
||||||
|
&exports,
|
||||||
|
&mut self.wam.indices.code_dir,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref defining_module_name) => {
|
||||||
|
match self.wam.indices.modules.get_mut(defining_module_name) {
|
||||||
|
Some(ref mut target_module) => {
|
||||||
|
import_qualified_module_exports_into_module(
|
||||||
|
&mut self.retraction_info,
|
||||||
|
&self.compilation_target,
|
||||||
|
&module,
|
||||||
|
&exports,
|
||||||
|
&mut target_module.code_dir,
|
||||||
|
&mut target_module.op_dir,
|
||||||
|
&mut self.wam.indices.op_dir,
|
||||||
|
&mut self.module_op_exports,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// we find ourselves here because we're trying to import
|
||||||
|
// a module into itself as it is being defined.
|
||||||
|
self.wam.indices.modules.insert(module_name.clone(), module);
|
||||||
|
return Err(SessionError::ModuleCannotImportSelf(module_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.wam.indices.modules.insert(module_name, module);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> {
|
||||||
|
let (stream, listing_src) =
|
||||||
|
match module_src {
|
||||||
|
ModuleSource::File(filename) => {
|
||||||
|
let mut path_buf = PathBuf::from(filename.as_str());
|
||||||
|
path_buf.set_extension("pl");
|
||||||
|
let file = File::open(&path_buf)?;
|
||||||
|
|
||||||
|
(Stream::from_file_as_input(filename.clone(), file),
|
||||||
|
ListingSource::File(filename, path_buf))
|
||||||
|
}
|
||||||
|
ModuleSource::Library(library) => {
|
||||||
|
match LIBRARIES.borrow().get(library.as_str()) {
|
||||||
|
Some(code) => {
|
||||||
|
if let Some(ref module) = self.wam.indices.modules.get(&library) {
|
||||||
|
if let ListingSource::DynamicallyGenerated = &module.listing_src {
|
||||||
|
(Stream::from(*code), ListingSource::User)
|
||||||
|
} else {
|
||||||
|
return self.import_module(library);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(Stream::from(*code), ListingSource::User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return self.import_module(library);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let compilation_target = {
|
||||||
|
let stream = &mut parsing_stream(stream)?;
|
||||||
|
|
||||||
|
let ts = BootstrappingTermStream::from_prolog_stream(
|
||||||
|
stream,
|
||||||
|
self.wam.machine_st.atom_tbl.clone(),
|
||||||
|
self.wam.machine_st.flags,
|
||||||
|
listing_src,
|
||||||
|
);
|
||||||
|
|
||||||
|
let subloader = Loader::new(ts, self.wam);
|
||||||
|
subloader.load()?
|
||||||
|
};
|
||||||
|
|
||||||
|
match compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
// nothing to do.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(module_name) => {
|
||||||
|
self.import_module(module_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn use_qualified_module(
|
||||||
|
&mut self,
|
||||||
|
module_src: ModuleSource,
|
||||||
|
exports: IndexSet<ModuleExport>,
|
||||||
|
) -> Result<(), SessionError> {
|
||||||
|
let (stream, listing_src) =
|
||||||
|
match module_src {
|
||||||
|
ModuleSource::File(filename) => {
|
||||||
|
let mut path_buf = PathBuf::from(filename.as_str());
|
||||||
|
path_buf.set_extension("pl");
|
||||||
|
let file = File::open(&path_buf)?;
|
||||||
|
|
||||||
|
(Stream::from_file_as_input(filename.clone(), file),
|
||||||
|
ListingSource::File(filename, path_buf))
|
||||||
|
}
|
||||||
|
ModuleSource::Library(library) => {
|
||||||
|
match LIBRARIES.borrow().get(library.as_str()) {
|
||||||
|
Some(code) => {
|
||||||
|
if self.wam.indices.modules.contains_key(&library) {
|
||||||
|
return self.import_qualified_module(library, exports);
|
||||||
|
} else {
|
||||||
|
(Stream::from(*code), ListingSource::User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return self.import_qualified_module(library, exports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let compilation_target = {
|
||||||
|
let stream = &mut parsing_stream(stream)?;
|
||||||
|
|
||||||
|
let ts = BootstrappingTermStream::from_prolog_stream(
|
||||||
|
stream,
|
||||||
|
self.wam.machine_st.atom_tbl.clone(),
|
||||||
|
self.wam.machine_st.flags,
|
||||||
|
listing_src,
|
||||||
|
);
|
||||||
|
|
||||||
|
let subloader = Loader::new(ts, self.wam);
|
||||||
|
subloader.load()?
|
||||||
|
};
|
||||||
|
|
||||||
|
match compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
// nothing to do.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(module_name) => {
|
||||||
|
self.import_qualified_module(module_name, exports)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn composite_op_dir(&self) -> CompositeOpDir {
|
||||||
|
match &self.compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
CompositeOpDir::new(&self.wam.indices.op_dir, None)
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
match self.wam.indices.modules.get(module_name) {
|
||||||
|
Some(ref module) => {
|
||||||
|
CompositeOpDir::new(&self.wam.indices.op_dir, Some(&module.op_dir))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1708
src/machine/loader.rs
Normal file
1708
src/machine/loader.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::forms::{ModuleSource, Number, PredicateKey};
|
use crate::forms::{ModuleSource, Number}; //, PredicateKey};
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
use crate::machine::machine_state::*;
|
use crate::machine::machine_state::*;
|
||||||
@@ -355,24 +355,11 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
|
||||||
fn uninstantiation_error(culprit: Addr) -> Self {
|
|
||||||
let stub = functor!(
|
|
||||||
"uninstantiation_error",
|
|
||||||
[addr(culprit)]
|
|
||||||
);
|
|
||||||
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Received,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn session_error(h: usize, err: SessionError) -> Self {
|
fn session_error(h: usize, err: SessionError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
SessionError::CannotOverwriteBuiltIn(pred_str) |
|
// SessionError::CannotOverwriteBuiltIn(pred_str) |
|
||||||
|
/*
|
||||||
SessionError::CannotOverwriteImport(pred_str) => {
|
SessionError::CannotOverwriteImport(pred_str) => {
|
||||||
Self::permission_error(
|
Self::permission_error(
|
||||||
h,
|
h,
|
||||||
@@ -381,12 +368,14 @@ impl MachineError {
|
|||||||
functor!(clause_name(pred_str)),
|
functor!(clause_name(pred_str)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
SessionError::ExistenceError(err) => {
|
SessionError::ExistenceError(err) => {
|
||||||
Self::existence_error(h, err)
|
Self::existence_error(h, err)
|
||||||
}
|
}
|
||||||
SessionError::InvalidFileName(filename) => {
|
// SessionError::InvalidFileName(filename) => {
|
||||||
Self::existence_error(h, ExistenceError::Module(filename))
|
// Self::existence_error(h, ExistenceError::Module(filename))
|
||||||
}
|
// }
|
||||||
|
/*
|
||||||
SessionError::ModuleDoesNotContainExport(..) => {
|
SessionError::ModuleDoesNotContainExport(..) => {
|
||||||
Self::permission_error(
|
Self::permission_error(
|
||||||
h,
|
h,
|
||||||
@@ -395,6 +384,15 @@ impl MachineError {
|
|||||||
functor!("module_does_not_contain_claimed_export"),
|
functor!("module_does_not_contain_claimed_export"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
SessionError::ModuleCannotImportSelf(module_name) => {
|
||||||
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Modify,
|
||||||
|
"module",
|
||||||
|
functor!("module_cannot_import_self", [clause_name(module_name)]),
|
||||||
|
)
|
||||||
|
}
|
||||||
SessionError::NamelessEntry => {
|
SessionError::NamelessEntry => {
|
||||||
Self::permission_error(
|
Self::permission_error(
|
||||||
h,
|
h,
|
||||||
@@ -411,7 +409,7 @@ impl MachineError {
|
|||||||
functor!(clause_name(op)),
|
functor!(clause_name(op)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SessionError::ParserError(err) => {
|
SessionError::CompilationError(err) => {
|
||||||
Self::syntax_error(h, err)
|
Self::syntax_error(h, err)
|
||||||
}
|
}
|
||||||
SessionError::QueryCannotBeDefinedAsFact => {
|
SessionError::QueryCannotBeDefinedAsFact => {
|
||||||
@@ -426,13 +424,15 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn syntax_error(h: usize, err: ParserError) -> Self {
|
fn syntax_error<E: Into<CompilationError>>(h: usize, err: E) -> Self {
|
||||||
if let ParserError::Arithmetic(err) = err {
|
let err = err.into();
|
||||||
|
|
||||||
|
if let CompilationError::Arithmetic(err) = err {
|
||||||
return Self::arithmetic_error(h, err);
|
return Self::arithmetic_error(h, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let location = err.line_and_col_num();
|
let location = err.line_and_col_num();
|
||||||
let stub = functor!(err.as_str());
|
let stub = err.as_functor(h);
|
||||||
|
|
||||||
let stub = functor!(
|
let stub = functor!(
|
||||||
"syntax_error",
|
"syntax_error",
|
||||||
@@ -475,9 +475,103 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CompilationError {
|
||||||
|
Arithmetic(ArithmeticError),
|
||||||
|
ParserError(ParserError),
|
||||||
|
// BadPendingByte,
|
||||||
|
CannotParseCyclicTerm,
|
||||||
|
// ExpandedTermsListNotAList,
|
||||||
|
ExpectedRel,
|
||||||
|
// ExpectedTopLevelTerm,
|
||||||
|
InadmissibleFact,
|
||||||
|
InadmissibleQueryTerm,
|
||||||
|
InconsistentEntry,
|
||||||
|
// InvalidDoubleQuotesDecl,
|
||||||
|
// InvalidHook,
|
||||||
|
InvalidMetaPredicateDecl,
|
||||||
|
InvalidModuleDecl,
|
||||||
|
InvalidModuleExport,
|
||||||
|
InvalidRuleHead,
|
||||||
|
InvalidUseModuleDecl,
|
||||||
|
InvalidModuleResolution(ClauseName),
|
||||||
|
UnreadableTerm,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ArithmeticError> for CompilationError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: ArithmeticError) -> CompilationError {
|
||||||
|
CompilationError::Arithmetic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParserError> for CompilationError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: ParserError) -> CompilationError {
|
||||||
|
CompilationError::ParserError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompilationError {
|
||||||
|
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
|
||||||
|
match self {
|
||||||
|
&CompilationError::ParserError(ref err) =>
|
||||||
|
err.line_and_col_num(),
|
||||||
|
_ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_functor(&self, _h: usize) -> MachineStub {
|
||||||
|
match self {
|
||||||
|
&CompilationError::Arithmetic(..) =>
|
||||||
|
functor!("arithmetic_error"),
|
||||||
|
// &CompilationError::BadPendingByte =>
|
||||||
|
// functor!("bad_pending_byte"),
|
||||||
|
&CompilationError::CannotParseCyclicTerm =>
|
||||||
|
functor!("cannot_parse_cyclic_term"),
|
||||||
|
// &CompilationError::ExpandedTermsListNotAList =>
|
||||||
|
// functor!("expanded_terms_list_is_not_a_list"),
|
||||||
|
&CompilationError::ExpectedRel =>
|
||||||
|
functor!("expected_relation"),
|
||||||
|
// &CompilationError::ExpectedTopLevelTerm =>
|
||||||
|
// functor!("expected_atom_or_cons_or_clause"),
|
||||||
|
&CompilationError::InadmissibleFact =>
|
||||||
|
functor!("inadmissible_fact"),
|
||||||
|
&CompilationError::InadmissibleQueryTerm =>
|
||||||
|
functor!("inadmissible_query_term"),
|
||||||
|
&CompilationError::InconsistentEntry =>
|
||||||
|
functor!("inconsistent_entry"),
|
||||||
|
// &CompilationError::InvalidDoubleQuotesDecl =>
|
||||||
|
// functor!("invalid_double_quotes_declaration"),
|
||||||
|
// &CompilationError::InvalidHook =>
|
||||||
|
// functor!("invalid_hook"),
|
||||||
|
&CompilationError::InvalidMetaPredicateDecl =>
|
||||||
|
functor!("invalid_meta_predicate_decl"),
|
||||||
|
&CompilationError::InvalidModuleDecl =>
|
||||||
|
functor!("invalid_module_declaration"),
|
||||||
|
&CompilationError::InvalidModuleExport =>
|
||||||
|
functor!("invalid_module_export"),
|
||||||
|
&CompilationError::InvalidModuleResolution(ref module_name) =>
|
||||||
|
functor!(
|
||||||
|
"no_such_module",
|
||||||
|
[clause_name(module_name.clone())]
|
||||||
|
),
|
||||||
|
&CompilationError::InvalidRuleHead =>
|
||||||
|
functor!("invalid_head_of_rule"),
|
||||||
|
&CompilationError::InvalidUseModuleDecl =>
|
||||||
|
functor!("invalid_use_module_declaration"),
|
||||||
|
&CompilationError::ParserError(ref err) =>
|
||||||
|
functor!(err.as_str()),
|
||||||
|
&CompilationError::UnreadableTerm =>
|
||||||
|
functor!("unreadable_term"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Permission {
|
pub enum Permission {
|
||||||
Access,
|
// Access,
|
||||||
Create,
|
Create,
|
||||||
InputStream,
|
InputStream,
|
||||||
Modify,
|
Modify,
|
||||||
@@ -490,7 +584,7 @@ impl Permission {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Permission::Access => "access",
|
// Permission::Access => "access",
|
||||||
Permission::Create => "create",
|
Permission::Create => "create",
|
||||||
Permission::InputStream => "input",
|
Permission::InputStream => "input",
|
||||||
Permission::Modify => "modify",
|
Permission::Modify => "modify",
|
||||||
@@ -807,37 +901,55 @@ pub enum ExistenceError {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SessionError {
|
pub enum SessionError {
|
||||||
CannotOverwriteBuiltIn(ClauseName),
|
CompilationError(CompilationError),
|
||||||
CannotOverwriteImport(ClauseName),
|
// CannotOverwriteBuiltIn(ClauseName),
|
||||||
|
// CannotOverwriteImport(ClauseName),
|
||||||
ExistenceError(ExistenceError),
|
ExistenceError(ExistenceError),
|
||||||
InvalidFileName(ClauseName),
|
// InvalidFileName(ClauseName),
|
||||||
ModuleDoesNotContainExport(ClauseName, PredicateKey),
|
// ModuleDoesNotContainExport(ClauseName, PredicateKey),
|
||||||
|
ModuleCannotImportSelf(ClauseName),
|
||||||
NamelessEntry,
|
NamelessEntry,
|
||||||
OpIsInfixAndPostFix(ClauseName),
|
OpIsInfixAndPostFix(ClauseName),
|
||||||
QueryCannotBeDefinedAsFact,
|
QueryCannotBeDefinedAsFact,
|
||||||
ParserError(ParserError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EvalSession {
|
pub enum EvalSession {
|
||||||
EntrySuccess,
|
// EntrySuccess,
|
||||||
Error(SessionError),
|
Error(SessionError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SessionError> for EvalSession {
|
impl From<SessionError> for EvalSession {
|
||||||
|
#[inline]
|
||||||
fn from(err: SessionError) -> Self {
|
fn from(err: SessionError) -> Self {
|
||||||
EvalSession::Error(err)
|
EvalSession::Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for SessionError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: std::io::Error) -> SessionError {
|
||||||
|
SessionError::from(ParserError::from(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<ParserError> for SessionError {
|
impl From<ParserError> for SessionError {
|
||||||
|
#[inline]
|
||||||
fn from(err: ParserError) -> Self {
|
fn from(err: ParserError) -> Self {
|
||||||
SessionError::ParserError(err)
|
SessionError::CompilationError(CompilationError::from(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CompilationError> for SessionError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: CompilationError) -> Self {
|
||||||
|
SessionError::CompilationError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ParserError> for EvalSession {
|
impl From<ParserError> for EvalSession {
|
||||||
|
#[inline]
|
||||||
fn from(err: ParserError) -> Self {
|
fn from(err: ParserError) -> Self {
|
||||||
EvalSession::from(SessionError::ParserError(err))
|
EvalSession::from(SessionError::from(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::*;
|
||||||
use crate::prolog_parser::tabled_rc::*;
|
|
||||||
|
|
||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::fixtures::*;
|
use crate::fixtures::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
|
use crate::machine::CompilationTarget;
|
||||||
use crate::machine::code_repo::CodeRepo;
|
use crate::machine::code_repo::CodeRepo;
|
||||||
use crate::machine::Ball;
|
use crate::machine::Ball;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
@@ -11,20 +11,21 @@ use crate::machine::machine_state::*;
|
|||||||
use crate::machine::partial_string::*;
|
use crate::machine::partial_string::*;
|
||||||
use crate::machine::raw_block::RawBlockTraits;
|
use crate::machine::raw_block::RawBlockTraits;
|
||||||
use crate::machine::streams::Stream;
|
use crate::machine::streams::Stream;
|
||||||
|
use crate::machine::term_stream::LoadStatePayload;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::ordered_float::OrderedFloat;
|
use crate::ordered_float::OrderedFloat;
|
||||||
use crate::rug::{Integer, Rational};
|
use crate::rug::{Integer, Rational};
|
||||||
|
|
||||||
use crate::indexmap::IndexMap;
|
use crate::indexmap::IndexMap;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
// use std::mem;
|
||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
@@ -64,6 +65,7 @@ pub enum Addr {
|
|||||||
Fixnum(isize),
|
Fixnum(isize),
|
||||||
Float(OrderedFloat<f64>),
|
Float(OrderedFloat<f64>),
|
||||||
Lis(usize),
|
Lis(usize),
|
||||||
|
LoadStatePayload(usize),
|
||||||
HeapCell(usize),
|
HeapCell(usize),
|
||||||
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
||||||
StackCell(usize, usize),
|
StackCell(usize, usize),
|
||||||
@@ -231,7 +233,7 @@ impl Addr {
|
|||||||
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||||
Some(TermOrderCategory::Compound)
|
Some(TermOrderCategory::Compound)
|
||||||
}
|
}
|
||||||
Addr::CutPoint(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
|
Addr::CutPoint(_) | Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,6 +371,7 @@ pub enum HeapCellValue {
|
|||||||
Atom(ClauseName, Option<SharedOpDesc>),
|
Atom(ClauseName, Option<SharedOpDesc>),
|
||||||
DBRef(DBRef),
|
DBRef(DBRef),
|
||||||
Integer(Rc<Integer>),
|
Integer(Rc<Integer>),
|
||||||
|
LoadStatePayload(LoadStatePayload),
|
||||||
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
||||||
Rational(Rc<Rational>),
|
Rational(Rc<Rational>),
|
||||||
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
|
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
|
||||||
@@ -387,6 +390,9 @@ impl HeapCellValue {
|
|||||||
HeapCellValue::Rational(..) => {
|
HeapCellValue::Rational(..) => {
|
||||||
Addr::Con(focus)
|
Addr::Con(focus)
|
||||||
}
|
}
|
||||||
|
HeapCellValue::LoadStatePayload(_) => {
|
||||||
|
Addr::LoadStatePayload(focus)
|
||||||
|
}
|
||||||
HeapCellValue::NamedStr(_, _, _) => {
|
HeapCellValue::NamedStr(_, _, _) => {
|
||||||
Addr::Str(focus)
|
Addr::Str(focus)
|
||||||
}
|
}
|
||||||
@@ -417,6 +423,9 @@ impl HeapCellValue {
|
|||||||
&HeapCellValue::Integer(ref n) => {
|
&HeapCellValue::Integer(ref n) => {
|
||||||
HeapCellValue::Integer(n.clone())
|
HeapCellValue::Integer(n.clone())
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::LoadStatePayload(_) => {
|
||||||
|
HeapCellValue::Atom(clause_name!("$live_term_stream"), None)
|
||||||
|
}
|
||||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
}
|
}
|
||||||
@@ -443,50 +452,42 @@ impl From<Addr> for HeapCellValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub enum IndexPtr {
|
pub enum IndexPtr {
|
||||||
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||||
Undefined,
|
|
||||||
InSituDirEntry(usize),
|
|
||||||
Index(usize),
|
Index(usize),
|
||||||
UserGoalExpansion,
|
Undefined,
|
||||||
UserTermExpansion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct CodeIndex(pub Rc<RefCell<(IndexPtr, ClauseName)>>);
|
pub struct CodeIndex(pub Rc<Cell<IndexPtr>>);
|
||||||
|
|
||||||
|
impl Deref for CodeIndex {
|
||||||
|
type Target = Cell<IndexPtr>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.0.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CodeIndex {
|
impl CodeIndex {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(ptr: IndexPtr, module_name: ClauseName) -> Self {
|
pub(super)
|
||||||
CodeIndex(Rc::new(RefCell::new(( ptr, module_name ))))
|
fn new(ptr: IndexPtr) -> Self {
|
||||||
|
CodeIndex(Rc::new(Cell::new(ptr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_undefined(&self) -> bool {
|
pub fn is_undefined(&self) -> bool {
|
||||||
let index_ptr = &self.0.borrow().0;
|
match self.0.get() {
|
||||||
|
IndexPtr::Undefined => true, // | &IndexPtr::DynamicUndefined => true,
|
||||||
match index_ptr {
|
|
||||||
&IndexPtr::Undefined | &IndexPtr::DynamicUndefined => true,
|
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn dynamic_undefined(module_name: ClauseName) -> Self {
|
|
||||||
CodeIndex(Rc::new(RefCell::new((
|
|
||||||
IndexPtr::DynamicUndefined,
|
|
||||||
module_name
|
|
||||||
))))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn module_name(&self) -> ClauseName {
|
|
||||||
self.0.borrow().1.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn local(&self) -> Option<usize> {
|
pub fn local(&self) -> Option<usize> {
|
||||||
match self.0.borrow().0 {
|
match self.0.get() {
|
||||||
IndexPtr::Index(i) => Some(i),
|
IndexPtr::Index(i) => Some(i),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -495,60 +496,34 @@ impl CodeIndex {
|
|||||||
|
|
||||||
impl Default for CodeIndex {
|
impl Default for CodeIndex {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CodeIndex(Rc::new(RefCell::new((
|
CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)))
|
||||||
IndexPtr::Undefined,
|
|
||||||
clause_name!(""),
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(usize, ClauseName)> for CodeIndex {
|
|
||||||
fn from(value: (usize, ClauseName)) -> Self {
|
|
||||||
CodeIndex(Rc::new(RefCell::new((IndexPtr::Index(value.0), value.1))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
||||||
pub enum DynamicAssertPlace {
|
|
||||||
Back,
|
|
||||||
Front,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DynamicAssertPlace {
|
|
||||||
#[inline]
|
|
||||||
pub fn predicate_name(self) -> ClauseName {
|
|
||||||
match self {
|
|
||||||
DynamicAssertPlace::Back => clause_name!("assertz"),
|
|
||||||
DynamicAssertPlace::Front => clause_name!("asserta"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn push_to_queue(self, addrs: &mut VecDeque<Addr>, new_addr: Addr) {
|
|
||||||
match self {
|
|
||||||
DynamicAssertPlace::Back => addrs.push_back(new_addr),
|
|
||||||
DynamicAssertPlace::Front => addrs.push_front(new_addr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
||||||
pub enum DynamicTransactionType {
|
|
||||||
Abolish,
|
|
||||||
Assert(DynamicAssertPlace),
|
|
||||||
ModuleAbolish,
|
|
||||||
ModuleAssert(DynamicAssertPlace),
|
|
||||||
ModuleRetract,
|
|
||||||
Retract, // dynamic index of the clause to remove.
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
pub enum REPLCodePtr {
|
pub enum REPLCodePtr {
|
||||||
CompileBatch,
|
AddDynamicPredicate,
|
||||||
|
AddGoalExpansionClause,
|
||||||
|
AddTermExpansionClause,
|
||||||
|
ClauseToEvacuable,
|
||||||
|
ConcludeLoad,
|
||||||
|
DeclareModule,
|
||||||
|
LoadCompiledLibrary,
|
||||||
|
LoadContextSource,
|
||||||
|
LoadContextFile,
|
||||||
|
LoadContextDirectory,
|
||||||
|
LoadContextModule,
|
||||||
|
LoadContextStream,
|
||||||
|
PopLoadContext,
|
||||||
|
PopLoadStatePayload,
|
||||||
|
PushLoadContext,
|
||||||
|
PushLoadStatePayload,
|
||||||
UseModule,
|
UseModule,
|
||||||
UseQualifiedModule,
|
MetaPredicateProperty,
|
||||||
UseModuleFromFile,
|
CompilePendingPredicates,
|
||||||
UseQualifiedModuleFromFile
|
UserAsserta,
|
||||||
|
UserAssertz,
|
||||||
|
UserRetract,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@@ -556,7 +531,7 @@ pub enum CodePtr {
|
|||||||
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
||||||
CallN(usize, LocalCodePtr, bool), // arity, local, last call.
|
CallN(usize, LocalCodePtr, bool), // arity, local, last call.
|
||||||
Local(LocalCodePtr),
|
Local(LocalCodePtr),
|
||||||
DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
|
// DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
|
||||||
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
|
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
|
||||||
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
|
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
|
||||||
}
|
}
|
||||||
@@ -568,18 +543,26 @@ impl CodePtr {
|
|||||||
| &CodePtr::CallN(_, ref local, _)
|
| &CodePtr::CallN(_, ref local, _)
|
||||||
| &CodePtr::Local(ref local) => local.clone(),
|
| &CodePtr::Local(ref local) => local.clone(),
|
||||||
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
|
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
|
||||||
&CodePtr::REPL(_, p) | &CodePtr::DynamicTransaction(_, p) => p,
|
&CodePtr::REPL(_, p) => p // | &CodePtr::DynamicTransaction(_, p) => p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_halt(&self) -> bool {
|
||||||
|
if let CodePtr::Local(LocalCodePtr::Halt) = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum LocalCodePtr {
|
pub enum LocalCodePtr {
|
||||||
DirEntry(usize), // offset.
|
DirEntry(usize), // offset
|
||||||
InSituDirEntry(usize),
|
Halt,
|
||||||
TopLevel(usize, usize), // chunk_num, offset.
|
IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset
|
||||||
UserGoalExpansion(usize),
|
// TopLevel(usize, usize), // chunk_num, offset
|
||||||
UserTermExpansion(usize),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalCodePtr {
|
impl LocalCodePtr {
|
||||||
@@ -591,6 +574,16 @@ impl LocalCodePtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn abs_loc(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
LocalCodePtr::DirEntry(ref p) => *p,
|
||||||
|
LocalCodePtr::IndexingBuf(ref p, ..) => *p,
|
||||||
|
LocalCodePtr::Halt => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool {
|
fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool {
|
||||||
match code_repo.lookup_instr(last_call, &CodePtr::Local(*self)) {
|
match code_repo.lookup_instr(last_call, &CodePtr::Local(*self)) {
|
||||||
@@ -621,28 +614,21 @@ impl LocalCodePtr {
|
|||||||
[integer(*p)]
|
[integer(*p)]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::InSituDirEntry(p) => {
|
LocalCodePtr::Halt => {
|
||||||
heap.append(functor!(
|
heap.append(functor!("halt"));
|
||||||
"in_situ_dir_entry",
|
|
||||||
[integer(*p)]
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"top_level",
|
"top_level",
|
||||||
[integer(*chunk_num), integer(*offset)]
|
[integer(*chunk_num), integer(*offset)]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::UserGoalExpansion(p) => {
|
*/
|
||||||
|
LocalCodePtr::IndexingBuf(p, o, i) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"user_goal_expansion",
|
"indexed_buf",
|
||||||
[integer(*p)]
|
[integer(*p), integer(*o), integer(*i)]
|
||||||
));
|
|
||||||
}
|
|
||||||
LocalCodePtr::UserTermExpansion(p) => {
|
|
||||||
heap.append(functor!(
|
|
||||||
"user_term_expansion",
|
|
||||||
[integer(*p)]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,6 +637,7 @@ impl LocalCodePtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
impl PartialOrd<CodePtr> for CodePtr {
|
impl PartialOrd<CodePtr> for CodePtr {
|
||||||
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
@@ -667,11 +654,8 @@ impl PartialOrd<CodePtr> for CodePtr {
|
|||||||
impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
||||||
fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2))
|
(&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2)) |
|
||||||
| (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2))
|
(&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
||||||
| (&LocalCodePtr::UserTermExpansion(p1), &LocalCodePtr::UserTermExpansion(ref p2))
|
|
||||||
| (&LocalCodePtr::UserGoalExpansion(p1), &LocalCodePtr::UserGoalExpansion(ref p2))
|
|
||||||
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
|
||||||
p1.partial_cmp(p2)
|
p1.partial_cmp(p2)
|
||||||
}
|
}
|
||||||
(_, &LocalCodePtr::TopLevel(_, _)) => {
|
(_, &LocalCodePtr::TopLevel(_, _)) => {
|
||||||
@@ -683,29 +667,34 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
impl Default for CodePtr {
|
impl Default for CodePtr {
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CodePtr::Local(LocalCodePtr::default())
|
CodePtr::Local(LocalCodePtr::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LocalCodePtr {
|
impl Default for LocalCodePtr {
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
LocalCodePtr::TopLevel(0, 0)
|
LocalCodePtr::DirEntry(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<usize> for LocalCodePtr {
|
impl Add<usize> for LocalCodePtr {
|
||||||
type Output = LocalCodePtr;
|
type Output = LocalCodePtr;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn add(self, rhs: usize) -> Self::Output {
|
fn add(self, rhs: usize) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
LocalCodePtr::InSituDirEntry(p) => LocalCodePtr::InSituDirEntry(p + rhs),
|
LocalCodePtr::DirEntry(p) =>
|
||||||
LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs),
|
LocalCodePtr::DirEntry(p + rhs),
|
||||||
LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs),
|
LocalCodePtr::Halt =>
|
||||||
LocalCodePtr::UserTermExpansion(p) => LocalCodePtr::UserTermExpansion(p + rhs),
|
unreachable!(),
|
||||||
LocalCodePtr::UserGoalExpansion(p) => LocalCodePtr::UserGoalExpansion(p + rhs),
|
LocalCodePtr::IndexingBuf(p, o, i) =>
|
||||||
|
LocalCodePtr::IndexingBuf(p, o, i + rhs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,30 +702,40 @@ impl Add<usize> for LocalCodePtr {
|
|||||||
impl Sub<usize> for LocalCodePtr {
|
impl Sub<usize> for LocalCodePtr {
|
||||||
type Output = Option<LocalCodePtr>;
|
type Output = Option<LocalCodePtr>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn sub(self, rhs: usize) -> Self::Output {
|
fn sub(self, rhs: usize) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
LocalCodePtr::InSituDirEntry(p) =>
|
|
||||||
p.checked_sub(rhs).map(LocalCodePtr::InSituDirEntry),
|
|
||||||
LocalCodePtr::DirEntry(p) =>
|
LocalCodePtr::DirEntry(p) =>
|
||||||
p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
|
p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
|
||||||
LocalCodePtr::TopLevel(cn, p) =>
|
LocalCodePtr::Halt =>
|
||||||
p.checked_sub(rhs).map(|r| LocalCodePtr::TopLevel(cn, r)),
|
unreachable!(),
|
||||||
LocalCodePtr::UserTermExpansion(p) =>
|
LocalCodePtr::IndexingBuf(p, o, i) =>
|
||||||
p.checked_sub(rhs).map(LocalCodePtr::UserTermExpansion),
|
i.checked_sub(rhs).map(|r| LocalCodePtr::IndexingBuf(p, o, r)),
|
||||||
LocalCodePtr::UserGoalExpansion(p) =>
|
|
||||||
p.checked_sub(rhs).map(LocalCodePtr::UserGoalExpansion),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SubAssign<usize> for LocalCodePtr {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: usize) {
|
||||||
|
match self {
|
||||||
|
LocalCodePtr::DirEntry(ref mut p) =>
|
||||||
|
*p -= rhs,
|
||||||
|
LocalCodePtr::Halt | LocalCodePtr::IndexingBuf(..) =>
|
||||||
|
unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl AddAssign<usize> for LocalCodePtr {
|
impl AddAssign<usize> for LocalCodePtr {
|
||||||
|
#[inline]
|
||||||
fn add_assign(&mut self, rhs: usize) {
|
fn add_assign(&mut self, rhs: usize) {
|
||||||
match self {
|
match self {
|
||||||
&mut LocalCodePtr::InSituDirEntry(ref mut p)
|
&mut LocalCodePtr::DirEntry(ref mut p) /* |
|
||||||
| &mut LocalCodePtr::UserGoalExpansion(ref mut p)
|
&mut LocalCodePtr::TopLevel(_, ref mut p) */ => *p += rhs,
|
||||||
| &mut LocalCodePtr::UserTermExpansion(ref mut p)
|
&mut LocalCodePtr::IndexingBuf(_, _, ref mut i) => *i += rhs,
|
||||||
| &mut LocalCodePtr::DirEntry(ref mut p)
|
&mut LocalCodePtr::Halt => unreachable!(),
|
||||||
| &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -746,10 +745,14 @@ impl Add<usize> for CodePtr {
|
|||||||
|
|
||||||
fn add(self, rhs: usize) -> Self::Output {
|
fn add(self, rhs: usize) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
p @ CodePtr::REPL(..)
|
p @ CodePtr::REPL(..) |
|
||||||
| p @ CodePtr::VerifyAttrInterrupt(_)
|
p @ CodePtr::VerifyAttrInterrupt(_) => { // |
|
||||||
| p @ CodePtr::DynamicTransaction(..) => p,
|
// p @ CodePtr::DynamicTransaction(..) => {
|
||||||
CodePtr::Local(local) => CodePtr::Local(local + rhs),
|
p
|
||||||
|
}
|
||||||
|
CodePtr::Local(local) => {
|
||||||
|
CodePtr::Local(local + rhs)
|
||||||
|
}
|
||||||
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
|
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
|
||||||
CodePtr::Local(local + rhs)
|
CodePtr::Local(local + rhs)
|
||||||
}
|
}
|
||||||
@@ -767,186 +770,206 @@ impl AddAssign<usize> for CodePtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
impl SubAssign<usize> for CodePtr {
|
||||||
pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: usize) {
|
||||||
#[derive(Debug, Clone)]
|
match self {
|
||||||
pub struct DynamicPredicateInfo {
|
CodePtr::Local(ref mut local) => *local -= rhs,
|
||||||
pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value.
|
_ => unreachable!(),
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DynamicPredicateInfo {
|
|
||||||
fn default() -> Self {
|
|
||||||
DynamicPredicateInfo {
|
|
||||||
clauses_subsection_p: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
||||||
|
pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
|
||||||
|
|
||||||
pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
||||||
|
|
||||||
// key type: module name, predicate indicator.
|
|
||||||
pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
|
|
||||||
|
|
||||||
pub type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<usize>)>;
|
pub type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<usize>)>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct ModuleStub {
|
pub(crate) struct ModuleStub {
|
||||||
pub(crate) atom_tbl: TabledData<Atom>,
|
|
||||||
pub(crate) in_situ_code_dir: InSituCodeDir,
|
pub(crate) in_situ_code_dir: InSituCodeDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleStub {
|
// pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
|
||||||
pub(crate) fn new(atom_tbl: TabledData<Atom>) -> Self {
|
|
||||||
ModuleStub {
|
|
||||||
atom_tbl,
|
|
||||||
in_situ_code_dir: InSituCodeDir::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
|
|
||||||
pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
|
pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
|
||||||
pub(crate) type StreamDir = BTreeSet<Stream>;
|
pub(crate) type StreamDir = BTreeSet<Stream>;
|
||||||
|
|
||||||
|
pub type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>>;
|
||||||
|
|
||||||
|
pub type ExtensiblePredicates = IndexMap<PredicateKey, PredicateSkeleton>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IndexStore {
|
pub struct IndexStore {
|
||||||
pub(super) atom_tbl: TabledData<Atom>,
|
|
||||||
pub(super) code_dir: CodeDir,
|
pub(super) code_dir: CodeDir,
|
||||||
pub(super) dynamic_code_dir: DynamicCodeDir,
|
pub(super) extensible_predicates: ExtensiblePredicates,
|
||||||
pub(super) global_variables: GlobalVarDir,
|
pub(super) global_variables: GlobalVarDir,
|
||||||
pub(super) in_situ_code_dir: InSituCodeDir,
|
pub(super) meta_predicates: MetaPredicateDir,
|
||||||
pub(super) in_situ_module_dir: ModuleStubDir,
|
|
||||||
pub(super) module_dir: ModuleDir,
|
|
||||||
pub(super) modules: ModuleDir,
|
pub(super) modules: ModuleDir,
|
||||||
pub(super) op_dir: OpDir,
|
pub(super) op_dir: OpDir,
|
||||||
pub(super) streams: StreamDir,
|
pub(super) streams: StreamDir,
|
||||||
pub(super) stream_aliases: StreamAliasDir,
|
pub(super) stream_aliases: StreamAliasDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for IndexStore {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IndexStore {
|
impl IndexStore {
|
||||||
pub fn predicate_exists(
|
pub fn get_predicate_skeleton(
|
||||||
&self,
|
&mut self,
|
||||||
name: ClauseName,
|
compilation_target: &CompilationTarget,
|
||||||
module: ClauseName,
|
key: &PredicateKey,
|
||||||
arity: usize,
|
) -> Option<&mut PredicateSkeleton> {
|
||||||
op_spec: Option<SharedOpDesc>,
|
match (key.0.as_str(), key.1) {
|
||||||
) -> bool {
|
("term_expansion", 2) => {
|
||||||
match self.modules.get(&module) {
|
self.extensible_predicates.get_mut(key)
|
||||||
Some(module) => match ClauseType::from(name, arity, op_spec) {
|
}
|
||||||
ClauseType::Named(name, arity, _) => module.code_dir.contains_key(&(name, arity)),
|
_ => {
|
||||||
ClauseType::Op(name, spec, ..) => {
|
match compilation_target {
|
||||||
module.code_dir.contains_key(&(name, spec.arity()))
|
CompilationTarget::User => {
|
||||||
|
self.extensible_predicates.get_mut(key)
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
if let Some(module) = self.modules.get_mut(module_name) {
|
||||||
|
module.extensible_predicates.get_mut(key)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => true,
|
}
|
||||||
},
|
|
||||||
None => match ClauseType::from(name, arity, op_spec) {
|
|
||||||
ClauseType::Named(name, arity, _) => self.code_dir.contains_key(&(name, arity)),
|
|
||||||
ClauseType::Op(name, spec, ..) => self.code_dir.contains_key(&(name, spec.arity())),
|
|
||||||
_ => true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_term_and_goal_expansion_indices(&mut self) {
|
pub fn remove_predicate_skeleton(
|
||||||
self.code_dir.insert((clause_name!("term_expansion"), 2),
|
&mut self,
|
||||||
CodeIndex(Rc::new(RefCell::new(
|
compilation_target: &CompilationTarget,
|
||||||
(IndexPtr::UserTermExpansion,
|
key: &PredicateKey,
|
||||||
clause_name!("user"))
|
) {
|
||||||
))));
|
match (key.0.as_str(), key.1) {
|
||||||
self.code_dir.insert((clause_name!("goal_expansion"), 2),
|
("term_expansion", 2) => {
|
||||||
CodeIndex(Rc::new(RefCell::new(
|
self.extensible_predicates.remove(key);
|
||||||
(IndexPtr::UserGoalExpansion,
|
},
|
||||||
clause_name!("user"))
|
_ => {
|
||||||
))));
|
match compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
self.extensible_predicates.remove(key);
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
if let Some(module) = self.modules.get_mut(module_name) {
|
||||||
|
module.extensible_predicates.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn get_predicate_code_index(
|
||||||
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
|
|
||||||
self.dynamic_code_dir.swap_remove(&(module, name, arity));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_clause_subsection(
|
|
||||||
&self,
|
&self,
|
||||||
module: ClauseName,
|
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
) -> Option<DynamicPredicateInfo> {
|
module: ClauseName,
|
||||||
self.dynamic_code_dir.get(&(module, name, arity)).cloned()
|
op_spec: Option<SharedOpDesc>,
|
||||||
|
) -> Option<CodeIndex> {
|
||||||
|
if module.as_str() == "user" {
|
||||||
|
match ClauseType::from(name, arity, op_spec) {
|
||||||
|
ClauseType::Named(name, arity, _) => {
|
||||||
|
self.code_dir.get(&(name, arity)).cloned()
|
||||||
|
}
|
||||||
|
ClauseType::Op(name, spec, ..) => {
|
||||||
|
self.code_dir.get(&(name, spec.arity())).cloned()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.modules.get(&module).and_then(|module| {
|
||||||
|
match ClauseType::from(name, arity, op_spec) {
|
||||||
|
ClauseType::Named(name, arity, _) => {
|
||||||
|
module.code_dir.get(&(name, arity)).cloned()
|
||||||
|
}
|
||||||
|
ClauseType::Op(name, spec, ..) => {
|
||||||
|
module.code_dir.get(&(name, spec.arity())).cloned()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn get_meta_predicate_spec(
|
||||||
pub(crate) fn take_in_situ_module_dir(&mut self) -> ModuleStubDir {
|
&self,
|
||||||
mem::replace(&mut self.in_situ_module_dir, ModuleStubDir::new())
|
name: ClauseName,
|
||||||
|
arity: usize,
|
||||||
|
compilation_target: &CompilationTarget,
|
||||||
|
) -> Option<&Vec<MetaSpec>> {
|
||||||
|
match compilation_target {
|
||||||
|
CompilationTarget::User => {
|
||||||
|
self.meta_predicates.get(&(name, arity))
|
||||||
|
}
|
||||||
|
CompilationTarget::Module(ref module_name) => {
|
||||||
|
match self.modules.get(module_name) {
|
||||||
|
Some(ref module) => {
|
||||||
|
module.meta_predicates.get(&(name.clone(), arity))
|
||||||
|
.or_else(|| {
|
||||||
|
self.meta_predicates.get(&(name, arity))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.meta_predicates.get(&(name, arity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn is_dynamic_predicate(&self, module_name: ClauseName, key: PredicateKey) -> bool {
|
||||||
pub fn take_in_situ_code_dir(&mut self) -> InSituCodeDir {
|
match module_name.as_str() {
|
||||||
mem::replace(&mut self.in_situ_code_dir, InSituCodeDir::new())
|
"user" => {
|
||||||
}
|
self.extensible_predicates.get(&key)
|
||||||
|
.map(|skeleton| skeleton.is_dynamic)
|
||||||
#[inline]
|
.unwrap_or(false)
|
||||||
pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
|
}
|
||||||
self.modules.swap_remove(&name)
|
_ => {
|
||||||
}
|
match self.modules.get(&module_name) {
|
||||||
|
Some(ref module) => {
|
||||||
#[inline]
|
module.extensible_predicates.get(&key)
|
||||||
pub fn insert_module(&mut self, module: Module) {
|
.map(|skeleton| skeleton.is_dynamic)
|
||||||
self.modules.insert(module.module_decl.name.clone(), module);
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
IndexStore {
|
IndexStore::default()
|
||||||
atom_tbl: TabledData::new(Rc::new("user".to_string())),
|
|
||||||
code_dir: CodeDir::new(),
|
|
||||||
module_dir: ModuleDir::new(),
|
|
||||||
dynamic_code_dir: DynamicCodeDir::new(),
|
|
||||||
global_variables: GlobalVarDir::new(),
|
|
||||||
in_situ_code_dir: InSituCodeDir::new(),
|
|
||||||
in_situ_module_dir: ModuleStubDir::new(),
|
|
||||||
op_dir: default_op_dir(),
|
|
||||||
modules: ModuleDir::new(),
|
|
||||||
stream_aliases: StreamAliasDir::new(),
|
|
||||||
streams: StreamDir::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub(super)
|
||||||
pub(super) fn copy_and_swap(&mut self, other: &mut IndexStore) {
|
fn get_cleaner_sites(&self) -> (usize, usize) {
|
||||||
self.code_dir = other.code_dir.clone();
|
|
||||||
self.op_dir = other.op_dir.clone();
|
|
||||||
|
|
||||||
mem::swap(&mut self.code_dir, &mut other.code_dir);
|
|
||||||
mem::swap(&mut self.op_dir, &mut other.op_dir);
|
|
||||||
mem::swap(&mut self.modules, &mut other.modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_internal(
|
|
||||||
&self,
|
|
||||||
name: ClauseName,
|
|
||||||
arity: usize,
|
|
||||||
in_mod: ClauseName,
|
|
||||||
) -> Option<CodeIndex> {
|
|
||||||
self.modules
|
|
||||||
.get(&in_mod)
|
|
||||||
.and_then(|ref module| module.code_dir.get(&(name, arity)))
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
|
||||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||||
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
||||||
|
|
||||||
let iso_ext = clause_name!("iso_ext");
|
let iso_ext = clause_name!("iso_ext");
|
||||||
|
|
||||||
let r_w_h = self
|
let r_w_h = self
|
||||||
.get_internal(r_w_h, 0, iso_ext.clone())
|
.get_predicate_code_index(r_w_h, 0, iso_ext.clone(), None)
|
||||||
.and_then(|item| item.local());
|
.and_then(|item| item.local());
|
||||||
let r_wo_h = self
|
let r_wo_h = self
|
||||||
.get_internal(r_wo_h, 1, iso_ext)
|
.get_predicate_code_index(r_wo_h, 1, iso_ext, None)
|
||||||
.and_then(|item| item.local());
|
.and_then(|item| item.local());
|
||||||
|
|
||||||
if let Some(r_w_h) = r_w_h {
|
if let Some(r_w_h) = r_w_h {
|
||||||
@@ -960,129 +983,6 @@ impl IndexStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type CodeDir = BTreeMap<PredicateKey, CodeIndex>;
|
pub type CodeDir = BTreeMap<PredicateKey, CodeIndex>;
|
||||||
pub type TermDir = IndexMap<PredicateKey, (Predicate, VecDeque<TopLevel>)>;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TermDirQuantumEntry {
|
|
||||||
pub old_terms: (Predicate, VecDeque<TopLevel>),
|
|
||||||
pub new_terms: (Predicate, VecDeque<TopLevel>),
|
|
||||||
pub is_fresh: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TermDirQuantumEntry {
|
|
||||||
#[inline]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
TermDirQuantumEntry {
|
|
||||||
old_terms: (Predicate::new(), VecDeque::new()),
|
|
||||||
new_terms: (Predicate::new(), VecDeque::new()),
|
|
||||||
is_fresh: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from(preds: &Predicate, queue: &VecDeque<TopLevel>) -> Self
|
|
||||||
{
|
|
||||||
let mut entry = TermDirQuantumEntry::new();
|
|
||||||
entry.is_fresh = false;
|
|
||||||
|
|
||||||
(entry.old_terms.0).0.extend(preds.0.iter().cloned());
|
|
||||||
entry.old_terms.1.extend(queue.iter().cloned());
|
|
||||||
|
|
||||||
entry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TermDirQuantum(IndexMap<PredicateKey, TermDirQuantumEntry>);
|
|
||||||
|
|
||||||
impl TermDirQuantum {
|
|
||||||
#[inline]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
TermDirQuantum(IndexMap::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn insert_or_refresh(&mut self, key: PredicateKey, mut entry: TermDirQuantumEntry) {
|
|
||||||
if let Some(prev_entry) = self.get_mut(&key) {
|
|
||||||
prev_entry.is_fresh = true;
|
|
||||||
} else {
|
|
||||||
entry.is_fresh = true;
|
|
||||||
self.0.insert(key, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn insert(&mut self, key: PredicateKey, entry: TermDirQuantumEntry) {
|
|
||||||
self.0.insert(key, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_mut(&mut self, key: &PredicateKey) -> Option<&mut TermDirQuantumEntry> {
|
|
||||||
self.0.get_mut(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn consolidate(self) -> TermDir {
|
|
||||||
let mut term_dir = TermDir::new();
|
|
||||||
|
|
||||||
for (key, entry) in self.0 {
|
|
||||||
let (preds, queue) =
|
|
||||||
term_dir.entry(key).or_insert((Predicate::new(), VecDeque::new()));
|
|
||||||
|
|
||||||
preds.0.extend((entry.new_terms.0).0.into_iter());
|
|
||||||
queue.extend(entry.new_terms.1.into_iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
term_dir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
|
|
||||||
pub enum CompileTimeHook {
|
|
||||||
GoalExpansion,
|
|
||||||
TermExpansion,
|
|
||||||
UserGoalExpansion,
|
|
||||||
UserTermExpansion,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompileTimeHook {
|
|
||||||
pub fn name(self) -> ClauseName {
|
|
||||||
match self {
|
|
||||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
|
||||||
clause_name!("goal_expansion")
|
|
||||||
}
|
|
||||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
|
||||||
clause_name!("term_expansion")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn arity(self) -> usize {
|
|
||||||
match self {
|
|
||||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => 2,
|
|
||||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn user_scope(self) -> Self {
|
|
||||||
match self {
|
|
||||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
|
||||||
CompileTimeHook::UserGoalExpansion
|
|
||||||
}
|
|
||||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
|
||||||
CompileTimeHook::UserTermExpansion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn has_module_scope(self) -> bool {
|
|
||||||
match self {
|
|
||||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::UserGoalExpansion => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum RefOrOwned<'a, T: 'a> {
|
pub enum RefOrOwned<'a, T: 'a> {
|
||||||
Borrowed(&'a T),
|
Borrowed(&'a T),
|
||||||
@@ -1094,7 +994,8 @@ impl<'a, T: 'a + fmt::Debug> fmt::Debug for RefOrOwned<'a, T> {
|
|||||||
match self {
|
match self {
|
||||||
&RefOrOwned::Borrowed(ref borrowed) =>
|
&RefOrOwned::Borrowed(ref borrowed) =>
|
||||||
write!(f, "Borrowed({:?})", borrowed),
|
write!(f, "Borrowed({:?})", borrowed),
|
||||||
&RefOrOwned::Owned(ref owned) => write!(f, "Owned({:?})", owned),
|
&RefOrOwned::Owned(ref owned) =>
|
||||||
|
write!(f, "Owned({:?})", owned),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1107,9 +1008,7 @@ impl<'a, T> RefOrOwned<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_owned(self) -> T
|
pub fn to_owned(self) -> T where T: Clone
|
||||||
where
|
|
||||||
T: Clone,
|
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
RefOrOwned::Borrowed(item) => item.clone(),
|
RefOrOwned::Borrowed(item) => item.clone(),
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ use crate::machine::copier::*;
|
|||||||
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::modules::*;
|
use crate::machine::partial_string::HeapPStrIter;
|
||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
use crate::rug::Integer;
|
use crate::rug::Integer;
|
||||||
|
|
||||||
use crate::downcast::Any;
|
use crate::downcast::Any;
|
||||||
|
|
||||||
use crate::indexmap::{IndexMap, IndexSet};
|
use crate::indexmap::IndexMap;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -25,292 +25,6 @@ use std::io::Write;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct HeapPStrIter<'a> {
|
|
||||||
focus: Addr,
|
|
||||||
machine_st: &'a MachineState,
|
|
||||||
seen: IndexSet<Addr>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> HeapPStrIter<'a> {
|
|
||||||
#[inline]
|
|
||||||
fn new(machine_st: &'a MachineState, focus: Addr) -> Self {
|
|
||||||
HeapPStrIter {
|
|
||||||
focus,
|
|
||||||
machine_st,
|
|
||||||
seen: IndexSet::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate)
|
|
||||||
fn focus(&self) -> Addr {
|
|
||||||
self.machine_st.store(self.machine_st.deref(self.focus))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate)
|
|
||||||
fn to_string(&mut self) -> String {
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
while let Some(iteratee) = self.next() {
|
|
||||||
match iteratee {
|
|
||||||
PStrIteratee::Char(c) => {
|
|
||||||
buf.push(c);
|
|
||||||
}
|
|
||||||
PStrIteratee::PStrSegment(h, n) => {
|
|
||||||
match &self.machine_st.heap[h] {
|
|
||||||
HeapCellValue::PartialString(ref pstr, _) => {
|
|
||||||
buf += pstr.as_str_from(n);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub(crate) enum PStrIteratee {
|
|
||||||
Char(char),
|
|
||||||
PStrSegment(usize, usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for HeapPStrIter<'a> {
|
|
||||||
type Item = PStrIteratee;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(self.focus));
|
|
||||||
|
|
||||||
if !self.seen.contains(&addr) {
|
|
||||||
self.seen.insert(addr);
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
match addr {
|
|
||||||
Addr::PStrLocation(h, n) => {
|
|
||||||
if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
|
|
||||||
self.focus = if has_tail {
|
|
||||||
Addr::HeapCell(h + 1)
|
|
||||||
} else {
|
|
||||||
Addr::EmptyList
|
|
||||||
};
|
|
||||||
|
|
||||||
return Some(PStrIteratee::PStrSegment(h, n));
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Lis(l) => {
|
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
|
|
||||||
|
|
||||||
let opt_c = match addr {
|
|
||||||
Addr::Con(h) if self.machine_st.heap.atom_at(h) => {
|
|
||||||
if let HeapCellValue::Atom(ref atom, _) = &self.machine_st.heap[h] {
|
|
||||||
if atom.is_char() {
|
|
||||||
Some(atom.as_str().chars().next().unwrap())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Char(c) => {
|
|
||||||
Some(c)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(c) = opt_c {
|
|
||||||
self.focus = Addr::HeapCell(l + 1);
|
|
||||||
return Some(PStrIteratee::Char(c));
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::EmptyList => {
|
|
||||||
self.focus = Addr::EmptyList;
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(super)
|
|
||||||
fn compare_pstr_prefixes<'a>(
|
|
||||||
i1: &mut HeapPStrIter<'a>,
|
|
||||||
i2: &mut HeapPStrIter<'a>,
|
|
||||||
) -> Option<Ordering> {
|
|
||||||
let mut r1 = i1.next();
|
|
||||||
let mut r2 = i2.next();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if let Some(r1i) = r1 {
|
|
||||||
if let Some(r2i) = r2 {
|
|
||||||
match (r1i, r2i) {
|
|
||||||
(PStrIteratee::Char(c1), PStrIteratee::Char(c2)) => {
|
|
||||||
if c1 != c2 {
|
|
||||||
return c1.partial_cmp(&c2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(PStrIteratee::Char(c1), PStrIteratee::PStrSegment(h, n)) => {
|
|
||||||
if let &HeapCellValue::PartialString(ref pstr, _) = &i2.machine_st.heap[h] {
|
|
||||||
if let Some(c2) = pstr.as_str_from(n).chars().next() {
|
|
||||||
if c1 != c2 {
|
|
||||||
return c1.partial_cmp(&c2);
|
|
||||||
} else {
|
|
||||||
r1 = i1.next();
|
|
||||||
r2 = Some(PStrIteratee::PStrSegment(h, n + c2.len_utf8()));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r2 = i2.next();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(PStrIteratee::PStrSegment(h, n), PStrIteratee::Char(c2)) => {
|
|
||||||
if let &HeapCellValue::PartialString(ref pstr, _) = &i1.machine_st.heap[h] {
|
|
||||||
if let Some(c1) = pstr.as_str_from(n).chars().next() {
|
|
||||||
if c1 != c2 {
|
|
||||||
return c2.partial_cmp(&c1);
|
|
||||||
} else {
|
|
||||||
r1 = i1.next();
|
|
||||||
r2 = Some(PStrIteratee::PStrSegment(h, n + c1.len_utf8()));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r1 = i1.next();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(PStrIteratee::PStrSegment(h1, n1), PStrIteratee::PStrSegment(h2, n2)) => {
|
|
||||||
match (&i1.machine_st.heap[h1], &i2.machine_st.heap[h2]) {
|
|
||||||
(
|
|
||||||
&HeapCellValue::PartialString(ref pstr1, _),
|
|
||||||
&HeapCellValue::PartialString(ref pstr2, _),
|
|
||||||
) => {
|
|
||||||
let str1 = pstr1.as_str_from(n1);
|
|
||||||
let str2 = pstr2.as_str_from(n2);
|
|
||||||
|
|
||||||
if str1.starts_with(str2) {
|
|
||||||
r1 = Some(PStrIteratee::PStrSegment(h1, n1 + str2.len()));
|
|
||||||
r2 = i2.next();
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else if str2.starts_with(str1) {
|
|
||||||
r1 = i1.next();
|
|
||||||
r2 = Some(PStrIteratee::PStrSegment(h2, n2 + str1.len()));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
return str1.partial_cmp(str2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r1 = i1.next();
|
|
||||||
r2 = i2.next();
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return match (i1.focus(), i2.focus()) {
|
|
||||||
(Addr::EmptyList, Addr::EmptyList) => {
|
|
||||||
Some(Ordering::Equal)
|
|
||||||
}
|
|
||||||
(Addr::EmptyList, _) => {
|
|
||||||
Some(Ordering::Less)
|
|
||||||
}
|
|
||||||
(_, Addr::EmptyList) => {
|
|
||||||
Some(Ordering::Greater)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(super)
|
|
||||||
fn compare_pstr_to_string<'a>(
|
|
||||||
heap_pstr_iter: &mut HeapPStrIter<'a>,
|
|
||||||
s: &String,
|
|
||||||
) -> Option<usize> {
|
|
||||||
let mut s_offset = 0;
|
|
||||||
|
|
||||||
while let Some(iteratee) = heap_pstr_iter.next() {
|
|
||||||
match iteratee {
|
|
||||||
PStrIteratee::Char(c1) => {
|
|
||||||
if let Some(c2) = s[s_offset ..].chars().next() {
|
|
||||||
if c1 != c2 {
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
s_offset += c1.len_utf8();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Some(s_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PStrIteratee::PStrSegment(h, n) => {
|
|
||||||
match heap_pstr_iter.machine_st.heap[h] {
|
|
||||||
HeapCellValue::PartialString(ref pstr, _) => {
|
|
||||||
let t = pstr.as_str_from(n);
|
|
||||||
|
|
||||||
if s[s_offset ..].starts_with(t) {
|
|
||||||
s_offset += t.len();
|
|
||||||
} else if t.starts_with(&s[s_offset ..]) {
|
|
||||||
heap_pstr_iter.focus =
|
|
||||||
Addr::PStrLocation(h, n + s[s_offset ..].len());
|
|
||||||
|
|
||||||
s_offset += s[s_offset ..].len();
|
|
||||||
return Some(s_offset);
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if s[s_offset ..].is_empty() {
|
|
||||||
return Some(s_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(s_offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Ball {
|
pub struct Ball {
|
||||||
pub(super) boundary: usize,
|
pub(super) boundary: usize,
|
||||||
@@ -332,17 +46,6 @@ impl Ball {
|
|||||||
self.stub.clear();
|
self.stub.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
|
||||||
fn take(&mut self) -> Ball {
|
|
||||||
let boundary = self.boundary;
|
|
||||||
self.boundary = 0;
|
|
||||||
|
|
||||||
Ball {
|
|
||||||
boundary,
|
|
||||||
stub: self.stub.take(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn copy_and_align(&self, h: usize) -> Heap {
|
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;
|
||||||
@@ -586,6 +289,7 @@ impl Default for HeapPtr {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MachineState {
|
pub struct MachineState {
|
||||||
|
pub(crate) atom_tbl: TabledData<Atom>,
|
||||||
pub(super) s: HeapPtr,
|
pub(super) s: HeapPtr,
|
||||||
pub(super) p: CodePtr,
|
pub(super) p: CodePtr,
|
||||||
pub(super) b: usize,
|
pub(super) b: usize,
|
||||||
@@ -640,7 +344,7 @@ impl MachineState {
|
|||||||
loop {
|
loop {
|
||||||
match self.read(
|
match self.read(
|
||||||
stream.clone(),
|
stream.clone(),
|
||||||
indices.atom_tbl.clone(),
|
self.atom_tbl.clone(),
|
||||||
&indices.op_dir,
|
&indices.op_dir,
|
||||||
) {
|
) {
|
||||||
Ok(term_write_result) => {
|
Ok(term_write_result) => {
|
||||||
@@ -654,7 +358,7 @@ impl MachineState {
|
|||||||
let mut list_of_var_eqs = vec![];
|
let mut list_of_var_eqs = vec![];
|
||||||
|
|
||||||
for (var, binding) in term_write_result.var_dict.into_iter() {
|
for (var, binding) in term_write_result.var_dict.into_iter() {
|
||||||
let var_atom = clause_name!(var.to_string(), indices.atom_tbl);
|
let var_atom = clause_name!(var.to_string(), self.atom_tbl);
|
||||||
|
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
||||||
@@ -854,6 +558,15 @@ impl MachineState {
|
|||||||
Ok(Some(printer))
|
Ok(Some(printer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn throw_undefined_error(&mut self, name: ClauseName, arity: usize) -> MachineStub {
|
||||||
|
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||||
|
let h = self.heap.h();
|
||||||
|
let key = ExistenceError::Procedure(name, arity);
|
||||||
|
|
||||||
|
self.error_form(MachineError::existence_error(h, key), stub)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
|
fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
|
||||||
@@ -895,6 +608,24 @@ impl MachineState {
|
|||||||
Ok(chars)
|
Ok(chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn read_predicate_key(&self, name: Addr, arity: Addr) -> (ClauseName, usize) {
|
||||||
|
let predicate_name = atom_from!(self, self.store(self.deref(name)));
|
||||||
|
let arity = self.store(self.deref(arity));
|
||||||
|
|
||||||
|
let arity =
|
||||||
|
match Number::try_from((arity, &self.heap)) {
|
||||||
|
Ok(Number::Integer(n)) if &*n >= &0 && &*n <= &MAX_ARITY =>
|
||||||
|
n.to_usize().unwrap(),
|
||||||
|
Ok(Number::Fixnum(n)) if n >= 0 && n <= MAX_ARITY as isize =>
|
||||||
|
usize::try_from(n).unwrap(),
|
||||||
|
_ =>
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
(predicate_name, arity)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
|
fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
|
||||||
self.cp.assign_if_local(self.p.clone() + 1);
|
self.cp.assign_if_local(self.p.clone() + 1);
|
||||||
@@ -914,58 +645,35 @@ impl MachineState {
|
|||||||
fn module_lookup(
|
fn module_lookup(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &IndexStore,
|
indices: &IndexStore,
|
||||||
|
call_policy: &mut Box<dyn CallPolicy>,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
module_name: ClauseName,
|
module_name: ClauseName,
|
||||||
last_call: bool,
|
_last_call: bool,
|
||||||
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
let (name, arity) = key;
|
if module_name.as_str() == "user" {
|
||||||
|
return call_policy.call_clause_type(
|
||||||
if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) {
|
self,
|
||||||
match idx.0.borrow().0 {
|
key,
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
&indices.code_dir,
|
||||||
if last_call {
|
&indices.op_dir,
|
||||||
self.execute_at_index(arity, dir_entry!(compiled_tl_index));
|
current_input_stream,
|
||||||
} else {
|
current_output_stream,
|
||||||
self.call_at_index(arity, dir_entry!(compiled_tl_index));
|
);
|
||||||
}
|
} else if let Some(module) = indices.modules.get(&module_name) {
|
||||||
|
return call_policy.call_clause_type(
|
||||||
return Ok(());
|
self,
|
||||||
}
|
key,
|
||||||
IndexPtr::DynamicUndefined => {
|
&module.code_dir,
|
||||||
self.fail = true;
|
&module.op_dir,
|
||||||
return Ok(());
|
current_input_stream,
|
||||||
}
|
current_output_stream,
|
||||||
IndexPtr::UserTermExpansion => {
|
);
|
||||||
if last_call {
|
|
||||||
self.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
|
||||||
} else {
|
|
||||||
self.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
IndexPtr::UserGoalExpansion => {
|
|
||||||
if last_call {
|
|
||||||
self.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
|
||||||
} else {
|
|
||||||
self.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
IndexPtr::InSituDirEntry(p) => {
|
|
||||||
if last_call {
|
|
||||||
self.execute_at_index(arity, LocalCodePtr::InSituDirEntry(p));
|
|
||||||
} else {
|
|
||||||
self.call_at_index(arity, LocalCodePtr::InSituDirEntry(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (name, arity) = key;
|
||||||
|
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||||
let err = MachineError::module_resolution_error(h, module_name, name, arity);
|
let err = MachineError::module_resolution_error(h, module_name, name, arity);
|
||||||
@@ -974,49 +682,6 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<LocalCodePtr>
|
|
||||||
{
|
|
||||||
match indices.in_situ_code_dir.get(&(name.clone(), arity)) {
|
|
||||||
Some(p) => Some(LocalCodePtr::InSituDirEntry(*p)),
|
|
||||||
None =>
|
|
||||||
match indices.code_dir.get(&(name, arity)) {
|
|
||||||
Some(ref idx) => {
|
|
||||||
if let IndexPtr::Index(p) = idx.0.borrow().0 {
|
|
||||||
Some(LocalCodePtr::DirEntry(p))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_in_situ(
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
name: ClauseName,
|
|
||||||
arity: usize,
|
|
||||||
indices: &IndexStore,
|
|
||||||
last_call: bool,
|
|
||||||
) -> CallResult {
|
|
||||||
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
|
||||||
if last_call {
|
|
||||||
machine_st.execute_at_index(arity, p);
|
|
||||||
} else {
|
|
||||||
machine_st.call_at_index(arity, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.p = CodePtr::Local(p);
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
|
||||||
let h = machine_st.heap.h();
|
|
||||||
let key = ExistenceError::Procedure(name, arity);
|
|
||||||
|
|
||||||
Err(machine_st.error_form(MachineError::existence_error(h, key), stub))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||||
|
|
||||||
pub(crate) trait CallPolicy: Any + fmt::Debug {
|
pub(crate) trait CallPolicy: Any + fmt::Debug {
|
||||||
@@ -1090,7 +755,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
machine_st.attr_var_init.backtrack(attr_var_init_queue_b, attr_var_init_bindings_b);
|
machine_st.attr_var_init.backtrack(attr_var_init_queue_b, attr_var_init_bindings_b);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h();
|
machine_st.hb = machine_st.heap.h();
|
||||||
machine_st.p += offset;
|
machine_st.p = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1130,7 +795,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
machine_st.stack.truncate(b);
|
machine_st.stack.truncate(b);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h();
|
machine_st.hb = machine_st.heap.h();
|
||||||
machine_st.p += offset;
|
machine_st.p = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1180,13 +845,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
idx: CodeIndex,
|
idx: &CodeIndex,
|
||||||
indices: &mut IndexStore,
|
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
if machine_st.last_call {
|
if machine_st.last_call {
|
||||||
self.try_execute(machine_st, name, arity, idx, indices)
|
self.try_execute(machine_st, name, arity, idx)
|
||||||
} else {
|
} else {
|
||||||
self.try_call(machine_st, name, arity, idx, indices)
|
self.try_call(machine_st, name, arity, idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1195,27 +859,18 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
idx: CodeIndex,
|
idx: &CodeIndex,
|
||||||
indices: &IndexStore,
|
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
match idx.0.borrow().0 {
|
match idx.get() {
|
||||||
IndexPtr::DynamicUndefined => {
|
IndexPtr::DynamicUndefined => {
|
||||||
machine_st.fail = true;
|
machine_st.fail = true;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
IndexPtr::Undefined => {
|
IndexPtr::Undefined => {
|
||||||
return try_in_situ(machine_st, name, arity, indices, false);
|
return Err(machine_st.throw_undefined_error(name, arity));
|
||||||
}
|
}
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index))
|
machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index));
|
||||||
}
|
|
||||||
IndexPtr::UserTermExpansion => {
|
|
||||||
machine_st.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
|
||||||
}
|
|
||||||
IndexPtr::UserGoalExpansion => {
|
|
||||||
machine_st.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
|
||||||
}
|
|
||||||
IndexPtr::InSituDirEntry(p) => {
|
|
||||||
machine_st.call_at_index(arity, LocalCodePtr::InSituDirEntry(p));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1227,26 +882,19 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
idx: CodeIndex,
|
idx: &CodeIndex,
|
||||||
indices: &IndexStore,
|
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
match idx.0.borrow().0 {
|
match idx.get() {
|
||||||
IndexPtr::DynamicUndefined =>
|
IndexPtr::DynamicUndefined => {
|
||||||
machine_st.fail = true,
|
machine_st.fail = true;
|
||||||
IndexPtr::Undefined =>
|
return Ok(());
|
||||||
return try_in_situ(machine_st, name, arity, indices, true),
|
}
|
||||||
|
IndexPtr::Undefined => {
|
||||||
|
return Err(machine_st.throw_undefined_error(name, arity));
|
||||||
|
}
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
|
machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
|
||||||
}
|
}
|
||||||
IndexPtr::UserTermExpansion => {
|
|
||||||
machine_st.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
|
||||||
}
|
|
||||||
IndexPtr::UserGoalExpansion => {
|
|
||||||
machine_st.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
|
||||||
}
|
|
||||||
IndexPtr::InSituDirEntry(p) => {
|
|
||||||
machine_st.execute_at_index(arity, LocalCodePtr::InSituDirEntry(p));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1256,7 +904,8 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
&mut self,
|
&mut self,
|
||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
ct: &BuiltInClauseType,
|
ct: &BuiltInClauseType,
|
||||||
indices: &mut IndexStore,
|
_code_dir: &CodeDir,
|
||||||
|
op_dir: &OpDir,
|
||||||
current_input_stream: &mut Stream,
|
current_input_stream: &mut Stream,
|
||||||
current_output_stream: &mut Stream,
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
@@ -1305,15 +954,15 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
|
|
||||||
let atom = match machine_st.compare_term_test(&a2, &a3) {
|
let atom = match machine_st.compare_term_test(&a2, &a3) {
|
||||||
Some(Ordering::Greater) => {
|
Some(Ordering::Greater) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!(">"), None, op_dir);
|
||||||
HeapCellValue::Atom(clause_name!(">"), spec)
|
HeapCellValue::Atom(clause_name!(">"), spec)
|
||||||
}
|
}
|
||||||
Some(Ordering::Equal) => {
|
Some(Ordering::Equal) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("="), None, op_dir);
|
||||||
HeapCellValue::Atom(clause_name!("="), spec)
|
HeapCellValue::Atom(clause_name!("="), spec)
|
||||||
}
|
}
|
||||||
None | Some(Ordering::Less) => {
|
None | Some(Ordering::Less) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("<"), None, op_dir);
|
||||||
HeapCellValue::Atom(clause_name!("<"), spec)
|
HeapCellValue::Atom(clause_name!("<"), spec)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1338,8 +987,8 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
&BuiltInClauseType::Read => {
|
&BuiltInClauseType::Read => {
|
||||||
match machine_st.read(
|
match machine_st.read(
|
||||||
current_input_stream.clone(),
|
current_input_stream.clone(),
|
||||||
indices.atom_tbl.clone(),
|
machine_st.atom_tbl.clone(),
|
||||||
&indices.op_dir,
|
op_dir,
|
||||||
) {
|
) {
|
||||||
Ok(offset) => {
|
Ok(offset) => {
|
||||||
let addr = machine_st[temp_v!(1)];
|
let addr = machine_st[temp_v!(1)];
|
||||||
@@ -1347,16 +996,18 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
}
|
}
|
||||||
Err(ParserError::UnexpectedEOF) => {
|
Err(ParserError::UnexpectedEOF) => {
|
||||||
let addr = machine_st[temp_v!(1)];
|
let addr = machine_st[temp_v!(1)];
|
||||||
let eof = clause_name!("end_of_file".to_string(),
|
let eof = clause_name!("end_of_file".to_string(), machine_st.atom_tbl);
|
||||||
indices.atom_tbl);
|
|
||||||
let atom = machine_st.heap.to_unifiable(
|
let atom = machine_st.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(eof, None)
|
HeapCellValue::Atom(eof, None)
|
||||||
);
|
);
|
||||||
|
|
||||||
machine_st.unify(addr, atom);
|
machine_st.unify(addr, atom);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let h = machine_st.heap.h();
|
let h = machine_st.heap.h();
|
||||||
let stub = MachineError::functor_stub(clause_name!("read"), 1);
|
let stub = MachineError::functor_stub(clause_name!("read"), 1);
|
||||||
|
|
||||||
let err = MachineError::syntax_error(h, e);
|
let err = MachineError::syntax_error(h, e);
|
||||||
let err = machine_st.error_form(err, stub);
|
let err = machine_st.error_form(err, stub);
|
||||||
|
|
||||||
@@ -1382,7 +1033,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Functor => {
|
&BuiltInClauseType::Functor => {
|
||||||
machine_st.try_functor(&indices)?;
|
machine_st.try_functor(op_dir)?;
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::NotEq => {
|
&BuiltInClauseType::NotEq => {
|
||||||
@@ -1453,24 +1104,66 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_hook(
|
fn call_clause_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
hook: &CompileTimeHook,
|
key: PredicateKey,
|
||||||
|
code_dir: &CodeDir,
|
||||||
|
op_dir: &OpDir,
|
||||||
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
machine_st.cp = LocalCodePtr::TopLevel(0, 0);
|
let (name, arity) = key;
|
||||||
|
|
||||||
machine_st.num_of_args = hook.arity();
|
match ClauseType::from(name.clone(), arity, None) {
|
||||||
machine_st.b0 = machine_st.b;
|
ClauseType::BuiltIn(built_in) => {
|
||||||
|
machine_st.setup_built_in_call(built_in.clone());
|
||||||
|
self.call_builtin(
|
||||||
|
machine_st,
|
||||||
|
&built_in,
|
||||||
|
code_dir,
|
||||||
|
op_dir,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
ClauseType::CallN => {
|
||||||
|
machine_st.handle_internal_call_n(arity);
|
||||||
|
|
||||||
machine_st.p = match hook {
|
if machine_st.fail {
|
||||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
return Ok(());
|
||||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(0))
|
}
|
||||||
|
|
||||||
|
machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
|
||||||
}
|
}
|
||||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
ClauseType::Inlined(inlined) => {
|
||||||
CodePtr::Local(LocalCodePtr::UserGoalExpansion(0))
|
machine_st.execute_inlined(&inlined);
|
||||||
|
|
||||||
|
if machine_st.last_call {
|
||||||
|
machine_st.p = CodePtr::Local(machine_st.cp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
ClauseType::Op(..) | ClauseType::Named(..) => {
|
||||||
|
if let Some(idx) = code_dir.get(&(name.clone(), arity)) {
|
||||||
|
self.context_call(machine_st, name, arity, idx)?;
|
||||||
|
} else {
|
||||||
|
return Err(machine_st.throw_undefined_error(name, arity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClauseType::System(_) => {
|
||||||
|
let name = functor!(clause_name(name));
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||||
|
|
||||||
|
return Err(machine_st.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
machine_st.heap.h(),
|
||||||
|
ValidType::Callable,
|
||||||
|
name
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1479,57 +1172,20 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
|
|||||||
&mut self,
|
&mut self,
|
||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
indices: &mut IndexStore,
|
code_dir: &CodeDir,
|
||||||
|
op_dir: &OpDir,
|
||||||
current_input_stream: &mut Stream,
|
current_input_stream: &mut Stream,
|
||||||
current_output_stream: &mut Stream,
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
if let Some(key) = machine_st.setup_call_n(arity) {
|
||||||
match ClauseType::from(name.clone(), arity, None) {
|
self.call_clause_type(
|
||||||
ClauseType::BuiltIn(built_in) => {
|
machine_st,
|
||||||
machine_st.setup_built_in_call(built_in.clone());
|
key,
|
||||||
self.call_builtin(
|
code_dir,
|
||||||
machine_st,
|
op_dir,
|
||||||
&built_in,
|
current_input_stream,
|
||||||
indices,
|
current_output_stream,
|
||||||
current_input_stream,
|
)?;
|
||||||
current_output_stream,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
ClauseType::CallN => {
|
|
||||||
machine_st.handle_internal_call_n(arity);
|
|
||||||
|
|
||||||
if machine_st.fail {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
|
|
||||||
}
|
|
||||||
ClauseType::Inlined(inlined) => {
|
|
||||||
machine_st.execute_inlined(&inlined);
|
|
||||||
|
|
||||||
if machine_st.last_call {
|
|
||||||
machine_st.p = CodePtr::Local(machine_st.cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClauseType::Op(..) | ClauseType::Named(..) => {
|
|
||||||
let module = name.owning_module();
|
|
||||||
|
|
||||||
if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
|
|
||||||
self.context_call(machine_st, name, arity, idx, indices)?;
|
|
||||||
} else {
|
|
||||||
try_in_situ(machine_st, name, arity, indices, machine_st.last_call)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClauseType::Hook(_) | ClauseType::System(_) => {
|
|
||||||
let name = functor!(clause_name(name));
|
|
||||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
|
||||||
|
|
||||||
return Err(machine_st.error_form(
|
|
||||||
MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name),
|
|
||||||
stub,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1542,11 +1198,9 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
idx: CodeIndex,
|
idx: &CodeIndex,
|
||||||
indices: &mut IndexStore,
|
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
self.prev_policy
|
self.prev_policy.context_call(machine_st, name, arity, idx)?;//, indices)?;
|
||||||
.context_call(machine_st, name, arity, idx, indices)?;
|
|
||||||
self.increment(machine_st)
|
self.increment(machine_st)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1574,14 +1228,16 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
&mut self,
|
&mut self,
|
||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
ct: &BuiltInClauseType,
|
ct: &BuiltInClauseType,
|
||||||
indices: &mut IndexStore,
|
code_dir: &CodeDir,
|
||||||
|
op_dir: &OpDir,
|
||||||
current_input_stream: &mut Stream,
|
current_input_stream: &mut Stream,
|
||||||
current_output_stream: &mut Stream,
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
self.prev_policy.call_builtin(
|
self.prev_policy.call_builtin(
|
||||||
machine_st,
|
machine_st,
|
||||||
ct,
|
ct,
|
||||||
indices,
|
code_dir,
|
||||||
|
op_dir,
|
||||||
current_input_stream,
|
current_input_stream,
|
||||||
current_output_stream
|
current_output_stream
|
||||||
)?;
|
)?;
|
||||||
@@ -1593,14 +1249,16 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
&mut self,
|
&mut self,
|
||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
indices: &mut IndexStore,
|
code_dir: &CodeDir,
|
||||||
|
op_dir: &OpDir,
|
||||||
current_input_stream: &mut Stream,
|
current_input_stream: &mut Stream,
|
||||||
current_output_stream: &mut Stream,
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
self.prev_policy.call_n(
|
self.prev_policy.call_n(
|
||||||
machine_st,
|
machine_st,
|
||||||
arity,
|
arity,
|
||||||
indices,
|
code_dir,
|
||||||
|
op_dir,
|
||||||
current_input_stream,
|
current_input_stream,
|
||||||
current_output_stream,
|
current_output_stream,
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use crate::prolog_parser::tabled_rc::*;
|
|||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::heap_iter::*;
|
use crate::heap_iter::*;
|
||||||
|
use crate::indexing::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::INTERRUPT;
|
use crate::machine::INTERRUPT;
|
||||||
use crate::machine::attributed_variables::*;
|
use crate::machine::attributed_variables::*;
|
||||||
@@ -13,6 +14,7 @@ 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::machine::partial_string::*;
|
||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
use crate::ordered_float::*;
|
use crate::ordered_float::*;
|
||||||
@@ -24,22 +26,11 @@ use std::cmp::Ordering;
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
macro_rules! try_or_fail {
|
|
||||||
($s:ident, $e:expr) => {{
|
|
||||||
match $e {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(msg) => {
|
|
||||||
$s.throw_exception(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
MachineState {
|
MachineState {
|
||||||
|
atom_tbl: TabledData::new(Rc::new("".to_owned())),
|
||||||
s: HeapPtr::default(),
|
s: HeapPtr::default(),
|
||||||
p: CodePtr::default(),
|
p: CodePtr::default(),
|
||||||
b: 0,
|
b: 0,
|
||||||
@@ -67,36 +58,6 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
|
||||||
fn with_small_heap() -> Self {
|
|
||||||
MachineState {
|
|
||||||
s: HeapPtr::default(),
|
|
||||||
p: CodePtr::default(),
|
|
||||||
b: 0,
|
|
||||||
b0: 0,
|
|
||||||
e: 0,
|
|
||||||
num_of_args: 0,
|
|
||||||
cp: LocalCodePtr::default(),
|
|
||||||
attr_var_init: AttrVarInitializer::new(0, 0),
|
|
||||||
fail: false,
|
|
||||||
heap: Heap::new(),
|
|
||||||
mode: MachineMode::Write,
|
|
||||||
stack: Stack::new(),
|
|
||||||
registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used.
|
|
||||||
trail: vec![],
|
|
||||||
tr: 0,
|
|
||||||
hb: 0,
|
|
||||||
block: 0,
|
|
||||||
ball: Ball::new(),
|
|
||||||
lifted_heap: Heap::new(),
|
|
||||||
interms: vec![Number::default(); 0],
|
|
||||||
last_call: false,
|
|
||||||
heap_locs: HeapVarDict::new(),
|
|
||||||
flags: MachineFlags::default(),
|
|
||||||
at_end_of_expansion: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn machine_flags(&self) -> MachineFlags {
|
pub fn machine_flags(&self) -> MachineFlags {
|
||||||
self.flags
|
self.flags
|
||||||
@@ -1390,85 +1351,130 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
|
fn execute_indexing_instr(
|
||||||
match instr {
|
&mut self,
|
||||||
&IndexingInstruction::SwitchOnTerm(arg, v, c, l, s) => {
|
indexing_lines: &Vec<IndexingLine>,
|
||||||
let addr = self[temp_v!(arg)];
|
call_policy: &mut Box<dyn CallPolicy>,
|
||||||
let addr = self.store(self.deref(addr));
|
) {
|
||||||
|
let mut index = 0;
|
||||||
|
let addr =
|
||||||
|
match &indexing_lines[0] {
|
||||||
|
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => {
|
||||||
|
self.store(self.deref(self[temp_v!(arg)]))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let offset = match addr {
|
loop {
|
||||||
Addr::Stream(_) | Addr::TcpListener(_) => {
|
match &indexing_lines[index] {
|
||||||
0
|
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, c, l, s)) => {
|
||||||
}
|
let offset = match addr {
|
||||||
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => {
|
Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
|
||||||
v
|
IndexingCodePtr::Fail
|
||||||
}
|
|
||||||
Addr::PStrLocation(..) => {
|
|
||||||
l
|
|
||||||
}
|
|
||||||
Addr::Char(_) | Addr::Con(_) | Addr::CutPoint(_) |
|
|
||||||
Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
|
|
||||||
c
|
|
||||||
}
|
|
||||||
Addr::Lis(_) => {
|
|
||||||
l
|
|
||||||
}
|
|
||||||
Addr::Str(_) => {
|
|
||||||
s
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match offset {
|
|
||||||
0 => self.fail = true,
|
|
||||||
o => self.p += o,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
&IndexingInstruction::SwitchOnConstant(arg, _, ref hm) => {
|
|
||||||
let addr = self[temp_v!(arg)];
|
|
||||||
let addr = self.store(self.deref(addr));
|
|
||||||
|
|
||||||
let offset =
|
|
||||||
match addr.as_constant_index(&self) {
|
|
||||||
Some(c) => {
|
|
||||||
match hm.get(&c) {
|
|
||||||
Some(offset) => *offset,
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => {
|
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => {
|
||||||
0
|
IndexingCodePtr::External(v)
|
||||||
|
}
|
||||||
|
Addr::PStrLocation(..) => {
|
||||||
|
l
|
||||||
|
}
|
||||||
|
Addr::Char(_) | Addr::Con(_) | Addr::CutPoint(_) |
|
||||||
|
Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
|
||||||
|
c
|
||||||
|
}
|
||||||
|
Addr::Lis(_) => {
|
||||||
|
l
|
||||||
|
}
|
||||||
|
Addr::Str(_) => {
|
||||||
|
s
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match offset {
|
match offset {
|
||||||
0 => self.fail = true,
|
IndexingCodePtr::Fail => {
|
||||||
o => self.p += o,
|
self.fail = true;
|
||||||
};
|
break;
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(arg, _, ref hm) => {
|
IndexingCodePtr::External(o) => {
|
||||||
let a1 = self.registers[arg];
|
self.p += o;
|
||||||
let addr = self.store(self.deref(a1));
|
break;
|
||||||
|
}
|
||||||
let offset = match addr {
|
IndexingCodePtr::Internal(o) => {
|
||||||
Addr::Str(s) => {
|
index += o;
|
||||||
if let &HeapCellValue::NamedStr(arity, ref name, _) = &self.heap[s] {
|
}
|
||||||
match hm.get(&(name.clone(), arity)) {
|
};
|
||||||
Some(offset) => *offset,
|
}
|
||||||
_ => 0,
|
&IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
|
||||||
|
let offset =
|
||||||
|
match addr.as_constant_index(&self) {
|
||||||
|
Some(c) => {
|
||||||
|
match hm.get(&c) {
|
||||||
|
Some(offset) => *offset,
|
||||||
|
_ => IndexingCodePtr::Fail,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
None => {
|
||||||
0
|
IndexingCodePtr::Fail
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match offset {
|
||||||
|
IndexingCodePtr::Fail => {
|
||||||
|
self.fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
IndexingCodePtr::External(o) => {
|
||||||
|
self.p += o;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
IndexingCodePtr::Internal(o) => {
|
||||||
|
index += o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
&IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
|
||||||
|
let offset = match addr {
|
||||||
|
Addr::Str(s) => {
|
||||||
|
if let &HeapCellValue::NamedStr(arity, ref name, _) = &self.heap[s] {
|
||||||
|
match hm.get(&(name.clone(), arity)) {
|
||||||
|
Some(offset) => *offset,
|
||||||
|
_ => IndexingCodePtr::Fail
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IndexingCodePtr::Fail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
IndexingCodePtr::Fail
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match offset {
|
||||||
|
IndexingCodePtr::Fail => {
|
||||||
|
self.fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
IndexingCodePtr::External(o) => {
|
||||||
|
self.p += o;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
IndexingCodePtr::Internal(o) => {
|
||||||
|
index += o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
}
|
||||||
0
|
&IndexingLine::IndexedChoice(ref instrs) => {
|
||||||
|
if let LocalCodePtr::DirEntry(p) = self.p.local() {
|
||||||
|
self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(p, index, 0));
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
match offset {
|
self.execute_indexed_choice_instr(instrs.first().unwrap(), call_policy);
|
||||||
0 => self.fail = true,
|
break;
|
||||||
o => self.p += o,
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1679,23 +1685,38 @@ impl MachineState {
|
|||||||
Some((name, arity + narity - 1))
|
Some((name, arity + narity - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwind_stack(&mut self) {
|
pub(super)
|
||||||
|
fn unwind_stack(&mut self) {
|
||||||
self.b = self.block;
|
self.b = self.block;
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool {
|
pub(crate)
|
||||||
|
fn is_cyclic_term(&self, addr: Addr) -> bool {
|
||||||
let mut seen = IndexSet::new();
|
let mut seen = IndexSet::new();
|
||||||
let mut fail = false;
|
let mut fail = false;
|
||||||
let mut iter = self.pre_order_iter(addr);
|
let mut iter = self.pre_order_iter(addr);
|
||||||
|
|
||||||
|
let is_composite = |addr: &Addr| {
|
||||||
|
match *addr {
|
||||||
|
Addr::Str(_) | Addr::Lis(_) | Addr::PStrLocation(..) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(addr) = iter.stack().last() {
|
if let Some(addr) = iter.stack().last() {
|
||||||
if !seen.contains(addr) {
|
if is_composite(addr) {
|
||||||
seen.insert(*addr);
|
if !seen.contains(addr) {
|
||||||
} else {
|
seen.insert(*addr);
|
||||||
fail = true;
|
} else {
|
||||||
break;
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2513,7 +2534,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn try_functor(&mut self, indices: &IndexStore) -> CallResult {
|
fn try_functor(&mut self, op_dir: &OpDir) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("functor"), 3);
|
let stub = MachineError::functor_stub(clause_name!("functor"), 3);
|
||||||
let a1 = self.store(self.deref(self[temp_v!(1)]));
|
let a1 = self.store(self.deref(self[temp_v!(1)]));
|
||||||
|
|
||||||
@@ -2531,7 +2552,7 @@ impl MachineState {
|
|||||||
name.clone(),
|
name.clone(),
|
||||||
arity,
|
arity,
|
||||||
spec,
|
spec,
|
||||||
&indices.op_dir,
|
&op_dir,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.try_functor_compound_case(name, arity, spec)
|
self.try_functor_compound_case(name, arity, spec)
|
||||||
@@ -2545,7 +2566,7 @@ impl MachineState {
|
|||||||
clause_name!("."),
|
clause_name!("."),
|
||||||
2,
|
2,
|
||||||
None,
|
None,
|
||||||
&indices.op_dir,
|
&op_dir,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.try_functor_compound_case(clause_name!("."), 2, spec)
|
self.try_functor_compound_case(clause_name!("."), 2, spec)
|
||||||
@@ -2620,7 +2641,7 @@ impl MachineState {
|
|||||||
name,
|
name,
|
||||||
arity as usize,
|
arity as usize,
|
||||||
spec,
|
spec,
|
||||||
&indices.op_dir,
|
&op_dir,
|
||||||
a1.as_var().unwrap(),
|
a1.as_var().unwrap(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -2637,10 +2658,10 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
Addr::Char(c) => {
|
Addr::Char(c) => {
|
||||||
self.try_functor_fabricate_struct(
|
self.try_functor_fabricate_struct(
|
||||||
clause_name!(c.to_string(), indices.atom_tbl),
|
clause_name!(c.to_string(), self.atom_tbl),
|
||||||
arity as usize,
|
arity as usize,
|
||||||
None,
|
None,
|
||||||
&indices.op_dir,
|
&op_dir,
|
||||||
a1.as_var().unwrap(),
|
a1.as_var().unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -3156,16 +3177,23 @@ impl MachineState {
|
|||||||
call_policy.call_builtin(
|
call_policy.call_builtin(
|
||||||
self,
|
self,
|
||||||
ct,
|
ct,
|
||||||
indices,
|
&indices.code_dir,
|
||||||
|
&indices.op_dir,
|
||||||
current_input_stream,
|
current_input_stream,
|
||||||
current_output_stream,
|
current_output_stream,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
&ClauseType::CallN => try_or_fail!(
|
&ClauseType::CallN => try_or_fail!(
|
||||||
self,
|
self,
|
||||||
call_policy.call_n(self, arity, indices, current_input_stream, current_output_stream)
|
call_policy.call_n(
|
||||||
|
self,
|
||||||
|
arity,
|
||||||
|
&indices.code_dir,
|
||||||
|
&indices.op_dir,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
)
|
||||||
),
|
),
|
||||||
&ClauseType::Hook(ref hook) => try_or_fail!(self, call_policy.compile_hook(self, hook)),
|
|
||||||
&ClauseType::Inlined(ref ct) => {
|
&ClauseType::Inlined(ref ct) => {
|
||||||
self.execute_inlined(ct);
|
self.execute_inlined(ct);
|
||||||
|
|
||||||
@@ -3176,7 +3204,7 @@ impl MachineState {
|
|||||||
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
|
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
|
||||||
try_or_fail!(
|
try_or_fail!(
|
||||||
self,
|
self,
|
||||||
call_policy.context_call(self, name.clone(), arity, idx.clone(), indices)
|
call_policy.context_call(self, name.clone(), arity, idx)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
&ClauseType::System(ref ct) => try_or_fail!(
|
&ClauseType::System(ref ct) => try_or_fail!(
|
||||||
@@ -3234,6 +3262,9 @@ impl MachineState {
|
|||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
self.p += offset;
|
self.p += offset;
|
||||||
}
|
}
|
||||||
|
&ControlInstruction::RevJmpBy(offset) => {
|
||||||
|
self.p -= offset;
|
||||||
|
}
|
||||||
&ControlInstruction::Proceed => {
|
&ControlInstruction::Proceed => {
|
||||||
self.p = CodePtr::Local(self.cp);
|
self.p = CodePtr::Local(self.cp);
|
||||||
}
|
}
|
||||||
@@ -3272,7 +3303,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.hb = self.heap.h();
|
self.hb = self.heap.h();
|
||||||
self.p += offset;
|
self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset));
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Retry(l) => {
|
&IndexedChoiceInstruction::Retry(l) => {
|
||||||
try_or_fail!(self, call_policy.retry(self, l));
|
try_or_fail!(self, call_policy.retry(self, l));
|
||||||
@@ -3283,7 +3314,8 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn execute_choice_instr(
|
pub(super)
|
||||||
|
fn execute_choice_instr(
|
||||||
&mut self,
|
&mut self,
|
||||||
instr: &ChoiceInstruction,
|
instr: &ChoiceInstruction,
|
||||||
call_policy: &mut Box<dyn CallPolicy>,
|
call_policy: &mut Box<dyn CallPolicy>,
|
||||||
@@ -3320,14 +3352,14 @@ impl MachineState {
|
|||||||
let mut call_policy = DefaultCallPolicy {};
|
let mut call_policy = DefaultCallPolicy {};
|
||||||
try_or_fail!(self, call_policy.retry_me_else(self, offset))
|
try_or_fail!(self, call_policy.retry_me_else(self, offset))
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::DefaultTrustMe => {
|
&ChoiceInstruction::DefaultTrustMe(_) => {
|
||||||
let mut call_policy = DefaultCallPolicy {};
|
let mut call_policy = DefaultCallPolicy {};
|
||||||
try_or_fail!(self, call_policy.trust_me(self))
|
try_or_fail!(self, call_policy.trust_me(self))
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::RetryMeElse(offset) => {
|
&ChoiceInstruction::RetryMeElse(offset) => {
|
||||||
try_or_fail!(self, call_policy.retry_me_else(self, offset))
|
try_or_fail!(self, call_policy.retry_me_else(self, offset))
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::TrustMe => {
|
&ChoiceInstruction::TrustMe(_) => {
|
||||||
try_or_fail!(self, call_policy.trust_me(self))
|
try_or_fail!(self, call_policy.trust_me(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3374,30 +3406,4 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
|
||||||
self.stack.drop_in_place();
|
|
||||||
|
|
||||||
self.hb = 0;
|
|
||||||
self.e = 0;
|
|
||||||
self.b = 0;
|
|
||||||
self.b0 = 0;
|
|
||||||
self.s = HeapPtr::default();
|
|
||||||
self.tr = 0;
|
|
||||||
self.p = CodePtr::default();
|
|
||||||
self.cp = LocalCodePtr::default();
|
|
||||||
self.attr_var_init.reset();
|
|
||||||
self.num_of_args = 0;
|
|
||||||
|
|
||||||
self.fail = false;
|
|
||||||
self.trail.clear();
|
|
||||||
self.heap.clear();
|
|
||||||
self.mode = MachineMode::Write;
|
|
||||||
self.registers = vec![Addr::HeapCell(0); MAX_ARITY + 1]; // self.registers[0] is never used.
|
|
||||||
self.block = 0;
|
|
||||||
|
|
||||||
self.ball.reset();
|
|
||||||
self.heap_locs.clear();
|
|
||||||
self.lifted_heap.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,371 +0,0 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
|
||||||
use crate::prolog_parser::tabled_rc::*;
|
|
||||||
|
|
||||||
use crate::forms::*;
|
|
||||||
use crate::machine::code_repo::*;
|
|
||||||
use crate::machine::machine_errors::*;
|
|
||||||
use crate::machine::machine_indices::*;
|
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
// Module's and related types are defined in forms.
|
|
||||||
impl Module {
|
|
||||||
pub fn new(
|
|
||||||
module_decl: ModuleDecl,
|
|
||||||
atom_tbl: TabledData<Atom>,
|
|
||||||
listing_src: ListingSource,
|
|
||||||
) -> Self
|
|
||||||
{
|
|
||||||
Module {
|
|
||||||
atom_tbl,
|
|
||||||
module_decl,
|
|
||||||
term_dir: TermDir::new(),
|
|
||||||
user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
|
||||||
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
|
||||||
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
|
||||||
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
|
||||||
local_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
|
||||||
local_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
|
||||||
code_dir: CodeDir::new(),
|
|
||||||
op_dir: default_op_dir(),
|
|
||||||
inserted_expansions: false,
|
|
||||||
is_impromptu_module: false,
|
|
||||||
listing_src,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dump_expansions(
|
|
||||||
&self,
|
|
||||||
code_repo: &mut CodeRepo,
|
|
||||||
) -> Result<(), ParserError> {
|
|
||||||
{
|
|
||||||
let te = code_repo
|
|
||||||
.term_dir
|
|
||||||
.entry((clause_name!("term_expansion"), 2))
|
|
||||||
.or_insert((Predicate::new(), VecDeque::from(vec![])));
|
|
||||||
|
|
||||||
(te.0)
|
|
||||||
.0
|
|
||||||
.extend((self.user_term_expansions.0).0.iter().cloned());
|
|
||||||
|
|
||||||
te.1.extend(self.user_term_expansions.1.iter().cloned());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let ge = code_repo
|
|
||||||
.term_dir
|
|
||||||
.entry((clause_name!("goal_expansion"), 2))
|
|
||||||
.or_insert((Predicate::new(), VecDeque::from(vec![])));
|
|
||||||
|
|
||||||
(ge.0)
|
|
||||||
.0
|
|
||||||
.extend((self.user_goal_expansions.0).0.iter().cloned());
|
|
||||||
|
|
||||||
ge.1.extend(self.user_goal_expansions.1.iter().cloned());
|
|
||||||
}
|
|
||||||
|
|
||||||
code_repo.compile_hook(CompileTimeHook::TermExpansion)?;
|
|
||||||
code_repo.compile_hook(CompileTimeHook::GoalExpansion)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_expansion_record(
|
|
||||||
&mut self,
|
|
||||||
hook: CompileTimeHook,
|
|
||||||
clause: PredicateClause,
|
|
||||||
queue: VecDeque<TopLevel>,
|
|
||||||
) {
|
|
||||||
match hook {
|
|
||||||
CompileTimeHook::TermExpansion | CompileTimeHook::UserTermExpansion => {
|
|
||||||
(self.term_expansions.0).0.push(clause);
|
|
||||||
self.term_expansions.1.extend(queue.into_iter());
|
|
||||||
}
|
|
||||||
CompileTimeHook::GoalExpansion | CompileTimeHook::UserGoalExpansion => {
|
|
||||||
(self.goal_expansions.0).0.push(clause);
|
|
||||||
self.goal_expansions.1.extend(queue.into_iter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_local_expansion(
|
|
||||||
&mut self,
|
|
||||||
hook: CompileTimeHook,
|
|
||||||
clause: PredicateClause,
|
|
||||||
queue: VecDeque<TopLevel>,
|
|
||||||
) {
|
|
||||||
match hook {
|
|
||||||
CompileTimeHook::TermExpansion => {
|
|
||||||
(self.local_term_expansions.0).0.push(clause);
|
|
||||||
self.local_term_expansions.1.extend(queue.into_iter());
|
|
||||||
}
|
|
||||||
CompileTimeHook::GoalExpansion => {
|
|
||||||
(self.local_goal_expansions.0).0.push(clause);
|
|
||||||
self.local_goal_expansions.1.extend(queue.into_iter());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn take_local_expansions(&mut self) -> Vec<(Predicate, VecDeque<TopLevel>)>
|
|
||||||
{
|
|
||||||
let term_expansions =
|
|
||||||
mem::replace(&mut self.local_term_expansions, (Predicate::new(), VecDeque::new()));
|
|
||||||
let goal_expansions =
|
|
||||||
mem::replace(&mut self.local_goal_expansions, (Predicate::new(), VecDeque::new()));
|
|
||||||
|
|
||||||
vec![term_expansions, goal_expansions]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait SubModuleUser {
|
|
||||||
fn atom_tbl(&self) -> TabledData<Atom>;
|
|
||||||
fn op_dir(&mut self) -> &mut OpDir;
|
|
||||||
fn remove_code_index(&mut self, _: PredicateKey);
|
|
||||||
fn get_code_index(&self, _: PredicateKey, _: ClauseName) -> Option<CodeIndex>;
|
|
||||||
|
|
||||||
fn insert_dir_entry(&mut self, _: ClauseName, _: usize, _: CodeIndex);
|
|
||||||
|
|
||||||
fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option<ClauseName> {
|
|
||||||
self.op_dir()
|
|
||||||
.get(&(name, fixity))
|
|
||||||
.map(|op_val| op_val.owning_module())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_module(&mut self, mod_name: ClauseName, module: &Module) {
|
|
||||||
for export in module.module_decl.exports.iter().cloned() {
|
|
||||||
match export {
|
|
||||||
ModuleExport::PredicateKey((name, arity)) => {
|
|
||||||
let name = name.defrock_brackets();
|
|
||||||
|
|
||||||
match self.get_code_index((name.clone(), arity), mod_name.clone()) {
|
|
||||||
Some(CodeIndex(ref code_idx)) => {
|
|
||||||
if &code_idx.borrow().1 != &module.module_decl.name {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.remove_code_index((name.clone(), arity));
|
|
||||||
|
|
||||||
// remove or respecify ops.
|
|
||||||
if arity == 2 {
|
|
||||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) {
|
|
||||||
if mod_name == module.module_decl.name {
|
|
||||||
self.op_dir().remove(&(name.clone(), Fixity::In));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if arity == 1 {
|
|
||||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) {
|
|
||||||
if mod_name == module.module_decl.name {
|
|
||||||
self.op_dir().remove(&(name.clone(), Fixity::Pre));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Post)
|
|
||||||
{
|
|
||||||
if mod_name == module.module_decl.name {
|
|
||||||
self.op_dir().remove(&(name.clone(), Fixity::Post));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
ModuleExport::OpDecl(op_decl) => {
|
|
||||||
let op_dir = self.op_dir();
|
|
||||||
op_dir.remove(&(op_decl.name(), op_decl.fixity()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns true on successful import.
|
|
||||||
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
|
|
||||||
let name = name.defrock_brackets();
|
|
||||||
|
|
||||||
if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
|
|
||||||
let name = name.with_table(submodule.atom_tbl.clone());
|
|
||||||
let atom_tbl = self.atom_tbl();
|
|
||||||
|
|
||||||
atom_tbl.borrow_mut().insert(name.to_rc());
|
|
||||||
|
|
||||||
self.insert_dir_entry(name, arity, code_data.clone());
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
submodule.is_impromptu_module
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_qualified_module(
|
|
||||||
&mut self,
|
|
||||||
_: &mut CodeRepo,
|
|
||||||
_: MachineFlags,
|
|
||||||
_: &Module,
|
|
||||||
_: &Vec<ModuleExport>,
|
|
||||||
) -> Result<(), SessionError>;
|
|
||||||
|
|
||||||
fn use_module(
|
|
||||||
&mut self,
|
|
||||||
_: &mut CodeRepo,
|
|
||||||
_: MachineFlags,
|
|
||||||
_: &Module
|
|
||||||
) -> Result<(), SessionError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn use_qualified_module<User>(
|
|
||||||
user: &mut User,
|
|
||||||
submodule: &Module,
|
|
||||||
exports: &Vec<ModuleExport>,
|
|
||||||
) -> Result<(), SessionError>
|
|
||||||
where
|
|
||||||
User: SubModuleUser,
|
|
||||||
{
|
|
||||||
for export in exports.iter().cloned() {
|
|
||||||
match export {
|
|
||||||
ModuleExport::PredicateKey((name, arity)) => {
|
|
||||||
if !submodule
|
|
||||||
.module_decl
|
|
||||||
.exports
|
|
||||||
.contains(&ModuleExport::PredicateKey((name.clone(), arity)))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !user.import_decl(name.clone(), arity, submodule) {
|
|
||||||
let submodule_name = submodule.module_decl.name.clone();
|
|
||||||
|
|
||||||
return Err(SessionError::ModuleDoesNotContainExport(
|
|
||||||
submodule_name,
|
|
||||||
(name, arity)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ModuleExport::OpDecl(op_decl) => {
|
|
||||||
if !submodule
|
|
||||||
.module_decl
|
|
||||||
.exports
|
|
||||||
.contains(&ModuleExport::OpDecl(op_decl.clone()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let op_dir = user.op_dir();
|
|
||||||
let prec = op_decl.0;
|
|
||||||
|
|
||||||
op_decl.insert_into_op_dir(
|
|
||||||
submodule.module_decl.name.clone(),
|
|
||||||
op_dir,
|
|
||||||
prec,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn use_module<User: SubModuleUser>(
|
|
||||||
user: &mut User,
|
|
||||||
submodule: &Module,
|
|
||||||
) -> Result<(), SessionError> {
|
|
||||||
for export in submodule.module_decl.exports.iter().cloned() {
|
|
||||||
match export {
|
|
||||||
ModuleExport::PredicateKey((name, arity)) => {
|
|
||||||
if !user.import_decl(name.clone(), arity, submodule) {
|
|
||||||
let submodule_name = submodule.module_decl.name.clone();
|
|
||||||
|
|
||||||
return Err(SessionError::ModuleDoesNotContainExport(
|
|
||||||
submodule_name,
|
|
||||||
(name, arity)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ModuleExport::OpDecl(op_decl) => {
|
|
||||||
let op_dir = user.op_dir();
|
|
||||||
let prec = op_decl.0;
|
|
||||||
|
|
||||||
op_decl.insert_into_op_dir(
|
|
||||||
submodule.module_decl.name.clone(),
|
|
||||||
op_dir,
|
|
||||||
prec,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubModuleUser for Module {
|
|
||||||
fn atom_tbl(&self) -> TabledData<Atom> {
|
|
||||||
self.atom_tbl.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn op_dir(&mut self) -> &mut OpDir {
|
|
||||||
&mut self.op_dir
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option<CodeIndex> {
|
|
||||||
self.code_dir.get(&key).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_code_index(&mut self, key: PredicateKey) {
|
|
||||||
self.code_dir.remove(&key);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
|
|
||||||
self.code_dir.insert((name, arity), idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_qualified_module(
|
|
||||||
&mut self,
|
|
||||||
_: &mut CodeRepo,
|
|
||||||
_: MachineFlags,
|
|
||||||
submodule: &Module,
|
|
||||||
exports: &Vec<ModuleExport>,
|
|
||||||
) -> Result<(), SessionError> {
|
|
||||||
use_qualified_module(self, submodule, exports)?;
|
|
||||||
|
|
||||||
(self.user_term_expansions.0)
|
|
||||||
.0
|
|
||||||
.extend((submodule.term_expansions.0).0.iter().cloned());
|
|
||||||
self.user_term_expansions
|
|
||||||
.1
|
|
||||||
.extend(submodule.term_expansions.1.iter().cloned());
|
|
||||||
|
|
||||||
(self.user_goal_expansions.0)
|
|
||||||
.0
|
|
||||||
.extend((submodule.goal_expansions.0).0.iter().cloned());
|
|
||||||
self.user_goal_expansions
|
|
||||||
.1
|
|
||||||
.extend(submodule.goal_expansions.1.iter().cloned());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_module(
|
|
||||||
&mut self,
|
|
||||||
_: &mut CodeRepo,
|
|
||||||
_: MachineFlags,
|
|
||||||
submodule: &Module,
|
|
||||||
) -> Result<(), SessionError> {
|
|
||||||
use_module(self, submodule)?;
|
|
||||||
|
|
||||||
(self.user_term_expansions.0)
|
|
||||||
.0
|
|
||||||
.extend((submodule.term_expansions.0).0.iter().cloned());
|
|
||||||
self.user_term_expansions
|
|
||||||
.1
|
|
||||||
.extend(submodule.term_expansions.1.iter().cloned());
|
|
||||||
|
|
||||||
(self.user_goal_expansions.0)
|
|
||||||
.0
|
|
||||||
.extend((submodule.goal_expansions.0).0.iter().cloned());
|
|
||||||
self.user_goal_expansions
|
|
||||||
.1
|
|
||||||
.extend(submodule.goal_expansions.1.iter().cloned());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
|
use crate::machine::*;
|
||||||
|
use crate::machine::machine_indices::*;
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use std::alloc;
|
use std::alloc;
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ops::RangeFrom;
|
use std::ops::RangeFrom;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PartialString {
|
pub struct PartialString {
|
||||||
buf: *const u8,
|
buf: *const u8,
|
||||||
@@ -200,3 +206,290 @@ impl PartialString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct HeapPStrIter<'a> {
|
||||||
|
focus: Addr,
|
||||||
|
machine_st: &'a MachineState,
|
||||||
|
seen: IndexSet<Addr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HeapPStrIter<'a> {
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn new(machine_st: &'a MachineState, focus: Addr) -> Self {
|
||||||
|
HeapPStrIter {
|
||||||
|
focus,
|
||||||
|
machine_st,
|
||||||
|
seen: IndexSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn focus(&self) -> Addr {
|
||||||
|
self.machine_st.store(self.machine_st.deref(self.focus))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn to_string(&mut self) -> String {
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
while let Some(iteratee) = self.next() {
|
||||||
|
match iteratee {
|
||||||
|
PStrIteratee::Char(c) => {
|
||||||
|
buf.push(c);
|
||||||
|
}
|
||||||
|
PStrIteratee::PStrSegment(h, n) => {
|
||||||
|
match &self.machine_st.heap[h] {
|
||||||
|
HeapCellValue::PartialString(ref pstr, _) => {
|
||||||
|
buf += pstr.as_str_from(n);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub(crate) enum PStrIteratee {
|
||||||
|
Char(char),
|
||||||
|
PStrSegment(usize, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for HeapPStrIter<'a> {
|
||||||
|
type Item = PStrIteratee;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let addr = self.machine_st.store(self.machine_st.deref(self.focus));
|
||||||
|
|
||||||
|
if !self.seen.contains(&addr) {
|
||||||
|
self.seen.insert(addr);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match addr {
|
||||||
|
Addr::PStrLocation(h, n) => {
|
||||||
|
if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
|
||||||
|
self.focus = if has_tail {
|
||||||
|
Addr::HeapCell(h + 1)
|
||||||
|
} else {
|
||||||
|
Addr::EmptyList
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(PStrIteratee::PStrSegment(h, n));
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Lis(l) => {
|
||||||
|
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
|
||||||
|
|
||||||
|
let opt_c = match addr {
|
||||||
|
Addr::Con(h) if self.machine_st.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref atom, _) = &self.machine_st.heap[h] {
|
||||||
|
if atom.is_char() {
|
||||||
|
Some(atom.as_str().chars().next().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Char(c) => {
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(c) = opt_c {
|
||||||
|
self.focus = Addr::HeapCell(l + 1);
|
||||||
|
return Some(PStrIteratee::Char(c));
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::EmptyList => {
|
||||||
|
self.focus = Addr::EmptyList;
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn compare_pstr_prefixes<'a>(
|
||||||
|
i1: &mut HeapPStrIter<'a>,
|
||||||
|
i2: &mut HeapPStrIter<'a>,
|
||||||
|
) -> Option<Ordering> {
|
||||||
|
let mut r1 = i1.next();
|
||||||
|
let mut r2 = i2.next();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(r1i) = r1 {
|
||||||
|
if let Some(r2i) = r2 {
|
||||||
|
match (r1i, r2i) {
|
||||||
|
(PStrIteratee::Char(c1), PStrIteratee::Char(c2)) => {
|
||||||
|
if c1 != c2 {
|
||||||
|
return c1.partial_cmp(&c2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PStrIteratee::Char(c1), PStrIteratee::PStrSegment(h, n)) => {
|
||||||
|
if let &HeapCellValue::PartialString(ref pstr, _) = &i2.machine_st.heap[h] {
|
||||||
|
if let Some(c2) = pstr.as_str_from(n).chars().next() {
|
||||||
|
if c1 != c2 {
|
||||||
|
return c1.partial_cmp(&c2);
|
||||||
|
} else {
|
||||||
|
r1 = i1.next();
|
||||||
|
r2 = Some(PStrIteratee::PStrSegment(h, n + c2.len_utf8()));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r2 = i2.next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PStrIteratee::PStrSegment(h, n), PStrIteratee::Char(c2)) => {
|
||||||
|
if let &HeapCellValue::PartialString(ref pstr, _) = &i1.machine_st.heap[h] {
|
||||||
|
if let Some(c1) = pstr.as_str_from(n).chars().next() {
|
||||||
|
if c1 != c2 {
|
||||||
|
return c2.partial_cmp(&c1);
|
||||||
|
} else {
|
||||||
|
r1 = i1.next();
|
||||||
|
r2 = Some(PStrIteratee::PStrSegment(h, n + c1.len_utf8()));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r1 = i1.next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PStrIteratee::PStrSegment(h1, n1), PStrIteratee::PStrSegment(h2, n2)) => {
|
||||||
|
match (&i1.machine_st.heap[h1], &i2.machine_st.heap[h2]) {
|
||||||
|
(
|
||||||
|
&HeapCellValue::PartialString(ref pstr1, _),
|
||||||
|
&HeapCellValue::PartialString(ref pstr2, _),
|
||||||
|
) => {
|
||||||
|
let str1 = pstr1.as_str_from(n1);
|
||||||
|
let str2 = pstr2.as_str_from(n2);
|
||||||
|
|
||||||
|
if str1.starts_with(str2) {
|
||||||
|
r1 = Some(PStrIteratee::PStrSegment(h1, n1 + str2.len()));
|
||||||
|
r2 = i2.next();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else if str2.starts_with(str1) {
|
||||||
|
r1 = i1.next();
|
||||||
|
r2 = Some(PStrIteratee::PStrSegment(h2, n2 + str1.len()));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return str1.partial_cmp(str2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r1 = i1.next();
|
||||||
|
r2 = i2.next();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return match (i1.focus(), i2.focus()) {
|
||||||
|
(Addr::EmptyList, Addr::EmptyList) => {
|
||||||
|
Some(Ordering::Equal)
|
||||||
|
}
|
||||||
|
(Addr::EmptyList, _) => {
|
||||||
|
Some(Ordering::Less)
|
||||||
|
}
|
||||||
|
(_, Addr::EmptyList) => {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn compare_pstr_to_string<'a>(
|
||||||
|
heap_pstr_iter: &mut HeapPStrIter<'a>,
|
||||||
|
s: &String,
|
||||||
|
) -> Option<usize> {
|
||||||
|
let mut s_offset = 0;
|
||||||
|
|
||||||
|
while let Some(iteratee) = heap_pstr_iter.next() {
|
||||||
|
match iteratee {
|
||||||
|
PStrIteratee::Char(c1) => {
|
||||||
|
if let Some(c2) = s[s_offset ..].chars().next() {
|
||||||
|
if c1 != c2 {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
s_offset += c1.len_utf8();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Some(s_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PStrIteratee::PStrSegment(h, n) => {
|
||||||
|
match heap_pstr_iter.machine_st.heap[h] {
|
||||||
|
HeapCellValue::PartialString(ref pstr, _) => {
|
||||||
|
let t = pstr.as_str_from(n);
|
||||||
|
|
||||||
|
if s[s_offset ..].starts_with(t) {
|
||||||
|
s_offset += t.len();
|
||||||
|
} else if t.starts_with(&s[s_offset ..]) {
|
||||||
|
heap_pstr_iter.focus =
|
||||||
|
Addr::PStrLocation(h, n + s[s_offset ..].len());
|
||||||
|
|
||||||
|
s_offset += s[s_offset ..].len();
|
||||||
|
return Some(s_offset);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s[s_offset ..].is_empty() {
|
||||||
|
return Some(s_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(s_offset)
|
||||||
|
}
|
||||||
|
|||||||
987
src/machine/preprocessor.rs
Normal file
987
src/machine/preprocessor.rs
Normal file
@@ -0,0 +1,987 @@
|
|||||||
|
use crate::prolog_parser::ast::*;
|
||||||
|
use crate::prolog_parser::tabled_rc::*;
|
||||||
|
|
||||||
|
use crate::forms::*;
|
||||||
|
use crate::iterators::*;
|
||||||
|
use crate::machine::*;
|
||||||
|
use crate::machine::load_state::*;
|
||||||
|
use crate::machine::machine_errors::*;
|
||||||
|
|
||||||
|
use crate::indexmap::IndexSet;
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The preprocessor fabricates if-then-else ( .. -> ... ; ...)
|
||||||
|
* clauses into nameless standalone predicates, which it queues for
|
||||||
|
* later preprocessing and compilation. Fabricated predicates inherit
|
||||||
|
* explicit "cut variables" from the handwritten predicate
|
||||||
|
* surrounding their source if-then-else. They must be specially
|
||||||
|
* handled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(crate) enum CutContext {
|
||||||
|
BlocksCuts,
|
||||||
|
HasCutVariable,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
||||||
|
where
|
||||||
|
I: DoubleEndedIterator<Item = Term>,
|
||||||
|
{
|
||||||
|
for prec in terms.rev() {
|
||||||
|
term = Term::Clause(
|
||||||
|
Cell::default(),
|
||||||
|
sym.clone(),
|
||||||
|
vec![Box::new(prec), Box::new(term)],
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
term
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_op_decl(prec: usize, spec: &str, name: ClauseName) -> Result<OpDecl, CompilationError> {
|
||||||
|
match spec {
|
||||||
|
"xfx" => Ok(OpDecl::new(prec, XFX, name)),
|
||||||
|
"xfy" => Ok(OpDecl::new(prec, XFY, name)),
|
||||||
|
"yfx" => Ok(OpDecl::new(prec, YFX, name)),
|
||||||
|
"fx" => Ok(OpDecl::new(prec, FX, name)),
|
||||||
|
"fy" => Ok(OpDecl::new(prec, FY, name)),
|
||||||
|
"xf" => Ok(OpDecl::new(prec, XF, name)),
|
||||||
|
"yf" => Ok(OpDecl::new(prec, YF, name)),
|
||||||
|
_ => Err(CompilationError::InconsistentEntry),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_op_decl(
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
) -> Result<OpDecl, CompilationError> {
|
||||||
|
let name = match *terms.pop().unwrap() {
|
||||||
|
Term::Constant(_, Constant::Atom(name, _)) => name,
|
||||||
|
Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl),
|
||||||
|
_ => return Err(CompilationError::InconsistentEntry),
|
||||||
|
};
|
||||||
|
|
||||||
|
let spec = match *terms.pop().unwrap() {
|
||||||
|
Term::Constant(_, Constant::Atom(name, _)) => name,
|
||||||
|
Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl),
|
||||||
|
_ => return Err(CompilationError::InconsistentEntry),
|
||||||
|
};
|
||||||
|
|
||||||
|
let prec = match *terms.pop().unwrap() {
|
||||||
|
Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
|
||||||
|
Ok(n) if n <= 1200 => n,
|
||||||
|
_ => return Err(CompilationError::InconsistentEntry),
|
||||||
|
},
|
||||||
|
_ => return Err(CompilationError::InconsistentEntry),
|
||||||
|
};
|
||||||
|
|
||||||
|
to_op_decl(prec, spec.as_str(), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError>
|
||||||
|
{
|
||||||
|
match term {
|
||||||
|
Term::Clause(_, ref slash, ref mut terms, Some(_))
|
||||||
|
if (slash.as_str() == "/" || slash.as_str() == "//") && terms.len() == 2 =>
|
||||||
|
{
|
||||||
|
let arity = *terms.pop().unwrap();
|
||||||
|
let name = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
let arity = arity
|
||||||
|
.to_constant()
|
||||||
|
.and_then(|c| {
|
||||||
|
match c {
|
||||||
|
Constant::Integer(n) => n.to_usize(),
|
||||||
|
Constant::Fixnum(n) => usize::try_from(n).ok(),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok_or(CompilationError::InvalidModuleExport)?;
|
||||||
|
|
||||||
|
let name = name
|
||||||
|
.to_constant()
|
||||||
|
.and_then(|c| c.to_atom())
|
||||||
|
.ok_or(CompilationError::InvalidModuleExport)?;
|
||||||
|
|
||||||
|
if slash.as_str() == "/" {
|
||||||
|
Ok((name, arity))
|
||||||
|
} else {
|
||||||
|
Ok((name, arity + 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidModuleExport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn setup_scoped_predicate_indicator(term: &mut Term) -> Result<ScopedPredicateKey, CompilationError>
|
||||||
|
{
|
||||||
|
match term {
|
||||||
|
Term::Clause(_, ref name, ref mut terms, Some(_))
|
||||||
|
if name.as_str() == ":" && terms.len() == 2 =>
|
||||||
|
{
|
||||||
|
let mut predicate_indicator = *terms.pop().unwrap();
|
||||||
|
let module_name = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
let module_name = module_name
|
||||||
|
.to_constant()
|
||||||
|
.and_then(|c| c.to_atom())
|
||||||
|
.ok_or(CompilationError::InvalidModuleExport)?;
|
||||||
|
|
||||||
|
let key = setup_predicate_indicator(&mut predicate_indicator)?;
|
||||||
|
|
||||||
|
Ok((module_name, key))
|
||||||
|
}
|
||||||
|
_ => Err(CompilationError::InvalidModuleExport),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
fn setup_module_export(
|
||||||
|
mut term: Term,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
) -> Result<ModuleExport, CompilationError> {
|
||||||
|
setup_predicate_indicator(&mut term)
|
||||||
|
.map(ModuleExport::PredicateKey)
|
||||||
|
.or_else(|_| {
|
||||||
|
if let Term::Clause(_, name, terms, _) = term {
|
||||||
|
if terms.len() == 3 && name.as_str() == "op" {
|
||||||
|
Ok(ModuleExport::OpDecl(setup_op_decl(
|
||||||
|
terms,
|
||||||
|
atom_tbl
|
||||||
|
)?))
|
||||||
|
} else {
|
||||||
|
Err(CompilationError::InvalidModuleDecl)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(CompilationError::InvalidModuleDecl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn setup_module_export_list(
|
||||||
|
mut export_list: Term,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
) -> Result<Vec<ModuleExport>, CompilationError> {
|
||||||
|
let mut exports = vec![];
|
||||||
|
|
||||||
|
while let Term::Cons(_, t1, t2) = export_list {
|
||||||
|
let module_export = setup_module_export(*t1, atom_tbl.clone())?;
|
||||||
|
|
||||||
|
exports.push(module_export);
|
||||||
|
export_list = *t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if export_list.to_constant() != Some(Constant::EmptyList) {
|
||||||
|
Err(CompilationError::InvalidModuleDecl)
|
||||||
|
} else {
|
||||||
|
Ok(exports)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_module_decl(
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
) -> Result<ModuleDecl, CompilationError> {
|
||||||
|
let export_list = *terms.pop().unwrap();
|
||||||
|
let name = terms
|
||||||
|
.pop()
|
||||||
|
.unwrap()
|
||||||
|
.to_constant()
|
||||||
|
.and_then(|c| c.to_atom())
|
||||||
|
.ok_or(CompilationError::InvalidModuleDecl)?;
|
||||||
|
|
||||||
|
let exports = setup_module_export_list(export_list, atom_tbl)?;
|
||||||
|
Ok(ModuleDecl { name, exports })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, CompilationError> {
|
||||||
|
match *terms.pop().unwrap() {
|
||||||
|
Term::Clause(_, ref name, ref mut terms, None)
|
||||||
|
if name.as_str() == "library" && terms.len() == 1 =>
|
||||||
|
{
|
||||||
|
terms
|
||||||
|
.pop()
|
||||||
|
.unwrap()
|
||||||
|
.to_constant()
|
||||||
|
.and_then(|c| c.to_atom())
|
||||||
|
.map(|c| ModuleSource::Library(c))
|
||||||
|
.ok_or(CompilationError::InvalidUseModuleDecl)
|
||||||
|
}
|
||||||
|
Term::Constant(_, Constant::Atom(ref name, _)) =>
|
||||||
|
Ok(ModuleSource::File(name.clone())),
|
||||||
|
_ => Err(CompilationError::InvalidUseModuleDecl),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, CompilationError> {
|
||||||
|
let dbl_quotes = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
match terms[0].as_ref() {
|
||||||
|
Term::Constant(_, Constant::Atom(ref name, _))
|
||||||
|
if name.as_str() == "double_quotes" => {
|
||||||
|
match dbl_quotes {
|
||||||
|
Term::Constant(_, Constant::Atom(name, _)) => {
|
||||||
|
match name.as_str() {
|
||||||
|
"atom" => Ok(DoubleQuotes::Atom),
|
||||||
|
"chars" => Ok(DoubleQuotes::Chars),
|
||||||
|
"codes" => Ok(DoubleQuotes::Codes),
|
||||||
|
_ => Err(CompilationError::InvalidDoubleQuotesDecl),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidDoubleQuotesDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidDoubleQuotesDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
|
||||||
|
|
||||||
|
fn setup_qualified_import(
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
) -> Result<UseModuleExport, CompilationError> {
|
||||||
|
let mut export_list = *terms.pop().unwrap();
|
||||||
|
let module_src = match *terms.pop().unwrap() {
|
||||||
|
Term::Clause(_, ref name, ref mut terms, None)
|
||||||
|
if name.as_str() == "library" && terms.len() == 1 =>
|
||||||
|
{
|
||||||
|
terms
|
||||||
|
.pop()
|
||||||
|
.unwrap()
|
||||||
|
.to_constant()
|
||||||
|
.and_then(|c| c.to_atom())
|
||||||
|
.map(|c| ModuleSource::Library(c))
|
||||||
|
.ok_or(CompilationError::InvalidUseModuleDecl)
|
||||||
|
}
|
||||||
|
Term::Constant(_, Constant::Atom(ref name, _)) => {
|
||||||
|
Ok(ModuleSource::File(name.clone()))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidUseModuleDecl)
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let mut exports = IndexSet::new();
|
||||||
|
|
||||||
|
while let Term::Cons(_, t1, t2) = export_list {
|
||||||
|
exports.insert(setup_module_export(*t1, atom_tbl.clone())?);
|
||||||
|
export_list = *t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if export_list.to_constant() != Some(Constant::EmptyList) {
|
||||||
|
Err(CompilationError::InvalidModuleDecl)
|
||||||
|
} else {
|
||||||
|
Ok((module_src, exports))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup_meta_predicate tries to extract meta-predicate information
|
||||||
|
* from an appropriately formed declaration
|
||||||
|
*
|
||||||
|
* :- meta_predicate maplist(:, ?, ?).
|
||||||
|
*
|
||||||
|
* indicating that, for each QueryTerm call to maplist/3, the first
|
||||||
|
* argument is to be expanded with the call resolution ((:)/2)
|
||||||
|
* operator, the first argument of which is the name of the host
|
||||||
|
* module, as an atom. For example,
|
||||||
|
*
|
||||||
|
* p(X) :- maplist(X, [a,b,c], Result).
|
||||||
|
*
|
||||||
|
* If p/2 is defined in a module named "mod", the call is expanded to
|
||||||
|
*
|
||||||
|
* maplist(mod:X, [a,b,c], Result).
|
||||||
|
*
|
||||||
|
* before the predicate is compiled to WAM instructions.
|
||||||
|
*
|
||||||
|
* If the term bound to X -- the predicate to be called -- is
|
||||||
|
* qualified with (:)/2 already, the innermost qualifier is used for
|
||||||
|
* call resolution.
|
||||||
|
*
|
||||||
|
* The three arguments returned by a successful call are the module name,
|
||||||
|
* predicate name, and the list of meta-specs, one for each predicate argument.
|
||||||
|
*
|
||||||
|
* The module name might be used to specify intra-module meta-predicates whose
|
||||||
|
* module is not yet defined. There are several examples of this
|
||||||
|
* contained in src/lib/ops_and_meta_predicates.pl, which is loaded before
|
||||||
|
* src/lib/builtins.pl.
|
||||||
|
*
|
||||||
|
* Meta-specs have three forms:
|
||||||
|
*
|
||||||
|
* (:) (the argument should be expanded with (:)/2 as described above)
|
||||||
|
* + (mode declarations under the mode syntax, which currently have no effect)
|
||||||
|
* -
|
||||||
|
* ?
|
||||||
|
*/
|
||||||
|
fn setup_meta_predicate<'a>(
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
load_state: &LoadState<'a>,
|
||||||
|
) -> Result<(ClauseName, ClauseName, Vec<MetaSpec>), CompilationError>
|
||||||
|
{
|
||||||
|
fn get_name_and_meta_specs(
|
||||||
|
name: ClauseName,
|
||||||
|
terms: &mut [Box<Term>],
|
||||||
|
) -> Result<(ClauseName, Vec<MetaSpec>), CompilationError> {
|
||||||
|
let mut meta_specs = vec![];
|
||||||
|
|
||||||
|
for meta_spec in terms.into_iter() {
|
||||||
|
match &**meta_spec {
|
||||||
|
Term::Constant(_, Constant::Atom(meta_spec, _)) => {
|
||||||
|
let meta_spec =
|
||||||
|
match meta_spec.as_str() {
|
||||||
|
":" => MetaSpec::RequiresExpansion,
|
||||||
|
"+" => MetaSpec::Plus,
|
||||||
|
"-" => MetaSpec::Minus,
|
||||||
|
"?" => MetaSpec::Either,
|
||||||
|
_ => return Err(CompilationError::InvalidMetaPredicateDecl),
|
||||||
|
};
|
||||||
|
|
||||||
|
meta_specs.push(meta_spec);
|
||||||
|
}
|
||||||
|
Term::Constant(_, Constant::Fixnum(n)) => {
|
||||||
|
match usize::try_from(*n) {
|
||||||
|
Ok(n) if n <= MAX_ARITY => {
|
||||||
|
meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(CompilationError::InvalidMetaPredicateDecl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(CompilationError::InvalidMetaPredicateDecl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((name, meta_specs))
|
||||||
|
}
|
||||||
|
|
||||||
|
match *terms.pop().unwrap() {
|
||||||
|
Term::Clause(_, name, mut terms, _)
|
||||||
|
if name.as_str() == ":" && terms.len() == 2 => {
|
||||||
|
let spec = *terms.pop().unwrap();
|
||||||
|
let module_name = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
match module_name {
|
||||||
|
Term::Constant(_, Constant::Atom(module_name, _)) => {
|
||||||
|
match spec {
|
||||||
|
Term::Clause(_, name, mut terms, _) => {
|
||||||
|
let (name, meta_specs) =
|
||||||
|
get_name_and_meta_specs(name, &mut terms)?;
|
||||||
|
|
||||||
|
Ok((module_name, name, meta_specs))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidMetaPredicateDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidMetaPredicateDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Term::Clause(_, name, mut terms, _) => {
|
||||||
|
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
|
||||||
|
Ok((load_state.module_name(), name, meta_specs))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidMetaPredicateDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, CompilationError>
|
||||||
|
{
|
||||||
|
let mut clauses = vec![];
|
||||||
|
|
||||||
|
while let Some(tl) = tls.pop_front() {
|
||||||
|
match tl {
|
||||||
|
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => {
|
||||||
|
return Ok(tl);
|
||||||
|
}
|
||||||
|
TopLevel::Declaration(_) if clauses.is_empty() => {
|
||||||
|
return Ok(tl);
|
||||||
|
}
|
||||||
|
TopLevel::Query(_) => {
|
||||||
|
return Err(CompilationError::InconsistentEntry);
|
||||||
|
}
|
||||||
|
TopLevel::Fact(fact) => {
|
||||||
|
let clause = PredicateClause::Fact(fact);
|
||||||
|
clauses.push(clause);
|
||||||
|
}
|
||||||
|
TopLevel::Rule(rule) => {
|
||||||
|
let clause = PredicateClause::Rule(rule);
|
||||||
|
clauses.push(clause);
|
||||||
|
}
|
||||||
|
TopLevel::Predicate(predicate) => {
|
||||||
|
clauses.extend(predicate.into_iter())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tls.push_front(tl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if clauses.is_empty() {
|
||||||
|
Err(CompilationError::InconsistentEntry)
|
||||||
|
} else {
|
||||||
|
Ok(TopLevel::Predicate(clauses))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_cut_variables_as(terms: &mut Vec<Term>, name: ClauseName) {
|
||||||
|
for term in terms.iter_mut() {
|
||||||
|
match term {
|
||||||
|
&mut Term::Constant(_, Constant::Atom(ref mut var, _)) if var.as_str() == "!" => {
|
||||||
|
*var = name.clone()
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_cut_variable(term: &mut Term) -> bool {
|
||||||
|
let cut_var_found = match term {
|
||||||
|
&mut Term::Constant(_, Constant::Atom(ref var, _)) if var.as_str() == "!" => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if cut_var_found {
|
||||||
|
*term = Term::Var(Cell::default(), rc_atom!("!"));
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_cut_variables(terms: &mut Vec<Term>) -> bool {
|
||||||
|
let mut found_cut_var = false;
|
||||||
|
|
||||||
|
for item in terms.iter_mut() {
|
||||||
|
found_cut_var = mark_cut_variable(item) || found_cut_var;
|
||||||
|
}
|
||||||
|
|
||||||
|
found_cut_var
|
||||||
|
}
|
||||||
|
|
||||||
|
// terms is a list of goals composing one clause in a (;) functor. it
|
||||||
|
// checks that the first (and only) of these clauses is a ->. if so,
|
||||||
|
// it expands its terms using a blocked_!.
|
||||||
|
fn check_for_internal_if_then(terms: &mut Vec<Term>) {
|
||||||
|
if terms.len() != 1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(Term::Clause(_, ref name, ref subterms, _)) = terms.last() {
|
||||||
|
if name.as_str() != "->" || subterms.len() != 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(Term::Clause(_, _, mut subterms, _)) = terms.pop() {
|
||||||
|
let mut conq_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
|
||||||
|
let mut pre_cut_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
|
||||||
|
|
||||||
|
conq_terms.push_front(Term::Constant(
|
||||||
|
Cell::default(),
|
||||||
|
Constant::Atom(clause_name!("blocked_!"), None))
|
||||||
|
);
|
||||||
|
|
||||||
|
while let Some(term) = pre_cut_terms.pop_back() {
|
||||||
|
conq_terms.push_front(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tail_term = conq_terms.pop_back().unwrap();
|
||||||
|
|
||||||
|
terms.push(fold_by_str(
|
||||||
|
conq_terms.into_iter(),
|
||||||
|
tail_term,
|
||||||
|
clause_name!(","),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_declaration<'a>(
|
||||||
|
load_state: &LoadState<'a>,
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
) -> Result<Declaration, CompilationError> {
|
||||||
|
let term = *terms.pop().unwrap();
|
||||||
|
let atom_tbl = load_state.wam.machine_st.atom_tbl.clone();
|
||||||
|
|
||||||
|
match term {
|
||||||
|
Term::Clause(_, name, mut terms, _) =>
|
||||||
|
match (name.as_str(), terms.len()) {
|
||||||
|
("dynamic", 1) => {
|
||||||
|
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||||
|
Ok(Declaration::Dynamic(name, arity))
|
||||||
|
}
|
||||||
|
("module", 2) =>
|
||||||
|
Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?)),
|
||||||
|
("op", 3) =>
|
||||||
|
Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?)),
|
||||||
|
("non_counted_backtracking", 1) => {
|
||||||
|
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||||
|
Ok(Declaration::NonCountedBacktracking(name, arity))
|
||||||
|
}
|
||||||
|
("use_module", 1) => {
|
||||||
|
Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
|
||||||
|
}
|
||||||
|
("use_module", 2) => {
|
||||||
|
let (name, exports) = setup_qualified_import(terms, atom_tbl)?;
|
||||||
|
Ok(Declaration::UseQualifiedModule(name, exports))
|
||||||
|
}
|
||||||
|
("meta_predicate", 1) => {
|
||||||
|
let (module_name, name, meta_specs) = setup_meta_predicate(terms, load_state)?;
|
||||||
|
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InconsistentEntry)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InconsistentEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn clause_to_query_term<'a>(
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
name: ClauseName,
|
||||||
|
terms: Vec<Box<Term>>,
|
||||||
|
fixity: Option<SharedOpDesc>,
|
||||||
|
) -> QueryTerm {
|
||||||
|
let ct = load_state.get_clause_type(name, terms.len(), fixity);
|
||||||
|
QueryTerm::Clause(Cell::default(), ct, terms, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn qualified_clause_to_query_term<'a>(
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
module_name: ClauseName,
|
||||||
|
name: ClauseName,
|
||||||
|
terms: Vec<Box<Term>>,
|
||||||
|
fixity: Option<SharedOpDesc>,
|
||||||
|
) -> QueryTerm {
|
||||||
|
let ct = load_state.get_qualified_clause_type(module_name, name, terms.len(), fixity);
|
||||||
|
QueryTerm::Clause(Cell::default(), ct, terms, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct Preprocessor {
|
||||||
|
flags: MachineFlags,
|
||||||
|
queue: VecDeque<VecDeque<Term>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Preprocessor {
|
||||||
|
pub(super)
|
||||||
|
fn new(flags: MachineFlags) -> Self {
|
||||||
|
Preprocessor {
|
||||||
|
flags,
|
||||||
|
queue: VecDeque::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_fact(&mut self, term: Term) -> Result<Term, CompilationError> {
|
||||||
|
match term {
|
||||||
|
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => {
|
||||||
|
Ok(term)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InadmissibleFact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_head(&self, term: &Term) -> Vec<Term> {
|
||||||
|
let mut vars = IndexSet::new();
|
||||||
|
|
||||||
|
for term in post_order_iter(term) {
|
||||||
|
if let TermRef::Var(_, _, v) = term {
|
||||||
|
vars.insert(v.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vars.insert(rc_atom!("!"));
|
||||||
|
vars.into_iter()
|
||||||
|
.map(|v| Term::Var(Cell::default(), v))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fabricate_rule_body(&self, vars: &Vec<Term>, body_term: Term) -> Term {
|
||||||
|
let vars_of_head = vars.iter().cloned().map(Box::new).collect();
|
||||||
|
let head_term = Term::Clause(Cell::default(), clause_name!(""), vars_of_head, None);
|
||||||
|
|
||||||
|
let rule = vec![Box::new(head_term), Box::new(body_term)];
|
||||||
|
let turnstile = clause_name!(":-");
|
||||||
|
|
||||||
|
Term::Clause(Cell::default(), turnstile, rule, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the terms form the body of the rule. We create a head, by
|
||||||
|
// gathering variables from the body of terms and recording them
|
||||||
|
// in the head clause.
|
||||||
|
fn fabricate_rule(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
|
||||||
|
// collect the vars of body_term into a head, return the num_vars
|
||||||
|
// (the arity) as well.
|
||||||
|
let vars = self.compute_head(&body_term);
|
||||||
|
let rule = self.fabricate_rule_body(&vars, body_term);
|
||||||
|
|
||||||
|
(vars, VecDeque::from(vec![rule]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
|
||||||
|
let vars = self.compute_head(&body_term);
|
||||||
|
let results = unfold_by_str(body_term, ";")
|
||||||
|
.into_iter()
|
||||||
|
.map(|term| {
|
||||||
|
let mut subterms = unfold_by_str(term, ",");
|
||||||
|
mark_cut_variables(&mut subterms);
|
||||||
|
|
||||||
|
check_for_internal_if_then(&mut subterms);
|
||||||
|
|
||||||
|
let term = subterms.pop().unwrap();
|
||||||
|
let clause = fold_by_str(subterms.into_iter(), term, clause_name!(","));
|
||||||
|
|
||||||
|
self.fabricate_rule_body(&vars, clause)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(vars, results)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fabricate_if_then(&self, prec: Term, conq: Term) -> (JumpStub, VecDeque<Term>) {
|
||||||
|
let mut prec_seq = unfold_by_str(prec, ",");
|
||||||
|
let comma_sym = clause_name!(",");
|
||||||
|
let cut_sym = atom!("!");
|
||||||
|
|
||||||
|
prec_seq.push(Term::Constant(Cell::default(), cut_sym));
|
||||||
|
|
||||||
|
mark_cut_variables_as(&mut prec_seq, clause_name!("blocked_!"));
|
||||||
|
|
||||||
|
let mut conq_seq = unfold_by_str(conq, ",");
|
||||||
|
|
||||||
|
mark_cut_variables(&mut conq_seq);
|
||||||
|
prec_seq.extend(conq_seq.into_iter());
|
||||||
|
|
||||||
|
let back_term = Box::new(prec_seq.pop().unwrap());
|
||||||
|
let front_term = Box::new(prec_seq.pop().unwrap());
|
||||||
|
|
||||||
|
let body_term = Term::Clause(
|
||||||
|
Cell::default(),
|
||||||
|
comma_sym.clone(),
|
||||||
|
vec![front_term, back_term],
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_query_term<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
term: Term,
|
||||||
|
) -> Result<QueryTerm, CompilationError> {
|
||||||
|
match term {
|
||||||
|
Term::Constant(_, Constant::Atom(name, fixity)) => {
|
||||||
|
if name.as_str() == "!" || name.as_str() == "blocked_!" {
|
||||||
|
Ok(QueryTerm::BlockedCut)
|
||||||
|
} else {
|
||||||
|
Ok(clause_to_query_term(load_state, name, vec![], fixity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Term::Var(_, ref v) if v.as_str() == "!" => {
|
||||||
|
Ok(QueryTerm::UnblockedCut(Cell::default()))
|
||||||
|
}
|
||||||
|
Term::Clause(r, name, mut terms, fixity) => {
|
||||||
|
match (name.as_str(), terms.len()) {
|
||||||
|
(";", 2) => {
|
||||||
|
let term = Term::Clause(r, name.clone(), terms, fixity);
|
||||||
|
|
||||||
|
let (stub, clauses) = self.fabricate_disjunct(term);
|
||||||
|
self.queue.push_back(clauses);
|
||||||
|
|
||||||
|
Ok(QueryTerm::Jump(stub))
|
||||||
|
}
|
||||||
|
("->", 2) => {
|
||||||
|
let conq = *terms.pop().unwrap();
|
||||||
|
let prec = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
let (stub, clauses) = self.fabricate_if_then(prec, conq);
|
||||||
|
self.queue.push_back(clauses);
|
||||||
|
|
||||||
|
Ok(QueryTerm::Jump(stub))
|
||||||
|
}
|
||||||
|
("\\+", 1) => {
|
||||||
|
terms.push(Box::new(Term::Constant(
|
||||||
|
Cell::default(),
|
||||||
|
Constant::Atom(clause_name!("$fail"), None)
|
||||||
|
)));
|
||||||
|
|
||||||
|
let conq = Term::Constant(
|
||||||
|
Cell::default(),
|
||||||
|
Constant::Atom(clause_name!("true"), None)
|
||||||
|
);
|
||||||
|
|
||||||
|
let prec = Term::Clause(Cell::default(), clause_name!("->"), terms, None);
|
||||||
|
let terms = vec![Box::new(prec), Box::new(conq)];
|
||||||
|
|
||||||
|
let term = Term::Clause(Cell::default(), clause_name!(";"), terms, None);
|
||||||
|
let (stub, clauses) = self.fabricate_disjunct(term);
|
||||||
|
|
||||||
|
debug_assert!(clauses.len() > 0);
|
||||||
|
self.queue.push_back(clauses);
|
||||||
|
|
||||||
|
Ok(QueryTerm::Jump(stub))
|
||||||
|
}
|
||||||
|
("$get_level", 1) => {
|
||||||
|
if let Term::Var(_, ref var) = *terms[0] {
|
||||||
|
Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone()))
|
||||||
|
} else {
|
||||||
|
Err(CompilationError::InadmissibleQueryTerm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(":", 2) => {
|
||||||
|
let predicate_name = *terms.pop().unwrap();
|
||||||
|
let module_name = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
match (module_name, predicate_name) {
|
||||||
|
(Term::Constant(_, Constant::Atom(module_name, _)),
|
||||||
|
Term::Constant(_, Constant::Atom(predicate_name, fixity))) => {
|
||||||
|
Ok(qualified_clause_to_query_term(
|
||||||
|
load_state,
|
||||||
|
module_name,
|
||||||
|
predicate_name,
|
||||||
|
vec![],
|
||||||
|
fixity,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(Term::Constant(_, Constant::Atom(module_name, _)),
|
||||||
|
Term::Clause(_, name, terms, fixity)) => {
|
||||||
|
Ok(qualified_clause_to_query_term(
|
||||||
|
load_state,
|
||||||
|
module_name,
|
||||||
|
name,
|
||||||
|
terms,
|
||||||
|
fixity,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(module_name, predicate_name) => {
|
||||||
|
terms.push(Box::new(module_name));
|
||||||
|
terms.push(Box::new(predicate_name));
|
||||||
|
|
||||||
|
Ok(clause_to_query_term(load_state, name, terms, fixity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Ok(clause_to_query_term(load_state, name, terms, fixity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Term::Var(..) => {
|
||||||
|
Ok(QueryTerm::Clause(
|
||||||
|
Cell::default(),
|
||||||
|
ClauseType::CallN,
|
||||||
|
vec![Box::new(term)],
|
||||||
|
false,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InadmissibleQueryTerm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pre_query_term<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
term: Term,
|
||||||
|
) -> Result<QueryTerm, CompilationError> {
|
||||||
|
match term {
|
||||||
|
Term::Clause(r, name, mut subterms, fixity) => {
|
||||||
|
if subterms.len() == 1 && name.as_str() == "$call_with_default_policy" {
|
||||||
|
self.to_query_term(load_state, *subterms.pop().unwrap())
|
||||||
|
.map(|mut query_term| {
|
||||||
|
query_term.set_default_caller();
|
||||||
|
query_term
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
self.to_query_term(load_state, Term::Clause(r, name, subterms, fixity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.to_query_term(load_state, term)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_query<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
terms: Vec<Box<Term>>,
|
||||||
|
cut_context: CutContext,
|
||||||
|
) -> Result<Vec<QueryTerm>, CompilationError> {
|
||||||
|
let mut query_terms = vec![];
|
||||||
|
let mut work_queue = VecDeque::from(terms);
|
||||||
|
|
||||||
|
while let Some(term) = work_queue.pop_front() {
|
||||||
|
let mut term = *term;
|
||||||
|
|
||||||
|
if let Term::Clause(cell, name, terms, op_spec) = term {
|
||||||
|
if name.as_str() == "," && terms.len() == 2 {
|
||||||
|
let term = Term::Clause(cell, name, terms, op_spec);
|
||||||
|
let mut subterms = unfold_by_str(term, ",");
|
||||||
|
|
||||||
|
while let Some(subterm) = subterms.pop() {
|
||||||
|
work_queue.push_front(Box::new(subterm));
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
term = Term::Clause(cell, name, terms, op_spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let CutContext::HasCutVariable = cut_context {
|
||||||
|
mark_cut_variable(&mut term);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_terms.push(self.pre_query_term(load_state, term)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(query_terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_rule<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
cut_context: CutContext,
|
||||||
|
) -> Result<Rule, CompilationError> {
|
||||||
|
let post_head_terms: Vec<_> = terms.drain(1 ..).collect();
|
||||||
|
|
||||||
|
let mut query_terms =
|
||||||
|
self.setup_query(load_state, post_head_terms, cut_context)?;
|
||||||
|
|
||||||
|
let clauses = query_terms.drain(1 ..).collect();
|
||||||
|
let qt = query_terms.pop().unwrap();
|
||||||
|
|
||||||
|
match *terms.pop().unwrap() {
|
||||||
|
Term::Clause(_, name, terms, _) => {
|
||||||
|
Ok(Rule {
|
||||||
|
head: (name, terms, qt),
|
||||||
|
clauses,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Term::Constant(_, Constant::Atom(name, _)) => {
|
||||||
|
Ok(Rule {
|
||||||
|
head: (name, vec![], qt),
|
||||||
|
clauses,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(CompilationError::InvalidRuleHead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_term_to_query<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
terms: Vec<Box<Term>>,
|
||||||
|
cut_context: CutContext,
|
||||||
|
) -> Result<TopLevel, CompilationError> {
|
||||||
|
Ok(TopLevel::Query(self.setup_query(load_state, terms, cut_context)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn try_term_to_tl<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
term: Term,
|
||||||
|
cut_context: CutContext,
|
||||||
|
) -> Result<TopLevel, CompilationError> {
|
||||||
|
match term {
|
||||||
|
Term::Clause(r, name, terms, fixity) => {
|
||||||
|
if name.as_str() == "?-" {
|
||||||
|
self.try_term_to_query(load_state, terms, cut_context)
|
||||||
|
} else if name.as_str() == ":-" && terms.len() == 2 {
|
||||||
|
Ok(TopLevel::Rule(self.setup_rule(
|
||||||
|
load_state,
|
||||||
|
terms,
|
||||||
|
cut_context,
|
||||||
|
)?))
|
||||||
|
} else if name.as_str() == ":-" && terms.len() == 1 {
|
||||||
|
Ok(TopLevel::Declaration(setup_declaration(load_state, terms)?))
|
||||||
|
} else {
|
||||||
|
let term = Term::Clause(r, name, terms, fixity);
|
||||||
|
Ok(TopLevel::Fact(self.setup_fact(term)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
term => {
|
||||||
|
Ok(TopLevel::Fact(self.setup_fact(term)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
terms: I,
|
||||||
|
cut_context: CutContext,
|
||||||
|
) -> Result<VecDeque<TopLevel>, CompilationError> {
|
||||||
|
let mut results = VecDeque::new();
|
||||||
|
|
||||||
|
for term in terms.into_iter() {
|
||||||
|
results.push_back(self.try_term_to_tl(load_state, term, cut_context)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn parse_queue<'a>(
|
||||||
|
&mut self,
|
||||||
|
load_state: &mut LoadState<'a>,
|
||||||
|
) -> Result<VecDeque<TopLevel>, CompilationError> {
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
|
||||||
|
while let Some(terms) = self.queue.pop_front() {
|
||||||
|
let clauses = merge_clauses(
|
||||||
|
&mut self.try_terms_to_tls(
|
||||||
|
load_state,
|
||||||
|
terms,
|
||||||
|
CutContext::HasCutVariable,
|
||||||
|
)?
|
||||||
|
)?;
|
||||||
|
|
||||||
|
queue.push_back(clauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(queue)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
:- module('$project_atts', [copy_term/3]).
|
:- module('$project_atts', [copy_term/3]).
|
||||||
|
|
||||||
'$attribute_goals_driver'(QueryVars, AttrVars) :-
|
driver(QueryVars, AttrVars) :-
|
||||||
gather_modules(AttrVars, Modules0, _),
|
gather_attr_modules(AttrVars, Modules0),
|
||||||
sort(Modules0, Modules),
|
sort(Modules0, Modules),
|
||||||
call_project_attributes(Modules, QueryVars, AttrVars),
|
call_project_attributes(Modules, QueryVars, AttrVars),
|
||||||
call_attribute_goals(Modules, call_query_var_goals, QueryVars),
|
call_attribute_goals(Modules, '$project_atts':call_query_var_goals, QueryVars),
|
||||||
call_attribute_goals(Modules, call_attr_var_goals, AttrVars).
|
call_attribute_goals(Modules, '$project_atts':call_attr_var_goals, AttrVars).
|
||||||
|
|
||||||
enqueue_goals(Goals0) :-
|
enqueue_goals(Goals0) :-
|
||||||
nonvar(Goals0),
|
nonvar(Goals0),
|
||||||
@@ -36,7 +36,7 @@ call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
|
|||||||
call_project_attributes(Modules, QueryVars, AttrVars).
|
call_project_attributes(Modules, QueryVars, AttrVars).
|
||||||
|
|
||||||
call_attribute_goals([], _, _).
|
call_attribute_goals([], _, _).
|
||||||
call_attribute_goals([Module | Modules], GoalCaller, AttrVars) :-
|
call_attribute_goals([Module|Modules], GoalCaller, AttrVars) :-
|
||||||
call(GoalCaller, AttrVars, Module, Goals),
|
call(GoalCaller, AttrVars, Module, Goals),
|
||||||
enqueue_goals(Goals),
|
enqueue_goals(Goals),
|
||||||
call_attribute_goals(Modules, GoalCaller, AttrVars).
|
call_attribute_goals(Modules, GoalCaller, AttrVars).
|
||||||
@@ -51,13 +51,13 @@ call_attribute_goals([Module | Modules], GoalCaller, AttrVars) :-
|
|||||||
|
|
||||||
call_query_var_goals([], _, []).
|
call_query_var_goals([], _, []).
|
||||||
call_query_var_goals([AttrVar|AttrVars], Module, Goals) :-
|
call_query_var_goals([AttrVar|AttrVars], Module, Goals) :-
|
||||||
( catch(( Module:attribute_goals(AttrVar, Goals, RGoals0)
|
( catch(( Module:attribute_goals(AttrVar, Goals, RGoals0),
|
||||||
, atts:'$default_attr_list'(Module, AttrVar, RGoals0, RGoals)
|
atts:'$default_attr_list'(Module, AttrVar, RGoals0, RGoals)
|
||||||
),
|
),
|
||||||
E,
|
E,
|
||||||
( '$print_attribute_goals_exception'(Module, E),
|
( '$project_atts':'$print_attribute_goals_exception'(Module, E),
|
||||||
atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
|
atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
|
||||||
))
|
))
|
||||||
-> true
|
-> true
|
||||||
; atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
|
; atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
|
||||||
),
|
),
|
||||||
@@ -66,25 +66,14 @@ call_query_var_goals([AttrVar|AttrVars], Module, Goals) :-
|
|||||||
call_attr_var_goals([], _, []).
|
call_attr_var_goals([], _, []).
|
||||||
call_attr_var_goals([AttrVar|AttrVars], Module, Goals) :-
|
call_attr_var_goals([AttrVar|AttrVars], Module, Goals) :-
|
||||||
( catch(Module:attribute_goals(AttrVar, Goals, RGoals),
|
( catch(Module:attribute_goals(AttrVar, Goals, RGoals),
|
||||||
E,
|
E,
|
||||||
'$print_attribute_goals_exception'(Module, E)
|
'$project_atts':'$print_attribute_goals_exception'(Module, E)
|
||||||
)
|
)
|
||||||
-> true
|
-> true
|
||||||
; true
|
; true
|
||||||
),
|
),
|
||||||
call_attr_var_goals(AttrVars, Module, RGoals).
|
call_attr_var_goals(AttrVars, Module, RGoals).
|
||||||
|
|
||||||
gather_modules([], [], _).
|
|
||||||
gather_modules([AttrVar|AttrVars], Modules, Modules0) :-
|
|
||||||
'$get_attr_list'(AttrVar, Attrs),
|
|
||||||
gather_modules_for_attrs(Attrs, Modules, Modules0),
|
|
||||||
gather_modules(AttrVars, Modules0, _).
|
|
||||||
|
|
||||||
gather_modules_for_attrs(Attrs, Modules, Modules) :-
|
|
||||||
var(Attrs), !.
|
|
||||||
gather_modules_for_attrs([Attr|Attrs], [Module|Modules], Modules0) :-
|
|
||||||
'$module_of'(Module, Attr),
|
|
||||||
gather_modules_for_attrs(Attrs, Modules, Modules0).
|
|
||||||
|
|
||||||
module_prefixed_goals([], _, Gs, Gs).
|
module_prefixed_goals([], _, Gs, Gs).
|
||||||
module_prefixed_goals([G|Gs], Module, [MG|MGs], TailGs) :-
|
module_prefixed_goals([G|Gs], Module, [MG|MGs], TailGs) :-
|
||||||
@@ -100,11 +89,25 @@ call_attribute_goals_with_module_prefix([Module | Modules], GoalCaller, AttrVars
|
|||||||
module_prefixed_goals(Goals0, Module, Goals, Gs),
|
module_prefixed_goals(Goals0, Module, Goals, Gs),
|
||||||
call_attribute_goals_with_module_prefix(Modules, GoalCaller, AttrVars, Gs).
|
call_attribute_goals_with_module_prefix(Modules, GoalCaller, AttrVars, Gs).
|
||||||
|
|
||||||
|
|
||||||
|
gather_attr_modules([], []).
|
||||||
|
gather_attr_modules([AttrVar|AttrVars], Modules) :-
|
||||||
|
'$get_attr_list'(AttrVar, Attrs),
|
||||||
|
copy_attribute_modules(Attrs, Modules, Modules0),
|
||||||
|
gather_attr_modules(AttrVars, Modules0).
|
||||||
|
|
||||||
|
copy_attribute_modules(Attrs, Ls, Ls) :-
|
||||||
|
var(Attrs), !.
|
||||||
|
copy_attribute_modules([Module:_|Attrs], [Module|Modules0], Modules1) :-
|
||||||
|
copy_attribute_modules(Attrs, Modules0, Modules1).
|
||||||
|
|
||||||
|
|
||||||
copy_term(Source, Dest, Goals) :-
|
copy_term(Source, Dest, Goals) :-
|
||||||
'$term_attributed_variables'(Source, Vars),
|
'$term_attributed_variables'(Source, AttrVars),
|
||||||
gather_modules(Vars, Modules0, _),
|
gather_attr_modules(AttrVars, Modules0),
|
||||||
sort(Modules0, Modules),
|
sort(Modules0, Modules),
|
||||||
call_attribute_goals_with_module_prefix(Modules, call_query_var_goals, Vars, Goals0),
|
call_attribute_goals_with_module_prefix(Modules, '$project_atts':call_query_var_goals,
|
||||||
|
AttrVars, Goals0),
|
||||||
sort(Goals0, Goals1),
|
sort(Goals0, Goals1),
|
||||||
!,
|
!,
|
||||||
'$copy_term_without_attr_vars'([Source | Goals1], [Dest | Goals]).
|
'$copy_term_without_attr_vars'([Source | Goals1], [Dest | Goals]).
|
||||||
|
|||||||
@@ -246,10 +246,6 @@ impl Stack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take(&mut self) -> Self {
|
|
||||||
Stack { buf: self.buf.take(), _marker: PhantomData }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn truncate(&mut self, b: usize) {
|
pub fn truncate(&mut self, b: usize) {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
|
|||||||
@@ -179,10 +179,10 @@ impl Drop for StreamInstance {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||||
discard_result!(tcp_stream.shutdown(Shutdown::Both));
|
tcp_stream.shutdown(Shutdown::Both).unwrap();
|
||||||
}
|
}
|
||||||
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||||
discard_result!(tls_stream.shutdown());
|
tls_stream.shutdown().unwrap();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ use crate::clause_types::*;
|
|||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::heap_print::*;
|
use crate::heap_print::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
|
use crate::machine;
|
||||||
use crate::machine::code_repo::CodeRepo;
|
use crate::machine::code_repo::CodeRepo;
|
||||||
use crate::machine::copier::*;
|
use crate::machine::copier::*;
|
||||||
use crate::machine::code_walker::*;
|
use crate::machine::code_walker::*;
|
||||||
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::machine::preprocessor::to_op_decl;
|
||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
use crate::machine::toplevel::to_op_decl;
|
|
||||||
use crate::ordered_float::OrderedFloat;
|
use crate::ordered_float::OrderedFloat;
|
||||||
use crate::read::readline;
|
use crate::read::readline;
|
||||||
use crate::rug::Integer;
|
use crate::rug::Integer;
|
||||||
@@ -402,9 +404,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode =
|
let mode = atom_from!(self, self.store(self.deref(self[temp_v!(2)])));
|
||||||
atom_from!(self, indices, self.store(self.deref(self[temp_v!(2)])));
|
|
||||||
|
|
||||||
let mut open_options = fs::OpenOptions::new();
|
let mut open_options = fs::OpenOptions::new();
|
||||||
|
|
||||||
let (is_input_file, in_append_mode) =
|
let (is_input_file, in_append_mode) =
|
||||||
@@ -560,7 +560,7 @@ impl MachineState {
|
|||||||
let spec = get_clause_spec(
|
let spec = get_clause_spec(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
*arity,
|
*arity,
|
||||||
composite_op!(&indices.op_dir),
|
&CompositeOpDir::new(&indices.op_dir, None),
|
||||||
);
|
);
|
||||||
|
|
||||||
let addr = self.heap.to_unifiable(HeapCellValue::DBRef(
|
let addr = self.heap.to_unifiable(HeapCellValue::DBRef(
|
||||||
@@ -681,11 +681,11 @@ impl MachineState {
|
|||||||
|
|
||||||
let mut parser = Parser::new(
|
let mut parser = Parser::new(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
indices.atom_tbl.clone(),
|
self.atom_tbl.clone(),
|
||||||
self.machine_flags(),
|
self.machine_flags(),
|
||||||
);
|
);
|
||||||
|
|
||||||
match parser.read_term(composite_op!(&indices.op_dir)) {
|
match parser.read_term(&CompositeOpDir::new(&indices.op_dir, None)) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
let err = MachineError::syntax_error(h, err);
|
let err = MachineError::syntax_error(h, err);
|
||||||
@@ -792,6 +792,7 @@ impl MachineState {
|
|||||||
current_output_stream: &mut Stream,
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
match ct {
|
match ct {
|
||||||
|
/*
|
||||||
&SystemClauseType::AbolishClause => {
|
&SystemClauseType::AbolishClause => {
|
||||||
let p = self.cp;
|
let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::Abolish;
|
let trans_type = DynamicTransactionType::Abolish;
|
||||||
@@ -806,6 +807,7 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::BindFromRegister => {
|
&SystemClauseType::BindFromRegister => {
|
||||||
let reg = self.store(self.deref(self[temp_v!(2)]));
|
let reg = self.store(self.deref(self[temp_v!(2)]));
|
||||||
let n =
|
let n =
|
||||||
@@ -833,6 +835,7 @@ impl MachineState {
|
|||||||
|
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::AssertDynamicPredicateToFront => {
|
&SystemClauseType::AssertDynamicPredicateToFront => {
|
||||||
let p = self.cp;
|
let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
|
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
|
||||||
@@ -841,19 +844,21 @@ impl MachineState {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
&SystemClauseType::AssertDynamicPredicateToBack => {
|
&SystemClauseType::AssertDynamicPredicateToBack => {
|
||||||
let p = self.cp;
|
// let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Back);
|
// let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Back);
|
||||||
|
|
||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
// self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
|
self.p = CodePtr::REPL(REPLCodePtr::UserAssertz, self.cp);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::CurrentHostname => {
|
&SystemClauseType::CurrentHostname => {
|
||||||
match hostname::get().ok() {
|
match hostname::get().ok() {
|
||||||
Some(host) => {
|
Some(host) => {
|
||||||
match host.into_string().ok() {
|
match host.into_string().ok() {
|
||||||
Some(host) => {
|
Some(host) => {
|
||||||
let hostname = self.heap.to_unifiable(
|
let hostname = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(clause_name!(host, indices.atom_tbl), None)
|
HeapCellValue::Atom(clause_name!(host, self.atom_tbl), None)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.unify(self[temp_v!(1)], hostname);
|
self.unify(self[temp_v!(1)], hostname);
|
||||||
@@ -1016,6 +1021,7 @@ impl MachineState {
|
|||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let chars = self.heap.put_complete_string(current);
|
let chars = self.heap.put_complete_string(current);
|
||||||
self.unify(self[temp_v!(1)], chars);
|
self.unify(self[temp_v!(1)], chars);
|
||||||
|
|
||||||
@@ -1092,11 +1098,13 @@ impl MachineState {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::AtEndOfExpansion => {
|
&SystemClauseType::AtEndOfExpansion => {
|
||||||
if self.cp == LocalCodePtr::TopLevel(0, 0) {
|
if self.cp == LocalCodePtr::TopLevel(0, 0) {
|
||||||
self.at_end_of_expansion = true;
|
self.at_end_of_expansion = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::AtomChars => {
|
&SystemClauseType::AtomChars => {
|
||||||
let a1 = self[temp_v!(1)];
|
let a1 = self[temp_v!(1)];
|
||||||
|
|
||||||
@@ -1139,7 +1147,7 @@ impl MachineState {
|
|||||||
if &string == "[]" {
|
if &string == "[]" {
|
||||||
self.unify(addr, Addr::EmptyList);
|
self.unify(addr, Addr::EmptyList);
|
||||||
} else {
|
} else {
|
||||||
let chars = clause_name!(string, indices.atom_tbl);
|
let chars = clause_name!(string, self.atom_tbl);
|
||||||
let atom = self.heap.to_unifiable(
|
let atom = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(chars, None)
|
HeapCellValue::Atom(chars, None)
|
||||||
);
|
);
|
||||||
@@ -1254,7 +1262,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let string = self.heap.to_unifiable(
|
let string = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(clause_name!(chars, indices.atom_tbl), None)
|
HeapCellValue::Atom(clause_name!(chars, self.atom_tbl), None)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.bind(addr.as_var().unwrap(), string);
|
self.bind(addr.as_var().unwrap(), string);
|
||||||
@@ -1281,7 +1289,7 @@ impl MachineState {
|
|||||||
clause_name!("[]")
|
clause_name!("[]")
|
||||||
}
|
}
|
||||||
Addr::Char(c) => {
|
Addr::Char(c) => {
|
||||||
clause_name!(c.to_string(), indices.atom_tbl)
|
clause_name!(c.to_string(), self.atom_tbl)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -1858,6 +1866,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
|
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
|
||||||
let p = self.cp;
|
let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Front);
|
let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Front);
|
||||||
@@ -1872,6 +1881,7 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::LiftedHeapLength => {
|
&SystemClauseType::LiftedHeapLength => {
|
||||||
let a1 = self[temp_v!(1)];
|
let a1 = self[temp_v!(1)];
|
||||||
let lh_len = Addr::Usize(self.lifted_heap.h());
|
let lh_len = Addr::Usize(self.lifted_heap.h());
|
||||||
@@ -2854,6 +2864,7 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(Addr::Char(c), a1);
|
self.unify(Addr::Char(c), a1);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::GetModuleClause => {
|
&SystemClauseType::GetModuleClause => {
|
||||||
let module = self[temp_v!(3)];
|
let module = self[temp_v!(3)];
|
||||||
let head = self[temp_v!(1)];
|
let head = self[temp_v!(1)];
|
||||||
@@ -2944,20 +2955,24 @@ impl MachineState {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::HeadIsDynamic => {
|
&SystemClauseType::HeadIsDynamic => {
|
||||||
let head = self[temp_v!(1)];
|
let module_name = atom_from!(
|
||||||
|
self,
|
||||||
|
self.store(self.deref(
|
||||||
|
self[temp_v!(1)]
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
self.fail = !match self.store(self.deref(head)) {
|
self.fail = !match self.store(self.deref(self[temp_v!(2)])) {
|
||||||
Addr::Str(s) => match &self.heap[s] {
|
Addr::Str(s) => match &self.heap[s] {
|
||||||
&HeapCellValue::NamedStr(arity, ref name, ..) => indices
|
&HeapCellValue::NamedStr(arity, ref name, ..) =>
|
||||||
.get_clause_subsection(name.owning_module(), name.clone(), arity)
|
indices.is_dynamic_predicate(module_name, (name.clone(), arity)),
|
||||||
.is_some(),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
if let HeapCellValue::Atom(name, _) = &self.heap[h] {
|
if let HeapCellValue::Atom(name, _) = &self.heap[h] {
|
||||||
indices.get_clause_subsection(name.owning_module(), name.clone(), 0)
|
indices.is_dynamic_predicate(module_name, (name.clone(), 0))
|
||||||
.is_some()
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -3111,21 +3126,27 @@ impl MachineState {
|
|||||||
|
|
||||||
return self.module_lookup(
|
return self.module_lookup(
|
||||||
indices,
|
indices,
|
||||||
|
call_policy,
|
||||||
(name, arity + narity),
|
(name, arity + narity),
|
||||||
module_name,
|
module_name,
|
||||||
true,
|
true,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
|
if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
|
||||||
return self.module_lookup(
|
return self.module_lookup(
|
||||||
indices,
|
indices,
|
||||||
|
call_policy,
|
||||||
(name.clone(), narity),
|
(name.clone(), narity),
|
||||||
module_name,
|
module_name,
|
||||||
true,
|
true,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -3160,6 +3181,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::ExpandGoal => {
|
&SystemClauseType::ExpandGoal => {
|
||||||
self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
|
self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -3168,6 +3190,7 @@ impl MachineState {
|
|||||||
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
|
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::GetNextDBRef => {
|
&SystemClauseType::GetNextDBRef => {
|
||||||
let a1 = self[temp_v!(1)];
|
let a1 = self[temp_v!(1)];
|
||||||
|
|
||||||
@@ -3185,7 +3208,7 @@ impl MachineState {
|
|||||||
let spec = get_clause_spec(
|
let spec = get_clause_spec(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
*arity,
|
*arity,
|
||||||
composite_op!(&indices.op_dir),
|
&CompositeOpDir::new(&indices.op_dir, None),
|
||||||
);
|
);
|
||||||
|
|
||||||
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
|
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
|
||||||
@@ -3429,7 +3452,7 @@ impl MachineState {
|
|||||||
|
|
||||||
let op = match self.store(self.deref(op)) {
|
let op = match self.store(self.deref(op)) {
|
||||||
Addr::Char(c) =>
|
Addr::Char(c) =>
|
||||||
clause_name!(c.to_string(), indices.atom_tbl),
|
clause_name!(c.to_string(), self.atom_tbl),
|
||||||
Addr::Con(h) if self.heap.atom_at(h) =>
|
Addr::Con(h) if self.heap.atom_at(h) =>
|
||||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
name.clone()
|
name.clone()
|
||||||
@@ -3440,16 +3463,18 @@ impl MachineState {
|
|||||||
unreachable!(),
|
unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let module = op.owning_module();
|
|
||||||
|
|
||||||
let result = to_op_decl(priority, specifier.as_str(), op)
|
let result = to_op_decl(priority, specifier.as_str(), op)
|
||||||
.map_err(SessionError::from)
|
.map_err(SessionError::from)
|
||||||
.and_then(|op_decl| {
|
.and_then(|mut op_decl| {
|
||||||
if op_decl.0 == 0 {
|
if op_decl.prec == 0 {
|
||||||
Ok(op_decl.remove(&mut indices.op_dir))
|
Ok(op_decl.remove(&mut indices.op_dir))
|
||||||
} else {
|
} else {
|
||||||
let spec = get_desc(op_decl.name(), composite_op!(&indices.op_dir));
|
let spec = get_op_desc(
|
||||||
op_decl.submit(module, spec, &mut indices.op_dir)
|
op_decl.name.clone(),
|
||||||
|
&CompositeOpDir::new(&indices.op_dir, None),
|
||||||
|
);
|
||||||
|
|
||||||
|
op_decl.submit(spec, &mut indices.op_dir)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3493,10 +3518,10 @@ impl MachineState {
|
|||||||
let mut heap_pstr_iter =
|
let mut heap_pstr_iter =
|
||||||
self.heap_pstr_iter(Addr::PStrLocation(h, n));
|
self.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||||
|
|
||||||
let file_spec =
|
let file_spec =
|
||||||
clause_name!(
|
clause_name!(
|
||||||
heap_pstr_iter.to_string(),
|
heap_pstr_iter.to_string(),
|
||||||
indices.atom_tbl.clone()
|
self.atom_tbl
|
||||||
);
|
);
|
||||||
|
|
||||||
self.stream_from_file_spec(file_spec, indices, &options)?
|
self.stream_from_file_spec(file_spec, indices, &options)?
|
||||||
@@ -3901,65 +3926,18 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
&SystemClauseType::ModuleOf => {
|
|
||||||
let module = self.store(self.deref(self[temp_v!(2)]));
|
|
||||||
|
|
||||||
match module {
|
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
|
||||||
if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
|
|
||||||
let module = self.heap.to_unifiable(
|
|
||||||
HeapCellValue::Atom(
|
|
||||||
name.owning_module(),
|
|
||||||
None
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
let target = self[temp_v!(1)];
|
|
||||||
|
|
||||||
self.unify(target, module);
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Str(s) => match self.heap.clone(s) {
|
|
||||||
HeapCellValue::NamedStr(_, name, ..) => {
|
|
||||||
let module = self.heap.to_unifiable(
|
|
||||||
HeapCellValue::Atom(
|
|
||||||
name.owning_module(),
|
|
||||||
None
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
let target = self[temp_v!(1)];
|
|
||||||
|
|
||||||
self.unify(target, module);
|
|
||||||
}
|
|
||||||
HeapCellValue::Addr(addr) if addr.is_ref() => {
|
|
||||||
let err = MachineError::uninstantiation_error(addr);
|
|
||||||
let stub = MachineError::functor_stub(
|
|
||||||
clause_name!("$module_of"),
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Err(self.error_form(err, stub));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
self.fail = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
&SystemClauseType::NoSuchPredicate => {
|
&SystemClauseType::NoSuchPredicate => {
|
||||||
let head = self[temp_v!(1)];
|
let module_name = atom_from!(self, self.store(self.deref(self[temp_v!(1)])));
|
||||||
|
|
||||||
self.fail = match self.store(self.deref(head)) {
|
self.fail = match self.store(self.deref(self[temp_v!(2)])) {
|
||||||
Addr::Str(s) => match &self.heap[s] {
|
Addr::Str(s) => match &self.heap[s] {
|
||||||
&HeapCellValue::NamedStr(arity, ref name, ref spec) => {
|
&HeapCellValue::NamedStr(arity, ref name, ref spec) => {
|
||||||
let module = name.owning_module();
|
indices.get_predicate_code_index(
|
||||||
indices.predicate_exists(name.clone(), module, arity, spec.clone())
|
name.clone(),
|
||||||
|
arity,
|
||||||
|
module_name,
|
||||||
|
spec.clone(),
|
||||||
|
).is_some()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -3967,14 +3945,14 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
if let &HeapCellValue::Atom(ref name, ref spec) = &self.heap[h] {
|
if let &HeapCellValue::Atom(ref name, ref spec) = &self.heap[h] {
|
||||||
let module = name.owning_module();
|
|
||||||
let spec = fetch_atom_op_spec(
|
let spec = fetch_atom_op_spec(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
spec.clone(),
|
spec.clone(),
|
||||||
&indices.op_dir,
|
&indices.op_dir,
|
||||||
);
|
);
|
||||||
|
|
||||||
indices.predicate_exists(name.clone(), module, 0, spec)
|
indices.get_predicate_code_index(name.clone(), 0, module_name, spec)
|
||||||
|
.is_some()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -4116,6 +4094,7 @@ impl MachineState {
|
|||||||
&SystemClauseType::REPL(repl_code_ptr) => {
|
&SystemClauseType::REPL(repl_code_ptr) => {
|
||||||
return self.repl_redirect(repl_code_ptr);
|
return self.repl_redirect(repl_code_ptr);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::ModuleRetractClause => {
|
&SystemClauseType::ModuleRetractClause => {
|
||||||
let p = self.cp;
|
let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::ModuleRetract;
|
let trans_type = DynamicTransactionType::ModuleRetract;
|
||||||
@@ -4130,6 +4109,7 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::ReturnFromVerifyAttr => {
|
&SystemClauseType::ReturnFromVerifyAttr => {
|
||||||
let e = self.e;
|
let e = self.e;
|
||||||
let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
|
let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
|
||||||
@@ -4326,6 +4306,7 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(a1, a2);
|
self.unify(a1, a2);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
&SystemClauseType::GetClause => {
|
&SystemClauseType::GetClause => {
|
||||||
let head = self[temp_v!(1)];
|
let head = self[temp_v!(1)];
|
||||||
|
|
||||||
@@ -4343,14 +4324,14 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
indices.get_clause_subsection(
|
indices.get_clause_subsection(
|
||||||
name.owning_module(),
|
name.owning_module(),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -4372,6 +4353,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
&SystemClauseType::GetCutPoint => {
|
&SystemClauseType::GetCutPoint => {
|
||||||
let a1 = self[temp_v!(1)];
|
let a1 = self[temp_v!(1)];
|
||||||
let a2 = Addr::CutPoint(self.b0);
|
let a2 = Addr::CutPoint(self.b0);
|
||||||
@@ -4524,7 +4506,7 @@ impl MachineState {
|
|||||||
let term_write_result =
|
let term_write_result =
|
||||||
match self.read(
|
match self.read(
|
||||||
Stream::from(chars),
|
Stream::from(chars),
|
||||||
indices.atom_tbl.clone(),
|
self.atom_tbl.clone(),
|
||||||
&indices.op_dir,
|
&indices.op_dir,
|
||||||
) {
|
) {
|
||||||
Ok(term_write_result) => {
|
Ok(term_write_result) => {
|
||||||
@@ -4595,10 +4577,11 @@ impl MachineState {
|
|||||||
let mut rand = RANDOM_STATE.borrow_mut();
|
let mut rand = RANDOM_STATE.borrow_mut();
|
||||||
rand.seed(&seed);
|
rand.seed(&seed);
|
||||||
}
|
}
|
||||||
&SystemClauseType::SkipMaxList =>
|
&SystemClauseType::SkipMaxList => {
|
||||||
if let Err(err) = self.skip_max_list() {
|
if let Err(err) = self.skip_max_list() {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
},
|
}
|
||||||
|
}
|
||||||
&SystemClauseType::Sleep => {
|
&SystemClauseType::Sleep => {
|
||||||
let time = self.store(self.deref(self[temp_v!(1)]));
|
let time = self.store(self.deref(self[temp_v!(1)]));
|
||||||
|
|
||||||
@@ -4695,11 +4678,10 @@ impl MachineState {
|
|||||||
let stream =
|
let stream =
|
||||||
match TcpStream::connect(&socket_addr).map_err(|e| e.kind()) {
|
match TcpStream::connect(&socket_addr).map_err(|e| e.kind()) {
|
||||||
Ok(tcp_stream) => {
|
Ok(tcp_stream) => {
|
||||||
let socket_addr = clause_name!(socket_addr, indices.atom_tbl.clone());
|
let socket_addr = clause_name!(socket_addr, self.atom_tbl);
|
||||||
|
|
||||||
|
let mut stream = {
|
||||||
let mut stream =
|
let tls = match self.store(self.deref(self[temp_v!(8)])) {
|
||||||
{ let tls = match self.store(self.deref(self[temp_v!(8)])) {
|
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
|
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
|
||||||
atom.as_str()
|
atom.as_str()
|
||||||
@@ -4711,6 +4693,7 @@ impl MachineState {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match tls {
|
match tls {
|
||||||
"false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) }
|
"false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) }
|
||||||
"true" => { let connector = TlsConnector::new().unwrap();
|
"true" => { let connector = TlsConnector::new().unwrap();
|
||||||
@@ -4724,6 +4707,7 @@ impl MachineState {
|
|||||||
_ => { unreachable!() }
|
_ => { unreachable!() }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
stream.options = options;
|
stream.options = options;
|
||||||
|
|
||||||
if let Some(ref alias) = &stream.options.alias {
|
if let Some(ref alias) = &stream.options.alias {
|
||||||
@@ -4877,7 +4861,7 @@ impl MachineState {
|
|||||||
match tcp_listener.accept().ok() {
|
match tcp_listener.accept().ok() {
|
||||||
Some((tcp_stream, socket_addr)) => {
|
Some((tcp_stream, socket_addr)) => {
|
||||||
let client =
|
let client =
|
||||||
clause_name!(format!("{}", socket_addr), indices.atom_tbl);
|
clause_name!(format!("{}", socket_addr), self.atom_tbl);
|
||||||
|
|
||||||
let mut tcp_stream =
|
let mut tcp_stream =
|
||||||
Stream::from_tcp_stream(client.clone(), tcp_stream);
|
Stream::from_tcp_stream(client.clone(), tcp_stream);
|
||||||
@@ -5226,8 +5210,13 @@ impl MachineState {
|
|||||||
self.fail = self.structural_eq_test();
|
self.fail = self.structural_eq_test();
|
||||||
}
|
}
|
||||||
&SystemClauseType::WAMInstructions => {
|
&SystemClauseType::WAMInstructions => {
|
||||||
let name = self[temp_v!(1)];
|
let module_name = atom_from!(
|
||||||
let arity = self[temp_v!(2)];
|
self,
|
||||||
|
self.store(self.deref(self[temp_v!(1)]))
|
||||||
|
);
|
||||||
|
|
||||||
|
let name = self[temp_v!(2)];
|
||||||
|
let arity = self[temp_v!(3)];
|
||||||
|
|
||||||
let name = match self.store(self.deref(name)) {
|
let name = match self.store(self.deref(name)) {
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
@@ -5257,51 +5246,84 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_idx = match indices
|
let key = (name.clone(), arity.to_usize().unwrap());
|
||||||
.code_dir
|
|
||||||
.get(&(name.clone(), arity.to_usize().unwrap()))
|
let first_idx = match module_name.as_str() {
|
||||||
{
|
"user" => indices.code_dir.get(&key),
|
||||||
Some(ref idx) if idx.local().is_some() => {
|
_ => match indices.modules.get(&module_name) {
|
||||||
if let Some(idx) = idx.local() {
|
Some(module) => module.code_dir.get(&key),
|
||||||
idx
|
None => {
|
||||||
} else {
|
let stub = MachineError::functor_stub(key.0, key.1);
|
||||||
unreachable!()
|
let h = self.heap.h();
|
||||||
|
|
||||||
|
let err = MachineError::session_error(
|
||||||
|
h,
|
||||||
|
SessionError::from(
|
||||||
|
CompilationError::InvalidModuleResolution(
|
||||||
|
module_name
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
let err = self.error_form(err, stub);
|
||||||
|
|
||||||
|
self.throw_exception(err);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
_ => {
|
|
||||||
let arity = arity.to_usize().unwrap();
|
|
||||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
|
||||||
let h = self.heap.h();
|
|
||||||
|
|
||||||
let err = MachineError::existence_error(
|
|
||||||
h,
|
|
||||||
ExistenceError::Procedure(name, arity),
|
|
||||||
);
|
|
||||||
|
|
||||||
let err = self.error_form(err, stub);
|
|
||||||
|
|
||||||
self.throw_exception(err);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let first_idx =
|
||||||
|
match first_idx {
|
||||||
|
Some(ref idx) if idx.local().is_some() => {
|
||||||
|
if let Some(idx) = idx.local() {
|
||||||
|
idx
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let arity = arity.to_usize().unwrap();
|
||||||
|
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||||
|
let h = self.heap.h();
|
||||||
|
|
||||||
|
let err = MachineError::existence_error(
|
||||||
|
h,
|
||||||
|
ExistenceError::Procedure(name, arity),
|
||||||
|
);
|
||||||
|
|
||||||
|
let err = self.error_form(err, stub);
|
||||||
|
|
||||||
|
self.throw_exception(err);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut h = self.heap.h();
|
let mut h = self.heap.h();
|
||||||
let mut functors = vec![];
|
let mut functors = vec![];
|
||||||
|
let mut functor_list = vec![];
|
||||||
|
|
||||||
walk_code(
|
walk_code(
|
||||||
&code_repo.code,
|
&code_repo.code,
|
||||||
first_idx,
|
first_idx,
|
||||||
|instr| {
|
|instr| {
|
||||||
let section = instr.to_functor(h);
|
let old_len = functors.len();
|
||||||
functors.push(Addr::HeapCell(h));
|
instr.enqueue_functors(h, &mut functors);
|
||||||
|
let new_len = functors.len();
|
||||||
|
|
||||||
h += section.len();
|
for index in old_len .. new_len {
|
||||||
self.heap.extend(section.into_iter());
|
functor_list.push(Addr::HeapCell(h));
|
||||||
|
h += functors[index].len();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let listing = Addr::HeapCell(self.heap.to_list(functors.into_iter()));
|
for functor in functors {
|
||||||
let listing_var = self[temp_v!(3)];
|
self.heap.extend(functor.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
let listing = Addr::HeapCell(self.heap.to_list(functor_list.into_iter()));
|
||||||
|
let listing_var = self[temp_v!(4)];
|
||||||
|
|
||||||
self.unify(listing, listing_var);
|
self.unify(listing, listing_var);
|
||||||
}
|
}
|
||||||
@@ -5831,6 +5853,53 @@ impl MachineState {
|
|||||||
self.unify(self[temp_v!(2)], cstr);
|
self.unify(self[temp_v!(2)], cstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::LoadLibraryAsStream => {
|
||||||
|
let library_name =
|
||||||
|
atom_from!(
|
||||||
|
self,
|
||||||
|
self.store(self.deref(self[temp_v!(1)]))
|
||||||
|
);
|
||||||
|
|
||||||
|
use crate::LIBRARIES;
|
||||||
|
|
||||||
|
match LIBRARIES.borrow().get(library_name.as_str()) {
|
||||||
|
Some(library) => {
|
||||||
|
let var_ref = Ref::HeapCell(self.heap.push(
|
||||||
|
HeapCellValue::Stream(Stream::from(*library))
|
||||||
|
));
|
||||||
|
|
||||||
|
self.bind(var_ref, self[temp_v!(2)]);
|
||||||
|
|
||||||
|
let mut path_buf = machine::current_dir();
|
||||||
|
|
||||||
|
path_buf.push("/lib");
|
||||||
|
path_buf.push(library_name.as_str());
|
||||||
|
|
||||||
|
let library_path_str = path_buf.to_str().unwrap();
|
||||||
|
let library_path =
|
||||||
|
clause_name!(library_path_str.to_string(), self.atom_tbl);
|
||||||
|
|
||||||
|
let library_path_ref = Ref::HeapCell(
|
||||||
|
self.heap.push(HeapCellValue::Atom(library_path, None))
|
||||||
|
);
|
||||||
|
|
||||||
|
self.bind(library_path_ref, self[temp_v!(3)]);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(
|
||||||
|
self.error_form(
|
||||||
|
MachineError::existence_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ExistenceError::ModuleSource(
|
||||||
|
ModuleSource::Library(library_name)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MachineError::functor_stub(clause_name!("load"), 1),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return_from_clause!(self.last_call, self)
|
return_from_clause!(self.last_call, self)
|
||||||
@@ -5905,7 +5974,7 @@ impl MachineState {
|
|||||||
} else {
|
} else {
|
||||||
let mut avec = Vec::new();
|
let mut avec = Vec::new();
|
||||||
for attr in node.attributes() {
|
for attr in node.attributes() {
|
||||||
let chars = clause_name!(String::from(attr.name()), indices.atom_tbl);
|
let chars = clause_name!(String::from(attr.name()), self.atom_tbl);
|
||||||
let name = self.heap.to_unifiable(
|
let name = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(chars, None)
|
HeapCellValue::Atom(chars, None)
|
||||||
);
|
);
|
||||||
@@ -5926,7 +5995,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter()));
|
let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter()));
|
||||||
|
|
||||||
let chars = clause_name!(String::from(node.tag_name().name()), indices.atom_tbl);
|
let chars = clause_name!(String::from(node.tag_name().name()), self.atom_tbl);
|
||||||
let tag = self.heap.to_unifiable(
|
let tag = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(chars, None)
|
HeapCellValue::Atom(chars, None)
|
||||||
);
|
);
|
||||||
@@ -5955,7 +6024,7 @@ impl MachineState {
|
|||||||
Some(name) => {
|
Some(name) => {
|
||||||
let mut avec = Vec::new();
|
let mut avec = Vec::new();
|
||||||
for attr in node.attrs() {
|
for attr in node.attrs() {
|
||||||
let chars = clause_name!(String::from(attr.0), indices.atom_tbl);
|
let chars = clause_name!(String::from(attr.0), self.atom_tbl);
|
||||||
let name = self.heap.to_unifiable(
|
let name = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(chars, None)
|
HeapCellValue::Atom(chars, None)
|
||||||
);
|
);
|
||||||
@@ -5976,7 +6045,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter()));
|
let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter()));
|
||||||
|
|
||||||
let chars = clause_name!(String::from(name), indices.atom_tbl);
|
let chars = clause_name!(String::from(name), self.atom_tbl);
|
||||||
let tag = self.heap.to_unifiable(
|
let tag = self.heap.to_unifiable(
|
||||||
HeapCellValue::Atom(chars, None)
|
HeapCellValue::Atom(chars, None)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,394 +0,0 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
|
||||||
use crate::prolog_parser::parser::*;
|
|
||||||
|
|
||||||
use crate::machine::machine_indices::HeapCellValue;
|
|
||||||
use crate::machine::*;
|
|
||||||
use crate::rug::ops::Pow;
|
|
||||||
use crate::rug::Integer;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::iter::Rev;
|
|
||||||
use std::vec::IntoIter;
|
|
||||||
|
|
||||||
pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
|
||||||
where
|
|
||||||
I: DoubleEndedIterator<Item = Term>,
|
|
||||||
{
|
|
||||||
for prec in terms.rev() {
|
|
||||||
term = Term::Clause(
|
|
||||||
Cell::default(),
|
|
||||||
sym.clone(),
|
|
||||||
vec![Box::new(prec), Box::new(term)],
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
term
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_from_list(
|
|
||||||
head: Box<Term>,
|
|
||||||
tail: Box<Term>,
|
|
||||||
) -> Result<Rev<IntoIter<Term>>, ParserError>
|
|
||||||
{
|
|
||||||
let mut terms = vec![*head];
|
|
||||||
let mut tail = *tail;
|
|
||||||
|
|
||||||
while let Term::Cons(_, head, next_tail) = tail {
|
|
||||||
terms.push(*head);
|
|
||||||
tail = *next_tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Term::Constant(_, Constant::EmptyList) = tail {
|
|
||||||
Ok(terms.into_iter().rev())
|
|
||||||
} else {
|
|
||||||
Err(ParserError::ExpectedTopLevelTerm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TermStream<'a> {
|
|
||||||
stack: Vec<Term>,
|
|
||||||
pub(crate) wam: &'a mut Machine,
|
|
||||||
parser: Parser<'a, Stream>,
|
|
||||||
pub(crate) flags: MachineFlags,
|
|
||||||
term_expansion_lens: (usize, usize),
|
|
||||||
goal_expansion_lens: (usize, usize),
|
|
||||||
top_level_terms: Vec<(Term, usize, usize)>, // term, line_num, col_num.
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ExpansionAdditionResult {
|
|
||||||
term_expansion_additions: (Predicate, VecDeque<TopLevel>),
|
|
||||||
goal_expansion_additions: (Predicate, VecDeque<TopLevel>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpansionAdditionResult {
|
|
||||||
pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
|
||||||
let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
|
|
||||||
let teqs = mem::replace(&mut self.term_expansion_additions.1, VecDeque::from(vec![]));
|
|
||||||
|
|
||||||
(tes, teqs)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn take_goal_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
|
||||||
let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
|
|
||||||
let geqs = mem::replace(&mut self.goal_expansion_additions.1, VecDeque::from(vec![]));
|
|
||||||
|
|
||||||
(ges, geqs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for TermStream<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.wam.indices.in_situ_code_dir.clear();
|
|
||||||
self.wam.indices.in_situ_module_dir.clear();
|
|
||||||
|
|
||||||
self.wam.code_repo.in_situ_code.clear();
|
|
||||||
discard_result!(self.rollback_expansion_code());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TermStream<'a> {
|
|
||||||
pub fn new(
|
|
||||||
src: &'a mut ParsingStream<Stream>,
|
|
||||||
atom_tbl: TabledData<Atom>,
|
|
||||||
flags: MachineFlags,
|
|
||||||
wam: &'a mut Machine,
|
|
||||||
) -> Self {
|
|
||||||
TermStream {
|
|
||||||
stack: Vec::new(),
|
|
||||||
term_expansion_lens: wam
|
|
||||||
.code_repo
|
|
||||||
.term_dir_entry_len((clause_name!("term_expansion"), 2)),
|
|
||||||
goal_expansion_lens: wam
|
|
||||||
.code_repo
|
|
||||||
.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
|
|
||||||
wam,
|
|
||||||
parser: Parser::new(src, atom_tbl, flags),
|
|
||||||
flags,
|
|
||||||
top_level_terms: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn top_level_terms(&mut self) -> Vec<(Term, usize, usize)> {
|
|
||||||
mem::replace(&mut self.top_level_terms, vec![])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) {
|
|
||||||
match hook {
|
|
||||||
CompileTimeHook::UserTermExpansion => {
|
|
||||||
self.term_expansion_lens.0 += len;
|
|
||||||
self.term_expansion_lens.1 += queue_len;
|
|
||||||
}
|
|
||||||
CompileTimeHook::UserGoalExpansion => {
|
|
||||||
self.goal_expansion_lens.0 += len;
|
|
||||||
self.goal_expansion_lens.1 += queue_len;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn line_num(&self) -> usize {
|
|
||||||
self.parser.line_num()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn col_num(&self) -> usize {
|
|
||||||
self.parser.col_num()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn update_expansion_lens(&mut self) {
|
|
||||||
let te_key = (clause_name!("term_expansion"), 2);
|
|
||||||
let ge_key = (clause_name!("goal_expansion"), 2);
|
|
||||||
|
|
||||||
let (tes_len, tes_q_len) = self.wam.code_repo.term_dir_entry_len(te_key);
|
|
||||||
|
|
||||||
self.term_expansion_lens.0 = tes_len;
|
|
||||||
self.term_expansion_lens.1 = tes_q_len;
|
|
||||||
|
|
||||||
let (ges_len, ges_q_len) = self.wam.code_repo.term_dir_entry_len(ge_key);
|
|
||||||
|
|
||||||
self.goal_expansion_lens.0 = ges_len;
|
|
||||||
self.goal_expansion_lens.1 = ges_q_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn set_atom_tbl(&mut self, atom_tbl: TabledData<Atom>) {
|
|
||||||
self.parser.set_atom_tbl(atom_tbl);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn eof(&mut self) -> Result<bool, ParserError> {
|
|
||||||
self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
|
|
||||||
Ok(self.stack.is_empty() && self.parser.eof()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> {
|
|
||||||
let te_len = self.term_expansion_lens.0;
|
|
||||||
let te_queue_len = self.term_expansion_lens.1;
|
|
||||||
|
|
||||||
let ge_len = self.goal_expansion_lens.0;
|
|
||||||
let ge_queue_len = self.goal_expansion_lens.1;
|
|
||||||
|
|
||||||
let term_expansion_additions = self.wam.code_repo.truncate_terms(
|
|
||||||
(clause_name!("term_expansion"), 2),
|
|
||||||
te_len,
|
|
||||||
te_queue_len,
|
|
||||||
);
|
|
||||||
|
|
||||||
let goal_expansion_additions = self.wam.code_repo.truncate_terms(
|
|
||||||
(clause_name!("goal_expansion"), 2),
|
|
||||||
ge_len,
|
|
||||||
ge_queue_len,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.wam
|
|
||||||
.code_repo
|
|
||||||
.compile_hook(CompileTimeHook::TermExpansion)?;
|
|
||||||
self.wam
|
|
||||||
.code_repo
|
|
||||||
.compile_hook(CompileTimeHook::GoalExpansion)?;
|
|
||||||
|
|
||||||
Ok(ExpansionAdditionResult {
|
|
||||||
term_expansion_additions,
|
|
||||||
goal_expansion_additions,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enqueue_term(&mut self, term: Term) -> Result<(), ParserError> {
|
|
||||||
match term {
|
|
||||||
Term::Cons(_, head, tail) => {
|
|
||||||
let iter = extract_from_list(head, tail)?;
|
|
||||||
Ok(self.stack.extend(iter))
|
|
||||||
}
|
|
||||||
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => {
|
|
||||||
Ok(self.stack.push(term))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
Err(ParserError::ExpectedTopLevelTerm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_expansion_output(
|
|
||||||
&self,
|
|
||||||
term_string: &str,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
) -> Result<Term, ParserError> {
|
|
||||||
let mut stream = parsing_stream(term_string.trim().as_bytes())?;
|
|
||||||
let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags);
|
|
||||||
|
|
||||||
parser.read_term(composite_op!(
|
|
||||||
false,
|
|
||||||
&self.wam.indices.op_dir,
|
|
||||||
op_dir
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expand_term(&mut self, term: Term, op_dir: &OpDir) -> Result<Term, ParserError> {
|
|
||||||
let mut machine_st = MachineState::new();
|
|
||||||
|
|
||||||
self.stack.push(term);
|
|
||||||
|
|
||||||
while let Some(term) = self.stack.pop() {
|
|
||||||
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) {
|
|
||||||
Some(term_string) => {
|
|
||||||
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
|
|
||||||
self.enqueue_term(term)?;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Ok(term);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> {
|
|
||||||
loop {
|
|
||||||
if let Some(term) = self.stack.pop() {
|
|
||||||
return Ok(self.expand_term(term, op_dir)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.parser.reset();
|
|
||||||
|
|
||||||
let line_num = self.line_num();
|
|
||||||
let col_num = self.col_num();
|
|
||||||
|
|
||||||
let term = self.parser.read_term(composite_op!(
|
|
||||||
false,
|
|
||||||
&self.wam.indices.op_dir,
|
|
||||||
op_dir
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// preserve a copy of the original unexpanded term for warning scans,
|
|
||||||
// if that stage is reached.
|
|
||||||
self.top_level_terms.push((term.clone(), line_num, col_num));
|
|
||||||
self.stack.push(term);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
|
||||||
fn expand_goals(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
mut terms: VecDeque<Term>,
|
|
||||||
) -> Result<Vec<Term>, ParserError> {
|
|
||||||
let mut results = vec![];
|
|
||||||
|
|
||||||
while let Some(term) = terms.pop_front() {
|
|
||||||
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion) {
|
|
||||||
Some(term_string) => {
|
|
||||||
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
|
|
||||||
|
|
||||||
match term {
|
|
||||||
Term::Cons(_, head, tail) => {
|
|
||||||
for term in extract_from_list(head, tail)? {
|
|
||||||
terms.push_front(term);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
term => terms.push_front(term),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
None => results.push(term),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(results)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MachineState {
|
|
||||||
pub(super)
|
|
||||||
fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
|
|
||||||
let output = PrinterOutputter::new();
|
|
||||||
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
|
|
||||||
let mut max_var_length = 0;
|
|
||||||
|
|
||||||
for var in self.heap_locs.keys() {
|
|
||||||
max_var_length = std::cmp::max(var.len(), max_var_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
printer.quoted = true;
|
|
||||||
printer.numbervars = true;
|
|
||||||
|
|
||||||
// the purpose of the offset is to avoid clashes with variable
|
|
||||||
// names that might occur after the addresses in the expanded
|
|
||||||
// term are substituted with the variable names in the
|
|
||||||
// pre-expansion term. This formula ensures that all generated
|
|
||||||
// "numbervars"- style variable names will be longer than the
|
|
||||||
// keys of the var_dict, and therefore not equal to any of
|
|
||||||
// them.
|
|
||||||
printer.numbervars_offset = Integer::from(10).pow(max_var_length as u32) * 26;
|
|
||||||
printer.print_strings_as_strs = true;
|
|
||||||
printer.drop_toplevel_spec();
|
|
||||||
|
|
||||||
printer.see_all_locs();
|
|
||||||
|
|
||||||
let mut output = printer.print(addr);
|
|
||||||
|
|
||||||
output.push_char('.');
|
|
||||||
output
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset the machine, but keep the heap contents as they were.
|
|
||||||
// this prevents clashes between underscored variable names in the
|
|
||||||
// same query.
|
|
||||||
fn reset_with_heap_preservation(&mut self) {
|
|
||||||
let heap = self.heap.take();
|
|
||||||
self.reset();
|
|
||||||
self.heap = heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_expand_term(
|
|
||||||
&mut self,
|
|
||||||
wam: &mut Machine,
|
|
||||||
term: &Term,
|
|
||||||
hook: CompileTimeHook,
|
|
||||||
) -> Option<String> {
|
|
||||||
let term_write_result = write_term_to_heap(term, self);
|
|
||||||
let h = self.heap.h();
|
|
||||||
|
|
||||||
self[temp_v!(1)] = Addr::HeapCell(term_write_result.heap_loc);
|
|
||||||
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
|
||||||
self[temp_v!(2)] = Addr::HeapCell(h);
|
|
||||||
|
|
||||||
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
|
|
||||||
wam.code_repo.cached_query = code;
|
|
||||||
|
|
||||||
self.cp = LocalCodePtr::TopLevel(0, 0);
|
|
||||||
|
|
||||||
self.at_end_of_expansion = false;
|
|
||||||
self.flags.double_quotes = DoubleQuotes::Chars;
|
|
||||||
|
|
||||||
self.query_stepper(
|
|
||||||
&mut wam.indices,
|
|
||||||
&mut MachinePolicies::default(),
|
|
||||||
&mut wam.code_repo,
|
|
||||||
&mut readline::input_stream(),
|
|
||||||
&mut Stream::stdout(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.fail || self.at_end_of_expansion {
|
|
||||||
self.reset_with_heap_preservation();
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let TermWriteResult { var_dict, .. } = term_write_result;
|
|
||||||
|
|
||||||
self.heap_locs = var_dict;
|
|
||||||
let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
|
|
||||||
|
|
||||||
self.reset_with_heap_preservation();
|
|
||||||
|
|
||||||
Some(output.result())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
149
src/machine/term_stream.rs
Normal file
149
src/machine/term_stream.rs
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
use crate::prolog_parser::ast::*;
|
||||||
|
use crate::prolog_parser::parser::*;
|
||||||
|
|
||||||
|
use crate::machine::*;
|
||||||
|
use crate::machine::machine_errors::CompilationError;
|
||||||
|
use crate::machine::preprocessor::*;
|
||||||
|
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub(crate) trait TermStream : Sized {
|
||||||
|
type Evacuable;
|
||||||
|
|
||||||
|
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError>;
|
||||||
|
fn eof(&mut self) -> Result<bool, CompilationError>;
|
||||||
|
fn listing_src(&self) -> &ListingSource;
|
||||||
|
fn evacuate<'a>(loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(super) struct BootstrappingTermStream<'a> {
|
||||||
|
listing_src: ListingSource,
|
||||||
|
parser: Parser<'a, Stream>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BootstrappingTermStream<'a> {
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn from_prolog_stream(
|
||||||
|
stream: &'a mut PrologStream,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
flags: MachineFlags,
|
||||||
|
listing_src: ListingSource,
|
||||||
|
) -> Self {
|
||||||
|
let parser = Parser::new(stream, atom_tbl, flags);
|
||||||
|
Self { parser, listing_src }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TermStream for BootstrappingTermStream<'a> {
|
||||||
|
type Evacuable = CompilationTarget;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError> {
|
||||||
|
self.parser.reset();
|
||||||
|
self.parser.read_term(op_dir)
|
||||||
|
.map_err(CompilationError::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn eof(&mut self) -> Result<bool, CompilationError> {
|
||||||
|
self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
|
||||||
|
Ok(self.parser.eof()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn listing_src(&self) -> &ListingSource {
|
||||||
|
&self.listing_src
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evacuate(mut loader: Loader<Self>) -> Result<Self::Evacuable, SessionError> {
|
||||||
|
if !loader.predicates.is_empty() {
|
||||||
|
loader.compile_and_submit()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.load_state.retraction_info.reset(
|
||||||
|
loader.load_state.wam.code_repo.code.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
loader.load_state.remove_module_op_exports();
|
||||||
|
|
||||||
|
Ok(loader.load_state.compilation_target.take())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LiveTermStream {
|
||||||
|
pub(super) term_queue: VecDeque<Term>,
|
||||||
|
pub(super) listing_src: ListingSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveTermStream {
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn new(listing_src: ListingSource) -> Self {
|
||||||
|
Self {
|
||||||
|
term_queue: VecDeque::new(),
|
||||||
|
listing_src,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LoadStatePayload {
|
||||||
|
pub(super) term_stream: LiveTermStream,
|
||||||
|
pub(super) compilation_target: CompilationTarget,
|
||||||
|
pub(super) retraction_info: RetractionInfo,
|
||||||
|
pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>,
|
||||||
|
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
|
||||||
|
pub(super) preprocessor: Preprocessor,
|
||||||
|
pub(super) predicates: Vec<PredicateClause>,
|
||||||
|
pub(super) clause_clauses: Vec<(Term, Term)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for LoadStatePayload {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "LoadStatePayload")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoadStatePayload {
|
||||||
|
pub(super)
|
||||||
|
fn new(wam: &Machine) -> Self {
|
||||||
|
Self {
|
||||||
|
term_stream: LiveTermStream::new(ListingSource::User),
|
||||||
|
compilation_target: CompilationTarget::default(),
|
||||||
|
retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
|
||||||
|
module_op_exports: vec![],
|
||||||
|
non_counted_bt_preds: IndexSet::new(),
|
||||||
|
preprocessor: Preprocessor::new(wam.machine_st.flags),
|
||||||
|
predicates: vec![],
|
||||||
|
clause_clauses: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TermStream for LiveTermStream {
|
||||||
|
type Evacuable = LoadStatePayload;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
|
||||||
|
Ok(self.term_queue.pop_front().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn eof(&mut self) -> Result<bool, CompilationError> {
|
||||||
|
return Ok(self.term_queue.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn listing_src(&self) -> &ListingSource {
|
||||||
|
&self.listing_src
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn evacuate(loader: Loader<Self>) -> Result<LoadStatePayload, SessionError> {
|
||||||
|
Ok(loader.to_load_state_payload())
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -68,10 +68,18 @@ macro_rules! functor {
|
|||||||
});
|
});
|
||||||
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||||
{
|
{
|
||||||
let arity = count_tt!($($dt) +);
|
use crate::machine::heap::*;
|
||||||
|
|
||||||
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
let arity = count_tt!($($dt) +);
|
||||||
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ]
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
($name:expr, $fixity:expr) => (
|
($name:expr, $fixity:expr) => (
|
||||||
@@ -112,13 +120,28 @@ macro_rules! functor_term {
|
|||||||
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
$e.into()
|
$e.into()
|
||||||
);
|
);
|
||||||
(integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
(integer($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
HeapCellValue::Integer(Rc::new(Integer::from($e)))
|
HeapCellValue::Integer(Rc::new(Integer::from($e)))
|
||||||
);
|
);
|
||||||
(clause_name($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
(indexing_code_ptr($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
let stub =
|
||||||
|
match $e {
|
||||||
|
IndexingCodePtr::External(o) => functor!("external", [integer(o)]),
|
||||||
|
IndexingCodePtr::Internal(o) => functor!("internal", [integer(o)]),
|
||||||
|
IndexingCodePtr::Fail => vec![HeapCellValue::Atom(clause_name!("fail"), None)],
|
||||||
|
};
|
||||||
|
|
||||||
|
let len: usize = $aux_lens.iter().sum();
|
||||||
|
let h = len + $arity + 1 + $addendum.h() + $h;
|
||||||
|
|
||||||
|
$addendum.extend(stub.into_iter());
|
||||||
|
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell(h))
|
||||||
|
});
|
||||||
|
(clause_name($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
HeapCellValue::Atom($e, None)
|
HeapCellValue::Atom($e, None)
|
||||||
);
|
);
|
||||||
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
HeapCellValue::Atom(clause_name!($e), None)
|
HeapCellValue::Atom(clause_name!($e), None)
|
||||||
);
|
);
|
||||||
(value($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
(value($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
@@ -312,14 +335,6 @@ macro_rules! jmp_call {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! try_eval_session {
|
|
||||||
($e:expr) => {
|
|
||||||
match $e {
|
|
||||||
Ok(result) => result,
|
|
||||||
Err(e) => return EvalSession::from(e),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
macro_rules! return_from_clause {
|
macro_rules! return_from_clause {
|
||||||
($lco:expr, $machine_st:expr) => {{
|
($lco:expr, $machine_st:expr) => {{
|
||||||
if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
|
if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
|
||||||
@@ -342,39 +357,21 @@ macro_rules! dir_entry {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! set_code_index {
|
|
||||||
($idx:expr, $ip:expr, $mod_name:expr) => {{
|
|
||||||
let mut idx = $idx.0.borrow_mut();
|
|
||||||
|
|
||||||
idx.0 = $ip;
|
|
||||||
idx.1 = $mod_name.clone();
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! index_store {
|
macro_rules! index_store {
|
||||||
($atom_tbl:expr, $code_dir:expr, $op_dir:expr, $modules:expr) => {
|
($code_dir:expr, $op_dir:expr, $modules:expr) => {
|
||||||
IndexStore {
|
IndexStore {
|
||||||
atom_tbl: $atom_tbl,
|
|
||||||
code_dir: $code_dir,
|
code_dir: $code_dir,
|
||||||
module_dir: ModuleDir::new(),
|
extensible_predicates: ExtensiblePredicates::new(),
|
||||||
dynamic_code_dir: DynamicCodeDir::new(),
|
|
||||||
global_variables: GlobalVarDir::new(),
|
global_variables: GlobalVarDir::new(),
|
||||||
in_situ_code_dir: InSituCodeDir::new(),
|
meta_predicates: MetaPredicateDir::new(),
|
||||||
in_situ_module_dir: ModuleStubDir::new(),
|
|
||||||
op_dir: $op_dir,
|
|
||||||
modules: $modules,
|
modules: $modules,
|
||||||
stream_aliases: StreamAliasDir::new(),
|
op_dir: $op_dir,
|
||||||
streams: StreamDir::new(),
|
streams: StreamDir::new(),
|
||||||
|
stream_aliases: StreamAliasDir::new(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! default_index_store {
|
|
||||||
($atom_tbl:expr) => {
|
|
||||||
index_store!($atom_tbl, CodeDir::new(), default_op_dir(), IndexMap::new())
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! put_constant {
|
macro_rules! put_constant {
|
||||||
($lvl:expr, $cons:expr, $r:expr) => {
|
($lvl:expr, $cons:expr, $r:expr) => {
|
||||||
QueryInstruction::PutConstant($lvl, $cons, $r)
|
QueryInstruction::PutConstant($lvl, $cons, $r)
|
||||||
@@ -387,6 +384,7 @@ macro_rules! get_level_and_unify {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
macro_rules! unwind_protect {
|
macro_rules! unwind_protect {
|
||||||
($e: expr, $protected: expr) => {
|
($e: expr, $protected: expr) => {
|
||||||
match $e {
|
match $e {
|
||||||
@@ -398,7 +396,8 @@ macro_rules! unwind_protect {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
macro_rules! discard_result {
|
macro_rules! discard_result {
|
||||||
($f: expr) => {
|
($f: expr) => {
|
||||||
match $f {
|
match $f {
|
||||||
@@ -406,7 +405,7 @@ macro_rules! discard_result {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
macro_rules! ar_reg {
|
macro_rules! ar_reg {
|
||||||
($r: expr) => {
|
($r: expr) => {
|
||||||
ArithmeticTerm::Reg($r)
|
ArithmeticTerm::Reg($r)
|
||||||
@@ -414,7 +413,7 @@ macro_rules! ar_reg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! atom_from {
|
macro_rules! atom_from {
|
||||||
($self:expr, $indices:expr, $e:expr) => {
|
($self:expr, $e:expr) => {
|
||||||
match $e {
|
match $e {
|
||||||
Addr::Con(h) if $self.heap.atom_at(h) => {
|
Addr::Con(h) if $self.heap.atom_at(h) => {
|
||||||
match &$self.heap[h] {
|
match &$self.heap[h] {
|
||||||
@@ -427,7 +426,7 @@ macro_rules! atom_from {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Addr::Char(c) => {
|
Addr::Char(c) => {
|
||||||
clause_name!(c.to_string(), $indices.atom_tbl.clone())
|
clause_name!(c.to_string(), $self.atom_tbl)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -435,3 +434,15 @@ macro_rules! atom_from {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! try_or_fail {
|
||||||
|
($s:expr, $e:expr) => {{
|
||||||
|
match $e {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(msg) => {
|
||||||
|
$s.throw_exception(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ use crate::nix::sys::signal;
|
|||||||
mod macros;
|
mod macros;
|
||||||
mod allocator;
|
mod allocator;
|
||||||
mod arithmetic;
|
mod arithmetic;
|
||||||
|
mod machine;
|
||||||
mod codegen;
|
mod codegen;
|
||||||
mod clause_types;
|
mod clause_types;
|
||||||
mod debray_allocator;
|
mod debray_allocator;
|
||||||
@@ -45,7 +46,6 @@ mod heap_print;
|
|||||||
mod indexing;
|
mod indexing;
|
||||||
mod instructions;
|
mod instructions;
|
||||||
mod iterators;
|
mod iterators;
|
||||||
mod machine;
|
|
||||||
mod read;
|
mod read;
|
||||||
mod targets;
|
mod targets;
|
||||||
mod write;
|
mod write;
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ impl MachineState {
|
|||||||
|
|
||||||
let term = {
|
let term = {
|
||||||
let mut parser = Parser::new(&mut stream, atom_tbl, self.flags);
|
let mut parser = Parser::new(&mut stream, atom_tbl, self.flags);
|
||||||
parser.read_term(composite_op!(op_dir))?
|
parser.read_term(&CompositeOpDir::new(op_dir, None))?
|
||||||
};
|
};
|
||||||
|
|
||||||
// 'pausing' the stream saves the pending top buffer
|
// 'pausing' the stream saves the pending top buffer
|
||||||
|
|||||||
44
src/term_and_goal_expansion.pl
Normal file
44
src/term_and_goal_expansion.pl
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
% Unsure how to handle the printing of exceptions from term & goal expansion.
|
||||||
|
|
||||||
|
'$print_message_and_fail'(Error, Culprit) :-
|
||||||
|
% writeq(error(Error, Culprit)),
|
||||||
|
% nl,
|
||||||
|
'$fail'.
|
||||||
|
|
||||||
|
term_expansion(Term, ExpandedTerm) :-
|
||||||
|
( catch(user:'$term_expansion'(Term, ExpandedTerm0),
|
||||||
|
E,
|
||||||
|
user:'$print_message_and_fail'(E, user:term_expansion)) ->
|
||||||
|
( var(ExpandedTerm0) ->
|
||||||
|
error:instantiation_error(term_expansion/2)
|
||||||
|
; ExpandedTerm0 = [_|_] ->
|
||||||
|
term_expansion_list(ExpandedTerm0, ExpandedTerm, [])
|
||||||
|
; term_expansion(ExpandedTerm0, ExpandedTerm)
|
||||||
|
)
|
||||||
|
; Term = ExpandedTerm
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
term_expansion_list([], ExpandedTerms, ExpandedTerms).
|
||||||
|
term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :-
|
||||||
|
term_expansion(Term, ExpandedTerm0),
|
||||||
|
( var(ExpandedTerm0) ->
|
||||||
|
error:instantiation_error(term_expansion/2)
|
||||||
|
; ExpandedTerm0 = [_|_] ->
|
||||||
|
term_expansion_list(ExpandedTerm0, ExpandedTermsHead, ExpandedTerms0Tail),
|
||||||
|
term_expansion_list(Terms, ExpandedTerms0Tail, ExpandedTermsTail)
|
||||||
|
; ExpandedTermsHead = [ExpandedTerm0 | ExpandedTerms0Tail],
|
||||||
|
term_expansion_list(Terms, ExpandedTerms0Tail, ExpandedTermsTail)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
goal_expansion(Goal, Module, ExpandedGoal) :-
|
||||||
|
( catch(Module:goal_expansion(Goal, ExpandedGoal0),
|
||||||
|
E,
|
||||||
|
user:'$print_message_and_fail'(E, Module:goal_expansion)) ->
|
||||||
|
( var(ExpandedGoal0) ->
|
||||||
|
error:instantiation_error(goal_expansion/2)
|
||||||
|
; goal_expansion(ExpandedGoal0, Module, ExpandedGoal)
|
||||||
|
)
|
||||||
|
; Goal = ExpandedGoal
|
||||||
|
).
|
||||||
188
src/toplevel.pl
188
src/toplevel.pl
@@ -1,10 +1,18 @@
|
|||||||
:- module('$toplevel', ['$repl'/1, consult/1, use_module/1, use_module/2,
|
:- module('$toplevel', [argv/1,
|
||||||
argv/1]).
|
copy_term/3,
|
||||||
|
predicate_property/2,
|
||||||
|
prolog_load_context/2]).
|
||||||
|
|
||||||
|
:- use_module(library(loader)).
|
||||||
|
|
||||||
:- use_module(library(charsio)).
|
:- use_module(library(charsio)).
|
||||||
|
:- use_module(library(iso_ext)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(si)).
|
:- use_module(library(si)).
|
||||||
|
|
||||||
|
:- use_module(library('$project_atts')).
|
||||||
|
:- use_module(library('$atts')).
|
||||||
|
|
||||||
:- dynamic(argv/1).
|
:- dynamic(argv/1).
|
||||||
|
|
||||||
'$repl'([_|Args0]) :-
|
'$repl'([_|Args0]) :-
|
||||||
@@ -109,9 +117,6 @@ read_and_match :-
|
|||||||
instruction_match(Term, VarList).
|
instruction_match(Term, VarList).
|
||||||
|
|
||||||
|
|
||||||
% make compile_batch, a system routine, callable.
|
|
||||||
compile_batch :- '$compile_batch'.
|
|
||||||
|
|
||||||
instruction_match(Term, VarList) :-
|
instruction_match(Term, VarList) :-
|
||||||
( var(Term) ->
|
( var(Term) ->
|
||||||
throw(error(instantiation_error, repl/0))
|
throw(error(instantiation_error, repl/0))
|
||||||
@@ -119,38 +124,43 @@ instruction_match(Term, VarList) :-
|
|||||||
!,
|
!,
|
||||||
( atom(Item) ->
|
( atom(Item) ->
|
||||||
( Item == user ->
|
( Item == user ->
|
||||||
catch(compile_batch, E, print_exception_with_check(E))
|
catch(load(user_input), E, print_exception_with_check(E))
|
||||||
; consult(Item)
|
;
|
||||||
|
consult(Item)
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
catch(throw(error(type_error(atom, Item), repl/0)),
|
catch(type_error(atom, Item, repl/0),
|
||||||
E,
|
E,
|
||||||
print_exception_with_check(E))
|
print_exception_with_check(E))
|
||||||
)
|
)
|
||||||
; Term = end_of_file ->
|
; Term = end_of_file ->
|
||||||
halt
|
halt
|
||||||
; submit_query_and_print_results(Term, VarList)
|
;
|
||||||
|
submit_query_and_print_results(Term, VarList)
|
||||||
).
|
).
|
||||||
|
|
||||||
:- use_module(library(iso_ext)).
|
|
||||||
|
|
||||||
% auxiliary predicates, so that using them in setup_call_cleanup/3 works
|
submit_query_and_print_results_(Term, VarList) :-
|
||||||
get_b_value(B) :- '$get_b_value'(B).
|
'$get_b_value'(B),
|
||||||
clear_attribute_goals :- '$clear_attribute_goals'.
|
call(Term),
|
||||||
|
write_eqs_and_read_input(B, VarList),
|
||||||
|
!.
|
||||||
|
submit_query_and_print_results_(_, _) :-
|
||||||
|
% clear attribute goal lists, which may be populated by
|
||||||
|
% copy_term/3 prior to failure.
|
||||||
|
'$clear_attribute_goals',
|
||||||
|
write('false.'),
|
||||||
|
nl.
|
||||||
|
|
||||||
|
|
||||||
submit_query_and_print_results(Term0, VarList) :-
|
submit_query_and_print_results(Term0, VarList) :-
|
||||||
( expand_goals(Term0, Term) -> true
|
expand_goal(call(Term0), user, Term),
|
||||||
; Term0 = Term
|
!,
|
||||||
),
|
|
||||||
setup_call_cleanup(bb_put('$first_answer', true),
|
setup_call_cleanup(bb_put('$first_answer', true),
|
||||||
( get_b_value(B), call(Term), write_eqs_and_read_input(B, VarList),
|
submit_query_and_print_results_(Term, VarList),
|
||||||
!
|
|
||||||
; % clear attribute goal lists, which may be populated by
|
|
||||||
% copy_term/3 prior to failure.
|
|
||||||
clear_attribute_goals, write('false.'), nl
|
|
||||||
),
|
|
||||||
bb_put('$first_answer', false)).
|
bb_put('$first_answer', false)).
|
||||||
|
|
||||||
|
|
||||||
needs_bracketing(Value, Op) :-
|
needs_bracketing(Value, Op) :-
|
||||||
catch((functor(Value, F, _),
|
catch((functor(Value, F, _),
|
||||||
current_op(EqPrec, EqSpec, Op),
|
current_op(EqPrec, EqSpec, Op),
|
||||||
@@ -254,12 +264,12 @@ write_eqs_and_read_input(B, VarList) :-
|
|||||||
( B0 == B ->
|
( B0 == B ->
|
||||||
( Goals == [] ->
|
( Goals == [] ->
|
||||||
write('true.'), nl
|
write('true.'), nl
|
||||||
; thread_goals(Goals, ThreadedGoals, (',')),
|
; loader:thread_goals(Goals, ThreadedGoals, (',')),
|
||||||
write_eq(ThreadedGoals, NewVarList0, 20),
|
write_eq(ThreadedGoals, NewVarList0, 20),
|
||||||
write('.'),
|
write('.'),
|
||||||
nl
|
nl
|
||||||
)
|
)
|
||||||
; thread_goals(Goals, ThreadedGoals, (',')),
|
; loader:thread_goals(Goals, ThreadedGoals, (',')),
|
||||||
write_eq(ThreadedGoals, NewVarList0, 20),
|
write_eq(ThreadedGoals, NewVarList0, 20),
|
||||||
read_input(ThreadedGoals, NewVarList0)
|
read_input(ThreadedGoals, NewVarList0)
|
||||||
).
|
).
|
||||||
@@ -353,133 +363,3 @@ print_exception_with_check(E) :-
|
|||||||
% is expected to be printed instead.
|
% is expected to be printed instead.
|
||||||
; print_exception(E)
|
; print_exception(E)
|
||||||
).
|
).
|
||||||
|
|
||||||
module_export(Source, PI) :-
|
|
||||||
( nonvar(PI) ->
|
|
||||||
( PI = Name / Arity ->
|
|
||||||
( var(Name) -> throw(error(instantiation_error, Source))
|
|
||||||
; integer(Arity) ->
|
|
||||||
( \+ atom(Name) -> throw(error(type_error(atom, Name), Source))
|
|
||||||
; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), Source))
|
|
||||||
; true
|
|
||||||
)
|
|
||||||
; throw(error(type_error(integer, Arity), Source))
|
|
||||||
)
|
|
||||||
; PI = op(Prec, Spec, Name) ->
|
|
||||||
( integer(Prec) ->
|
|
||||||
( \+ atom(Name) ->
|
|
||||||
throw(error(type_error(atom, Name), Source))
|
|
||||||
; Prec < 0 ->
|
|
||||||
throw(error(domain_error(not_less_than_zero, Prec), Source))
|
|
||||||
; Prec > 1200 ->
|
|
||||||
throw(error(domain_error(operator_precision, Prec), Source))
|
|
||||||
; memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf])
|
|
||||||
; throw(error(domain_error(operator_specification, Spec), Source))
|
|
||||||
)
|
|
||||||
; throw(error(type_error(integer, Prec), Source))
|
|
||||||
)
|
|
||||||
; throw(error(type_error(module_export, PI), Source))
|
|
||||||
)
|
|
||||||
; throw(error(instantiation_error, Source))
|
|
||||||
).
|
|
||||||
|
|
||||||
consult(Item) :-
|
|
||||||
( atom(Item) -> use_module(Item)
|
|
||||||
; throw(error(type_error(atom, Item), consult/1))
|
|
||||||
).
|
|
||||||
|
|
||||||
use_module(Module) :-
|
|
||||||
( nonvar(Module) ->
|
|
||||||
( Module = library(Filename) ->
|
|
||||||
write_term_to_chars(Filename, [], FilenameString),
|
|
||||||
'$use_module'(FilenameString)
|
|
||||||
; atom(Module) ->
|
|
||||||
'$use_module_from_file'(Module)
|
|
||||||
; throw(error(invalid_module_specifier, use_module/1))
|
|
||||||
)
|
|
||||||
; throw(error(instantiation_error, use_module/1))
|
|
||||||
).
|
|
||||||
|
|
||||||
use_module(Module, QualifiedExports) :-
|
|
||||||
( nonvar(Module) ->
|
|
||||||
( list_si(QualifiedExports) ->
|
|
||||||
maplist('$module_export'(use_module/2), QualifiedExports) ->
|
|
||||||
( Module = library(Filename) ->
|
|
||||||
write_term_to_chars(Filename, [], FilenameString),
|
|
||||||
'$use_qualified_module'(FilenameString, QualifiedExports)
|
|
||||||
; atom(Module) ->
|
|
||||||
'$use_qualified_module_from_file'(Module, QualifiedExports)
|
|
||||||
; throw(error(invalid_module_specifier, use_module/2))
|
|
||||||
)
|
|
||||||
; throw(error(type_error(list, QualifiedExports), use_module/2))
|
|
||||||
)
|
|
||||||
; throw(error(instantiation_error, use_module/2))
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
% expand goals in initialization directives.
|
|
||||||
user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
|
|
||||||
nonvar(Term0),
|
|
||||||
Term0 = (:- initialization(Goals)),
|
|
||||||
expand_goals(Goals, ExpandedGoals),
|
|
||||||
Goals \== ExpandedGoals.
|
|
||||||
|
|
||||||
module_expand_goal(UnexpandedGoals, ExpandedGoals) :-
|
|
||||||
( '$module_of'(Module, UnexpandedGoals),
|
|
||||||
'$module_exists'(Module),
|
|
||||||
Module:goal_expansion(UnexpandedGoals, ExpandedGoals),
|
|
||||||
UnexpandedGoals \== ExpandedGoals ->
|
|
||||||
true
|
|
||||||
; user:goal_expansion(UnexpandedGoals, ExpandedGoals)
|
|
||||||
).
|
|
||||||
|
|
||||||
expand_goals(UnexpandedGoals, ExpandedGoals) :-
|
|
||||||
nonvar(UnexpandedGoals),
|
|
||||||
var(ExpandedGoals),
|
|
||||||
( module_expand_goal(UnexpandedGoals, Goals) ->
|
|
||||||
true
|
|
||||||
; Goals = UnexpandedGoals
|
|
||||||
),
|
|
||||||
( Goals = (Goal0, Goals0) ->
|
|
||||||
( expand_goals(Goal0, Goal1) ->
|
|
||||||
expand_goals(Goals0, Goals1),
|
|
||||||
thread_goals(Goal1, ExpandedGoals, Goals1, (','))
|
|
||||||
; expand_goals(Goals0, Goals1),
|
|
||||||
ExpandedGoals = (Goal0, Goals1)
|
|
||||||
)
|
|
||||||
; Goals = (Goals0 -> Goals1) ->
|
|
||||||
expand_goals(Goals0, ExpandedGoals0),
|
|
||||||
expand_goals(Goals1, ExpandedGoals1),
|
|
||||||
ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1)
|
|
||||||
; Goals = (Goals0 ; Goals1) ->
|
|
||||||
expand_goals(Goals0, ExpandedGoals0),
|
|
||||||
expand_goals(Goals1, ExpandedGoals1),
|
|
||||||
ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
|
|
||||||
; Goals = (\+ Goals0) ->
|
|
||||||
expand_goals(Goals0, Goals1),
|
|
||||||
ExpandedGoals = (\+ Goals1)
|
|
||||||
; thread_goals(Goals, ExpandedGoals, (','))
|
|
||||||
; Goals = ExpandedGoals
|
|
||||||
).
|
|
||||||
|
|
||||||
thread_goals(Goals0, Goals1, Hole, Functor) :-
|
|
||||||
nonvar(Goals0),
|
|
||||||
( Goals0 = [G | Gs] ->
|
|
||||||
( Gs == [] ->
|
|
||||||
Goals1 =.. [Functor, G, Hole]
|
|
||||||
; Goals1 =.. [Functor, G, Goals2],
|
|
||||||
thread_goals(Gs, Goals2, Hole, Functor)
|
|
||||||
)
|
|
||||||
; Goals1 =.. [Functor, Goals0, Hole]
|
|
||||||
).
|
|
||||||
|
|
||||||
thread_goals(Goals0, Goals1, Functor) :-
|
|
||||||
nonvar(Goals0),
|
|
||||||
( Goals0 = [G | Gs] ->
|
|
||||||
( Gs = [] ->
|
|
||||||
Goals1 = G
|
|
||||||
; Goals1 =.. [Functor, G, Goals2],
|
|
||||||
thread_goals(Gs, Goals2, Functor)
|
|
||||||
)
|
|
||||||
; Goals1 = Goals0
|
|
||||||
).
|
|
||||||
|
|||||||
208
src/write.rs
208
src/write.rs
@@ -1,5 +1,6 @@
|
|||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
|
use crate::indexing::IndexingCodePtr;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::machine_errors::*;
|
use crate::machine::machine_errors::*;
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
@@ -10,14 +11,8 @@ impl fmt::Display for LocalCodePtr {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
LocalCodePtr::DirEntry(p) => write!(f, "LocalCodePtr::DirEntry({})", p),
|
LocalCodePtr::DirEntry(p) => write!(f, "LocalCodePtr::DirEntry({})", p),
|
||||||
LocalCodePtr::InSituDirEntry(p) => write!(f, "LocalCodePtr::InSituDirEntry({})", p),
|
LocalCodePtr::Halt => write!(f, "LocalCodePtr::Halt"),
|
||||||
LocalCodePtr::TopLevel(cn, p) => write!(f, "LocalCodePtr::TopLevel({}, {})", cn, p),
|
LocalCodePtr::IndexingBuf(p, o, i) => write!(f, "LocalCodePtr::IndexingBuf({}, {}, {})", p, o, i),
|
||||||
LocalCodePtr::UserGoalExpansion(p) => {
|
|
||||||
write!(f, "LocalCodePtr::UserGoalExpansion({})", p)
|
|
||||||
}
|
|
||||||
LocalCodePtr::UserTermExpansion(p) => {
|
|
||||||
write!(f, "LocalCodePtr::UserTermExpansion({})", p)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,16 +20,50 @@ impl fmt::Display for LocalCodePtr {
|
|||||||
impl fmt::Display for REPLCodePtr {
|
impl fmt::Display for REPLCodePtr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
REPLCodePtr::CompileBatch =>
|
REPLCodePtr::AddDynamicPredicate =>
|
||||||
write!(f, "REPLCodePtr::CompileBatch"),
|
write!(f, "REPLCodePtr::AddDynamicPredicate"),
|
||||||
|
REPLCodePtr::AddGoalExpansionClause =>
|
||||||
|
write!(f, "REPLCodePtr::AddGoalExpansionClause"),
|
||||||
|
REPLCodePtr::AddTermExpansionClause =>
|
||||||
|
write!(f, "REPLCodePtr::AddTermExpansionClause"),
|
||||||
|
REPLCodePtr::UserAssertz =>
|
||||||
|
write!(f, "REPLCodePtr::UserAssertz"),
|
||||||
|
REPLCodePtr::UserAsserta =>
|
||||||
|
write!(f, "REPLCodePtr::UserAsserta"),
|
||||||
|
REPLCodePtr::UserRetract =>
|
||||||
|
write!(f, "REPLCodePtr::UserRetract"),
|
||||||
|
REPLCodePtr::ClauseToEvacuable =>
|
||||||
|
write!(f, "REPLCodePtr::ClauseToEvacuable"),
|
||||||
|
REPLCodePtr::ConcludeLoad =>
|
||||||
|
write!(f, "REPLCodePtr::ConcludeLoad"),
|
||||||
|
REPLCodePtr::DeclareModule =>
|
||||||
|
write!(f, "REPLCodePtr::DeclareModule"),
|
||||||
|
REPLCodePtr::LoadCompiledLibrary =>
|
||||||
|
write!(f, "REPLCodePtr::LoadCompiledLibrary"),
|
||||||
|
REPLCodePtr::LoadContextSource =>
|
||||||
|
write!(f, "REPLCodePtr::LoadContextSource"),
|
||||||
|
REPLCodePtr::LoadContextFile =>
|
||||||
|
write!(f, "REPLCodePtr::LoadContextFile"),
|
||||||
|
REPLCodePtr::LoadContextDirectory =>
|
||||||
|
write!(f, "REPLCodePtr::LoadContextDirectory"),
|
||||||
|
REPLCodePtr::LoadContextModule =>
|
||||||
|
write!(f, "REPLCodePtr::LoadContextModule"),
|
||||||
|
REPLCodePtr::LoadContextStream =>
|
||||||
|
write!(f, "REPLCodePtr::LoadContextStream"),
|
||||||
|
REPLCodePtr::PopLoadContext =>
|
||||||
|
write!(f, "REPLCodePtr::PopLoadContext"),
|
||||||
|
REPLCodePtr::PopLoadStatePayload =>
|
||||||
|
write!(f, "REPLCodePtr::PopLoadStatePayload"),
|
||||||
|
REPLCodePtr::PushLoadContext =>
|
||||||
|
write!(f, "REPLCodePtr::PushLoadContext"),
|
||||||
|
REPLCodePtr::PushLoadStatePayload =>
|
||||||
|
write!(f, "REPLCodePtr::PushLoadStatePayload"),
|
||||||
REPLCodePtr::UseModule =>
|
REPLCodePtr::UseModule =>
|
||||||
write!(f, "REPLCodePtr::UseModule"),
|
write!(f, "REPLCodePtr::UseModule"),
|
||||||
REPLCodePtr::UseQualifiedModule =>
|
REPLCodePtr::MetaPredicateProperty =>
|
||||||
write!(f, "REPLCodePtr::UseQualifiedModule"),
|
write!(f, "REPLCodePtr::MetaPredicateProperty"),
|
||||||
REPLCodePtr::UseModuleFromFile =>
|
REPLCodePtr::CompilePendingPredicates =>
|
||||||
write!(f, "REPLCodePtr::UseModuleFromFile"),
|
write!(f, "REPLCodePtr::CompilePendingPredicates"),
|
||||||
REPLCodePtr::UseQualifiedModuleFromFile =>
|
|
||||||
write!(f, "REPLCodePtr::UseQualifiedModuleFromFile")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,9 +74,6 @@ impl fmt::Display for IndexPtr {
|
|||||||
&IndexPtr::DynamicUndefined => write!(f, "undefined"),
|
&IndexPtr::DynamicUndefined => write!(f, "undefined"),
|
||||||
&IndexPtr::Undefined => write!(f, "undefined"),
|
&IndexPtr::Undefined => write!(f, "undefined"),
|
||||||
&IndexPtr::Index(i) => write!(f, "{}", i),
|
&IndexPtr::Index(i) => write!(f, "{}", i),
|
||||||
&IndexPtr::InSituDirEntry(i) => write!(f, "in_situ({})", i),
|
|
||||||
&IndexPtr::UserTermExpansion => write!(f, "user:term_expansion"),
|
|
||||||
&IndexPtr::UserGoalExpansion => write!(f, "user:goal_expansion"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,17 +94,27 @@ impl fmt::Display for FactInstruction {
|
|||||||
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
|
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
|
||||||
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
|
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetValue(ref x, ref a) => write!(f, "get_value {}, A{}", x, a),
|
&FactInstruction::GetValue(ref x, ref a) => {
|
||||||
|
write!(f, "get_value {}, A{}", x, a)
|
||||||
|
}
|
||||||
&FactInstruction::GetVariable(ref x, ref a) => {
|
&FactInstruction::GetVariable(ref x, ref a) => {
|
||||||
write!(f, "fact:get_variable {}, A{}", x, a)
|
write!(f, "fact:get_variable {}, A{}", x, a)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyConstant(ref constant) => {
|
&FactInstruction::UnifyConstant(ref constant) => {
|
||||||
write!(f, "unify_constant {}", constant)
|
write!(f, "unify_constant {}", constant)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVariable(ref r) => write!(f, "unify_variable {}", r),
|
&FactInstruction::UnifyVariable(ref r) => {
|
||||||
&FactInstruction::UnifyLocalValue(ref r) => write!(f, "unify_local_value {}", r),
|
write!(f, "unify_variable {}", r)
|
||||||
&FactInstruction::UnifyValue(ref r) => write!(f, "unify_value {}", r),
|
}
|
||||||
&FactInstruction::UnifyVoid(n) => write!(f, "unify_void {}", n),
|
&FactInstruction::UnifyLocalValue(ref r) => {
|
||||||
|
write!(f, "unify_local_value {}", r)
|
||||||
|
}
|
||||||
|
&FactInstruction::UnifyValue(ref r) => {
|
||||||
|
write!(f, "unify_value {}", r)
|
||||||
|
}
|
||||||
|
&FactInstruction::UnifyVoid(n) => {
|
||||||
|
write!(f, "unify_void {}", n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,12 +177,16 @@ impl fmt::Display for CompareTermQT {
|
|||||||
impl fmt::Display for ClauseType {
|
impl fmt::Display for ClauseType {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&ClauseType::System(SystemClauseType::SetCutPoint(r)) => write!(f, "$set_cp({})", r),
|
&ClauseType::System(SystemClauseType::SetCutPoint(r)) => {
|
||||||
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
|
write!(f, "$set_cp({})", r)
|
||||||
let idx = idx.0.borrow();
|
}
|
||||||
write!(f, "{}:{}/{}", idx.1, name, idx.0)
|
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
|
||||||
|
let idx = idx.0.get();
|
||||||
|
write!(f, "{}/{}", name, idx)
|
||||||
|
}
|
||||||
|
ref ct => {
|
||||||
|
write!(f, "{}", ct.name())
|
||||||
}
|
}
|
||||||
ref ct => write!(f, "{}", ct.name()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,6 +198,7 @@ impl fmt::Display for HeapCellValue {
|
|||||||
&HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
|
&HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
|
||||||
&HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
|
&HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
|
||||||
&HeapCellValue::Integer(ref n) => write!(f, "{}", n),
|
&HeapCellValue::Integer(ref n) => write!(f, "{}", n),
|
||||||
|
&HeapCellValue::LoadStatePayload(_) => write!(f, "LoadStatePayload"),
|
||||||
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
|
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
|
||||||
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
||||||
f,
|
f,
|
||||||
@@ -209,6 +250,7 @@ impl fmt::Display for Addr {
|
|||||||
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
|
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
|
||||||
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
||||||
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
||||||
|
&Addr::LoadStatePayload(s) => write!(f, "Addr::LoadStatePayload({})", s),
|
||||||
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
||||||
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
||||||
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
||||||
@@ -244,6 +286,9 @@ impl fmt::Display for ControlInstruction {
|
|||||||
&ControlInstruction::JmpBy(arity, offset, pvs, true) => {
|
&ControlInstruction::JmpBy(arity, offset, pvs, true) => {
|
||||||
write!(f, "jmp_by_execute {}/{}, {}", offset, arity, pvs)
|
write!(f, "jmp_by_execute {}/{}, {}", offset, arity, pvs)
|
||||||
}
|
}
|
||||||
|
&ControlInstruction::RevJmpBy(offset) => {
|
||||||
|
write!(f, "rev_jmp_by {}", offset)
|
||||||
|
}
|
||||||
&ControlInstruction::Proceed => write!(f, "proceed"),
|
&ControlInstruction::Proceed => write!(f, "proceed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,13 +307,33 @@ impl fmt::Display for IndexedChoiceInstruction {
|
|||||||
impl fmt::Display for ChoiceInstruction {
|
impl fmt::Display for ChoiceInstruction {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&ChoiceInstruction::TryMeElse(offset) => write!(f, "try_me_else {}", offset),
|
&ChoiceInstruction::TryMeElse(offset) =>
|
||||||
|
write!(f, "try_me_else {}", offset),
|
||||||
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
||||||
write!(f, "retry_me_else_by_default {}", offset)
|
write!(f, "retry_me_else_by_default {}", offset)
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::RetryMeElse(offset) => write!(f, "retry_me_else {}", offset),
|
&ChoiceInstruction::RetryMeElse(offset) =>
|
||||||
&ChoiceInstruction::DefaultTrustMe => write!(f, "trust_me_by_default"),
|
write!(f, "retry_me_else {}", offset),
|
||||||
&ChoiceInstruction::TrustMe => write!(f, "trust_me"),
|
&ChoiceInstruction::DefaultTrustMe(_) =>
|
||||||
|
write!(f, "trust_me_by_default"),
|
||||||
|
&ChoiceInstruction::TrustMe(_) =>
|
||||||
|
write!(f, "trust_me"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for IndexingCodePtr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
&IndexingCodePtr::External(o) => {
|
||||||
|
write!(f, "IndexingCodePtr::External({})", o)
|
||||||
|
}
|
||||||
|
&IndexingCodePtr::Fail => {
|
||||||
|
write!(f, "IndexingCodePtr::Fail")
|
||||||
|
}
|
||||||
|
&IndexingCodePtr::Internal(o) => {
|
||||||
|
write!(f, "IndexingCodePtr::Internal({})", o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,11 +344,11 @@ impl fmt::Display for IndexingInstruction {
|
|||||||
&IndexingInstruction::SwitchOnTerm(a, v, c, l, s) => {
|
&IndexingInstruction::SwitchOnTerm(a, v, c, l, s) => {
|
||||||
write!(f, "switch_on_term {}, {}, {}, {}, {}", a, v, c, l, s)
|
write!(f, "switch_on_term {}, {}, {}, {}, {}", a, v, c, l, s)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnConstant(_, num_cs, _) => {
|
&IndexingInstruction::SwitchOnConstant(ref constants) => {
|
||||||
write!(f, "switch_on_constant {}", num_cs)
|
write!(f, "switch_on_constant {}", constants.len())
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(_, num_ss, _) => {
|
&IndexingInstruction::SwitchOnStructure(ref structures) => {
|
||||||
write!(f, "switch_on_structure {}", num_ss)
|
write!(f, "switch_on_structure {}", structures.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,36 +360,40 @@ impl fmt::Display for SessionError {
|
|||||||
&SessionError::ExistenceError(ref err) => {
|
&SessionError::ExistenceError(ref err) => {
|
||||||
write!(f, "{}", err)
|
write!(f, "{}", err)
|
||||||
}
|
}
|
||||||
&SessionError::CannotOverwriteBuiltIn(ref msg) => {
|
// &SessionError::CannotOverwriteBuiltIn(ref msg) => {
|
||||||
write!(f, "cannot overwrite {}", msg)
|
// write!(f, "cannot overwrite {}", msg)
|
||||||
}
|
// }
|
||||||
&SessionError::CannotOverwriteImport(ref msg) => {
|
// &SessionError::CannotOverwriteImport(ref msg) => {
|
||||||
write!(f, "cannot overwrite import {}", msg)
|
// write!(f, "cannot overwrite import {}", msg)
|
||||||
}
|
// }
|
||||||
&SessionError::InvalidFileName(ref filename) => {
|
// &SessionError::InvalidFileName(ref filename) => {
|
||||||
write!(f, "filename {} is invalid", filename)
|
// write!(f, "filename {} is invalid", filename)
|
||||||
}
|
// }
|
||||||
&SessionError::ModuleDoesNotContainExport(ref module, ref key) => {
|
// &SessionError::ModuleDoesNotContainExport(ref module, ref key) => {
|
||||||
write!(
|
// write!(
|
||||||
f,
|
// f,
|
||||||
"module {} does not contain claimed export {}/{}",
|
// "module {} does not contain claimed export {}/{}",
|
||||||
module,
|
// module,
|
||||||
key.0,
|
// key.0,
|
||||||
key.1,
|
// key.1,
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
&SessionError::OpIsInfixAndPostFix(_) => {
|
&SessionError::OpIsInfixAndPostFix(_) => {
|
||||||
write!(f, "cannot define an op to be both postfix and infix.")
|
write!(f, "cannot define an op to be both postfix and infix.")
|
||||||
}
|
}
|
||||||
&SessionError::NamelessEntry => {
|
&SessionError::NamelessEntry => {
|
||||||
write!(f, "the predicate head is not an atom or clause.")
|
write!(f, "the predicate head is not an atom or clause.")
|
||||||
}
|
}
|
||||||
&SessionError::ParserError(ref e) => {
|
&SessionError::CompilationError(ref e) => {
|
||||||
write!(f, "syntax_error({})", e.as_str())
|
write!(f, "syntax_error({:?})", e)
|
||||||
}
|
}
|
||||||
&SessionError::QueryCannotBeDefinedAsFact => {
|
&SessionError::QueryCannotBeDefinedAsFact => {
|
||||||
write!(f, "queries cannot be defined as facts.")
|
write!(f, "queries cannot be defined as facts.")
|
||||||
}
|
}
|
||||||
|
&SessionError::ModuleCannotImportSelf(ref module_name) => {
|
||||||
|
write!(f, "modules ({}, in this case) cannot import themselves.",
|
||||||
|
module_name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,6 +433,23 @@ impl fmt::Display for ModuleSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for IndexingLine {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
&IndexingLine::Indexing(ref indexing_instr) => {
|
||||||
|
write!(f, "{}", indexing_instr)
|
||||||
|
}
|
||||||
|
&IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
|
||||||
|
for indexed_choice_instr in indexed_choice_instrs {
|
||||||
|
write!(f, "{}", indexed_choice_instr)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Line {
|
impl fmt::Display for Line {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -372,7 +458,13 @@ impl fmt::Display for Line {
|
|||||||
&Line::Control(ref control_instr) => write!(f, "{}", control_instr),
|
&Line::Control(ref control_instr) => write!(f, "{}", control_instr),
|
||||||
&Line::Cut(ref cut_instr) => write!(f, "{}", cut_instr),
|
&Line::Cut(ref cut_instr) => write!(f, "{}", cut_instr),
|
||||||
&Line::Fact(ref fact_instr) => write!(f, "{}", fact_instr),
|
&Line::Fact(ref fact_instr) => write!(f, "{}", fact_instr),
|
||||||
&Line::Indexing(ref indexing_instr) => write!(f, "{}", indexing_instr),
|
&Line::IndexingCode(ref indexing_instrs) => {
|
||||||
|
for indexing_instr in indexing_instrs {
|
||||||
|
write!(f, "{}", indexing_instr)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
&Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr),
|
&Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr),
|
||||||
&Line::Query(ref query_instr) => write!(f, "{}", query_instr),
|
&Line::Query(ref query_instr) => write!(f, "{}", query_instr),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user