From 3d8c0a43a6fd44cb53c01be8512deaf79d54c5e0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 3 Mar 2019 23:29:02 -0700 Subject: [PATCH] refactor to actual modules --- src/main.rs | 7 +- src/prolog/allocator.rs | 3 +- src/prolog/arithmetic.rs | 7 + src/prolog/clause_types.rs | 481 +++++++ src/prolog/codegen.rs | 5 +- src/prolog/debray_allocator.rs | 4 +- src/prolog/fixtures.rs | 66 +- src/prolog/forms.rs | 245 ++++ src/prolog/heap_iter.rs | 2 +- src/prolog/heap_print.rs | 5 +- src/prolog/instructions.rs | 1515 +--------------------- src/prolog/iterators.rs | 39 +- src/prolog/{ => machine}/and_stack.rs | 2 +- src/prolog/machine/code_repo.rs | 124 ++ src/prolog/{ => machine}/compile.rs | 12 +- src/prolog/{ => machine}/copier.rs | 4 +- src/prolog/machine/dynamic_database.rs | 3 +- src/prolog/{ => machine}/heap.rs | 2 +- src/prolog/machine/machine_errors.rs | 58 +- src/prolog/machine/machine_indices.rs | 533 ++++++++ src/prolog/machine/machine_state.rs | 17 +- src/prolog/machine/machine_state_impl.rs | 15 +- src/prolog/machine/mod.rs | 242 +--- src/prolog/machine/modules.rs | 242 ++++ src/prolog/{ => machine}/or_stack.rs | 2 +- src/prolog/machine/system_calls.rs | 6 +- src/prolog/machine/term_expansion.rs | 2 +- src/prolog/{ => machine}/toplevel.rs | 7 +- src/prolog/mod.rs | 12 +- src/prolog/read.rs | 3 +- src/prolog/targets.rs | 2 + src/prolog/write.rs | 6 +- src/tests.rs | 7 +- 33 files changed, 1887 insertions(+), 1793 deletions(-) create mode 100644 src/prolog/clause_types.rs create mode 100644 src/prolog/forms.rs rename src/prolog/{ => machine}/and_stack.rs (97%) create mode 100644 src/prolog/machine/code_repo.rs rename src/prolog/{ => machine}/compile.rs (98%) rename src/prolog/{ => machine}/copier.rs (98%) rename src/prolog/{ => machine}/heap.rs (97%) create mode 100644 src/prolog/machine/machine_indices.rs create mode 100644 src/prolog/machine/modules.rs rename src/prolog/{ => machine}/or_stack.rs (98%) rename src/prolog/{ => machine}/toplevel.rs (99%) diff --git a/src/main.rs b/src/main.rs index 6b85d72c..bfbda33f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,14 +2,13 @@ #[macro_use] extern crate prolog_parser; extern crate termion; -use prolog::instructions::*; - mod prolog; -use prolog::compile::*; use prolog::machine::*; +use prolog::machine::compile::*; +use prolog::machine::machine_errors::*; +use prolog::machine::toplevel::string_to_toplevel; use prolog::read::*; -use prolog::toplevel::string_to_toplevel; use prolog::write::*; use std::io::{Write, stdin, stdout}; diff --git a/src/prolog/allocator.rs b/src/prolog/allocator.rs index a498fbaf..8ae88742 100644 --- a/src/prolog/allocator.rs +++ b/src/prolog/allocator.rs @@ -1,7 +1,8 @@ use prolog_parser::ast::*; -use prolog::instructions::*; use prolog::fixtures::*; +use prolog::forms::*; +use prolog::machine::machine_indices::*; use prolog::targets::*; use std::cell::Cell; diff --git a/src/prolog/arithmetic.rs b/src/prolog/arithmetic.rs index a3cdc5f6..bc36e407 100644 --- a/src/prolog/arithmetic.rs +++ b/src/prolog/arithmetic.rs @@ -1,6 +1,13 @@ use prolog_parser::ast::*; +use prolog::clause_types::*; +use prolog::fixtures::*; +use prolog::forms::*; use prolog::instructions::*; +use prolog::iterators::*; + +use prolog::machine::machine_indices::*; + use std::cell::Cell; use std::cmp::{min, max}; use std::rc::Rc; diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs new file mode 100644 index 00000000..8804d8ff --- /dev/null +++ b/src/prolog/clause_types.rs @@ -0,0 +1,481 @@ +use prolog_parser::ast::*; + +use prolog::forms::OpDecl; +use prolog::machine::machine_indices::*; + +#[derive(Clone, Copy, PartialEq)] +pub enum CompareNumberQT { + GreaterThan, + LessThan, + GreaterThanOrEqual, + LessThanOrEqual, + NotEqual, + Equal +} + +impl CompareNumberQT { + fn name(self) -> &'static str { + match self { + CompareNumberQT::GreaterThan => ">", + CompareNumberQT::LessThan => "<", + CompareNumberQT::GreaterThanOrEqual => ">=", + CompareNumberQT::LessThanOrEqual => "=<", + CompareNumberQT::NotEqual => "=\\=", + CompareNumberQT::Equal => "=:=" + } + } +} + +#[derive(Clone, Copy, PartialEq)] +pub enum CompareTermQT { + LessThan, + LessThanOrEqual, + Equal, + GreaterThanOrEqual, + GreaterThan, + NotEqual, +} + +impl CompareTermQT { + fn name<'a>(self) -> &'a str { + match self { + CompareTermQT::GreaterThan => "@>", + CompareTermQT::LessThan => "@<", + CompareTermQT::GreaterThanOrEqual => "@>=", + CompareTermQT::LessThanOrEqual => "@=<", + CompareTermQT::NotEqual => "\\=@=", + CompareTermQT::Equal => "=@=" + } + } +} + +#[derive(Clone, PartialEq)] +pub enum ArithmeticTerm { + Reg(RegType), + Interm(usize), + Number(Number) +} + +impl ArithmeticTerm { + pub fn interm_or(&self, interm: usize) -> usize { + if let &ArithmeticTerm::Interm(interm) = self { + interm + } else { + interm + } + } +} + +#[derive(Clone, PartialEq)] +pub enum InlinedClauseType { + CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), + IsAtom(RegType), + IsAtomic(RegType), + IsCompound(RegType), + IsInteger(RegType), + IsRational(RegType), + IsString(RegType), + IsFloat(RegType), + IsNonVar(RegType), + IsPartialString(RegType), + IsVar(RegType) +} + +impl InlinedClauseType { + pub fn name(&self) -> &'static str { + match self { + &InlinedClauseType::CompareNumber(qt, ..) => qt.name(), + &InlinedClauseType::IsAtom(..) => "atom", + &InlinedClauseType::IsAtomic(..) => "atomic", + &InlinedClauseType::IsCompound(..) => "compound", + &InlinedClauseType::IsInteger (..) => "integer", + &InlinedClauseType::IsRational(..) => "rational", + &InlinedClauseType::IsString(..) => "string", + &InlinedClauseType::IsFloat (..) => "float", + &InlinedClauseType::IsNonVar(..) => "nonvar", + &InlinedClauseType::IsPartialString(..) => "is_partial_string", + &InlinedClauseType::IsVar(..) => "var", + } + } + + pub fn from(name: &str, arity: usize) -> Option { + let r1 = temp_v!(1); + let r2 = temp_v!(2); + + let a1 = ArithmeticTerm::Reg(r1); + let a2 = ArithmeticTerm::Reg(r2); + + match (name, arity) { + (">", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, a1, a2)), + ("<", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, a1, a2)), + (">=", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,a1, a2)), + ("=<", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, a1, a2)), + ("=\\=", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, a1, a2)), + ("=:=", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, a1, a2)), + ("atom", 1) => Some(InlinedClauseType::IsAtom(r1)), + ("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)), + ("compound", 1) => Some(InlinedClauseType::IsCompound(r1)), + ("integer", 1) => Some(InlinedClauseType::IsInteger(r1)), + ("rational", 1) => Some(InlinedClauseType::IsRational(r1)), + ("string", 1) => Some(InlinedClauseType::IsString(r1)), + ("float", 1) => Some(InlinedClauseType::IsFloat(r1)), + ("nonvar", 1) => Some(InlinedClauseType::IsNonVar(r1)), + ("var", 1) => Some(InlinedClauseType::IsVar(r1)), + ("is_partial_string", 1) => Some(InlinedClauseType::IsPartialString(r1)), + _ => None + } + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum SystemClauseType { + AbolishClause, + AssertDynamicPredicateToBack, + AssertDynamicPredicateToFront, + CheckCutPoint, + CopyToLiftedHeap, + DeleteAttribute, + DeleteHeadAttribute, + DynamicModuleResolution, + EnqueueAttributeGoal, + EnqueueAttributedVar, + ExpandGoal, + ExpandTerm, + TruncateIfNoLiftedHeapGrowthDiff, + TruncateIfNoLiftedHeapGrowth, + GetAttributedVariableList, + GetAttrVarQueueDelimiter, + GetAttrVarQueueBeyond, + GetBValue, + GetClause, + GetCurrentPredicateList, + GetLiftedHeapFromOffset, + GetLiftedHeapFromOffsetDiff, + GetSCCCleaner, + HeadIsDynamic, + InstallSCCCleaner, + InstallInferenceCounter, + LiftedHeapLength, + ModuleOf, + NoSuchPredicate, + RedoAttrVarBindings, + RemoveCallPolicyCheck, + RemoveInferenceCounter, + RetractClause, + RestoreCutPolicy, + SetCutPoint(RegType), + InferenceLevel, + CleanUpBlock, + EraseBall, + Fail, + GetBall, + GetCurrentBlock, + GetCutPoint, + GetDoubleQuotes, + InstallNewBlock, + ResetBlock, + ReturnFromAttributeGoals, + ReturnFromVerifyAttr, + SetBall, + SetCutPointByDefault(RegType), + SetDoubleQuotes, + SkipMaxList, + Succeed, + TermVariables, + TruncateLiftedHeapTo, + UnwindStack, + WriteTerm +} + +impl SystemClauseType { + pub fn name(&self) -> ClauseName { + match self { + &SystemClauseType::AbolishClause => clause_name!("$abolish_clause"), + &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$asserta"), + &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$assertz"), + &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), + &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), + &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), + &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"), + &SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"), + &SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"), + &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), + &SystemClauseType::ExpandTerm => clause_name!("$expand_term"), + &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"), + &SystemClauseType::TruncateIfNoLiftedHeapGrowth => clause_name!("$truncate_if_no_lh_growth"), + &SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => clause_name!("$truncate_if_no_lh_growth_diff"), + &SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"), + &SystemClauseType::GetAttrVarQueueDelimiter => clause_name!("$get_attr_var_queue_delim"), + &SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"), + &SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"), + &SystemClauseType::GetLiftedHeapFromOffsetDiff => clause_name!("$get_lh_from_offset_diff"), + &SystemClauseType::GetCurrentPredicateList => clause_name!("$get_current_predicate_list"), + &SystemClauseType::GetBValue => clause_name!("$get_b_value"), + &SystemClauseType::GetClause => clause_name!("$get_clause"), + &SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"), + &SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"), + &SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"), + &SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"), + &SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"), + &SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"), + &SystemClauseType::ModuleOf => clause_name!("$module_of"), + &SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"), + &SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"), + &SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"), + &SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"), + &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), + &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"), + &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), + &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), + &SystemClauseType::EraseBall => clause_name!("$erase_ball"), + &SystemClauseType::Fail => clause_name!("$fail"), + &SystemClauseType::GetBall => clause_name!("$get_ball"), + &SystemClauseType::GetCutPoint => clause_name!("$get_cp"), + &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), + &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), + &SystemClauseType::RetractClause => clause_name!("$retract_clause"), + &SystemClauseType::ResetBlock => clause_name!("$reset_block"), + &SystemClauseType::ReturnFromAttributeGoals => clause_name!("$return_from_attribute_goals"), + &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), + &SystemClauseType::SetBall => clause_name!("$set_ball"), + &SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"), + &SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"), + &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), + &SystemClauseType::Succeed => clause_name!("$succeed"), + &SystemClauseType::TermVariables => clause_name!("$term_variables"), + &SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"), + &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), + &SystemClauseType::WriteTerm => clause_name!("$write_term"), + } + } + + pub fn from(name: &str, arity: usize) -> Option { + match (name, arity) { + ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause), + ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront), + ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack), + ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint), + ("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap), + ("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute), + ("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute), + ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution), + ("$enqueue_attribute_goal", 1) => Some(SystemClauseType::EnqueueAttributeGoal), + ("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar), + ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm), + ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal), + ("$truncate_if_no_lh_growth", 1) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth), + ("$truncate_if_no_lh_growth_diff", 2) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff), + ("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList), + ("$get_b_value", 1) => Some(SystemClauseType::GetBValue), + ("$get_clause", 2) => Some(SystemClauseType::GetClause), + ("$get_current_predicate_list", 1) => Some(SystemClauseType::GetCurrentPredicateList), + ("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset), + ("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff), + ("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes), + ("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner), + ("$head_is_dynamic", 1) => Some(SystemClauseType::HeadIsDynamic), + ("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner), + ("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter), + ("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength), + ("$module_of", 2) => Some(SystemClauseType::ModuleOf), + ("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate), + ("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings), + ("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck), + ("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter), + ("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy), + ("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))), + ("$inference_level", 2) => Some(SystemClauseType::InferenceLevel), + ("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock), + ("$erase_ball", 0) => Some(SystemClauseType::EraseBall), + ("$fail", 0) => Some(SystemClauseType::Fail), + ("$get_attr_var_queue_beyond", 2) => Some(SystemClauseType::GetAttrVarQueueBeyond), + ("$get_attr_var_queue_delim", 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter), + ("$get_ball", 1) => Some(SystemClauseType::GetBall), + ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), + ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), + ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), + ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), + ("$retract_clause", 4) => Some(SystemClauseType::RetractClause), + ("$return_from_attribute_goals", 0) => Some(SystemClauseType::ReturnFromAttributeGoals), + ("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr), + ("$set_ball", 1) => Some(SystemClauseType::SetBall), + ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), + ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), + ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), + ("$term_variables", 2) => Some(SystemClauseType::TermVariables), + ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), + ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), + ("$write_term", 4) => Some(SystemClauseType::WriteTerm), + _ => None + } + } +} + +#[derive(Clone, PartialEq)] +pub enum BuiltInClauseType { + AcyclicTerm, + Arg, + Compare, + CompareTerm(CompareTermQT), + CyclicTerm, + CopyTerm, + Eq, + Functor, + Ground, + Is(RegType, ArithmeticTerm), + KeySort, + Nl, + NotEq, + PartialString, + Read, + ReifySwitch, + Sort, +} + +#[derive(Clone)] +pub enum ClauseType { + BuiltIn(BuiltInClauseType), + CallN, + Hook(CompileTimeHook), + Inlined(InlinedClauseType), + Named(ClauseName, usize, CodeIndex), // name, arity, index. + Op(OpDecl, CodeIndex), + System(SystemClauseType) +} + +impl BuiltInClauseType { + pub fn name(&self) -> ClauseName { + match self { + &BuiltInClauseType::AcyclicTerm => clause_name!("acyclic_term"), + &BuiltInClauseType::Arg => clause_name!("arg"), + &BuiltInClauseType::Compare => clause_name!("compare"), + &BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()), + &BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"), + &BuiltInClauseType::CopyTerm => clause_name!("copy_term"), + &BuiltInClauseType::Eq => clause_name!("=="), + &BuiltInClauseType::Functor => clause_name!("functor"), + &BuiltInClauseType::Ground => clause_name!("ground"), + &BuiltInClauseType::Is(..) => clause_name!("is"), + &BuiltInClauseType::KeySort => clause_name!("keysort"), + &BuiltInClauseType::Nl => clause_name!("nl"), + &BuiltInClauseType::NotEq => clause_name!("\\=="), + &BuiltInClauseType::PartialString => clause_name!("partial_string"), + &BuiltInClauseType::Read => clause_name!("read"), + &BuiltInClauseType::ReifySwitch => clause_name!("$reify_switch"), + &BuiltInClauseType::Sort => clause_name!("sort"), + } + } + + pub fn arity(&self) -> usize { + match self { + &BuiltInClauseType::AcyclicTerm => 1, + &BuiltInClauseType::Arg => 3, + &BuiltInClauseType::Compare => 2, + &BuiltInClauseType::CompareTerm(_) => 2, + &BuiltInClauseType::CyclicTerm => 1, + &BuiltInClauseType::CopyTerm => 2, + &BuiltInClauseType::Eq => 2, + &BuiltInClauseType::Functor => 3, + &BuiltInClauseType::Ground => 1, + &BuiltInClauseType::Is(..) => 2, + &BuiltInClauseType::KeySort => 2, + &BuiltInClauseType::NotEq => 2, + &BuiltInClauseType::Nl => 0, + &BuiltInClauseType::PartialString => 1, + &BuiltInClauseType::Read => 1, + &BuiltInClauseType::ReifySwitch => 3, + &BuiltInClauseType::Sort => 2, + } + } + + pub fn from(name: &str, arity: usize) -> Option { + match (name, arity) { + ("acyclic_term", 1) => Some(BuiltInClauseType::AcyclicTerm), + ("arg", 3) => Some(BuiltInClauseType::Arg), + ("compare", 3) => Some(BuiltInClauseType::Compare), + ("cyclic_term", 1) => Some(BuiltInClauseType::CyclicTerm), + ("@>", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThan)), + ("@<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThan)), + ("@>=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual)), + ("@=<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)), + ("\\=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::NotEqual)), + ("=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::Equal)), + ("copy_term", 2) => Some(BuiltInClauseType::CopyTerm), + ("==", 2) => Some(BuiltInClauseType::Eq), + ("functor", 3) => Some(BuiltInClauseType::Functor), + ("ground", 1) => Some(BuiltInClauseType::Ground), + ("is", 2) => Some(BuiltInClauseType::Is(temp_v!(1), ArithmeticTerm::Reg(temp_v!(2)))), + ("keysort", 2) => Some(BuiltInClauseType::KeySort), + ("nl", 0) => Some(BuiltInClauseType::Nl), + ("\\==", 2) => Some(BuiltInClauseType::NotEq), + ("partial_string", 2) => Some(BuiltInClauseType::PartialString), + ("read", 1) => Some(BuiltInClauseType::Read), + ("$reify_switch", 3) => Some(BuiltInClauseType::ReifySwitch), + ("sort", 2) => Some(BuiltInClauseType::Sort), + _ => None + } + } +} + +impl ClauseType { + pub fn spec(&self) -> Option<(usize, Specifier)> { + match self { + &ClauseType::Op(ref op_decl, _) => + Some((op_decl.0, op_decl.1)), + &ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) + | &ClauseType::BuiltIn(BuiltInClauseType::Is(..)) + | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_)) + | &ClauseType::BuiltIn(BuiltInClauseType::NotEq) + | &ClauseType::BuiltIn(BuiltInClauseType::Eq) => + Some((700, XFX)), + _ => None + } + } + + pub fn name(&self) -> ClauseName { + match self { + &ClauseType::CallN => clause_name!("call"), + &ClauseType::BuiltIn(ref built_in) => built_in.name(), + &ClauseType::Hook(ref hook) => hook.name(), + &ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()), + &ClauseType::Op(ref op_decl, ..) => op_decl.name(), + &ClauseType::Named(ref name, ..) => name.clone(), + &ClauseType::System(ref system) => system.name(), + } + } + + pub fn from(name: ClauseName, arity: usize, spec: Option<(usize, Specifier)>) -> Self { + InlinedClauseType::from(name.as_str(), arity) + .map(ClauseType::Inlined) + .unwrap_or_else(|| { + BuiltInClauseType::from(name.as_str(), arity) + .map(ClauseType::BuiltIn) + .unwrap_or_else(|| { + SystemClauseType::from(name.as_str(), arity) + .map(ClauseType::System) + .unwrap_or_else(|| { + if let Some(spec) = spec { + let op_decl = OpDecl(spec.0, spec.1, name); + ClauseType::Op(op_decl, CodeIndex::default()) + } else if name.as_str() == "call" { + ClauseType::CallN + } else { + ClauseType::Named(name, arity, CodeIndex::default()) + } + }) + }) + }) + } +} + +impl From for ClauseType { + fn from(inlined_ct: InlinedClauseType) -> Self { + ClauseType::Inlined(inlined_ct) + } +} diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index ca4a81ac..462cda0f 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -1,11 +1,14 @@ use prolog_parser::ast::*; -use prolog::instructions::*; use prolog::allocator::*; use prolog::arithmetic::*; +use prolog::clause_types::*; use prolog::fixtures::*; +use prolog::forms::*; use prolog::indexing::*; +use prolog::instructions::*; use prolog::iterators::*; +use prolog::machine::machine_indices::*; use prolog::targets::*; use std::cell::Cell; diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index 86053c48..a9e62954 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -1,7 +1,9 @@ use prolog_parser::ast::*; -use prolog::instructions::*; use prolog::allocator::*; +use prolog::forms::*; +use prolog::fixtures::*; +use prolog::machine::machine_indices::*; use prolog::targets::*; use std::cell::Cell; diff --git a/src/prolog/fixtures.rs b/src/prolog/fixtures.rs index 3394ea95..474858c7 100644 --- a/src/prolog/fixtures.rs +++ b/src/prolog/fixtures.rs @@ -1,15 +1,79 @@ use prolog_parser::ast::*; +use prolog::forms::*; use prolog::instructions::*; use prolog::iterators::*; use std::cell::Cell; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::collections::btree_map::{IntoIter, IterMut, Values}; use std::mem::swap; use std::rc::Rc; use std::vec::Vec; +// labeled with chunk numbers. +pub enum VarStatus { + Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _) +} + +pub type OccurrenceSet = BTreeSet<(GenContext, usize)>; + +// Perm: 0 initially, a stack register once processed. +// Temp: labeled with chunk_num and temp offset (unassigned if 0). +pub enum VarData { + Perm(usize), Temp(usize, usize, TempVarData) +} + +impl VarData { + pub fn as_reg_type(&self) -> RegType { + match self { + &VarData::Temp(_, r, _) => RegType::Temp(r), + &VarData::Perm(r) => RegType::Perm(r) + } + } +} + +pub struct TempVarData { + pub last_term_arity: usize, + pub use_set: OccurrenceSet, + pub no_use_set: BTreeSet, + pub conflict_set: BTreeSet +} + +impl TempVarData { + pub fn new(last_term_arity: usize) -> Self { + TempVarData { + last_term_arity: last_term_arity, + use_set: BTreeSet::new(), + no_use_set: BTreeSet::new(), + conflict_set: BTreeSet::new() + } + } + + pub fn uses_reg(&self, reg: usize) -> bool { + for &(_, nreg) in self.use_set.iter() { + if reg == nreg { + return true; + } + } + + return false; + } + + pub fn populate_conflict_set(&mut self) { + if self.last_term_arity > 0 { + let arity = self.last_term_arity; + let mut conflict_set : BTreeSet = (1..arity).collect(); + + for &(_, reg) in self.use_set.iter() { + conflict_set.remove(®); + } + + self.conflict_set = conflict_set; + } + } +} + type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); pub struct VariableFixtures<'a>(BTreeMap, VariableFixture<'a>>); diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs new file mode 100644 index 00000000..c2bf01a5 --- /dev/null +++ b/src/prolog/forms.rs @@ -0,0 +1,245 @@ +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; + +use prolog::clause_types::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; + +use std::cell::Cell; +use std::collections::{HashMap, VecDeque}; +use std::rc::Rc; + +pub type PredicateKey = (ClauseName, usize); // name, arity. + +// vars of predicate, toplevel offset. Vec is always a vector +// of vars (we get their adjoining cells this way). +pub type JumpStub = Vec; + +#[derive(Clone)] +pub enum TopLevel { + Declaration(Declaration), + Fact(Term), + Predicate(Predicate), + Query(Vec), + Rule(Rule), +} + +impl TopLevel { + pub fn name(&self) -> Option { + match self { + &TopLevel::Declaration(_) => None, + &TopLevel::Fact(ref term) => term.name(), + &TopLevel::Predicate(ref clauses) => + clauses.0.first().and_then(|ref term| term.name()), + &TopLevel::Query(_) => None, + &TopLevel::Rule(Rule { ref head, .. }) => + Some(head.0.clone()) + } + } + + pub fn arity(&self) -> usize { + match self { + &TopLevel::Declaration(_) => 0, + &TopLevel::Fact(ref term) => term.arity(), + &TopLevel::Predicate(ref clauses) => + clauses.0.first().map(|t| t.arity()).unwrap_or(0), + &TopLevel::Query(_) => 0, + &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() + } + } +} + +#[derive(Clone, Copy)] +pub enum Level { + Deep, Root, Shallow +} + +impl Level { + pub fn child_level(self) -> Level { + match self { + Level::Root => Level::Shallow, + _ => Level::Deep + } + } +} + +#[derive(Clone)] +pub enum QueryTerm { + // register, clause type, subterms, use default call policy. + Clause(Cell, ClauseType, Vec>, bool), + BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. + UnblockedCut(Cell), + GetLevelAndUnify(Cell, Rc), + Jump(JumpStub) +} + +impl QueryTerm { + pub fn set_default_caller(&mut self) { + match self { + &mut QueryTerm::Clause(_, _, _, ref mut use_default_cp) => *use_default_cp = true, + _ => {} + } + } + + pub fn arity(&self) -> usize { + match self { + &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), + &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, + &QueryTerm::Jump(ref vars) => vars.len(), + &QueryTerm::GetLevelAndUnify(..) => 1, + } + } +} + +#[derive(Clone)] +pub struct Rule { + pub head: (ClauseName, Vec>, QueryTerm), + pub clauses: Vec +} + +#[derive(Clone)] +pub struct Predicate(pub Vec); + +impl Predicate { + #[inline] + pub fn new() -> Self { + Predicate(vec![]) + } + + #[inline] + pub fn clauses(self) -> Vec { + self.0 + } + + #[inline] + pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> { + self.0.first() + .and_then(|clause| clause.name().map(|name| (name, clause.arity()))) + } +} + +pub type CompiledResult = (Predicate, VecDeque); + +#[derive(Clone)] +pub enum PredicateClause { + Fact(Term), + Rule(Rule) +} + +impl PredicateClause { + pub fn first_arg(&self) -> Option<&Term> { + match self { + &PredicateClause::Fact(ref term) => term.first_arg(), + &PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()), + } + } + + pub fn arity(&self) -> usize { + match self { + &PredicateClause::Fact(ref term) => term.arity(), + &PredicateClause::Rule(ref rule) => rule.head.1.len() + } + } + + pub fn name(&self) -> Option { + match self { + &PredicateClause::Fact(ref term) => term.name(), + &PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()), + } + } +} + +#[derive(Clone)] +pub enum Declaration { + Dynamic(ClauseName, usize), // name, arity + Hook(CompileTimeHook, PredicateClause, VecDeque), + Module(ModuleDecl), + NonCountedBacktracking(ClauseName, usize), // name, arity + Op(OpDecl), + UseModule(ClauseName), + UseQualifiedModule(ClauseName, Vec) +} + +impl Declaration { + #[inline] + pub fn is_module_decl(&self) -> bool { + if let &Declaration::Module(_) = self { true } else { false } + } +} + +#[derive(Clone)] +pub struct OpDecl(pub usize, pub Specifier, pub ClauseName); + +impl OpDecl { + #[inline] + pub fn name(&self) -> ClauseName { + self.2.clone() + } + + pub fn arity(&self) -> usize { + let spec = self.1; + + if (spec | XFX != 0) || (spec | XFY != 0) || (spec | YFX != 0) { + 2 + } else { + 1 + } + } + + pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), SessionError> + { + let (prec, spec, name) = (self.0, self.1, self.2.clone()); + + if is_infix!(spec) { + match op_dir.get(&(name.clone(), Fixity::Post)) { + Some(_) => return Err(SessionError::OpIsInfixAndPostFix), + _ => {} + }; + } + + if is_postfix!(spec) { + match op_dir.get(&(name.clone(), Fixity::In)) { + Some(_) => return Err(SessionError::OpIsInfixAndPostFix), + _ => {} + }; + } + + if prec > 0 { + match spec { + XFY | XFX | YFX => op_dir.insert((name.clone(), Fixity::In), + (spec, prec, module.clone())), + XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec, module.clone())), + FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec, prec, module.clone())), + _ => None + }; + } else { + op_dir.remove(&(name.clone(), Fixity::Pre)); + op_dir.remove(&(name.clone(), Fixity::In)); + op_dir.remove(&(name.clone(), Fixity::Post)); + } + + Ok(()) + } +} + +pub type ModuleCodeDir = HashMap; +pub type ModuleDir = HashMap; + +#[derive(Clone)] +pub struct ModuleDecl { + pub name: ClauseName, + pub exports: Vec +} + +pub struct Module { + pub atom_tbl: TabledData, + pub module_decl: ModuleDecl, + pub code_dir: ModuleCodeDir, + pub op_dir: OpDir, + pub term_expansions: (Predicate, VecDeque), + pub goal_expansions: (Predicate, VecDeque), + pub inserted_expansions: bool // has the module been successfully inserted into toplevel?? +} + +#[derive(Clone)] +pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName); diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 4847a4a3..7f32c1bf 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -1,6 +1,6 @@ use prolog_parser::ast::*; -use prolog::instructions::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; use std::cmp::Ordering; diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index 0b2ac0f9..5fe5267b 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -1,9 +1,10 @@ use prolog_parser::ast::*; -use prolog::instructions::*; +use prolog::clause_types::*; +use prolog::heap_iter::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; use prolog::num::*; -use prolog::heap_iter::*; use prolog::ordered_float::OrderedFloat; use std::cell::Cell; diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index 64b88227..1abfb0c6 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -1,641 +1,9 @@ use prolog_parser::ast::*; -use prolog_parser::tabled_rc::*; -use std::cell::{Cell, RefCell}; -use std::collections::{BTreeSet, HashMap, VecDeque}; -use std::cmp::Ordering; -use std::ops::{Add, AddAssign, Sub, SubAssign}; -use std::rc::Rc; +use prolog::clause_types::*; +use prolog::forms::*; -#[derive(Clone, PartialEq)] -pub enum InlinedClauseType { - CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), - IsAtom(RegType), - IsAtomic(RegType), - IsCompound(RegType), - IsInteger(RegType), - IsRational(RegType), - IsString(RegType), - IsFloat(RegType), - IsNonVar(RegType), - IsPartialString(RegType), - IsVar(RegType) -} - -impl InlinedClauseType { - pub fn name(&self) -> &'static str { - match self { - &InlinedClauseType::CompareNumber(qt, ..) => qt.name(), - &InlinedClauseType::IsAtom(..) => "atom", - &InlinedClauseType::IsAtomic(..) => "atomic", - &InlinedClauseType::IsCompound(..) => "compound", - &InlinedClauseType::IsInteger (..) => "integer", - &InlinedClauseType::IsRational(..) => "rational", - &InlinedClauseType::IsString(..) => "string", - &InlinedClauseType::IsFloat (..) => "float", - &InlinedClauseType::IsNonVar(..) => "nonvar", - &InlinedClauseType::IsPartialString(..) => "is_partial_string", - &InlinedClauseType::IsVar(..) => "var", - } - } - - pub fn from(name: &str, arity: usize) -> Option { - let r1 = temp_v!(1); - let r2 = temp_v!(2); - - let a1 = ArithmeticTerm::Reg(r1); - let a2 = ArithmeticTerm::Reg(r2); - - match (name, arity) { - (">", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, a1, a2)), - ("<", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, a1, a2)), - (">=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,a1, a2)), - ("=<", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, a1, a2)), - ("=\\=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, a1, a2)), - ("=:=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, a1, a2)), - ("atom", 1) => Some(InlinedClauseType::IsAtom(r1)), - ("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)), - ("compound", 1) => Some(InlinedClauseType::IsCompound(r1)), - ("integer", 1) => Some(InlinedClauseType::IsInteger(r1)), - ("rational", 1) => Some(InlinedClauseType::IsRational(r1)), - ("string", 1) => Some(InlinedClauseType::IsString(r1)), - ("float", 1) => Some(InlinedClauseType::IsFloat(r1)), - ("nonvar", 1) => Some(InlinedClauseType::IsNonVar(r1)), - ("var", 1) => Some(InlinedClauseType::IsVar(r1)), - ("is_partial_string", 1) => Some(InlinedClauseType::IsPartialString(r1)), - _ => None - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum CompareNumberQT { - GreaterThan, - LessThan, - GreaterThanOrEqual, - LessThanOrEqual, - NotEqual, - Equal -} - -impl CompareNumberQT { - fn name(self) -> &'static str { - match self { - CompareNumberQT::GreaterThan => ">", - CompareNumberQT::LessThan => "<", - CompareNumberQT::GreaterThanOrEqual => ">=", - CompareNumberQT::LessThanOrEqual => "=<", - CompareNumberQT::NotEqual => "=\\=", - CompareNumberQT::Equal => "=:=" - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum CompareTermQT { - LessThan, - LessThanOrEqual, - Equal, - GreaterThanOrEqual, - GreaterThan, - NotEqual, -} - -impl CompareTermQT { - fn name<'a>(self) -> &'a str { - match self { - CompareTermQT::GreaterThan => "@>", - CompareTermQT::LessThan => "@<", - CompareTermQT::GreaterThanOrEqual => "@>=", - CompareTermQT::LessThanOrEqual => "@=<", - CompareTermQT::NotEqual => "\\=@=", - CompareTermQT::Equal => "=@=" - } - } -} - -// vars of predicate, toplevel offset. Vec is always a vector -// of vars (we get their adjoining cells this way). -pub type JumpStub = Vec; - -#[derive(Clone)] -pub enum QueryTerm { - // register, clause type, subterms, use default call policy. - Clause(Cell, ClauseType, Vec>, bool), - BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. - UnblockedCut(Cell), - GetLevelAndUnify(Cell, Rc), - Jump(JumpStub) -} - -impl QueryTerm { - pub fn set_default_caller(&mut self) { - match self { - &mut QueryTerm::Clause(_, _, _, ref mut use_default_cp) => *use_default_cp = true, - _ => {} - } - } - - pub fn arity(&self) -> usize { - match self { - &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, - &QueryTerm::Jump(ref vars) => vars.len(), - &QueryTerm::GetLevelAndUnify(..) => 1, - } - } -} - -#[derive(Clone)] -pub struct Rule { - pub head: (ClauseName, Vec>, QueryTerm), - pub clauses: Vec -} - -#[derive(Clone)] -pub struct Predicate(pub Vec); - -impl Predicate { - #[inline] - pub fn new() -> Self { - Predicate(vec![]) - } - - #[inline] - pub fn clauses(self) -> Vec { - 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(Clone)] -pub enum PredicateClause { - Fact(Term), - Rule(Rule) -} - -impl PredicateClause { - pub fn first_arg(&self) -> Option<&Term> { - match self { - &PredicateClause::Fact(ref term) => term.first_arg(), - &PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()), - } - } - - pub fn arity(&self) -> usize { - match self { - &PredicateClause::Fact(ref term) => term.arity(), - &PredicateClause::Rule(ref rule) => rule.head.1.len() - } - } - - pub fn name(&self) -> Option { - match self { - &PredicateClause::Fact(ref term) => term.name(), - &PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()), - } - } -} - -pub type ModuleCodeDir = HashMap; - -pub type CodeDir = HashMap; - -pub type TermDir = HashMap)>; - -pub type ModuleDir = HashMap; - -pub type PredicateKey = (ClauseName, usize); // name, arity. - -pub struct CodeRepo { - pub(super) cached_query: Code, - pub(super) goal_expanders: Code, - pub(super) term_expanders: Code, - pub(super) code: Code, - pub(super) in_situ_code: Code, - pub(super) term_dir: TermDir -} - -#[derive(Clone)] -pub struct ModuleDecl { - pub name: ClauseName, - pub exports: Vec -} - -pub struct Module { - pub atom_tbl: TabledData, - pub module_decl: ModuleDecl, - pub code_dir: ModuleCodeDir, - pub op_dir: OpDir, - pub term_expansions: (Predicate, VecDeque), - pub goal_expansions: (Predicate, VecDeque), - pub inserted_expansions: bool // has the module been successfully inserted into toplevel?? -} - -#[derive(Copy, Clone, PartialEq)] -pub enum SystemClauseType { - AbolishClause, - AssertDynamicPredicateToBack, - AssertDynamicPredicateToFront, - CheckCutPoint, - CopyToLiftedHeap, - DeleteAttribute, - DeleteHeadAttribute, - DynamicModuleResolution, - EnqueueAttributeGoal, - EnqueueAttributedVar, - ExpandGoal, - ExpandTerm, - TruncateIfNoLiftedHeapGrowthDiff, - TruncateIfNoLiftedHeapGrowth, - GetAttributedVariableList, - GetAttrVarQueueDelimiter, - GetAttrVarQueueBeyond, - GetBValue, - GetClause, - GetCurrentPredicateList, - GetLiftedHeapFromOffset, - GetLiftedHeapFromOffsetDiff, - GetSCCCleaner, - HeadIsDynamic, - InstallSCCCleaner, - InstallInferenceCounter, - LiftedHeapLength, - ModuleOf, - NoSuchPredicate, - RedoAttrVarBindings, - RemoveCallPolicyCheck, - RemoveInferenceCounter, - RetractClause, - RestoreCutPolicy, - SetCutPoint(RegType), - InferenceLevel, - CleanUpBlock, - EraseBall, - Fail, - GetBall, - GetCurrentBlock, - GetCutPoint, - GetDoubleQuotes, - InstallNewBlock, - ResetBlock, - ReturnFromAttributeGoals, - ReturnFromVerifyAttr, - SetBall, - SetCutPointByDefault(RegType), - SetDoubleQuotes, - SkipMaxList, - Succeed, - TermVariables, - TruncateLiftedHeapTo, - UnwindStack, - WriteTerm -} - -impl SystemClauseType { - pub fn name(&self) -> ClauseName { - match self { - &SystemClauseType::AbolishClause => clause_name!("$abolish_clause"), - &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$asserta"), - &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$assertz"), - &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), - &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), - &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), - &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"), - &SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"), - &SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"), - &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), - &SystemClauseType::ExpandTerm => clause_name!("$expand_term"), - &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"), - &SystemClauseType::TruncateIfNoLiftedHeapGrowth => clause_name!("$truncate_if_no_lh_growth"), - &SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => clause_name!("$truncate_if_no_lh_growth_diff"), - &SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"), - &SystemClauseType::GetAttrVarQueueDelimiter => clause_name!("$get_attr_var_queue_delim"), - &SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"), - &SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"), - &SystemClauseType::GetLiftedHeapFromOffsetDiff => clause_name!("$get_lh_from_offset_diff"), - &SystemClauseType::GetCurrentPredicateList => clause_name!("$get_current_predicate_list"), - &SystemClauseType::GetBValue => clause_name!("$get_b_value"), - &SystemClauseType::GetClause => clause_name!("$get_clause"), - &SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"), - &SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"), - &SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"), - &SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"), - &SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"), - &SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"), - &SystemClauseType::ModuleOf => clause_name!("$module_of"), - &SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"), - &SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"), - &SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"), - &SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"), - &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), - &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"), - &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), - &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), - &SystemClauseType::EraseBall => clause_name!("$erase_ball"), - &SystemClauseType::Fail => clause_name!("$fail"), - &SystemClauseType::GetBall => clause_name!("$get_ball"), - &SystemClauseType::GetCutPoint => clause_name!("$get_cp"), - &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), - &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), - &SystemClauseType::RetractClause => clause_name!("$retract_clause"), - &SystemClauseType::ResetBlock => clause_name!("$reset_block"), - &SystemClauseType::ReturnFromAttributeGoals => clause_name!("$return_from_attribute_goals"), - &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), - &SystemClauseType::SetBall => clause_name!("$set_ball"), - &SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"), - &SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"), - &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), - &SystemClauseType::Succeed => clause_name!("$succeed"), - &SystemClauseType::TermVariables => clause_name!("$term_variables"), - &SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"), - &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), - &SystemClauseType::WriteTerm => clause_name!("$write_term"), - } - } - - pub fn from(name: &str, arity: usize) -> Option { - match (name, arity) { - ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause), - ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront), - ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack), - ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint), - ("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap), - ("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute), - ("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute), - ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution), - ("$enqueue_attribute_goal", 1) => Some(SystemClauseType::EnqueueAttributeGoal), - ("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar), - ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm), - ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal), - ("$truncate_if_no_lh_growth", 1) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth), - ("$truncate_if_no_lh_growth_diff", 2) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff), - ("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList), - ("$get_b_value", 1) => Some(SystemClauseType::GetBValue), - ("$get_clause", 2) => Some(SystemClauseType::GetClause), - ("$get_current_predicate_list", 1) => Some(SystemClauseType::GetCurrentPredicateList), - ("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset), - ("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff), - ("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes), - ("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner), - ("$head_is_dynamic", 1) => Some(SystemClauseType::HeadIsDynamic), - ("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner), - ("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter), - ("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength), - ("$module_of", 2) => Some(SystemClauseType::ModuleOf), - ("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate), - ("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings), - ("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck), - ("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter), - ("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy), - ("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))), - ("$inference_level", 2) => Some(SystemClauseType::InferenceLevel), - ("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock), - ("$erase_ball", 0) => Some(SystemClauseType::EraseBall), - ("$fail", 0) => Some(SystemClauseType::Fail), - ("$get_attr_var_queue_beyond", 2) => Some(SystemClauseType::GetAttrVarQueueBeyond), - ("$get_attr_var_queue_delim", 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter), - ("$get_ball", 1) => Some(SystemClauseType::GetBall), - ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), - ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), - ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), - ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), - ("$retract_clause", 4) => Some(SystemClauseType::RetractClause), - ("$return_from_attribute_goals", 0) => Some(SystemClauseType::ReturnFromAttributeGoals), - ("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr), - ("$set_ball", 1) => Some(SystemClauseType::SetBall), - ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), - ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), - ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), - ("$term_variables", 2) => Some(SystemClauseType::TermVariables), - ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), - ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), - ("$write_term", 4) => Some(SystemClauseType::WriteTerm), - _ => None - } - } -} - -#[derive(Clone, PartialEq)] -pub enum BuiltInClauseType { - AcyclicTerm, - Arg, - Compare, - CompareTerm(CompareTermQT), - CyclicTerm, - CopyTerm, - Eq, - Functor, - Ground, - Is(RegType, ArithmeticTerm), - KeySort, - Nl, - NotEq, - PartialString, - Read, - ReifySwitch, - Sort, -} - -#[derive(Clone, Copy)] -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 - } - } -} - -#[derive(Clone)] -pub enum ClauseType { - BuiltIn(BuiltInClauseType), - CallN, - Hook(CompileTimeHook), - Inlined(InlinedClauseType), - Named(ClauseName, usize, CodeIndex), // name, arity, index. - Op(OpDecl, CodeIndex), - System(SystemClauseType) -} - -impl BuiltInClauseType { - pub fn name(&self) -> ClauseName { - match self { - &BuiltInClauseType::AcyclicTerm => clause_name!("acyclic_term"), - &BuiltInClauseType::Arg => clause_name!("arg"), - &BuiltInClauseType::Compare => clause_name!("compare"), - &BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()), - &BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"), - &BuiltInClauseType::CopyTerm => clause_name!("copy_term"), - &BuiltInClauseType::Eq => clause_name!("=="), - &BuiltInClauseType::Functor => clause_name!("functor"), - &BuiltInClauseType::Ground => clause_name!("ground"), - &BuiltInClauseType::Is(..) => clause_name!("is"), - &BuiltInClauseType::KeySort => clause_name!("keysort"), - &BuiltInClauseType::Nl => clause_name!("nl"), - &BuiltInClauseType::NotEq => clause_name!("\\=="), - &BuiltInClauseType::PartialString => clause_name!("partial_string"), - &BuiltInClauseType::Read => clause_name!("read"), - &BuiltInClauseType::ReifySwitch => clause_name!("$reify_switch"), - &BuiltInClauseType::Sort => clause_name!("sort"), - } - } - - pub fn arity(&self) -> usize { - match self { - &BuiltInClauseType::AcyclicTerm => 1, - &BuiltInClauseType::Arg => 3, - &BuiltInClauseType::Compare => 2, - &BuiltInClauseType::CompareTerm(_) => 2, - &BuiltInClauseType::CyclicTerm => 1, - &BuiltInClauseType::CopyTerm => 2, - &BuiltInClauseType::Eq => 2, - &BuiltInClauseType::Functor => 3, - &BuiltInClauseType::Ground => 1, - &BuiltInClauseType::Is(..) => 2, - &BuiltInClauseType::KeySort => 2, - &BuiltInClauseType::NotEq => 2, - &BuiltInClauseType::Nl => 0, - &BuiltInClauseType::PartialString => 1, - &BuiltInClauseType::Read => 1, - &BuiltInClauseType::ReifySwitch => 3, - &BuiltInClauseType::Sort => 2, - } - } - - pub fn from(name: &str, arity: usize) -> Option { - match (name, arity) { - ("acyclic_term", 1) => Some(BuiltInClauseType::AcyclicTerm), - ("arg", 3) => Some(BuiltInClauseType::Arg), - ("compare", 3) => Some(BuiltInClauseType::Compare), - ("cyclic_term", 1) => Some(BuiltInClauseType::CyclicTerm), - ("@>", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThan)), - ("@<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThan)), - ("@>=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual)), - ("@=<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)), - ("\\=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::NotEqual)), - ("=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::Equal)), - ("copy_term", 2) => Some(BuiltInClauseType::CopyTerm), - ("==", 2) => Some(BuiltInClauseType::Eq), - ("functor", 3) => Some(BuiltInClauseType::Functor), - ("ground", 1) => Some(BuiltInClauseType::Ground), - ("is", 2) => Some(BuiltInClauseType::Is(temp_v!(1), ArithmeticTerm::Reg(temp_v!(2)))), - ("keysort", 2) => Some(BuiltInClauseType::KeySort), - ("nl", 0) => Some(BuiltInClauseType::Nl), - ("\\==", 2) => Some(BuiltInClauseType::NotEq), - ("partial_string", 2) => Some(BuiltInClauseType::PartialString), - ("read", 1) => Some(BuiltInClauseType::Read), - ("$reify_switch", 3) => Some(BuiltInClauseType::ReifySwitch), - ("sort", 2) => Some(BuiltInClauseType::Sort), - _ => None - } - } -} - -impl ClauseType { - pub fn spec(&self) -> Option<(usize, Specifier)> { - match self { - &ClauseType::Op(ref op_decl, _) => - Some((op_decl.0, op_decl.1)), - &ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) - | &ClauseType::BuiltIn(BuiltInClauseType::Is(..)) - | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_)) - | &ClauseType::BuiltIn(BuiltInClauseType::NotEq) - | &ClauseType::BuiltIn(BuiltInClauseType::Eq) => - Some((700, XFX)), - _ => None - } - } - - pub fn name(&self) -> ClauseName { - match self { - &ClauseType::CallN => clause_name!("call"), - &ClauseType::BuiltIn(ref built_in) => built_in.name(), - &ClauseType::Hook(ref hook) => hook.name(), - &ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()), - &ClauseType::Op(ref op_decl, ..) => op_decl.name(), - &ClauseType::Named(ref name, ..) => name.clone(), - &ClauseType::System(ref system) => system.name(), - } - } - - pub fn from(name: ClauseName, arity: usize, spec: Option<(usize, Specifier)>) -> Self { - InlinedClauseType::from(name.as_str(), arity) - .map(ClauseType::Inlined) - .unwrap_or_else(|| { - BuiltInClauseType::from(name.as_str(), arity) - .map(ClauseType::BuiltIn) - .unwrap_or_else(|| { - SystemClauseType::from(name.as_str(), arity) - .map(ClauseType::System) - .unwrap_or_else(|| { - if let Some(spec) = spec { - let op_decl = OpDecl(spec.0, spec.1, name); - ClauseType::Op(op_decl, CodeIndex::default()) - } else if name.as_str() == "call" { - ClauseType::CallN - } else { - ClauseType::Named(name, arity, CodeIndex::default()) - } - }) - }) - }) - } -} - -impl From for ClauseType { - fn from(inlined_ct: InlinedClauseType) -> Self { - ClauseType::Inlined(inlined_ct) - } -} +use std::collections::{HashMap, VecDeque}; pub enum ChoiceInstruction { DefaultRetryMeElse(usize), @@ -673,21 +41,16 @@ impl IndexedChoiceInstruction { } } } -#[derive(Clone, PartialEq)] -pub enum ArithmeticTerm { - Reg(RegType), - Interm(usize), - Number(Number) -} -impl ArithmeticTerm { - pub fn interm_or(&self, interm: usize) -> usize { - if let &ArithmeticTerm::Interm(interm) = self { - interm - } else { - interm - } - } +pub enum Line { + Arithmetic(ArithmeticInstruction), + Choice(ChoiceInstruction), + Control(ControlInstruction), + Cut(CutInstruction), + Fact(FactInstruction), + Indexing(IndexingInstruction), + IndexedChoice(IndexedChoiceInstruction), + Query(QueryInstruction) } #[derive(Clone)] @@ -774,862 +137,8 @@ pub enum QueryInstruction { pub type CompiledFact = Vec; -pub enum Line { - Arithmetic(ArithmeticInstruction), - Choice(ChoiceInstruction), - Control(ControlInstruction), - Cut(CutInstruction), - Fact(FactInstruction), - Indexing(IndexingInstruction), - IndexedChoice(IndexedChoiceInstruction), - Query(QueryInstruction) -} - pub type ThirdLevelIndex = Vec; pub type Code = Vec; pub type CodeDeque = VecDeque; - -#[derive(Clone, PartialEq, Eq, Hash)] -pub enum Addr { - AttrVar(usize), - Con(Constant), - Lis(usize), - HeapCell(usize), - StackCell(usize, usize), - Str(usize) -} - -impl PartialEq for Addr { - fn eq(&self, r: &Ref) -> bool { - self.as_var() == Some(*r) - } -} - -// for use in MachineState::bind. -impl PartialOrd for Addr { - fn partial_cmp(&self, r: &Ref) -> Option { - match self { - &Addr::StackCell(fr, sc) => - match *r { - Ref::AttrVar(_) | Ref::HeapCell(_) => - Some(Ordering::Greater), - Ref::StackCell(fr1, sc1) => - if fr1 < fr || (fr1 == fr && sc1 < sc) { - Some(Ordering::Greater) - } else if fr1 == fr && sc1 == sc { - Some(Ordering::Equal) - } else { - Some(Ordering::Less) - } - }, - &Addr::HeapCell(h) | &Addr::AttrVar(h) => - match r { - &Ref::StackCell(..) => Some(Ordering::Less), - &Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1) - }, - _ => None - } - } -} - -impl Addr { - pub fn is_ref(&self) -> bool { - match self { - &Addr::AttrVar(_) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true, - _ => false - } - } - - pub fn as_var(&self) -> Option { - match self { - &Addr::AttrVar(h) => Some(Ref::AttrVar(h)), - &Addr::HeapCell(h) => Some(Ref::HeapCell(h)), - &Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)), - _ => None - } - } - - pub fn is_protected(&self, e: usize) -> bool { - match self { - &Addr::StackCell(addr, _) if addr >= e => false, - _ => true - } - } -} - -impl Add for Addr { - type Output = Addr; - - fn add(self, rhs: usize) -> Self::Output { - match self { - Addr::Lis(a) => Addr::Lis(a + rhs), - Addr::AttrVar(h) => Addr::AttrVar(h + rhs), - Addr::HeapCell(h) => Addr::HeapCell(h + rhs), - Addr::Str(s) => Addr::Str(s + rhs), - _ => self - } - } -} - -impl Sub for Addr { - type Output = Addr; - - fn sub(self, rhs: usize) -> Self::Output { - match self { - Addr::Lis(a) => Addr::Lis(a - rhs), - Addr::AttrVar(h) => Addr::AttrVar(h - rhs), - Addr::HeapCell(h) => Addr::HeapCell(h - rhs), - Addr::Str(s) => Addr::Str(s - rhs), - _ => self - } - } -} - -impl SubAssign for Addr { - fn sub_assign(&mut self, rhs: usize) { - *self = self.clone() - rhs; - } -} - -impl From for Addr { - fn from(r: Ref) -> Self { - match r { - Ref::AttrVar(h) => Addr::AttrVar(h), - Ref::HeapCell(h) => Addr::HeapCell(h), - Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) - } - } -} - -#[derive(Clone, Copy, Hash, Eq, PartialEq)] -pub enum Ref { - AttrVar(usize), - HeapCell(usize), - StackCell(usize, usize) -} - -impl Ref { - pub fn as_addr(self) -> Addr { - match self { - Ref::AttrVar(h) => Addr::AttrVar(h), - Ref::HeapCell(h) => Addr::HeapCell(h), - Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) - } - } -} - -#[derive(Clone)] -pub enum TrailRef { - Ref(Ref), - AttrVarLink(usize, Addr) -} - -impl From for TrailRef { - fn from(r: Ref) -> Self { - TrailRef::Ref(r) - } -} - -#[derive(Clone, PartialEq)] -pub enum HeapCellValue { - Addr(Addr), - NamedStr(usize, ClauseName, Option<(usize, Specifier)>), // arity, name, precedence/Specifier if it has one. -} - -impl HeapCellValue { - pub fn as_addr(&self, focus: usize) -> Addr { - match self { - &HeapCellValue::Addr(ref a) => a.clone(), - &HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus) - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum IndexPtr { - Undefined, - Index(usize), -} - -#[derive(Clone)] -pub struct CodeIndex(pub Rc>); - -impl CodeIndex { - #[inline] - pub fn is_undefined(&self) -> bool { - let index_ptr = &self.0.borrow().0; - - if let &IndexPtr::Undefined = index_ptr { - true - } else { - false - } - } - - #[inline] - pub fn module_name(&self) -> ClauseName { - self.0.borrow().1.clone() - } -} - -#[derive(Clone)] -pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName); - -impl ModuleCodeIndex { - pub fn local(&self) -> Option { - match self.0 { - IndexPtr::Index(i) => Some(i), - _ => None - } - } -} - -impl From for CodeIndex { - fn from(value: ModuleCodeIndex) -> Self { - CodeIndex(Rc::new(RefCell::new((value.0, value.1)))) - } -} - -impl Default for CodeIndex { - fn default() -> Self { - CodeIndex(Rc::new(RefCell::new((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(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, new_addr: Addr) { - match self { - DynamicAssertPlace::Back => addrs.push_back(new_addr), - DynamicAssertPlace::Front => addrs.push_front(new_addr) - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum DynamicTransactionType { - Abolish, - Assert(DynamicAssertPlace), - Retract // dynamic index of the clause to remove. -} - -#[derive(Clone, PartialEq)] -pub enum CodePtr { - BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call. - CallN(usize, LocalCodePtr), // arity, local. - Local(LocalCodePtr), - DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer. - VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir. -} - -impl CodePtr { - pub fn local(&self) -> LocalCodePtr { - match self { - &CodePtr::BuiltInClause(_, ref local) - | &CodePtr::CallN(_, ref local) - | &CodePtr::Local(ref local) => local.clone(), - &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p), - &CodePtr::DynamicTransaction(_, p) => p - } - } -} - -#[derive(Copy, Clone, PartialEq)] -pub enum LocalCodePtr { - DirEntry(usize), // offset. - InSituDirEntry(usize), - TopLevel(usize, usize), // chunk_num, offset. - UserGoalExpansion(usize), - UserTermExpansion(usize) -} - -impl LocalCodePtr { - pub fn assign_if_local(&mut self, cp: CodePtr) { - match cp { - CodePtr::Local(local) => *self = local, - _ => {} - } - } -} - -impl PartialOrd for CodePtr { - fn partial_cmp(&self, other: &CodePtr) -> Option { - match (self, other) { - (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2), - _ => Some(Ordering::Greater) - } - } -} - -impl PartialOrd for LocalCodePtr { - fn partial_cmp(&self, other: &LocalCodePtr) -> Option { - match (self, other) { - (&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2)) - | (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(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), - (_, &LocalCodePtr::TopLevel(_, _)) => - Some(Ordering::Less), - _ => Some(Ordering::Greater) - } - } -} - -impl Default for CodePtr { - fn default() -> Self { - CodePtr::Local(LocalCodePtr::default()) - } -} - -impl Default for LocalCodePtr { - fn default() -> Self { - LocalCodePtr::TopLevel(0, 0) - } -} - -impl Add for LocalCodePtr { - type Output = LocalCodePtr; - - fn add(self, rhs: usize) -> Self::Output { - match self { - LocalCodePtr::InSituDirEntry(p) => LocalCodePtr::InSituDirEntry(p + rhs), - LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs), - LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs), - LocalCodePtr::UserTermExpansion(p) => LocalCodePtr::UserTermExpansion(p + rhs), - LocalCodePtr::UserGoalExpansion(p) => LocalCodePtr::UserGoalExpansion(p + rhs), - } - } -} - -impl AddAssign for LocalCodePtr { - fn add_assign(&mut self, rhs: usize) { - match self { - &mut LocalCodePtr::InSituDirEntry(ref mut p) - | &mut LocalCodePtr::UserGoalExpansion(ref mut p) - | &mut LocalCodePtr::UserTermExpansion(ref mut p) - | &mut LocalCodePtr::DirEntry(ref mut p) - | &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs - } - } -} - -impl Add for CodePtr { - type Output = CodePtr; - - fn add(self, rhs: usize) -> Self::Output { - match self { - p @ CodePtr::VerifyAttrInterrupt(_) - | p @ CodePtr::DynamicTransaction(..) => p, - CodePtr::Local(local) => CodePtr::Local(local + rhs), - CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs) - } - } -} - -impl AddAssign for CodePtr { - fn add_assign(&mut self, rhs: usize) { - match self { - &mut CodePtr::VerifyAttrInterrupt(_) => {}, - &mut CodePtr::Local(ref mut local) => *local += rhs, - _ => *self = CodePtr::Local(self.local() + rhs) - } - } -} - -pub type Registers = Vec; - -pub enum TermIterState<'a> { - AnonVar(Level), - Constant(Level, &'a Cell, &'a Constant), - Clause(Level, usize, &'a Cell, ClauseType, &'a Vec>), - InitialCons(Level, &'a Cell, &'a Term, &'a Term), - FinalCons(Level, &'a Cell, &'a Term, &'a Term), - Var(Level, &'a Cell, Rc) -} - -impl<'a> TermIterState<'a> { - pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { - match term { - &Term::AnonVar => - TermIterState::AnonVar(lvl), - &Term::Clause(ref cell, ref name, ref subterms, spec) => { - let ct = if let Some(spec) = spec { - let op_decl = OpDecl(spec.0, spec.1, name.clone()); - ClauseType::Op(op_decl, CodeIndex::default()) - } else { - ClauseType::Named(name.clone(), subterms.len(), CodeIndex::default()) - }; - - TermIterState::Clause(lvl, 0, cell, ct, subterms) - }, - &Term::Cons(ref cell, ref head, ref tail) => - TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()), - &Term::Constant(ref cell, ref constant) => - TermIterState::Constant(lvl, cell, constant), - &Term::Var(ref cell, ref var) => - TermIterState::Var(lvl, cell, var.clone()) - } - } -} - -impl Module { - pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData) -> Self { - Module { module_decl, atom_tbl, - term_expansions: (Predicate::new(), VecDeque::from(vec![])), - goal_expansions: (Predicate::new(), VecDeque::from(vec![])), - code_dir: ModuleCodeDir::new(), - op_dir: default_op_dir(), - inserted_expansions: false } - } - - pub fn dump_expansions(&self, code_repo: &mut CodeRepo, flags: MachineFlags) - -> 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.term_expansions.0).0.iter().cloned()); - te.1.extend(self.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.goal_expansions.0).0.iter().cloned()); - ge.1.extend(self.goal_expansions.1.iter().cloned()); - } - - code_repo.compile_hook(CompileTimeHook::TermExpansion, flags)?; - code_repo.compile_hook(CompileTimeHook::GoalExpansion, flags)?; - - Ok(()) - } -} - -pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir { - code_dir.into_iter() - .map(|(k, code_idx)| { - let (idx, module_name) = code_idx.0.borrow().clone(); - (k, ModuleCodeIndex(idx, module_name)) - }) - .collect() -} - -pub trait SubModuleUser { - fn atom_tbl(&self) -> TabledData; - fn op_dir(&mut self) -> &mut OpDir; - fn remove_code_index(&mut self, PredicateKey); - fn get_code_index(&self, PredicateKey, ClauseName) -> Option; - - fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex); - - fn remove_module(&mut self, mod_name: ClauseName, module: &Module) { - for (name, arity) in module.module_decl.exports.iter().cloned() { - 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.op_dir().get(&(name.clone(), Fixity::In)).cloned() - { - 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.op_dir().get(&(name.clone(), Fixity::Pre)).cloned() - { - if mod_name == module.module_decl.name { - self.op_dir().remove(&(name.clone(), Fixity::Pre)); - } - } - - if let Some((_, _, mod_name)) = self.op_dir().get(&(name.clone(), Fixity::Post)).cloned() - { - if mod_name == module.module_decl.name { - self.op_dir().remove(&(name.clone(), Fixity::Post)); - } - } - } - }, - _ => {} - }; - } - } - - // returns true on successful import. - fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool { - let name = name.defrock_brackets(); - let mut found_op = false; - - { - let mut insert_op_dir = |fix| { - if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) { - self.op_dir().insert((name.clone(), fix), op_data.clone()); - found_op = true; - } - }; - - if arity == 1 { - insert_op_dir(Fixity::Pre); - insert_op_dir(Fixity::Post); - } else if arity == 2 { - insert_op_dir(Fixity::In); - } - } - - if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) { - let name = name.with_table(submodule.atom_tbl.clone()); - - let mut atom_tbl = self.atom_tbl(); - atom_tbl.borrow_mut().insert(name.to_rc()); - - self.insert_dir_entry(name, arity, code_data.clone()); - true - } else { - found_op - } - } - - fn use_qualified_module(&mut self, &mut CodeRepo, MachineFlags, &Module, &Vec) - -> Result<(), SessionError>; - fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module) - -> Result<(), SessionError>; -} - -pub fn use_qualified_module(user: &mut User, submodule: &Module, exports: &Vec) - -> Result<(), SessionError> - where User: SubModuleUser -{ - for (name, arity) in exports.iter().cloned() { - if !submodule.module_decl.exports.contains(&(name.clone(), arity)) { - continue; - } - - if !user.import_decl(name, arity, submodule) { - return Err(SessionError::ModuleDoesNotContainExport); - } - } - - Ok(()) -} - -pub fn use_module(user: &mut User, submodule: &Module) - -> Result<(), SessionError> -{ - for (name, arity) in submodule.module_decl.exports.iter().cloned() { - if !user.import_decl(name, arity, submodule) { - return Err(SessionError::ModuleDoesNotContainExport); - } - } - - Ok(()) -} - -impl SubModuleUser for Module { - fn atom_tbl(&self) -> TabledData { - self.atom_tbl.clone() - } - - fn op_dir(&mut self) -> &mut OpDir { - &mut self.op_dir - } - - fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option { - self.code_dir.get(&key).cloned().map(CodeIndex::from) - } - - fn remove_code_index(&mut self, key: PredicateKey) { - self.code_dir.remove(&key); - } - - fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) { - self.code_dir.insert((name, arity), idx); - } - - fn use_qualified_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module, - exports: &Vec) - -> Result<(), SessionError> - { - use_qualified_module(self, submodule, exports)?; - - (self.term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned()); - self.term_expansions.1.extend(submodule.term_expansions.1.iter().cloned()); - - (self.goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned()); - self.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.term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned()); - self.term_expansions.1.extend(submodule.term_expansions.1.iter().cloned()); - - (self.goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned()); - self.goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned()); - - Ok(()) - } -} - -#[derive(Clone)] -pub enum Declaration { - Dynamic(ClauseName, usize), // name, arity - Hook(CompileTimeHook, PredicateClause, VecDeque), - Module(ModuleDecl), - NonCountedBacktracking(ClauseName, usize), // name, arity - Op(OpDecl), - UseModule(ClauseName), - UseQualifiedModule(ClauseName, Vec) -} - -impl Declaration { - #[inline] - pub fn is_module_decl(&self) -> bool { - if let &Declaration::Module(_) = self { true } else { false } - } -} - -#[derive(Clone)] -pub enum TopLevel { - Declaration(Declaration), - Fact(Term), - Predicate(Predicate), - Query(Vec), - Rule(Rule), -} - -impl TopLevel { - pub fn name(&self) -> Option { - match self { - &TopLevel::Declaration(_) => None, - &TopLevel::Fact(ref term) => term.name(), - &TopLevel::Predicate(ref clauses) => - clauses.0.first().and_then(|ref term| term.name()), - &TopLevel::Query(_) => None, - &TopLevel::Rule(Rule { ref head, .. }) => - Some(head.0.clone()) - } - } - - pub fn arity(&self) -> usize { - match self { - &TopLevel::Declaration(_) => 0, - &TopLevel::Fact(ref term) => term.arity(), - &TopLevel::Predicate(ref clauses) => - clauses.0.first().map(|t| t.arity()).unwrap_or(0), - &TopLevel::Query(_) => 0, - &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() - } - } -} - -#[derive(Clone, Copy)] -pub enum Level { - Deep, Root, Shallow -} - -impl Level { - pub fn child_level(self) -> Level { - match self { - Level::Root => Level::Shallow, - _ => Level::Deep - } - } -} - -// labeled with chunk numbers. -pub enum VarStatus { - Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _) -} - -pub type OccurrenceSet = BTreeSet<(GenContext, usize)>; - -// Perm: 0 initially, a stack register once processed. -// Temp: labeled with chunk_num and temp offset (unassigned if 0). -pub enum VarData { - Perm(usize), Temp(usize, usize, TempVarData) -} - -impl VarData { - pub fn as_reg_type(&self) -> RegType { - match self { - &VarData::Temp(_, r, _) => RegType::Temp(r), - &VarData::Perm(r) => RegType::Perm(r) - } - } -} - -pub struct TempVarData { - pub last_term_arity: usize, - pub use_set: OccurrenceSet, - pub no_use_set: BTreeSet, - pub conflict_set: BTreeSet -} - -impl TempVarData { - pub fn new(last_term_arity: usize) -> Self { - TempVarData { - last_term_arity: last_term_arity, - use_set: BTreeSet::new(), - no_use_set: BTreeSet::new(), - conflict_set: BTreeSet::new() - } - } - - pub fn uses_reg(&self, reg: usize) -> bool { - for &(_, nreg) in self.use_set.iter() { - if reg == nreg { - return true; - } - } - - return false; - } - - pub fn populate_conflict_set(&mut self) { - if self.last_term_arity > 0 { - let arity = self.last_term_arity; - let mut conflict_set : BTreeSet = (1..arity).collect(); - - for &(_, reg) in self.use_set.iter() { - conflict_set.remove(®); - } - - self.conflict_set = conflict_set; - } - } -} - -pub type HeapVarDict = HashMap, Addr>; -pub type AllocVarDict = HashMap, VarData>; - -pub enum SessionError { - CannotOverwriteBuiltIn(ClauseName), - CannotOverwriteImport(ClauseName), - ModuleDoesNotContainExport, - ModuleNotFound, - NamelessEntry, - OpIsInfixAndPostFix, - ParserError(ParserError), - QueryFailure, - QueryFailureWithException(ClauseName), - UserPrompt -} - -pub enum EvalSession { - EntrySuccess, - Error(SessionError), - InitialQuerySuccess(AllocVarDict, HeapVarDict), - SubsequentQuerySuccess, -} - -impl From for EvalSession { - fn from(err: SessionError) -> Self { - EvalSession::Error(err) - } -} - -impl From for SessionError { - fn from(err: ParserError) -> Self { - SessionError::ParserError(err) - } -} - -impl From for EvalSession { - fn from(err: ParserError) -> Self { - EvalSession::from(SessionError::ParserError(err)) - } -} - -#[derive(Clone)] -pub struct OpDecl(pub usize, pub Specifier, pub ClauseName); - -impl OpDecl { - #[inline] - pub fn name(&self) -> ClauseName { - self.2.clone() - } - - pub fn arity(&self) -> usize { - let spec = self.1; - - if (spec | XFX != 0) || (spec | XFY != 0) || (spec | YFX != 0) { - 2 - } else { - 1 - } - } - - pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), SessionError> - { - let (prec, spec, name) = (self.0, self.1, self.2.clone()); - - if is_infix!(spec) { - match op_dir.get(&(name.clone(), Fixity::Post)) { - Some(_) => return Err(SessionError::OpIsInfixAndPostFix), - _ => {} - }; - } - - if is_postfix!(spec) { - match op_dir.get(&(name.clone(), Fixity::In)) { - Some(_) => return Err(SessionError::OpIsInfixAndPostFix), - _ => {} - }; - } - - if prec > 0 { - match spec { - XFY | XFX | YFX => op_dir.insert((name.clone(), Fixity::In), - (spec, prec, module.clone())), - XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec, module.clone())), - FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec, prec, module.clone())), - _ => None - }; - } else { - op_dir.remove(&(name.clone(), Fixity::Pre)); - op_dir.remove(&(name.clone(), Fixity::In)); - op_dir.remove(&(name.clone(), Fixity::Post)); - } - - Ok(()) - } -} diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index 6b2c83b1..ce815249 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -1,6 +1,9 @@ use prolog_parser::ast::*; -use prolog::instructions::*; +use prolog::clause_types::*; +use prolog::forms::*; +use prolog::machine::machine_indices::*; + use std::cell::Cell; use std::collections::VecDeque; use std::iter::*; @@ -28,6 +31,40 @@ impl<'a> TermRef<'a> { } } +pub enum TermIterState<'a> { + AnonVar(Level), + Constant(Level, &'a Cell, &'a Constant), + Clause(Level, usize, &'a Cell, ClauseType, &'a Vec>), + InitialCons(Level, &'a Cell, &'a Term, &'a Term), + FinalCons(Level, &'a Cell, &'a Term, &'a Term), + Var(Level, &'a Cell, Rc) +} + +impl<'a> TermIterState<'a> { + pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { + match term { + &Term::AnonVar => + TermIterState::AnonVar(lvl), + &Term::Clause(ref cell, ref name, ref subterms, spec) => { + let ct = if let Some(spec) = spec { + let op_decl = OpDecl(spec.0, spec.1, name.clone()); + ClauseType::Op(op_decl, CodeIndex::default()) + } else { + ClauseType::Named(name.clone(), subterms.len(), CodeIndex::default()) + }; + + TermIterState::Clause(lvl, 0, cell, ct, subterms) + }, + &Term::Cons(ref cell, ref head, ref tail) => + TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()), + &Term::Constant(ref cell, ref constant) => + TermIterState::Constant(lvl, cell, constant), + &Term::Var(ref cell, ref var) => + TermIterState::Var(lvl, cell, var.clone()) + } + } +} + pub struct QueryIterator<'a> { state_stack: Vec>, } diff --git a/src/prolog/and_stack.rs b/src/prolog/machine/and_stack.rs similarity index 97% rename from src/prolog/and_stack.rs rename to src/prolog/machine/and_stack.rs index 368ada0f..747fc532 100644 --- a/src/prolog/and_stack.rs +++ b/src/prolog/machine/and_stack.rs @@ -1,4 +1,4 @@ -use prolog::instructions::*; +use prolog::machine::machine_indices::*; use std::ops::{Index, IndexMut}; use std::vec::Vec; diff --git a/src/prolog/machine/code_repo.rs b/src/prolog/machine/code_repo.rs new file mode 100644 index 00000000..23884595 --- /dev/null +++ b/src/prolog/machine/code_repo.rs @@ -0,0 +1,124 @@ +use prolog_parser::ast::MachineFlags; + +use prolog::clause_types::*; +use prolog::codegen::*; +use prolog::debray_allocator::*; +use prolog::forms::*; +use prolog::instructions::*; +use prolog::machine::compile::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; + +use std::collections::VecDeque; + +pub struct CodeRepo { + pub(super) cached_query: Code, + pub(super) goal_expanders: Code, + pub(super) term_expanders: Code, + pub(super) code: Code, + pub(super) in_situ_code: Code, + pub(super) term_dir: TermDir +} + +impl CodeRepo { + #[inline] + pub(super) fn new() -> Self { + CodeRepo { + cached_query: vec![], + goal_expanders: Code::new(), + term_expanders: Code::new(), + code: Code::new(), + in_situ_code: Code::new(), + term_dir: TermDir::new() + } + } + + #[inline] + pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) { + self.term_dir.get(&key) + .map(|entry| ((entry.0).0.len(), entry.1.len())) + .unwrap_or((0,0)) + } + + #[inline] + pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize) + -> (Predicate, VecDeque) + { + self.term_dir.get_mut(&key) + .map(|entry| (Predicate((entry.0).0.drain(len ..).collect()), + entry.1.drain(queue_len ..).collect())) + .unwrap_or((Predicate::new(), VecDeque::from(vec![]))) + } + + pub fn add_in_situ_result(&mut self, result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir, + flags: MachineFlags) + -> 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 p = self.in_situ_code.len(); + in_situ_code_dir.insert((name, arity), p); + + let mut cg = CodeGenerator::::new(true, flags); + // clone the decl to avoid the need to wipe its register cells later. + let mut decl_code = cg.compile_predicate(&decl.0.clone())?; + + compile_appendix(&mut decl_code, queue, true, flags)?; + + self.in_situ_code.extend(decl_code.into_iter()); + Ok(()) + } + + #[inline] + pub(super) + fn size_of_cached_query(&self) -> usize { + self.cached_query.len() + } + + pub(super) + fn lookup_instr<'a>(&'a self, last_call: bool, p: &CodePtr) -> Option> + { + match p { + &CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => + if p < self.goal_expanders.len() { + Some(RefOrOwned::Borrowed(&self.goal_expanders[p])) + } else { + None + }, + &CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => + if p < self.term_expanders.len() { + 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::BuiltInClause(ref built_in, _) => { + let call_clause = call_clause!(ClauseType::BuiltIn(built_in.clone()), + built_in.arity(), + 0, last_call); + Some(RefOrOwned::Owned(call_clause)) + }, + &CodePtr::CallN(arity, _) => { + let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call); + Some(RefOrOwned::Owned(call_clause)) + }, + &CodePtr::VerifyAttrInterrupt(p) => + Some(RefOrOwned::Borrowed(&self.code[p])), + &CodePtr::DynamicTransaction(..) => + None + } + } +} diff --git a/src/prolog/compile.rs b/src/prolog/machine/compile.rs similarity index 98% rename from src/prolog/compile.rs rename to src/prolog/machine/compile.rs index 727f70d5..91882632 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/machine/compile.rs @@ -2,11 +2,14 @@ use prolog_parser::ast::*; use prolog_parser::tabled_rc::TabledData; use prolog::instructions::*; -use prolog::debray_allocator::*; use prolog::codegen::*; +use prolog::debray_allocator::*; +use prolog::forms::*; use prolog::machine::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; use prolog::machine::term_expansion::{ExpansionAdditionResult}; -use prolog::toplevel::*; +use prolog::machine::toplevel::*; use std::cell::Cell; use std::collections::{HashMap, HashSet, VecDeque}; @@ -269,7 +272,6 @@ impl ListingCompiler { let mut code = vec![]; let mut pi_to_loc = HashMap::new(); - // the name of this function is misleading. first we generate the clause code.. for ((name, arity), heads_and_tails) in dynamic_clause_map { if heads_and_tails.is_empty() { continue; @@ -292,10 +294,8 @@ impl ListingCompiler { code.extend(decl_code.into_iter()); } - // now that we've reached this point without error, we are free to add to the WAM. wam.code_repo.code.extend(code.into_iter()); - // ... then we add it to the wam. for ((name, arity), p) in pi_to_loc { let entry = wam.indices.dynamic_code_dir.entry((name, arity)) .or_insert(DynamicPredicateInfo::default()); @@ -451,7 +451,7 @@ impl ListingCompiler { fn gather_items(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore) -> Result { - let flags = wam.machine_flags(); + let flags = wam.machine_flags(); let atom_tbl = wam.indices.atom_tbl.clone(); let mut worker = TopLevelBatchWorker::new(src, atom_tbl.clone(), flags, &mut wam.indices, &mut wam.policies, diff --git a/src/prolog/copier.rs b/src/prolog/machine/copier.rs similarity index 98% rename from src/prolog/copier.rs rename to src/prolog/machine/copier.rs index d3db0fef..edb54042 100644 --- a/src/prolog/copier.rs +++ b/src/prolog/machine/copier.rs @@ -1,5 +1,5 @@ -use prolog::and_stack::*; -use prolog::instructions::*; +use prolog::machine::and_stack::*; +use prolog::machine::machine_indices::*; use std::ops::IndexMut; diff --git a/src/prolog/machine/dynamic_database.rs b/src/prolog/machine/dynamic_database.rs index f47fcfd1..4fe01ad6 100644 --- a/src/prolog/machine/dynamic_database.rs +++ b/src/prolog/machine/dynamic_database.rs @@ -1,9 +1,8 @@ use prolog_parser::ast::*; -use prolog::compile::*; use prolog::heap_print::*; -use prolog::instructions::*; use prolog::machine::*; +use prolog::machine::compile::*; use prolog::machine::machine_errors::*; use prolog::num::ToPrimitive; diff --git a/src/prolog/heap.rs b/src/prolog/machine/heap.rs similarity index 97% rename from src/prolog/heap.rs rename to src/prolog/machine/heap.rs index 115e4e3a..b5141f08 100644 --- a/src/prolog/heap.rs +++ b/src/prolog/machine/heap.rs @@ -1,6 +1,6 @@ use prolog_parser::ast::*; -use prolog::instructions::*; +use prolog::machine::machine_indices::*; use std::ops::{Index, IndexMut}; diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 4c019af8..5e7d2af9 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -1,6 +1,6 @@ use prolog_parser::ast::*; -use prolog::instructions::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; use prolog::num::bigint::BigInt; @@ -81,26 +81,26 @@ impl MachineError { pub(super) fn permission_error(err: PermissionError, pred_str: ClauseName) -> Self { let pred_str = HeapCellValue::Addr(Addr::Con(Constant::Atom(pred_str, None))); - + let err = vec![heap_atom!(err.as_str()), pred_str]; let mut stub = functor!("permission_error", 2); - + stub.extend(err.into_iter()); MachineError { stub, from: ErrorProvenance::Constructed } } - + pub(super) fn syntax_error(h: usize, err: ParserError) -> Self { - let err = vec![heap_atom!(err.as_str())]; + let err = vec![heap_atom!(err.as_str())]; let mut stub = if err.len() == 1 { - functor!("syntax_error", 1) + functor!("syntax_error", 1) } else { functor!("syntax_error", 1, [heap_str!(h + 2)]) }; - + stub.extend(err.into_iter()); - + MachineError { stub, from: ErrorProvenance::Constructed } } @@ -153,7 +153,7 @@ impl PermissionError { } } } - + // from 7.12.2 b) of 13211-1:1995 #[derive(Clone, Copy)] pub enum ValidType { @@ -325,7 +325,7 @@ impl MachineState { // see 8.4.4 of Draft Technical Corrigendum 2. pub(super) fn check_keysort_errors(&self) -> CallResult { - let stub = MachineError::functor_stub(clause_name!("keysort"), 2); + let stub = MachineError::functor_stub(clause_name!("keysort"), 2); let pairs = self.store(self.deref(self[temp_v!(1)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone())); @@ -366,3 +366,41 @@ impl MachineState { self.unwind_stack(); } } + +pub enum SessionError { + CannotOverwriteBuiltIn(ClauseName), + CannotOverwriteImport(ClauseName), + ModuleDoesNotContainExport, + ModuleNotFound, + NamelessEntry, + OpIsInfixAndPostFix, + ParserError(ParserError), + QueryFailure, + QueryFailureWithException(ClauseName), + UserPrompt +} + +pub enum EvalSession { + EntrySuccess, + Error(SessionError), + InitialQuerySuccess(AllocVarDict, HeapVarDict), + SubsequentQuerySuccess, +} + +impl From for EvalSession { + fn from(err: SessionError) -> Self { + EvalSession::Error(err) + } +} + +impl From for SessionError { + fn from(err: ParserError) -> Self { + SessionError::ParserError(err) + } +} + +impl From for EvalSession { + fn from(err: ParserError) -> Self { + EvalSession::from(SessionError::ParserError(err)) + } +} diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs new file mode 100644 index 00000000..26db373b --- /dev/null +++ b/src/prolog/machine/machine_indices.rs @@ -0,0 +1,533 @@ +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; + +use prolog::clause_types::*; +use prolog::fixtures::*; +use prolog::forms::*; + +use std::cell::RefCell; +use std::cmp::Ordering; +use std::collections::{HashMap, VecDeque}; +use std::mem; +use std::ops::{Add, AddAssign, Sub, SubAssign}; +use std::rc::Rc; + +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum Addr { + AttrVar(usize), + Con(Constant), + Lis(usize), + HeapCell(usize), + StackCell(usize, usize), + Str(usize) +} + +#[derive(Clone, Copy, Hash, Eq, PartialEq)] +pub enum Ref { + AttrVar(usize), + HeapCell(usize), + StackCell(usize, usize) +} + +impl Ref { + pub fn as_addr(self) -> Addr { + match self { + Ref::AttrVar(h) => Addr::AttrVar(h), + Ref::HeapCell(h) => Addr::HeapCell(h), + Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) + } + } +} + +impl PartialEq for Addr { + fn eq(&self, r: &Ref) -> bool { + self.as_var() == Some(*r) + } +} + +// for use in MachineState::bind. +impl PartialOrd for Addr { + fn partial_cmp(&self, r: &Ref) -> Option { + match self { + &Addr::StackCell(fr, sc) => + match *r { + Ref::AttrVar(_) | Ref::HeapCell(_) => + Some(Ordering::Greater), + Ref::StackCell(fr1, sc1) => + if fr1 < fr || (fr1 == fr && sc1 < sc) { + Some(Ordering::Greater) + } else if fr1 == fr && sc1 == sc { + Some(Ordering::Equal) + } else { + Some(Ordering::Less) + } + }, + &Addr::HeapCell(h) | &Addr::AttrVar(h) => + match r { + &Ref::StackCell(..) => Some(Ordering::Less), + &Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1) + }, + _ => None + } + } +} + +impl Addr { + pub fn is_ref(&self) -> bool { + match self { + &Addr::AttrVar(_) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true, + _ => false + } + } + + pub fn as_var(&self) -> Option { + match self { + &Addr::AttrVar(h) => Some(Ref::AttrVar(h)), + &Addr::HeapCell(h) => Some(Ref::HeapCell(h)), + &Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)), + _ => None + } + } + + pub fn is_protected(&self, e: usize) -> bool { + match self { + &Addr::StackCell(addr, _) if addr >= e => false, + _ => true + } + } +} + +impl Add for Addr { + type Output = Addr; + + fn add(self, rhs: usize) -> Self::Output { + match self { + Addr::Lis(a) => Addr::Lis(a + rhs), + Addr::AttrVar(h) => Addr::AttrVar(h + rhs), + Addr::HeapCell(h) => Addr::HeapCell(h + rhs), + Addr::Str(s) => Addr::Str(s + rhs), + _ => self + } + } +} + +impl Sub for Addr { + type Output = Addr; + + fn sub(self, rhs: usize) -> Self::Output { + match self { + Addr::Lis(a) => Addr::Lis(a - rhs), + Addr::AttrVar(h) => Addr::AttrVar(h - rhs), + Addr::HeapCell(h) => Addr::HeapCell(h - rhs), + Addr::Str(s) => Addr::Str(s - rhs), + _ => self + } + } +} + +impl SubAssign for Addr { + fn sub_assign(&mut self, rhs: usize) { + *self = self.clone() - rhs; + } +} + +impl From for Addr { + fn from(r: Ref) -> Self { + match r { + Ref::AttrVar(h) => Addr::AttrVar(h), + Ref::HeapCell(h) => Addr::HeapCell(h), + Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) + } + } +} + +#[derive(Clone)] +pub enum TrailRef { + Ref(Ref), + AttrVarLink(usize, Addr) +} + +impl From for TrailRef { + fn from(r: Ref) -> Self { + TrailRef::Ref(r) + } +} + +#[derive(Clone, PartialEq)] +pub enum HeapCellValue { + Addr(Addr), + NamedStr(usize, ClauseName, Option<(usize, Specifier)>), // arity, name, precedence/Specifier if it has one. +} + +impl HeapCellValue { + pub fn as_addr(&self, focus: usize) -> Addr { + match self { + &HeapCellValue::Addr(ref a) => a.clone(), + &HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus) + } + } +} + +#[derive(Clone, Copy, PartialEq)] +pub enum IndexPtr { + Undefined, + Index(usize), +} + +#[derive(Clone)] +pub struct CodeIndex(pub Rc>); + +impl CodeIndex { + #[inline] + pub fn is_undefined(&self) -> bool { + let index_ptr = &self.0.borrow().0; + + if let &IndexPtr::Undefined = index_ptr { + true + } else { + false + } + } + + #[inline] + pub fn module_name(&self) -> ClauseName { + self.0.borrow().1.clone() + } +} + +impl Default for CodeIndex { + fn default() -> Self { + CodeIndex(Rc::new(RefCell::new((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(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, new_addr: Addr) { + match self { + DynamicAssertPlace::Back => addrs.push_back(new_addr), + DynamicAssertPlace::Front => addrs.push_front(new_addr) + } + } +} + +#[derive(Clone, Copy, PartialEq)] +pub enum DynamicTransactionType { + Abolish, + Assert(DynamicAssertPlace), + Retract // dynamic index of the clause to remove. +} + +#[derive(Clone, PartialEq)] +pub enum CodePtr { + BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call. + CallN(usize, LocalCodePtr), // arity, local. + Local(LocalCodePtr), + DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer. + VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir. +} + +impl CodePtr { + pub fn local(&self) -> LocalCodePtr { + match self { + &CodePtr::BuiltInClause(_, ref local) + | &CodePtr::CallN(_, ref local) + | &CodePtr::Local(ref local) => local.clone(), + &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p), + &CodePtr::DynamicTransaction(_, p) => p + } + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum LocalCodePtr { + DirEntry(usize), // offset. + InSituDirEntry(usize), + TopLevel(usize, usize), // chunk_num, offset. + UserGoalExpansion(usize), + UserTermExpansion(usize) +} + +impl LocalCodePtr { + pub fn assign_if_local(&mut self, cp: CodePtr) { + match cp { + CodePtr::Local(local) => *self = local, + _ => {} + } + } +} + +impl PartialOrd for CodePtr { + fn partial_cmp(&self, other: &CodePtr) -> Option { + match (self, other) { + (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2), + _ => Some(Ordering::Greater) + } + } +} + +impl PartialOrd for LocalCodePtr { + fn partial_cmp(&self, other: &LocalCodePtr) -> Option { + match (self, other) { + (&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2)) + | (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(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), + (_, &LocalCodePtr::TopLevel(_, _)) => + Some(Ordering::Less), + _ => Some(Ordering::Greater) + } + } +} + +impl Default for CodePtr { + fn default() -> Self { + CodePtr::Local(LocalCodePtr::default()) + } +} + +impl Default for LocalCodePtr { + fn default() -> Self { + LocalCodePtr::TopLevel(0, 0) + } +} + +impl Add for LocalCodePtr { + type Output = LocalCodePtr; + + fn add(self, rhs: usize) -> Self::Output { + match self { + LocalCodePtr::InSituDirEntry(p) => LocalCodePtr::InSituDirEntry(p + rhs), + LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs), + LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs), + LocalCodePtr::UserTermExpansion(p) => LocalCodePtr::UserTermExpansion(p + rhs), + LocalCodePtr::UserGoalExpansion(p) => LocalCodePtr::UserGoalExpansion(p + rhs), + } + } +} + +impl AddAssign for LocalCodePtr { + fn add_assign(&mut self, rhs: usize) { + match self { + &mut LocalCodePtr::InSituDirEntry(ref mut p) + | &mut LocalCodePtr::UserGoalExpansion(ref mut p) + | &mut LocalCodePtr::UserTermExpansion(ref mut p) + | &mut LocalCodePtr::DirEntry(ref mut p) + | &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs + } + } +} + +impl Add for CodePtr { + type Output = CodePtr; + + fn add(self, rhs: usize) -> Self::Output { + match self { + p @ CodePtr::VerifyAttrInterrupt(_) + | p @ CodePtr::DynamicTransaction(..) => p, + CodePtr::Local(local) => CodePtr::Local(local + rhs), + CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs) + } + } +} + +impl AddAssign for CodePtr { + fn add_assign(&mut self, rhs: usize) { + match self { + &mut CodePtr::VerifyAttrInterrupt(_) => {}, + &mut CodePtr::Local(ref mut local) => *local += rhs, + _ => *self = CodePtr::Local(self.local() + rhs) + } + } +} + +pub type HeapVarDict = HashMap, Addr>; +pub type AllocVarDict = HashMap, VarData>; + +#[derive(Copy, Clone)] +pub struct DynamicPredicateInfo { + pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value. +} + +impl Default for DynamicPredicateInfo { + fn default() -> Self { + DynamicPredicateInfo { clauses_subsection_p: 0 } + } +} + +pub type InSituCodeDir = HashMap; +pub type DynamicCodeDir = HashMap; + +pub struct IndexStore { + pub(super) atom_tbl: TabledData, + pub(super) code_dir: CodeDir, + pub(super) dynamic_code_dir: DynamicCodeDir, + pub(super) in_situ_code_dir: InSituCodeDir, + pub(super) op_dir: OpDir, + pub(super) modules: ModuleDir, +} + +impl IndexStore { + pub fn predicate_exists(&self, name: ClauseName, arity: usize, + op_spec: Option<(usize, Specifier)>) + -> bool + { + match ClauseType::from(name, arity, op_spec) { + ClauseType::Named(name, arity, _) => + self.code_dir.contains_key(&(name, arity)), + ClauseType::Op(op_decl, ..) => + self.code_dir.contains_key(&(op_decl.name(), op_decl.arity())), + _ => true + } + } + + #[inline] + pub fn get_clause_subsection(&self, name: ClauseName, arity: usize) -> Option { + self.dynamic_code_dir.get(&(name, arity)).cloned() + } + + #[inline] + pub fn take_module(&mut self, name: ClauseName) -> Option { + self.modules.remove(&name) + } + + #[inline] + pub fn insert_module(&mut self, module: Module) { + self.modules.insert(module.module_decl.name.clone(), module); + } + + #[inline] + pub(super) fn new() -> Self { + IndexStore { + atom_tbl: TabledData::new(Rc::new("user".to_string())), + code_dir: CodeDir::new(), + dynamic_code_dir: DynamicCodeDir::new(), + in_situ_code_dir: InSituCodeDir::new(), + op_dir: default_op_dir(), + modules: ModuleDir::new(), + } + } + + #[inline] + pub(super) fn copy_and_swap(&mut self, other: &mut IndexStore) { + 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 + { + 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_wo_h = clause_name!("run_cleaners_without_handling"); + + let builtins = clause_name!("builtins"); + + let r_w_h = self.get_internal(r_w_h, 0, builtins.clone()).and_then(|item| item.local()); + let r_wo_h = self.get_internal(r_wo_h, 1, builtins).and_then(|item| item.local()); + + if let Some(r_w_h) = r_w_h { + if let Some(r_wo_h) = r_wo_h { + return (r_w_h, r_wo_h); + } + } + + return (0, 0); + } +} + +pub type CodeDir = HashMap; +pub type TermDir = HashMap)>; + +#[derive(Clone, Copy)] +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(super) enum RefOrOwned<'a, T: 'a> { + Borrowed(&'a T), + Owned(T) +} + +impl<'a, T> RefOrOwned<'a, T> { + pub(super) + fn as_ref(&'a self) -> &'a T { + match self { + &RefOrOwned::Borrowed(r) => r, + &RefOrOwned::Owned(ref r) => r + } + } +} diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index e634351c..f95fbf9f 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -1,14 +1,17 @@ use prolog_parser::ast::*; use prolog_parser::string_list::*; -use prolog::instructions::*; -use prolog::and_stack::*; -use prolog::copier::*; -use prolog::heap::*; -use prolog::machine::{AttrVarInitializer, IndexStore}; +use prolog::clause_types::*; +use prolog::forms::*; +use prolog::machine::and_stack::*; +use prolog::machine::attributed_variables::*; +use prolog::machine::copier::*; +use prolog::machine::heap::*; use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; +use prolog::machine::modules::*; +use prolog::machine::or_stack::*; use prolog::num::{BigInt, BigUint, Zero, One}; -use prolog::or_stack::*; use downcast::Any; @@ -188,6 +191,8 @@ impl IndexMut for MachineState { } } +pub type Registers = Vec; + #[derive(Clone, Copy)] pub(super) enum MachineMode { Read, diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 9e6c41a5..2fb5dd02 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1,19 +1,22 @@ use prolog_parser::ast::*; use prolog_parser::string_list::StringList; -use prolog::instructions::*; -use prolog::and_stack::*; -use prolog::copier::*; -use prolog::heap::*; +use prolog::clause_types::*; +use prolog::forms::*; use prolog::heap_iter::*; use prolog::heap_print::*; -use prolog::machine::{AttrVarInitializer, IndexStore}; +use prolog::instructions::*; +use prolog::machine::attributed_variables::*; +use prolog::machine::and_stack::*; +use prolog::machine::copier::*; +use prolog::machine::heap::*; +use prolog::machine::or_stack::*; use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; use prolog::num::{Integer, Signed, ToPrimitive, Zero}; use prolog::num::bigint::{BigInt, BigUint}; use prolog::num::rational::Ratio; -use prolog::or_stack::*; use std::cmp::{max, Ordering}; use std::collections::{HashMap, HashSet}; diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 2f104d51..b65eea09 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -1,15 +1,24 @@ use prolog_parser::ast::*; use prolog_parser::tabled_rc::*; -use prolog::codegen::*; -use prolog::compile::*; -use prolog::debray_allocator::*; +use prolog::clause_types::*; +use prolog::fixtures::*; +use prolog::forms::*; use prolog::heap_print::*; use prolog::instructions::*; +pub mod machine_indices; +pub mod heap; +mod and_stack; +mod or_stack; mod attributed_variables; +mod copier; mod dynamic_database; -mod machine_errors; +pub mod machine_errors; +pub mod toplevel; +pub mod compile; +pub(super) mod code_repo; +pub mod modules; pub(super) mod machine_state; pub(super) mod term_expansion; @@ -17,233 +26,18 @@ pub(super) mod term_expansion; mod system_calls; use prolog::machine::attributed_variables::*; +use prolog::machine::compile::*; +use prolog::machine::code_repo::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; +use prolog::machine::modules::*; use std::collections::{HashMap, VecDeque}; use std::mem; use std::ops::Index; use std::rc::Rc; - -#[derive(Copy, Clone)] -pub struct DynamicPredicateInfo { - pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value. -} - -impl Default for DynamicPredicateInfo { - fn default() -> Self { - DynamicPredicateInfo { clauses_subsection_p: 0 } - } -} - -pub type InSituCodeDir = HashMap; -pub type DynamicCodeDir = HashMap; - -pub struct IndexStore { - pub(super) atom_tbl: TabledData, - pub(super) code_dir: CodeDir, - pub(super) dynamic_code_dir: DynamicCodeDir, - pub(super) in_situ_code_dir: InSituCodeDir, - pub(super) op_dir: OpDir, - pub(super) modules: ModuleDir, -} - -enum RefOrOwned<'a, T: 'a> { - Borrowed(&'a T), - Owned(T) -} - -impl<'a, T> RefOrOwned<'a, T> { - fn as_ref(&'a self) -> &'a T { - match self { - &RefOrOwned::Borrowed(r) => r, - &RefOrOwned::Owned(ref r) => r - } - } -} - -impl IndexStore { - pub fn predicate_exists(&self, name: ClauseName, arity: usize, - op_spec: Option<(usize, Specifier)>) - -> bool - { - match ClauseType::from(name, arity, op_spec) { - ClauseType::Named(name, arity, _) => - self.code_dir.contains_key(&(name, arity)), - ClauseType::Op(op_decl, ..) => - self.code_dir.contains_key(&(op_decl.name(), op_decl.arity())), - _ => true - } - } - - #[inline] - pub fn get_clause_subsection(&self, name: ClauseName, arity: usize) -> Option { - self.dynamic_code_dir.get(&(name, arity)).cloned() - } - - #[inline] - pub fn take_module(&mut self, name: ClauseName) -> Option { - self.modules.remove(&name) - } - - #[inline] - pub fn insert_module(&mut self, module: Module) { - self.modules.insert(module.module_decl.name.clone(), module); - } - - #[inline] - pub(super) fn new() -> Self { - IndexStore { - atom_tbl: TabledData::new(Rc::new("user".to_string())), - code_dir: CodeDir::new(), - dynamic_code_dir: DynamicCodeDir::new(), - in_situ_code_dir: InSituCodeDir::new(), - op_dir: default_op_dir(), - modules: ModuleDir::new(), - } - } - - #[inline] - pub(super) fn copy_and_swap(&mut self, other: &mut IndexStore) { - 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 - { - 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_wo_h = clause_name!("run_cleaners_without_handling"); - - let builtins = clause_name!("builtins"); - - let r_w_h = self.get_internal(r_w_h, 0, builtins.clone()).and_then(|item| item.local()); - let r_wo_h = self.get_internal(r_wo_h, 1, builtins).and_then(|item| item.local()); - - if let Some(r_w_h) = r_w_h { - if let Some(r_wo_h) = r_wo_h { - return (r_w_h, r_wo_h); - } - } - - return (0, 0); - } -} - -pub type CompiledResult = (Predicate, VecDeque); - -impl CodeRepo { - #[inline] - fn new() -> Self { - CodeRepo { - cached_query: vec![], - goal_expanders: Code::new(), - term_expanders: Code::new(), - code: Code::new(), - in_situ_code: Code::new(), - term_dir: TermDir::new() - } - } - - #[inline] - pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) { - self.term_dir.get(&key) - .map(|entry| ((entry.0).0.len(), entry.1.len())) - .unwrap_or((0,0)) - } - - #[inline] - pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize) - -> (Predicate, VecDeque) - { - self.term_dir.get_mut(&key) - .map(|entry| (Predicate((entry.0).0.drain(len ..).collect()), - entry.1.drain(queue_len ..).collect())) - .unwrap_or((Predicate::new(), VecDeque::from(vec![]))) - } - - pub fn add_in_situ_result(&mut self, result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir, - flags: MachineFlags) - -> 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 p = self.in_situ_code.len(); - in_situ_code_dir.insert((name, arity), p); - - let mut cg = CodeGenerator::::new(true, flags); - // clone the decl to avoid the need to wipe its register cells later. - let mut decl_code = cg.compile_predicate(&decl.0.clone())?; - - compile_appendix(&mut decl_code, queue, true, flags)?; - - self.in_situ_code.extend(decl_code.into_iter()); - Ok(()) - } - - #[inline] - fn size_of_cached_query(&self) -> usize { - self.cached_query.len() - } - - fn lookup_instr<'a>(&'a self, last_call: bool, p: &CodePtr) -> Option> - { - match p { - &CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => - if p < self.goal_expanders.len() { - Some(RefOrOwned::Borrowed(&self.goal_expanders[p])) - } else { - None - }, - &CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => - if p < self.term_expanders.len() { - 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::BuiltInClause(ref built_in, _) => { - let call_clause = call_clause!(ClauseType::BuiltIn(built_in.clone()), - built_in.arity(), - 0, last_call); - Some(RefOrOwned::Owned(call_clause)) - }, - &CodePtr::CallN(arity, _) => { - let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call); - Some(RefOrOwned::Owned(call_clause)) - }, - &CodePtr::VerifyAttrInterrupt(p) => - Some(RefOrOwned::Borrowed(&self.code[p])), - &CodePtr::DynamicTransaction(..) => - None - } - } -} - pub struct MachinePolicies { call_policy: Box, cut_policy: Box, diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs new file mode 100644 index 00000000..0d94c177 --- /dev/null +++ b/src/prolog/machine/modules.rs @@ -0,0 +1,242 @@ +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; + +use prolog::forms::*; +use prolog::machine::code_repo::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; + +use std::cell::RefCell; +use std::collections::{VecDeque}; +use std::rc::Rc; + +impl ModuleCodeIndex { + pub fn local(&self) -> Option { + match self.0 { + IndexPtr::Index(i) => Some(i), + _ => None + } + } +} + +impl From for CodeIndex { + fn from(value: ModuleCodeIndex) -> Self { + CodeIndex(Rc::new(RefCell::new((value.0, value.1)))) + } +} + +// Module's and related types are defined in forms. +impl Module { + pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData) -> Self { + Module { module_decl, atom_tbl, + term_expansions: (Predicate::new(), VecDeque::from(vec![])), + goal_expansions: (Predicate::new(), VecDeque::from(vec![])), + code_dir: ModuleCodeDir::new(), + op_dir: default_op_dir(), + inserted_expansions: false } + } + + pub fn dump_expansions(&self, code_repo: &mut CodeRepo, flags: MachineFlags) + -> 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.term_expansions.0).0.iter().cloned()); + te.1.extend(self.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.goal_expansions.0).0.iter().cloned()); + ge.1.extend(self.goal_expansions.1.iter().cloned()); + } + + code_repo.compile_hook(CompileTimeHook::TermExpansion, flags)?; + code_repo.compile_hook(CompileTimeHook::GoalExpansion, flags)?; + + Ok(()) + } +} + +pub trait SubModuleUser +{ + fn atom_tbl(&self) -> TabledData; + fn op_dir(&mut self) -> &mut OpDir; + fn remove_code_index(&mut self, PredicateKey); + fn get_code_index(&self, PredicateKey, ClauseName) -> Option; + + fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex); + + fn remove_module(&mut self, mod_name: ClauseName, module: &Module) { + for (name, arity) in module.module_decl.exports.iter().cloned() { + 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.op_dir().get(&(name.clone(), Fixity::In)).cloned() + { + 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.op_dir().get(&(name.clone(), Fixity::Pre)).cloned() + { + if mod_name == module.module_decl.name { + self.op_dir().remove(&(name.clone(), Fixity::Pre)); + } + } + + if let Some((_, _, mod_name)) = self.op_dir().get(&(name.clone(), Fixity::Post)).cloned() + { + if mod_name == module.module_decl.name { + self.op_dir().remove(&(name.clone(), Fixity::Post)); + } + } + } + }, + _ => {} + }; + } + } + + // returns true on successful import. + fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool { + let name = name.defrock_brackets(); + let mut found_op = false; + + { + let mut insert_op_dir = |fix| { + if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) { + self.op_dir().insert((name.clone(), fix), op_data.clone()); + found_op = true; + } + }; + + if arity == 1 { + insert_op_dir(Fixity::Pre); + insert_op_dir(Fixity::Post); + } else if arity == 2 { + insert_op_dir(Fixity::In); + } + } + + if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) { + let name = name.with_table(submodule.atom_tbl.clone()); + + let mut atom_tbl = self.atom_tbl(); + atom_tbl.borrow_mut().insert(name.to_rc()); + + self.insert_dir_entry(name, arity, code_data.clone()); + true + } else { + found_op + } + } + + fn use_qualified_module(&mut self, &mut CodeRepo, MachineFlags, &Module, &Vec) + -> Result<(), SessionError>; + fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module) + -> Result<(), SessionError>; +} + +pub fn use_qualified_module(user: &mut User, submodule: &Module, exports: &Vec) + -> Result<(), SessionError> + where User: SubModuleUser +{ + for (name, arity) in exports.iter().cloned() { + if !submodule.module_decl.exports.contains(&(name.clone(), arity)) { + continue; + } + + if !user.import_decl(name, arity, submodule) { + return Err(SessionError::ModuleDoesNotContainExport); + } + } + + Ok(()) +} + +pub fn use_module(user: &mut User, submodule: &Module) + -> Result<(), SessionError> +{ + for (name, arity) in submodule.module_decl.exports.iter().cloned() { + if !user.import_decl(name, arity, submodule) { + return Err(SessionError::ModuleDoesNotContainExport); + } + } + + Ok(()) +} + +impl SubModuleUser for Module { + fn atom_tbl(&self) -> TabledData { + self.atom_tbl.clone() + } + + fn op_dir(&mut self) -> &mut OpDir { + &mut self.op_dir + } + + fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option { + self.code_dir.get(&key).cloned().map(CodeIndex::from) + } + + fn remove_code_index(&mut self, key: PredicateKey) { + self.code_dir.remove(&key); + } + + fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) { + self.code_dir.insert((name, arity), idx); + } + + fn use_qualified_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module, + exports: &Vec) + -> Result<(), SessionError> + { + use_qualified_module(self, submodule, exports)?; + + (self.term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned()); + self.term_expansions.1.extend(submodule.term_expansions.1.iter().cloned()); + + (self.goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned()); + self.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.term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned()); + self.term_expansions.1.extend(submodule.term_expansions.1.iter().cloned()); + + (self.goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned()); + self.goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned()); + + Ok(()) + } +} + +pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir { + code_dir.into_iter() + .map(|(k, code_idx)| { + let (idx, module_name) = code_idx.0.borrow().clone(); + (k, ModuleCodeIndex(idx, module_name)) + }) + .collect() +} diff --git a/src/prolog/or_stack.rs b/src/prolog/machine/or_stack.rs similarity index 98% rename from src/prolog/or_stack.rs rename to src/prolog/machine/or_stack.rs index d7e9f7f3..4c189548 100644 --- a/src/prolog/or_stack.rs +++ b/src/prolog/machine/or_stack.rs @@ -1,4 +1,4 @@ -use prolog::instructions::*; +use prolog::machine::machine_indices::*; use std::ops::{Index, IndexMut}; use std::vec::Vec; diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 48df5bff..bfdfe55e 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -1,11 +1,11 @@ use prolog_parser::ast::*; -use prolog::copier::*; +use prolog::clause_types::*; use prolog::heap_iter::*; use prolog::heap_print::*; -use prolog::instructions::*; -use prolog::machine::IndexStore; +use prolog::machine::copier::*; use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; use prolog::num::{ToPrimitive, Zero}; use prolog::num::bigint::{BigInt}; diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 3209d220..a7b8b8c8 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -1,8 +1,8 @@ use prolog_parser::ast::*; use prolog_parser::parser::*; -use prolog::instructions::HeapCellValue; use prolog::machine::*; +use prolog::machine::machine_indices::HeapCellValue; use prolog::num::*; use prolog::read::*; diff --git a/src/prolog/toplevel.rs b/src/prolog/machine/toplevel.rs similarity index 99% rename from src/prolog/toplevel.rs rename to src/prolog/machine/toplevel.rs index 2fdd8335..ac33c593 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -1,9 +1,12 @@ use prolog_parser::ast::*; use prolog_parser::tabled_rc::*; -use prolog::instructions::*; +use prolog::forms::*; use prolog::iterators::*; use prolog::machine::*; +use prolog::machine::code_repo::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::MachineState; use prolog::machine::term_expansion::*; use prolog::num::*; @@ -756,7 +759,7 @@ pub fn string_to_toplevel(src: R, buffer: String, wam: &mut Machine) -> Result { - let mut term_stream = TermStream::new(src, wam.indices.atom_tbl.clone(), + let mut term_stream = TermStream::new(src, wam.indices.atom_tbl(), wam.machine_flags(), &mut wam.indices, &mut wam.policies, &mut wam.code_repo); diff --git a/src/prolog/mod.rs b/src/prolog/mod.rs index 31ed6bcf..9ef14b8a 100644 --- a/src/prolog/mod.rs +++ b/src/prolog/mod.rs @@ -2,24 +2,20 @@ extern crate num; extern crate ordered_float; extern crate prolog_parser; -#[macro_use] pub mod instructions; -pub mod heap; -mod and_stack; +pub mod instructions; +mod clause_types; #[macro_use] mod macros; #[macro_use] mod allocator; -pub mod toplevel; +mod fixtures; pub mod machine; -pub mod compile; +mod forms; mod arithmetic; mod codegen; -mod copier; mod debray_allocator; -mod fixtures; mod heap_iter; mod indexing; pub mod write; mod iterators; -mod or_stack; pub mod heap_print; mod targets; pub mod read; diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 07f7a501..0c94bc5f 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -2,8 +2,9 @@ use prolog_parser::ast::*; use prolog_parser::parser::*; use prolog_parser::tabled_rc::TabledData; -use prolog::instructions::*; +use prolog::forms::*; use prolog::iterators::*; +use prolog::machine::machine_indices::*; use prolog::machine::machine_state::MachineState; use std::collections::VecDeque; diff --git a/src/prolog/targets.rs b/src/prolog/targets.rs index 5af37f57..b5718723 100644 --- a/src/prolog/targets.rs +++ b/src/prolog/targets.rs @@ -1,5 +1,7 @@ use prolog_parser::ast::*; +use prolog::clause_types::*; +use prolog::forms::*; use prolog::instructions::*; use prolog::iterators::*; diff --git a/src/prolog/write.rs b/src/prolog/write.rs index 1f3436b3..641135b6 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -1,6 +1,10 @@ -use prolog::instructions::*; +use prolog::clause_types::*; +use prolog::forms::*; use prolog::heap_print::*; +use prolog::instructions::*; use prolog::machine::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; use termion::raw::{IntoRawMode, RawTerminal}; use termion::input::TermRead; diff --git a/src/tests.rs b/src/tests.rs index 0c56bb16..fdd92c49 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,8 +1,9 @@ use prolog::heap_print::*; -use prolog::instructions::*; -use prolog::compile::*; use prolog::machine::*; -use prolog::toplevel::*; +use prolog::machine::compile::*; +use prolog::machine::machine_errors::*; +use prolog::machine::machine_indices::*; +use prolog::machine::toplevel::*; use std::collections::HashSet; use std::io::empty; -- 2.54.0