]> Repositorios git - scryer-prolog.git/commitdiff
refactor to actual modules
authorMark Thom <[email protected]>
Mon, 4 Mar 2019 06:29:02 +0000 (23:29 -0700)
committerMark Thom <[email protected]>
Mon, 4 Mar 2019 06:29:02 +0000 (23:29 -0700)
33 files changed:
src/main.rs
src/prolog/allocator.rs
src/prolog/arithmetic.rs
src/prolog/clause_types.rs [new file with mode: 0644]
src/prolog/codegen.rs
src/prolog/debray_allocator.rs
src/prolog/fixtures.rs
src/prolog/forms.rs [new file with mode: 0644]
src/prolog/heap_iter.rs
src/prolog/heap_print.rs
src/prolog/instructions.rs
src/prolog/iterators.rs
src/prolog/machine/and_stack.rs [moved from src/prolog/and_stack.rs with 97% similarity]
src/prolog/machine/code_repo.rs [new file with mode: 0644]
src/prolog/machine/compile.rs [moved from src/prolog/compile.rs with 98% similarity]
src/prolog/machine/copier.rs [moved from src/prolog/copier.rs with 98% similarity]
src/prolog/machine/dynamic_database.rs
src/prolog/machine/heap.rs [moved from src/prolog/heap.rs with 97% similarity]
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_indices.rs [new file with mode: 0644]
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/modules.rs [new file with mode: 0644]
src/prolog/machine/or_stack.rs [moved from src/prolog/or_stack.rs with 98% similarity]
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/prolog/machine/toplevel.rs [moved from src/prolog/toplevel.rs with 99% similarity]
src/prolog/mod.rs
src/prolog/read.rs
src/prolog/targets.rs
src/prolog/write.rs
src/tests.rs

index 6b85d72ca7a5235c5b970d765ffcf6f9a81381ac..bfbda33f79d258c5162d2b5dfaf4a8efd5ae0097 100644 (file)
@@ -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};
index a498fbaf4799eeee97498c7a242e078f411deef8..8ae88742c3076d2dc3898f6a928cf300f021b106 100644 (file)
@@ -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;
index a3cdc5f64f0c09698ba9e82db4ffe1e973eceb52..bc36e407ee670305e30270bb462533dc46e3b165 100644 (file)
@@ -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 (file)
index 0000000..8804d8f
--- /dev/null
@@ -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<Self> {
+        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<SystemClauseType> {
+        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<Self> {
+        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<InlinedClauseType> for ClauseType {
+    fn from(inlined_ct: InlinedClauseType) -> Self {
+        ClauseType::Inlined(inlined_ct)
+    }
+}
index ca4a81ace41ca00b324041c206ad20ccd1f15f1a..462cda0fce1ac702d15443f74e100439e3d7168f 100644 (file)
@@ -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;
index 86053c48031fdd9715f6b9f0af7140d3729be427..a9e629545b96b6fe52155467f7df19df5c1aa1c6 100644 (file)
@@ -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;
index 3394ea952f82c4c91168c71170905285d432b1dd..474858c745615a8ff5d4da78837c29d698c40b6e 100644 (file)
@@ -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<usize>,
+    pub conflict_set: BTreeSet<usize>
+}
+
+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<usize> = (1..arity).collect();
+
+            for &(_, reg) in self.use_set.iter() {
+                conflict_set.remove(&reg);
+            }
+
+            self.conflict_set = conflict_set;
+        }
+    }
+}
+
 type VariableFixture<'a> = (VarStatus, Vec<&'a Cell<VarReg>>);
 pub struct VariableFixtures<'a>(BTreeMap<Rc<Var>, VariableFixture<'a>>);
 
diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs
new file mode 100644 (file)
index 0000000..c2bf01a
--- /dev/null
@@ -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<Term> is always a vector
+// of vars (we get their adjoining cells this way).
+pub type JumpStub = Vec<Term>;
+
+#[derive(Clone)]
+pub enum TopLevel {
+    Declaration(Declaration),
+    Fact(Term),
+    Predicate(Predicate),
+    Query(Vec<QueryTerm>),
+    Rule(Rule),
+}
+
+impl TopLevel {
+    pub fn name(&self) -> Option<ClauseName> {
+        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<RegType>, ClauseType, Vec<Box<Term>>, bool),
+    BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
+    UnblockedCut(Cell<VarReg>),
+    GetLevelAndUnify(Cell<VarReg>, Rc<Var>),
+    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<Box<Term>>, QueryTerm),
+    pub clauses: Vec<QueryTerm>
+}
+
+#[derive(Clone)]
+pub struct Predicate(pub Vec<PredicateClause>);
+
+impl Predicate {
+    #[inline]
+    pub fn new() -> Self {
+        Predicate(vec![])
+    }
+
+    #[inline]
+    pub fn clauses(self) -> Vec<PredicateClause> {
+        self.0
+    }
+
+    #[inline]
+    pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> {
+        self.0.first()
+            .and_then(|clause| clause.name().map(|name| (name, clause.arity())))
+    }
+}
+
+pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
+
+#[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<ClauseName> {
+        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<TopLevel>),
+    Module(ModuleDecl),
+    NonCountedBacktracking(ClauseName, usize), // name, arity
+    Op(OpDecl),
+    UseModule(ClauseName),
+    UseQualifiedModule(ClauseName, Vec<PredicateKey>)
+}
+
+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<PredicateKey, ModuleCodeIndex>;
+pub type ModuleDir = HashMap<ClauseName, Module>;
+
+#[derive(Clone)]
+pub struct ModuleDecl {
+    pub name: ClauseName,
+    pub exports: Vec<PredicateKey>
+}
+
+pub struct Module {
+    pub atom_tbl: TabledData<Atom>,
+    pub module_decl: ModuleDecl,
+    pub code_dir: ModuleCodeDir,
+    pub op_dir: OpDir,
+    pub term_expansions: (Predicate, VecDeque<TopLevel>),
+    pub goal_expansions: (Predicate, VecDeque<TopLevel>),
+    pub inserted_expansions: bool // has the module been successfully inserted into toplevel??
+}
+
+#[derive(Clone)]
+pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName);
index 4847a4a3642f8c61b236e5b7f2f7ac0f9612bc5d..7f32c1bf2f343c7f67997f1f6a7b53a374338949 100644 (file)
@@ -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;
index 0b2ac0f9aa75b954ff766e5c453adf1c0078b170..5fe5267b3d34df48084d95345d159f57aa3cfc2b 100644 (file)
@@ -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;
index 64b8822706107514966bab8b560977b9e3c6c7c5..1abfb0c696da38177d6f1c38b5ce782f3993a9b7 100644 (file)
@@ -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<Self> {
-        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<Term> is always a vector
-// of vars (we get their adjoining cells this way).
-pub type JumpStub = Vec<Term>;
-
-#[derive(Clone)]
-pub enum QueryTerm {
-    // register, clause type, subterms, use default call policy.
-    Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>, bool),
-    BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
-    UnblockedCut(Cell<VarReg>),
-    GetLevelAndUnify(Cell<VarReg>, Rc<Var>),
-    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<Box<Term>>, QueryTerm),
-    pub clauses: Vec<QueryTerm>
-}
-
-#[derive(Clone)]
-pub struct Predicate(pub Vec<PredicateClause>);
-
-impl Predicate {
-    #[inline]
-    pub fn new() -> Self {
-        Predicate(vec![])
-    }
-
-    #[inline]
-    pub fn clauses(self) -> Vec<PredicateClause> {
-        self.0
-    }
-
-    #[inline]
-    pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> {
-        self.0.first()
-            .and_then(|clause| clause.name().map(|name| (name, clause.arity())))
-    }
-}
-
-#[derive(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<ClauseName> {
-        match self {
-            &PredicateClause::Fact(ref term) => term.name(),
-            &PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()),
-        }
-    }
-}
-
-pub type ModuleCodeDir = HashMap<PredicateKey, ModuleCodeIndex>;
-
-pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
-
-pub type TermDir = HashMap<PredicateKey, (Predicate, VecDeque<TopLevel>)>;
-
-pub type ModuleDir = HashMap<ClauseName, Module>;
-
-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<PredicateKey>
-}
-
-pub struct Module {
-    pub atom_tbl: TabledData<Atom>,
-    pub module_decl: ModuleDecl,
-    pub code_dir: ModuleCodeDir,
-    pub op_dir: OpDir,
-    pub term_expansions: (Predicate, VecDeque<TopLevel>),
-    pub goal_expansions: (Predicate, VecDeque<TopLevel>),
-    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<SystemClauseType> {
-        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<Self> {
-        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<InlinedClauseType> 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<FactInstruction>;
 
-pub enum Line {
-    Arithmetic(ArithmeticInstruction),
-    Choice(ChoiceInstruction),
-    Control(ControlInstruction),
-    Cut(CutInstruction),
-    Fact(FactInstruction),
-    Indexing(IndexingInstruction),
-    IndexedChoice(IndexedChoiceInstruction),
-    Query(QueryInstruction)
-}
-
 pub type ThirdLevelIndex = Vec<IndexedChoiceInstruction>;
 
 pub type Code = Vec<Line>;
 
 pub type CodeDeque = VecDeque<Line>;
-
-#[derive(Clone, PartialEq, Eq, Hash)]
-pub enum Addr {
-    AttrVar(usize),
-    Con(Constant),
-    Lis(usize),
-    HeapCell(usize),
-    StackCell(usize, usize),
-    Str(usize)
-}
-
-impl PartialEq<Ref> for Addr {
-    fn eq(&self, r: &Ref) -> bool {
-        self.as_var() == Some(*r)
-    }
-}
-
-// for use in MachineState::bind.
-impl PartialOrd<Ref> for Addr {
-    fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
-        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<Ref> {
-        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<usize> 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<usize> 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<usize> for Addr {
-    fn sub_assign(&mut self, rhs: usize) {
-        *self = self.clone() - rhs;
-    }
-}
-
-impl From<Ref> 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<Ref> 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<RefCell<(IndexPtr, ClauseName)>>);
-
-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<usize> {
-        match self.0 {
-            IndexPtr::Index(i) => Some(i),
-            _ => None
-        }
-    }
-}
-
-impl From<ModuleCodeIndex> 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<Addr>, 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<CodePtr> for CodePtr {
-    fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
-        match (self, other) {
-            (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
-            _ => Some(Ordering::Greater)
-        }
-    }
-}
-
-impl PartialOrd<LocalCodePtr> for LocalCodePtr {
-    fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
-        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<usize> 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<usize> 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<usize> 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<usize> 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<Addr>;
-
-pub enum TermIterState<'a> {
-    AnonVar(Level),
-    Constant(Level, &'a Cell<RegType>, &'a Constant),
-    Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
-    InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    Var(Level, &'a Cell<VarReg>, Rc<Var>)
-}
-
-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<Atom>) -> 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<Atom>;
-    fn op_dir(&mut self) -> &mut OpDir;
-    fn remove_code_index(&mut self, PredicateKey);
-    fn get_code_index(&self, PredicateKey, ClauseName) -> Option<CodeIndex>;
-
-    fn insert_dir_entry(&mut self, ClauseName, usize, 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<PredicateKey>)
-                            -> Result<(), SessionError>;
-    fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module)
-                  -> Result<(), SessionError>;
-}
-
-pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports: &Vec<PredicateKey>)
-                              -> 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: SubModuleUser>(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<Atom> {
-        self.atom_tbl.clone()
-    }
-
-    fn op_dir(&mut self) -> &mut OpDir {
-        &mut self.op_dir
-    }
-
-    fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option<CodeIndex> {
-        self.code_dir.get(&key).cloned().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<PredicateKey>)
-                            -> 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<TopLevel>),
-    Module(ModuleDecl),
-    NonCountedBacktracking(ClauseName, usize), // name, arity
-    Op(OpDecl),
-    UseModule(ClauseName),
-    UseQualifiedModule(ClauseName, Vec<PredicateKey>)
-}
-
-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<QueryTerm>),
-    Rule(Rule),
-}
-
-impl TopLevel {
-    pub fn name(&self) -> Option<ClauseName> {
-        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<usize>,
-    pub conflict_set: BTreeSet<usize>
-}
-
-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<usize> = (1..arity).collect();
-
-            for &(_, reg) in self.use_set.iter() {
-                conflict_set.remove(&reg);
-            }
-
-            self.conflict_set = conflict_set;
-        }
-    }
-}
-
-pub type HeapVarDict  = HashMap<Rc<Var>, Addr>;
-pub type AllocVarDict = HashMap<Rc<Var>, 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<SessionError> for EvalSession {
-    fn from(err: SessionError) -> Self {
-        EvalSession::Error(err)
-    }
-}
-
-impl From<ParserError> for SessionError {
-    fn from(err: ParserError) -> Self {
-        SessionError::ParserError(err)
-    }
-}
-
-impl From<ParserError> 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(())
-    }
-}
index 6b2c83b1029c496c90540be52dd2ce86b284ed37..ce815249c89f89c8180773051ce086db0ce669b2 100644 (file)
@@ -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<RegType>, &'a Constant),
+    Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
+    InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
+    FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
+    Var(Level, &'a Cell<VarReg>, Rc<Var>)
+}
+
+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<TermIterState<'a>>,
 }
