refactor to actual modules
This commit is contained in:
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
481
src/prolog/clause_types.rs
Normal file
481
src/prolog/clause_types.rs
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(®);
|
||||
}
|
||||
|
||||
self.conflict_set = conflict_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type VariableFixture<'a> = (VarStatus, Vec<&'a Cell<VarReg>>);
|
||||
pub struct VariableFixtures<'a>(BTreeMap<Rc<Var>, VariableFixture<'a>>);
|
||||
|
||||
|
||||
245
src/prolog/forms.rs
Normal file
245
src/prolog/forms.rs
Normal file
@@ -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);
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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>>,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use prolog::instructions::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::vec::Vec;
|
||||
124
src/prolog/machine/code_repo.rs
Normal file
124
src/prolog/machine/code_repo.rs
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use prolog::instructions::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
533
src/prolog/machine/machine_indices.rs
Normal file
533
src/prolog/machine/machine_indices.rs
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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>,
|
||||
|
||||
242
src/prolog/machine/modules.rs
Normal file
242
src/prolog/machine/modules.rs
Normal file
@@ -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()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use prolog::instructions::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::vec::Vec;
|
||||
@@ -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};
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use prolog::clause_types::*;
|
||||
use prolog::forms::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::iterators::*;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user