similarity index 97%
rename from src/prolog/and_stack.rs
rename to src/prolog/machine/and_stack.rs
index 368ada0f029bed97442b2384d8c93eb93bbc89c4..747fc53292de5839320491074bdd23df0b01a9b3 100644 (file)
@@ -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 (file)
index 0000000..2388459
--- /dev/null
@@ -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<TopLevel>)
+    {
+        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::<DebrayAllocator>::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<RefOrOwned<'a, Line>>
+    {
+        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
+        }
+    }
+}
similarity index 98%
rename from src/prolog/compile.rs
rename to src/prolog/machine/compile.rs
index 727f70d5dba875b053670d779298bdbb7b301949..91882632472e331d02e9ab76ae6800c39e1c6588 100644 (file)
@@ -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<R: Read>(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore)
                              -> Result<GatherResult, SessionError>
     {
-        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,
similarity index 98%
rename from src/prolog/copier.rs
rename to src/prolog/machine/copier.rs
index d3db0fef1d510b8b2b62a168ad197fd9eec21aa7..edb540426d60dc9af912b78db39edd9a87b8798a 100644 (file)
@@ -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;
 
index f47fcfd1b14bf512d75dac89f913ee3279a6beca..4fe01ad6d902f624f1e7649b25750f3d353fcc2f 100644 (file)
@@ -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;
 
similarity index 97%
rename from src/prolog/heap.rs
rename to src/prolog/machine/heap.rs
index 115e4e3ad8b7b145f980a6a9834ea76075f354ad..b5141f08c8cf738800c659a73eb55eed26cf010d 100644 (file)
@@ -1,6 +1,6 @@
 use prolog_parser::ast::*;
 
-use prolog::instructions::*;
+use prolog::machine::machine_indices::*;
 
 use std::ops::{Index, IndexMut};
 
index 4c019af873fa19f77f0cc2d9b00076c49af49aa8..5e7d2af93d4af71824b70334a97b59082342af58 100644 (file)
@@ -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<SessionError> for EvalSession {
+    fn from(err: SessionError) -> Self {
+        EvalSession::Error(err)
+    }
+}
+
+impl From<ParserError> for SessionError {
+    fn from(err: ParserError) -> Self {
+        SessionError::ParserError(err)
+    }
+}
+
+impl From<ParserError> 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 (file)
index 0000000..26db373
--- /dev/null
@@ -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<Ref> for Addr {
+    fn eq(&self, r: &Ref) -> bool {
+        self.as_var() == Some(*r)
+    }
+}
+
+// for use in MachineState::bind.
+impl PartialOrd<Ref> for Addr {
+    fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
+        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<Ref> {
+        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<usize> 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<usize> 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<usize> for Addr {
+    fn sub_assign(&mut self, rhs: usize) {
+        *self = self.clone() - rhs;
+    }
+}
+
+impl From<Ref> 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<Ref> 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<RefCell<(IndexPtr, ClauseName)>>);
+
+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<Addr>, 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<CodePtr> for CodePtr {
+    fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
+        match (self, other) {
+            (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
+            _ => Some(Ordering::Greater)
+        }
+    }
+}
+
+impl PartialOrd<LocalCodePtr> for LocalCodePtr {
+    fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
+        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<usize> 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<usize> 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<usize> 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<usize> 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<Rc<Var>, Addr>;
+pub type AllocVarDict = HashMap<Rc<Var>, 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<PredicateKey, usize>;
+pub type DynamicCodeDir = HashMap<PredicateKey, DynamicPredicateInfo>;
+
+pub struct IndexStore {
+    pub(super) atom_tbl: TabledData<Atom>,
+    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<DynamicPredicateInfo> {
+        self.dynamic_code_dir.get(&(name, arity)).cloned()
+    }
+
+    #[inline]
+    pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
+        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<ModuleCodeIndex>
+    {
+        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<PredicateKey, CodeIndex>;
+pub type TermDir = HashMap<PredicateKey, (Predicate, VecDeque<TopLevel>)>;
+
+#[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
+        }
+    }
+}
index e634351c4176f12f853eb2621ea97bc022f4d17c..f95fbf9f2285754df7f4a65b009b1b047a2854ed 100644 (file)
@@ -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<RegType> for MachineState {
     }
 }
 
+pub type Registers = Vec<Addr>;
+
 #[derive(Clone, Copy)]
 pub(super) enum MachineMode {
     Read,
index 9e6c41a5a6d8cf4e60f50fff77261cab813abdbe..2fb5dd0217c33cd4d09c369f1237864be38047b8 100644 (file)
@@ -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};
index 2f104d51f51790f6bd5ddd63e7abc96646a57f9c..b65eea0926e3861be7c3c317f68bf46a1dd5eb1d 100644 (file)
@@ -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<PredicateKey, usize>;
-pub type DynamicCodeDir = HashMap<PredicateKey, DynamicPredicateInfo>;
-
-pub struct IndexStore {
-    pub(super) atom_tbl: TabledData<Atom>,
-    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<DynamicPredicateInfo> {
-        self.dynamic_code_dir.get(&(name, arity)).cloned()
-    }
-
-    #[inline]
-    pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
-        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<ModuleCodeIndex>
-    {
-        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<TopLevel>);
-
-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<TopLevel>)
-    {
-        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::<DebrayAllocator>::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<RefOrOwned<'a, Line>>
-    {
-        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<CallPolicy>,
     cut_policy: Box<CutPolicy>,
diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs
new file mode 100644 (file)
index 0000000..0d94c17
--- /dev/null
@@ -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<usize> {
+        match self.0 {
+            IndexPtr::Index(i) => Some(i),
+            _ => None
+        }
+    }
+}
+
+impl From<ModuleCodeIndex> 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<Atom>) -> 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<Atom>;
+    fn op_dir(&mut self) -> &mut OpDir;
+    fn remove_code_index(&mut self, PredicateKey);
+    fn get_code_index(&self, PredicateKey, ClauseName) -> Option<CodeIndex>;
+
+    fn insert_dir_entry(&mut self, ClauseName, usize, 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<PredicateKey>)
+                            -> Result<(), SessionError>;
+    fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module)
+                  -> Result<(), SessionError>;
+}
+
+pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports: &Vec<PredicateKey>)
+                              -> 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: SubModuleUser>(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<Atom> {
+        self.atom_tbl.clone()
+    }
+
+    fn op_dir(&mut self) -> &mut OpDir {
+        &mut self.op_dir
+    }
+
+    fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option<CodeIndex> {
+        self.code_dir.get(&key).cloned().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<PredicateKey>)
+                            -> 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()
+}
similarity index 98%
rename from src/prolog/or_stack.rs
rename to src/prolog/machine/or_stack.rs
index d7e9f7f3ea96285fc3c9eae8dda402a93a29dd64..4c189548c3576bca2ab0663b226b641b5f1ff328 100644 (file)
@@ -1,4 +1,4 @@
-use prolog::instructions::*;
+use prolog::machine::machine_indices::*;
 
 use std::ops::{Index, IndexMut};
 use std::vec::Vec;
index 48df5bff71d203ecb1419b7d7c8390ed94e89e08..bfdfe55eda1c162c1d5b6ab2bbef16bab0f56d6e 100644 (file)
@@ -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};
index 3209d220e00b33bfeb85da1ce0e938bd3ca10021..a7b8b8c87c538b80a5d1d65b4f98334cd8399a4e 100644 (file)
@@ -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::*;
 
similarity index 99%
rename from src/prolog/toplevel.rs
rename to src/prolog/machine/toplevel.rs
index 2fdd833501baa1b70c3c960431146372a12a1abc..ac33c5935590e6432832405ad512697bdb5b3fcb 100644 (file)
@@ -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<R: Read>(src: R, buffer: String, wam: &mut Machine)
                                -> Result<TopLevelPacket, SessionError>
 {
-    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);
 
index 31ed6bcf3b729accad51ac83211179d2cef6db9f..9ef14b8ac5e549d96c34ac6c376f00ff860e633b 100644 (file)
@@ -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;
index 07f7a5019e156a0c0e2b479403fff989eb6215da..0c94bc5fcf13ef896977bee19d558c62af5a1e10 100644 (file)
@@ -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;
index 5af37f57052b5f5a5dab1e77a4898a01ce476f85..b571872394584af4441bd0901fadf5ea09daffc4 100644 (file)
@@ -1,5 +1,7 @@
 use prolog_parser::ast::*;
 
+use prolog::clause_types::*;
+use prolog::forms::*;
 use prolog::instructions::*;
 use prolog::iterators::*;
 
index 1f3436b3680ebe2ba9c8a1327ffa5a69280928bc..641135b68e0c5b50ea6adf165ffcbfb1f3d26376 100644 (file)
@@ -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;
index 0c56bb1631166ff936f642a63acfe355d80564af..fdd92c495c9adc69aba8b592edf4d3823977ee94 100644 (file)
@@ -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;