&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
&SystemClauseType::FileTime => clause_name!("$file_time"),
+ &SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate) => {
+ clause_name!("$add_discontiguous_predicate")
+ }
&SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) => {
clause_name!("$add_dynamic_predicate")
}
+ &SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate) => {
+ clause_name!("$add_multifile_predicate")
+ }
&SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) => {
clause_name!("$add_goal_expansion_clause")
}
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
("$abolish_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)),
- ("$add_dynamic_predicate", 3) => {
+ ("$add_dynamic_predicate", 4) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate))
}
+ ("$add_multifile_predicate", 4) => {
+ Some(SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate))
+ }
+ ("$add_discontiguous_predicate", 4) => {
+ Some(SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate))
+ }
("$add_goal_expansion_clause", 4) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause))
}
#[derive(Debug, Clone)]
pub enum TopLevel {
- Declaration(Declaration),
Fact(Term), // Term, line_num, col_num
Predicate(Predicate),
Query(Vec<QueryTerm>),
pub trait ClauseInfo {
fn is_consistent(&self, clauses: &PredicateQueue) -> bool {
match clauses.first() {
- Some(cl) => self.name() == cl.name() && self.arity() == cl.arity(),
+ Some(cl) => self.name() == ClauseInfo::name(cl) && self.arity() == ClauseInfo::arity(cl),
None => true,
}
}
}
}
}
-
- pub fn arity(&self) -> usize {
- match self {
- &PredicateClause::Fact(ref term, ..) => term.arity(),
- &PredicateClause::Rule(ref rule, ..) => {
- if rule.head.0.as_str() == ":" && rule.head.1.len() == 2 {
- match (rule.head.1)[0].as_ref() {
- &Term::Constant(_, Constant::Atom(..)) => {}
- _ => {
- return 2;
- }
- }
-
- (rule.head.1)[1].arity()
- } else {
- 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(Debug, Clone)]
pub local_extensible_predicates: LocalExtensiblePredicates,
pub is_impromptu_module: bool,
pub listing_src: ListingSource,
- pub clause_assert_margin: usize,
}
// Module's and related types are defined in forms.
extensible_predicates: ExtensiblePredicates::new(),
local_extensible_predicates: LocalExtensiblePredicates::new(),
listing_src,
- clause_assert_margin: 0,
}
}
}
}
}
-#[derive(Debug)]
+#[derive(Clone, Debug)]
pub struct ClauseIndexInfo {
pub clause_start: usize,
pub opt_arg_index_key: OptArgIndexKey,
}
}
+#[derive(Clone, Copy, Debug)]
+pub struct PredicateInfo {
+ pub is_extensible: bool,
+ pub is_discontiguous: bool,
+ pub is_dynamic: bool,
+ pub is_multifile: bool,
+ pub has_clauses: bool,
+}
+
+impl Default for PredicateInfo {
+ #[inline]
+ fn default() -> Self {
+ PredicateInfo {
+ is_extensible: false,
+ is_discontiguous: false,
+ is_dynamic: false,
+ is_multifile: false,
+ has_clauses: false,
+ }
+ }
+}
+
+impl PredicateInfo {
+ #[inline]
+ pub fn compile_incrementally(&self) -> bool {
+ let base = self.is_extensible && self.has_clauses;
+ base && (self.is_discontiguous || self.is_multifile)
+ }
+
+ #[inline]
+ pub fn must_retract_local_clauses(&self) -> bool {
+ self.is_extensible && !self.is_discontiguous
+ }
+}
+
#[derive(Debug)]
pub struct PredicateSkeleton {
pub is_discontiguous: bool,
pub is_multifile: bool,
pub clauses: SliceDeque<ClauseIndexInfo>,
pub clause_clause_locs: SliceDeque<usize>,
+ pub clause_assert_margin: usize,
}
impl PredicateSkeleton {
is_multifile: false,
clauses: sdeq![],
clause_clause_locs: sdeq![],
+ clause_assert_margin: 0,
}
}
- /*
- #[inline]
- pub fn set_discontiguous(self, is_discontiguous: bool) -> Self {
- PredicateSkeleton {
- is_discontiguous,
- is_dynamic: self.is_dynamic,
- is_multifile: self.is_multifile,
- clauses: self.clauses,
- }
- }
- */
-
#[inline]
- pub fn set_dynamic(self, is_dynamic: bool) -> Self {
- PredicateSkeleton {
+ pub fn predicate_info(&self) -> PredicateInfo {
+ PredicateInfo {
+ is_extensible: true,
is_discontiguous: self.is_discontiguous,
- is_dynamic,
+ is_dynamic: self.is_dynamic,
is_multifile: self.is_multifile,
- clauses: self.clauses,
- clause_clause_locs: self.clause_clause_locs,
+ has_clauses: !self.clauses.is_empty(),
}
}
- /*
#[inline]
- pub fn set_multifile(self, is_multifile: bool) -> Self {
- PredicateSkeleton {
- is_discontiguous: self.is_discontiguous,
- is_dynamic: self.is_dynamic,
- is_multifile,
- clauses: self.clauses,
- }
+ pub fn reset(&mut self) {
+ self.clauses.clear();
+ self.clause_clause_locs.clear();
+ self.clause_assert_margin = 0;
}
- */
pub fn target_pos_of_clause_clause_loc(
&self,
clause_clause_loc: usize,
- clause_assert_margin: usize,
- ) -> usize {
- let search_result = self.clause_clause_locs[0..clause_assert_margin]
+ ) -> Option<usize> {
+ let search_result = self.clause_clause_locs[0..self.clause_assert_margin]
.binary_search_by(|loc| clause_clause_loc.cmp(&loc));
- search_result.unwrap_or_else(|_| {
- self.clause_clause_locs[clause_assert_margin..]
+ match search_result {
+ Ok(loc) => Some(loc),
+ Err(_) => self.clause_clause_locs[self.clause_assert_margin..]
.binary_search_by(|loc| loc.cmp(&clause_clause_loc))
- .unwrap()
- + clause_assert_margin
- })
+ .map(|loc| loc + self.clause_assert_margin)
+ .ok()
+ }
}
}
type_error(atom, Module, load/1)
).
compile_declaration(dynamic(Name/Arity), Evacuable) :-
+ !,
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ prolog_load_context(module, Module),
+ '$add_dynamic_predicate'(Module, Name, Arity, Evacuable).
+compile_declaration(dynamic(Module:Name/Arity), Evacuable) :-
+ must_be(atom, Module),
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ '$add_dynamic_predicate'(Module, Name, Arity, Evacuable).
+compile_declaration(multifile(Name/Arity), Evacuable) :-
+ !,
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ prolog_load_context(module, Module),
+ '$add_multifile_predicate'(Module, Name, Arity, Evacuable).
+compile_declaration(multifile(Module:Name/Arity), Evacuable) :-
+ must_be(atom, Module),
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ '$add_multifile_predicate'(Module, Name, Arity, Evacuable).
+compile_declaration(discontiguous(Name/Arity), Evacuable) :-
+ !,
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ prolog_load_context(module, Module),
+ '$add_discontiguous_predicate'(Module, Name, Arity, Evacuable).
+compile_declaration(discontiguous(Module:Name/Arity), Evacuable) :-
+ must_be(atom, Module),
must_be(atom, Name),
must_be(integer, Arity),
- '$add_dynamic_predicate'(Name, Arity, Evacuable).
+ '$add_discontiguous_predicate'(Module, Name, Arity, Evacuable).
compile_declaration(initialization(Goal), Evacuable) :-
prolog_load_context(module, Module),
assertz(Module:'$initialization_goals'(Goal)).
'$cpp_dynamic_property'(Module, Name, Arity).
check_predicate_property(multifile, Module, Name, Arity, multifile) :-
'$cpp_multifile_property'(Module, Name, Arity).
-check_predicate_property(discontiguous, Module, Name, Arity, multifile) :-
+check_predicate_property(discontiguous, Module, Name, Arity, discontiguous) :-
'$cpp_discontiguous_property'(Module, Name, Arity).
predicate_property(Callable, Property) :-
( var(Callable) ->
instantiation_error(load/1)
- ; functor(Callable, (:), 2), % Callable =.. [(:), Module, Callable0],
+ ; functor(Callable, (:), 2),
arg(1, Callable, Module),
arg(2, Callable, Callable0),
atom(Module) ->
use crate::codegen::*;
use crate::debray_allocator::*;
use crate::indexing::{merge_clause_index, remove_index};
-use crate::machine::load_state::set_code_index;
-use crate::machine::load_state::LoadState;
+use crate::machine::load_state::*;
use crate::machine::loader::*;
+use crate::machine::preprocessor::*;
use crate::machine::term_stream::*;
use crate::machine::*;
tl: &TopLevel,
) -> Result<Code, CompilationError> {
match tl {
- &TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
+ &TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses),
&TopLevel::Fact(ref fact, ..) => Ok(cg.compile_fact(fact)),
&TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
pub(super) fn compile_appendix(
code: &mut Code,
- queue: &VecDeque<TopLevel>,
+ mut queue: VecDeque<TopLevel>,
jmp_by_locs: Vec<usize>,
non_counted_bt: bool,
atom_tbl: TabledData<Atom>,
) -> Result<(), CompilationError> {
let mut jmp_by_locs = VecDeque::from(jmp_by_locs);
- for tl in queue.iter() {
+ while let Some(jmp_by_offset) = jmp_by_locs.pop_front() {
let code_len = code.len();
- let jmp_by_offset = jmp_by_locs.pop_front().unwrap();
match &mut code[jmp_by_offset] {
&mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => {
// false because the inner predicate is a one-off, hence not extensible.
let settings = CodeGenSettings::new(false, non_counted_bt);
-
let mut cg = CodeGenerator::<DebrayAllocator>::new(atom_tbl.clone(), settings);
- let decl_code = compile_relation(&mut cg, tl)?;
+
+ let tl = queue.pop_front().unwrap();
+ let decl_code = compile_relation(&mut cg, &tl)?;
jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len()));
code.extend(decl_code.into_iter());
0
}
-fn compile_standalone_clause(
- clause: PredicateClause,
- queue: VecDeque<TopLevel>,
- settings: CodeGenSettings,
- atom_tbl: TabledData<Atom>,
-) -> Result<StandaloneCompileResult, SessionError> {
- let mut cg = CodeGenerator::<DebrayAllocator>::new(atom_tbl.clone(), settings);
- let mut clause_code = cg.compile_predicate(&vec![clause])?;
-
- compile_appendix(
- &mut clause_code,
- &queue,
- cg.jmp_by_locs,
- settings.non_counted_bt,
- atom_tbl,
- )?;
-
- Ok(StandaloneCompileResult {
- clause_code,
- standalone_skeleton: cg.skeleton,
- })
-}
-
fn derelictize_try_me_else(
code: &mut Code,
index: usize,
None
}
-fn delete_from_dynamic_skeleton(
+fn delete_from_skeleton(
compilation_target: CompilationTarget,
key: PredicateKey,
skeleton: &mut PredicateSkeleton,
target_pos: usize,
retraction_info: &mut RetractionInfo,
) -> usize {
- let clause_clause_loc = skeleton.clause_clause_locs.remove(target_pos);
let clause_index_info = skeleton.clauses.remove(target_pos);
+ let clause_clause_loc = skeleton.clause_clause_locs.remove(target_pos);
+
+ if target_pos < skeleton.clause_assert_margin {
+ skeleton.clause_assert_margin -= 1;
+ }
- retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause(
+ retraction_info.push_record(RetractionRecord::RemovedSkeletonClause(
compilation_target,
key,
target_pos,
index_ptr_opt: Option<IndexPtr>,
retraction_info: &mut RetractionInfo,
) -> usize {
- let clause_clause_loc = delete_from_dynamic_skeleton(
+ let clause_clause_loc = delete_from_skeleton(
compilation_target.clone(),
key.clone(),
skeleton,
}
impl<'a> LoadState<'a> {
+ fn compile_standalone_clause(
+ &mut self,
+ term: Term,
+ settings: CodeGenSettings,
+ atom_tbl: TabledData<Atom>,
+ ) -> Result<StandaloneCompileResult, SessionError> {
+ let mut preprocessor = Preprocessor::new(self.wam.machine_st.flags);
+ let mut cg = CodeGenerator::<DebrayAllocator>::new(atom_tbl.clone(), settings);
+
+ let clause = self.try_term_to_tl(term, &mut preprocessor)?;
+ let queue = preprocessor.parse_queue(self)?;
+
+ let mut clause_code = cg.compile_predicate(&vec![clause])?;
+
+ compile_appendix(
+ &mut clause_code,
+ queue,
+ cg.jmp_by_locs,
+ settings.non_counted_bt,
+ atom_tbl,
+ )?;
+
+ Ok(StandaloneCompileResult {
+ clause_code,
+ standalone_skeleton: cg.skeleton,
+ })
+ }
+
fn compile(
&mut self,
key: PredicateKey,
- predicates: &PredicateQueue, // &Vec<PredicateClause>,
- queue: &VecDeque<TopLevel>,
+ predicates: &mut PredicateQueue,
settings: CodeGenSettings,
- ) -> Result<IndexPtr, SessionError> {
+ ) -> Result<(), SessionError> {
let code_index = self.get_or_insert_code_index(
key.clone(),
predicates.compilation_target.clone(),
let mut cg =
CodeGenerator::<DebrayAllocator>::new(self.wam.machine_st.atom_tbl.clone(), settings);
- let mut code = cg.compile_predicate(&predicates.predicates)?;
+ let mut clauses = vec![];
+ let mut preprocessor = Preprocessor::new(self.wam.machine_st.flags);
+
+ for term in predicates.predicates.drain(0 ..) {
+ clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
+ }
+
+ let queue = preprocessor.parse_queue(self)?;
+ let mut code = cg.compile_predicate(&clauses)?;
compile_appendix(
&mut code,
)?;
if settings.is_extensible {
+ let mut clause_clause_locs = sdeq![];
+
for clause_index_info in cg.skeleton.clauses.iter_mut() {
clause_index_info.clause_start += code_len;
clause_index_info.opt_arg_index_key += code_len;
+
+ clause_clause_locs.push_back(clause_index_info.clause_start);
}
match &mut code[0] {
));
skeleton.clauses.extend(cg.skeleton.clauses.into_iter());
+ skeleton.clause_clause_locs.extend_from_slice(
+ &clause_clause_locs[0 ..]
+ );
}
None => {
+ cg.skeleton.clause_clause_locs.extend_from_slice(
+ &clause_clause_locs[0 ..]
+ );
+
self.add_extensible_predicate(
key.clone(),
cg.skeleton,
);
}
}
+
+ let mut skeleton = PredicateSkeleton::new();
+ skeleton.clause_clause_locs = clause_clause_locs;
+
+ self.add_local_extensible_predicate(
+ predicates.compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ );
}
set_code_index(
);
self.wam.code_repo.code.extend(code.into_iter());
- Ok(code_index.get())
+ Ok(())
}
fn record_incremental_compile(
pub(super) fn incremental_compile_clause(
&mut self,
key: PredicateKey,
- clause: PredicateClause,
- queue: VecDeque<TopLevel>,
+ clause: Term,
compilation_target: CompilationTarget,
non_counted_bt: bool,
append_or_prepend: AppendOrPrepend,
- ) -> Result<IndexPtr, SessionError> {
+ ) -> Result<(), SessionError> {
self.record_incremental_compile(
key.clone(),
compilation_target.clone(),
append_or_prepend,
);
- let skeleton = match self
+ match self
.wam
.indices
.get_predicate_skeleton_mut(&compilation_target, &key)
{
- Some(skeleton) if !skeleton.clauses.is_empty() => skeleton,
+ Some(skeleton) if !skeleton.clauses.is_empty() => {},
_ => {
// true because this predicate is extensible.
let settings = CodeGenSettings::new(true, non_counted_bt);
let mut predicate_queue = predicate_queue![clause];
predicate_queue.compilation_target = compilation_target;
- return self.compile(key, &predicate_queue, &queue, settings);
+ return self.compile(key, &mut predicate_queue, settings);
}
};
let StandaloneCompileResult {
clause_code,
mut standalone_skeleton,
- } = compile_standalone_clause(clause, queue, settings, atom_tbl)?;
+ } = self.compile_standalone_clause(clause, settings, atom_tbl)?;
+
+ let code_len = self.wam.code_repo.code.len();
+
+ let skeleton = match self
+ .wam
+ .indices
+ .get_predicate_skeleton_mut(&compilation_target, &key)
+ {
+ Some(skeleton) if !skeleton.clauses.is_empty() => skeleton,
+ _ => unreachable!()
+ };
match append_or_prepend {
AppendOrPrepend::Append => {
- skeleton
- .clauses
- .push_back(standalone_skeleton.clauses.pop_back().unwrap());
+ let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap();
+ skeleton.clauses.push_back(clause_index_info);
+
+ skeleton.clause_clause_locs.push_back(code_len);
self.retraction_info
.push_record(RetractionRecord::SkeletonClausePopBack(
&mut self.retraction_info,
);
+ match self
+ .wam
+ .indices
+ .get_local_predicate_skeleton_mut(
+ &self.compilation_target,
+ compilation_target.clone(),
+ key.clone(),
+ )
+ {
+ Some(skeleton) => {
+ self.retraction_info.push_record(
+ RetractionRecord::SkeletonLocalClauseClausePopBack(
+ self.compilation_target.clone(),
+ compilation_target.clone(),
+ key.clone(),
+ ),
+ );
+
+ skeleton.clause_clause_locs.push_back(code_len);
+ }
+ None => {
+ let mut skeleton = PredicateSkeleton::new();
+ skeleton.clause_clause_locs.push_back(code_len);
+
+ self.add_local_extensible_predicate(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ );
+ }
+ }
+
let code_index = self.get_or_insert_code_index(
key.clone(),
compilation_target.clone(),
);
}
- Ok(code_index.get())
+ Ok(())
}
AppendOrPrepend::Prepend => {
- skeleton
- .clauses
- .push_front(standalone_skeleton.clauses.pop_back().unwrap());
+ let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap();
+ skeleton.clauses.push_front(clause_index_info);
+
+ skeleton.clause_clause_locs.push_front(code_len);
+ skeleton.clause_assert_margin += 1;
self.retraction_info
.push_record(RetractionRecord::SkeletonClausePopFront(
&mut self.retraction_info,
);
+ match self
+ .wam
+ .indices
+ .get_local_predicate_skeleton_mut(
+ &self.compilation_target,
+ compilation_target.clone(),
+ key.clone(),
+ )
+ {
+ Some(skeleton) => {
+ self.retraction_info.push_record(
+ RetractionRecord::SkeletonLocalClauseClausePopFront(
+ self.compilation_target.clone(),
+ compilation_target.clone(),
+ key.clone(),
+ ),
+ );
+
+ skeleton.clause_clause_locs.push_front(code_len);
+ }
+ None => {
+ let mut skeleton = PredicateSkeleton::new();
+ skeleton.clause_clause_locs.push_front(code_len);
+
+ self.add_local_extensible_predicate(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ );
+ }
+ }
+
let code_index = self.get_or_insert_code_index(
key.clone(),
compilation_target.clone(),
IndexPtr::Index(threaded_choice_instr_loc),
);
- Ok(IndexPtr::Index(threaded_choice_instr_loc))
+ Ok(())
}
}
}
skeleton.clauses[target_pos + 1].clause_start =
skeleton.clauses[target_pos].clause_start;
- return delete_from_dynamic_skeleton(
+ return delete_from_skeleton(
self.compilation_target.clone(),
key,
skeleton,
append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> {
let clause_predicates = clause_clauses.map(|(head, body)| {
- PredicateClause::Fact(Term::Clause(
+ Term::Clause(
Cell::default(),
clause_name!("$clause"),
vec![Box::new(head), Box::new(body)],
None,
- ))
+ )
});
let clause_clause_compilation_target = match compilation_target {
_ => compilation_target.clone(),
};
- let mut clause_clause_locs = sdeq![];
-
- for clause_predicate in clause_predicates {
- clause_clause_locs.push_back(self.load_state.wam.code_repo.code.len());
+ let mut num_clause_predicates = 0;
+ for clause_term in clause_predicates {
self.load_state.incremental_compile_clause(
(clause_name!("$clause"), 2),
- clause_predicate,
- VecDeque::new(),
+ clause_term,
clause_clause_compilation_target.clone(),
false, // non_counted_bt is false.
append_or_prepend,
)?;
+
+ num_clause_predicates += 1;
}
- match self.load_state.wam.indices.get_predicate_skeleton_mut(
- &clause_clause_compilation_target,
- &(clause_name!("$clause"), 2),
- ) {
+ let locs_vec: Vec<_> = match self
+ .load_state
+ .wam
+ .indices
+ .get_predicate_skeleton_mut(&compilation_target, &key)
+ {
Some(skeleton) if append_or_prepend.is_append() => {
- self.load_state.retraction_info.push_record(
- RetractionRecord::SkeletonClauseClausesTruncateBack(
- clause_clause_compilation_target.clone(),
- (clause_name!("$clause"), 2),
- skeleton.clause_clause_locs.len(),
- ),
- );
-
- skeleton
- .clause_clause_locs
- .extend_from_slice(&clause_clause_locs[0..]);
+ let tail_num = skeleton.clause_clause_locs.len() - num_clause_predicates;
+ skeleton.clause_clause_locs[tail_num ..]
+ .iter()
+ .cloned()
+ .collect()
}
Some(skeleton) => {
- self.load_state.retraction_info.push_record(
- RetractionRecord::SkeletonClauseClausesTruncateFront(
- clause_clause_compilation_target.clone(),
- (clause_name!("$clause"), 2),
- skeleton.clause_clause_locs.len(),
- ),
- );
-
- for loc in clause_clause_locs.iter() {
- skeleton.clause_clause_locs.push_front(*loc);
- }
+ skeleton.clause_clause_locs[0 .. num_clause_predicates]
+ .iter()
+ .cloned()
+ .collect()
}
None => {
- unreachable!();
+ unreachable!()
}
- }
+ };
- match self
- .load_state
- .wam
- .indices
- .get_predicate_skeleton_mut(&compilation_target, &key)
- {
+ match self.load_state.wam.indices.get_predicate_skeleton_mut(
+ &clause_clause_compilation_target,
+ &(clause_name!("$clause"), 2),
+ ) {
Some(skeleton) if append_or_prepend.is_append() => {
- self.load_state.retraction_info.push_record(
- RetractionRecord::SkeletonClauseClausesTruncateBack(
- compilation_target.clone(),
- key.clone(),
- skeleton.clause_clause_locs.len(),
- ),
- );
+ for _ in 0 .. num_clause_predicates {
+ skeleton.clause_clause_locs.pop_back();
+ }
- skeleton.clause_clause_locs.append(&mut clause_clause_locs);
+ for loc in locs_vec {
+ skeleton.clause_clause_locs.push_back(loc);
+ }
}
Some(skeleton) => {
- self.load_state.retraction_info.push_record(
- RetractionRecord::SkeletonClauseClausesTruncateFront(
- compilation_target.clone(),
- key.clone(),
- skeleton.clause_clause_locs.len(),
- ),
- );
-
- for loc in clause_clause_locs.iter() {
- skeleton.clause_clause_locs.push_front(*loc);
+ for _ in 0 .. num_clause_predicates {
+ skeleton.clause_clause_locs.pop_front();
}
- self.load_state.increment_clause_assert_margin(
- clause_clause_compilation_target,
- clause_clause_locs.len(),
- );
+ for loc in locs_vec.into_iter().rev() {
+ skeleton.clause_clause_locs.push_front(loc);
+ }
}
None => {
- unreachable!()
+ unreachable!();
}
}
}
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
- let queue = self.preprocessor.parse_queue(&mut self.load_state)?;
-
let key = self
.predicates
.first()
.and_then(|cl| {
- let arity = cl.arity();
- cl.name().map(|name| (name, arity))
+ let arity = ClauseInfo::arity(cl);
+ ClauseInfo::name(cl).map(|name| (name, arity))
})
.ok_or(SessionError::NamelessEntry)?;
- let (is_dynamic, is_extensible) = self
+ let mut predicate_info = self
.load_state
.wam
.indices
.get_predicate_skeleton(&self.predicates.compilation_target, &key)
- .map(|skeleton| (skeleton.is_dynamic, true))
- .unwrap_or((false, false));
+ .map(|skeleton| skeleton.predicate_info())
+ .unwrap_or_default();
+ let local_predicate_info = self
+ .load_state
+ .wam
+ .indices
+ .get_local_predicate_skeleton(
+ &self.load_state.compilation_target,
+ self.predicates.compilation_target.clone(),
+ key.clone(),
+ )
+ .map(|skeleton| skeleton.predicate_info())
+ .unwrap_or_default();
+
+ if predicate_info.must_retract_local_clauses() {
+ self.retract_local_clauses(&key, predicate_info.is_dynamic);
+ }
+
+ let do_incremental_compile =
+ if self.load_state.compilation_target == self.predicates.compilation_target {
+ predicate_info.compile_incrementally()
+ } else {
+ local_predicate_info.is_multifile && predicate_info.compile_incrementally()
+ };
+
+ let predicates_len = self.predicates.len();
let non_counted_bt = self.non_counted_bt_preds.contains(&key);
- let settings = CodeGenSettings::new(is_extensible, non_counted_bt);
- self.load_state
- .compile(key.clone(), &self.predicates, &queue, settings)?;
+ if do_incremental_compile {
+ for term in self.predicates.predicates.drain(0 ..) {
+ self.load_state.incremental_compile_clause(
+ key.clone(),
+ term,
+ self.predicates.compilation_target.clone(),
+ non_counted_bt,
+ AppendOrPrepend::Append,
+ )?;
+ }
+ } else {
+ if self.load_state.compilation_target != self.predicates.compilation_target {
+ if !local_predicate_info.is_extensible {
+ if predicate_info.is_multifile {
+ println!("Warning: overwriting multifile predicate {}:{}/{} because \
+ it was not locally declared multifile.",
+ self.predicates.compilation_target, key.0, key.1);
+ }
+
+ if let Some(skeleton) = self.load_state
+ .wam
+ .indices
+ .remove_predicate_skeleton(
+ &self.predicates.compilation_target,
+ &key,
+ )
+ {
+ if predicate_info.is_dynamic {
+ let clause_clause_compilation_target =
+ match &self.predicates.compilation_target {
+ CompilationTarget::User => {
+ CompilationTarget::Module(clause_name!("builtins"))
+ }
+ module => {
+ module.clone()
+ }
+ };
+
+ self.load_state.retract_local_clauses_by_locs(
+ clause_clause_compilation_target,
+ (clause_name!("$clause"), 2),
+ (0 .. skeleton.clauses.len()).map(Some).collect(),
+ );
+
+ predicate_info.is_dynamic = false;
+ }
+
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::RemovedSkeleton(
+ self.predicates.compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ ),
+ );
+ }
+ }
+ }
- if is_dynamic {
- let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter();
- let compilation_target = self.predicates.compilation_target.clone();
+ let settings = CodeGenSettings::new(predicate_info.is_extensible, non_counted_bt);
+ self.load_state.compile(key.clone(), &mut self.predicates, settings)?;
+ }
+
+ if predicate_info.is_dynamic {
+ let clauses_vec: Vec<_> = self.clause_clauses
+ .drain(0 .. predicates_len)
+ .collect();
- self.compile_clause_clauses(key, compilation_target, iter, AppendOrPrepend::Append)?;
+ self.compile_clause_clauses(
+ key,
+ self.predicates.compilation_target.clone(),
+ clauses_vec.into_iter(),
+ AppendOrPrepend::Append,
+ )?;
}
- Ok(self.predicates.clear())
+ Ok(())
}
}
use crate::machine::machine_indices::*;
+use crate::machine::preprocessor::*;
use crate::machine::*;
+use crate::machine::term_stream::*;
+
use prolog_parser::clause_name;
-use crate::machine::term_stream::*;
use indexmap::IndexSet;
-
use ref_thread_local::RefThreadLocal;
+use slice_deque::{sdeq, SliceDeque};
type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>;
}
impl<'a> LoadState<'a> {
- #[inline]
- pub(super) fn increment_clause_assert_margin(
+ pub(super) fn retract_local_clauses(
&mut self,
compilation_target: CompilationTarget,
- incr: usize,
+ key: PredicateKey,
+ clause_locs: &SliceDeque<usize>,
) {
- match compilation_target {
- CompilationTarget::User => {}
- CompilationTarget::Module(module_name) => {
- self.wam
- .indices
- .modules
- .get_mut(&module_name)
- .map(|module| module.clause_assert_margin += incr);
+ let clause_target_poses: Vec<_> = self
+ .wam
+ .indices
+ .get_predicate_skeleton(&compilation_target, &key)
+ .map(|skeleton| {
+ clause_locs
+ .iter()
+ .map(|clause_clause_loc| {
+ skeleton.target_pos_of_clause_clause_loc(
+ *clause_clause_loc,
+ )
+ })
+ .collect()
+ }).unwrap();
+
+ self.retract_local_clauses_by_locs(
+ compilation_target,
+ key,
+ clause_target_poses,
+ );
+ }
- self.retraction_info
- .push_record(RetractionRecord::IncreasedClauseAssertMargin(
- module_name,
- incr,
- ));
+ pub(super) fn retract_local_clauses_by_locs(
+ &mut self,
+ compilation_target: CompilationTarget,
+ key: PredicateKey,
+ mut clause_target_poses: Vec<Option<usize>>,
+ ) {
+ let old_compilation_target = mem::replace(
+ &mut self.compilation_target,
+ compilation_target,
+ );
+
+ while let Some(target_pos_opt) = clause_target_poses.pop() {
+ match target_pos_opt {
+ Some(target_pos) => {
+ self.retract_clause(key.clone(), target_pos);
+ }
+ None => {
+ // Here because the clause was been removed
+ // earlier, e.g., by retract, without updating the
+ // local skeleton. In this case, do nothing.
+ }
}
}
+
+ self.compilation_target = old_compilation_target;
+ }
+
+ pub(super) fn retract_local_clause_clauses(
+ &mut self,
+ clause_clause_compilation_target: CompilationTarget,
+ clause_locs: &SliceDeque<usize>,
+ ) {
+ let key = (clause_name!("$clause"), 2);
+
+ match self
+ .wam
+ .indices
+ .get_local_predicate_skeleton_mut(
+ &self.compilation_target,
+ clause_clause_compilation_target.clone(),
+ key.clone(),
+ )
+ {
+ Some(skeleton) => {
+ self.retraction_info.push_record(
+ RetractionRecord::RemovedLocalSkeletonClauseLocations(
+ self.compilation_target.clone(),
+ clause_clause_compilation_target.clone(),
+ key.clone(),
+ mem::replace(&mut skeleton.clause_clause_locs, sdeq![]),
+ ),
+ );
+
+ skeleton.reset();
+ }
+ None => {
+ // The local skeleton might be removed when reloading
+ // or redefining a module, in which case no retraction
+ // record is necessary.
+ }
+ };
+
+ self.retract_local_clauses(
+ clause_clause_compilation_target,
+ key,
+ &clause_locs,
+ );
+ }
+
+ pub(super) fn try_term_to_tl(
+ &mut self,
+ term: Term,
+ preprocessor: &mut Preprocessor,
+ ) -> Result<PredicateClause, SessionError> {
+ let tl = preprocessor.try_term_to_tl(
+ self,
+ term,
+ CutContext::BlocksCuts,
+ )?;
+
+ Ok(match tl {
+ TopLevel::Fact(fact) => PredicateClause::Fact(fact),
+ TopLevel::Rule(rule) => PredicateClause::Rule(rule),
+ TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact),
+ _ => unreachable!(),
+ })
}
#[inline]
.extensible_predicates
.insert(key.clone(), skeleton);
- self.retraction_info
- .push_record(RetractionRecord::AddedUserExtensiblePredicate(key));
+ let record = RetractionRecord::AddedExtensiblePredicate(
+ CompilationTarget::User,
+ key,
+ );
+
+ self.retraction_info.push_record(record);
}
CompilationTarget::Module(module_name) => {
if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
- module.extensible_predicates.insert(key.clone(), skeleton);
+ module
+ .extensible_predicates
+ .insert(key.clone(), skeleton);
- self.retraction_info.push_record(
- RetractionRecord::AddedModuleExtensiblePredicate(module_name, key),
+ let record = RetractionRecord::AddedExtensiblePredicate(
+ CompilationTarget::Module(module_name),
+ key,
);
+
+ self.retraction_info.push_record(record);
+ } else {
+ unreachable!()
+ }
+ }
+ }
+ }
+
+ #[inline]
+ pub(super) fn add_local_extensible_predicate(
+ &mut self,
+ local_compilation_target: CompilationTarget,
+ key: PredicateKey,
+ skeleton: PredicateSkeleton,
+ ) {
+ match self.compilation_target.clone() {
+ CompilationTarget::User => {
+ self.wam
+ .indices
+ .local_extensible_predicates
+ .insert((local_compilation_target.clone(), key.clone()), skeleton);
+ }
+ CompilationTarget::Module(module_name) => {
+ if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
+ module
+ .local_extensible_predicates
+ .insert((local_compilation_target.clone(), key.clone()), skeleton);
} else {
unreachable!()
}
}
}
None => {
- let module_decl = ModuleDecl {
- name: module_name.clone(),
- exports: vec![],
- };
-
- let listing_src = ListingSource::DynamicallyGenerated;
- let mut module = Module::new(module_decl, listing_src);
+ self.add_dynamically_generated_module(&module_name);
- module.meta_predicates.insert(key.clone(), meta_specs);
+ if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
+ module.meta_predicates.insert(key.clone(), meta_specs);
+ } else {
+ unreachable!()
+ }
self.retraction_info
.push_record(RetractionRecord::AddedMetaPredicate(
module_name.clone(),
key,
));
-
- self.retraction_info
- .push_record(RetractionRecord::AddedModule(module_name.clone()));
-
- self.wam.indices.modules.insert(module_name, module);
}
}
}
}
}
+ pub(super) fn add_dynamically_generated_module(&mut self, module_name: &ClauseName) {
+ let module_decl = ModuleDecl {
+ name: module_name.clone(),
+ exports: vec![],
+ };
+
+ let listing_src = ListingSource::DynamicallyGenerated;
+ let module = Module::new(module_decl, listing_src);
+
+ self.retraction_info
+ .push_record(RetractionRecord::AddedModule(module_name.clone()));
+
+ self.wam.indices.modules.insert(module_name.clone(), module);
+ }
+
fn import_builtins_in_module(
&mut self,
code_dir: &mut CodeDir,
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
let module_name = module_decl.name.clone();
- let mut module = match self.wam.indices.modules.remove(&module_name) {
- Some(mut module) => {
- let old_module_decl = mem::replace(&mut module.module_decl, module_decl);
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(module) => {
+ let old_module_decl = mem::replace(&mut module.module_decl, module_decl.clone());
- self.retraction_info
- .push_record(RetractionRecord::ReplacedModule(
- old_module_decl,
- listing_src.clone(),
- ));
+ let local_extensible_predicates = mem::replace(
+ &mut module.local_extensible_predicates,
+ LocalExtensiblePredicates::new(),
+ );
+
+ for ((compilation_target, key), skeleton) in local_extensible_predicates.iter() {
+ self.retract_local_clauses(
+ compilation_target.clone(),
+ key.clone(),
+ &skeleton.clause_clause_locs,
+ );
+
+ let is_dynamic = self
+ .wam
+ .indices
+ .get_predicate_skeleton(&compilation_target, &key)
+ .map(|skeleton| skeleton.is_dynamic)
+ .unwrap_or(false);
+
+ if is_dynamic {
+ let clause_clause_compilation_target = match compilation_target {
+ CompilationTarget::User => {
+ CompilationTarget::Module(clause_name!("builtins"))
+ }
+ module => {
+ module.clone()
+ }
+ };
+
+ self.retract_local_clause_clauses(
+ clause_clause_compilation_target,
+ &skeleton.clause_clause_locs,
+ );
+ }
+ }
+ self.retraction_info.push_record(RetractionRecord::ReplacedModule(
+ old_module_decl,
+ listing_src.clone(),
+ local_extensible_predicates,
+ ));
+ }
+ None => {}
+ }
+
+ let mut module = match self.wam.indices.modules.remove(&module_name) {
+ Some(mut module) => {
module.listing_src = listing_src;
module
}
use crate::machine::*;
use indexmap::IndexSet;
+use slice_deque::{sdeq, SliceDeque};
use std::cell::Cell;
use std::convert::TryFrom;
* compiling inline disjunctions.
*
* Since the loader can operate incrementally, it uses an intermittent
- * structure to rebuild the loader between
- * invocations. TopLevelBatchWorker needs access to a &'a mut Machine
- * for as long as it lives, and we can't have copies of &'a mut
- * Machine distributed among multiple owners.
+ * structure to rebuild the loader between invocations. Preprocessor
+ * needs access to a &'a mut Machine for as long as it lives, and we
+ * can't have copies of &'a mut Machine distributed among multiple
+ * owners.
*
* When loading a module, we modify the records of the WAM with the
* location of new predicates, with new meta-predicate information,
AddedMetaPredicate(ClauseName, PredicateKey),
ReplacedMetaPredicate(ClauseName, ClauseName, Vec<MetaSpec>),
AddedModule(ClauseName),
- ReplacedModule(ModuleDecl, ListingSource),
- AddedModuleDynamicPredicate(ClauseName, PredicateKey),
- AddedModuleExtensiblePredicate(ClauseName, PredicateKey),
+ ReplacedModule(ModuleDecl, ListingSource, LocalExtensiblePredicates),
AppendedModuleExtensiblePredicate(ClauseName, PredicateKey),
PrependedModuleExtensiblePredicate(ClauseName, PredicateKey),
AddedModuleOp(ClauseName, OpDecl),
ReplacedModuleOp(ClauseName, OpDecl, usize, Specifier),
AddedModulePredicate(ClauseName, PredicateKey),
ReplacedModulePredicate(ClauseName, PredicateKey, IndexPtr),
- AddedUserDynamicPredicate(PredicateKey),
+ AddedDiscontiguousPredicate(CompilationTarget, PredicateKey),
+ AddedDynamicPredicate(CompilationTarget, PredicateKey),
+ AddedMultifilePredicate(CompilationTarget, PredicateKey),
AddedUserOp(OpDecl),
ReplacedUserOp(OpDecl, usize, Specifier),
- AddedUserExtensiblePredicate(PredicateKey),
+ AddedExtensiblePredicate(CompilationTarget, PredicateKey),
AppendedUserExtensiblePredicate(PredicateKey),
PrependedUserExtensiblePredicate(PredicateKey),
AddedUserPredicate(PredicateKey),
ModifiedTryMeElse(usize, usize),
ModifiedRetryMeElse(usize, usize),
ModifiedRevJmpBy(usize, usize),
- IncreasedClauseAssertMargin(ClauseName, usize),
- SkeletonClauseClausesTruncateBack(CompilationTarget, PredicateKey, usize),
- SkeletonClauseClausesTruncateFront(CompilationTarget, PredicateKey, usize),
SkeletonClausePopBack(CompilationTarget, PredicateKey),
SkeletonClausePopFront(CompilationTarget, PredicateKey),
+ SkeletonLocalClauseClausePopBack(CompilationTarget, CompilationTarget, PredicateKey),
+ SkeletonLocalClauseClausePopFront(CompilationTarget, CompilationTarget, PredicateKey),
SkeletonClauseTruncateBack(CompilationTarget, PredicateKey, usize),
SkeletonClauseStartReplaced(CompilationTarget, PredicateKey, usize, usize),
- RemovedDynamicSkeletonClause(
+ RemovedSkeletonClause(
CompilationTarget,
PredicateKey,
usize,
usize,
),
ReplacedIndexingLine(usize, Vec<IndexingLine>),
+ RemovedLocalSkeletonClauseLocations(
+ CompilationTarget,
+ CompilationTarget,
+ PredicateKey,
+ SliceDeque<usize>,
+ ),
+ RemovedSkeleton(CompilationTarget, PredicateKey, PredicateSkeleton),
}
/*
Self {
orig_code_extent,
- records: mem::replace(&mut self.records, vec![]), //BTreeMap::new()),
+ records: mem::replace(&mut self.records, vec![]),
}
}
}
RetractionRecord::AddedModule(module_name) => {
self.wam.indices.modules.remove(&module_name);
}
- RetractionRecord::ReplacedModule(module_decl, listing_src) => {
+ RetractionRecord::ReplacedModule(
+ module_decl,
+ listing_src,
+ local_extensible_predicates,
+ ) => {
match self.wam.indices.modules.get_mut(&module_decl.name) {
Some(ref mut module) => {
module.module_decl = module_decl;
module.listing_src = listing_src;
+ module.local_extensible_predicates = local_extensible_predicates;
}
_ => {
unreachable!()
}
}
}
- RetractionRecord::AddedModuleDynamicPredicate(module_name, key) => {
- match self.wam.indices.modules.get_mut(&module_name) {
- Some(ref mut module) => {
- module.extensible_predicates.get_mut(&key).map(|skeleton| {
- skeleton.is_dynamic = false;
- });
+ RetractionRecord::AddedDiscontiguousPredicate(compilation_target, key) => {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.wam
+ .indices
+ .extensible_predicates
+ .get_mut(&key)
+ .map(|skeleton| {
+ skeleton.is_discontiguous = false;
+ });
+ }
+ CompilationTarget::Module(module_name) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.extensible_predicates.get_mut(&key).map(|skeleton| {
+ skeleton.is_discontiguous = false;
+ });
+ }
+ None => {}
+ }
}
- None => {}
}
}
- RetractionRecord::AddedModuleExtensiblePredicate(module_name, key) => {
- self.wam
- .indices
- .remove_predicate_skeleton(&CompilationTarget::Module(module_name), &key);
+ RetractionRecord::AddedDynamicPredicate(compilation_target, key) => {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.wam
+ .indices
+ .extensible_predicates
+ .get_mut(&key)
+ .map(|skeleton| {
+ skeleton.is_dynamic = false;
+ });
+ }
+ CompilationTarget::Module(module_name) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.extensible_predicates.get_mut(&key).map(|skeleton| {
+ skeleton.is_dynamic = false;
+ });
+ }
+ None => {}
+ }
+ }
+ }
+ }
+ RetractionRecord::AddedMultifilePredicate(compilation_target, key) => {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.wam
+ .indices
+ .extensible_predicates
+ .get_mut(&key)
+ .map(|skeleton| {
+ skeleton.is_multifile = false;
+ });
+ }
+ CompilationTarget::Module(module_name) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.extensible_predicates.get_mut(&key).map(|skeleton| {
+ skeleton.is_multifile = false;
+ });
+ }
+ None => {}
+ }
+ }
+ }
}
RetractionRecord::AppendedModuleExtensiblePredicate(module_name, key) => {
self.wam
None => {}
}
}
- RetractionRecord::AddedUserDynamicPredicate(key) => {
- self.wam
- .indices
- .extensible_predicates
- .get_mut(&key)
- .map(|skeleton| {
- skeleton.is_dynamic = false;
- });
- }
- RetractionRecord::AddedUserExtensiblePredicate(key) => {
+ RetractionRecord::AddedExtensiblePredicate(compilation_target, key) => {
self.wam
.indices
- .remove_predicate_skeleton(&CompilationTarget::User, &key);
+ .remove_predicate_skeleton(&compilation_target, &key);
}
RetractionRecord::AppendedUserExtensiblePredicate(key) => {
self.wam
self.wam.code_repo.code[instr_loc] =
Line::Control(ControlInstruction::RevJmpBy(o));
}
- RetractionRecord::IncreasedClauseAssertMargin(module_name, incr) => {
- if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
- module.clause_assert_margin -= incr;
- }
- }
- RetractionRecord::SkeletonClauseClausesTruncateFront(
- compilation_target,
- key,
- len,
- ) => {
+ RetractionRecord::SkeletonClausePopBack(compilation_target, key) => {
match self
.wam
.indices
.get_predicate_skeleton_mut(&compilation_target, &key)
{
Some(skeleton) => {
- skeleton.clause_clause_locs.truncate_front(len);
- }
- None => {}
- }
-
- let compilation_target = match compilation_target {
- CompilationTarget::User => {
- CompilationTarget::Module(clause_name!("builtins"))
- }
- _ => compilation_target,
- };
-
- match self
- .wam
- .indices
- .get_predicate_skeleton_mut(&compilation_target, &(clause_name!("$clause"), 2))
- {
- Some(skeleton) => {
- skeleton.clause_clause_locs.truncate_front(len);
+ skeleton.clauses.pop_back();
+ skeleton.clause_clause_locs.pop_back();
}
None => {}
}
}
- RetractionRecord::SkeletonClauseClausesTruncateBack(
- compilation_target,
- key,
- len,
- ) => {
+ RetractionRecord::SkeletonClausePopFront(compilation_target, key) => {
match self
.wam
.indices
.get_predicate_skeleton_mut(&compilation_target, &key)
{
Some(skeleton) => {
- skeleton.clause_clause_locs.truncate_back(len);
- }
- None => {}
- }
-
- let compilation_target = match compilation_target {
- CompilationTarget::User => {
- CompilationTarget::Module(clause_name!("builtins"))
- }
- _ => compilation_target,
- };
-
- match self
- .wam
- .indices
- .get_predicate_skeleton_mut(&compilation_target, &(clause_name!("$clause"), 2))
- {
- Some(skeleton) => {
- skeleton.clause_clause_locs.truncate_back(len);
+ skeleton.clauses.pop_front();
+ skeleton.clause_clause_locs.pop_front();
+ skeleton.clause_assert_margin -= 1;
}
None => {}
}
}
- RetractionRecord::SkeletonClausePopBack(compilation_target, key) => {
+ RetractionRecord::SkeletonLocalClauseClausePopFront(
+ src_compilation_target, local_compilation_target, key,
+ ) => {
match self
.wam
.indices
- .get_predicate_skeleton_mut(&compilation_target, &key)
+ .get_local_predicate_skeleton_mut(
+ &src_compilation_target,
+ local_compilation_target,
+ key,
+ )
{
Some(skeleton) => {
- skeleton.clauses.pop_back();
+ skeleton.clause_clause_locs.pop_front();
}
None => {}
}
}
- RetractionRecord::SkeletonClausePopFront(compilation_target, key) => {
+ RetractionRecord::SkeletonLocalClauseClausePopBack(
+ src_compilation_target, local_compilation_target, key,
+ ) => {
match self
.wam
.indices
- .get_predicate_skeleton_mut(&compilation_target, &key)
+ .get_local_predicate_skeleton_mut(
+ &src_compilation_target,
+ local_compilation_target,
+ key,
+ )
{
Some(skeleton) => {
- skeleton.clauses.pop_front();
+ skeleton.clause_clause_locs.pop_back();
}
None => {}
}
{
Some(skeleton) => {
skeleton.clauses.truncate_back(len);
+ skeleton.clause_clause_locs.truncate_back(len);
}
None => {}
}
None => {}
}
}
- RetractionRecord::RemovedDynamicSkeletonClause(
+ RetractionRecord::RemovedSkeletonClause(
compilation_target,
key,
target_pos,
RetractionRecord::ReplacedIndexingLine(index_loc, indexing_code) => {
self.wam.code_repo.code[index_loc] = Line::IndexingCode(indexing_code);
}
+ RetractionRecord::RemovedLocalSkeletonClauseLocations(
+ compilation_target,
+ local_compilation_target,
+ key,
+ clause_locs,
+ ) => {
+ match self
+ .wam
+ .indices
+ .get_local_predicate_skeleton_mut(
+ &compilation_target,
+ local_compilation_target,
+ key,
+ )
+ {
+ Some(skeleton) => skeleton.clause_clause_locs = clause_locs,
+ None => {}
+ }
+ }
+ RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton) => {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.wam.indices.extensible_predicates.insert(key, skeleton);
+ }
+ CompilationTarget::Module(module_name) => {
+ if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
+ module.extensible_predicates.insert(key, skeleton);
+ }
+ }
+ }
+ }
}
}
}
}
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum CompilationTarget {
Module(ClauseName),
User,
}
#[inline]
- pub(super) fn module_name(&self) -> ClauseName {
+ pub fn module_name(&self) -> ClauseName {
match self {
CompilationTarget::User => {
clause_name!("user")
}
pub struct PredicateQueue {
- pub(super) predicates: Vec<PredicateClause>,
+ pub(super) predicates: Vec<Term>,
pub(super) compilation_target: CompilationTarget,
}
impl PredicateQueue {
#[inline]
- pub(super) fn push(&mut self, clause: PredicateClause) {
+ pub(super) fn push(&mut self, clause: Term) {
self.predicates.push(clause);
}
#[inline]
- pub(super) fn extend(&mut self, iter: impl Iterator<Item = PredicateClause>) {
- self.predicates.extend(iter);
- }
-
- #[inline]
- pub(super) fn clear(&mut self) {
- self.predicates.clear();
- }
-
- #[inline]
- pub(crate) fn first(&self) -> Option<&PredicateClause> {
+ pub(crate) fn first(&self) -> Option<&Term> {
self.predicates.first()
}
compilation_target: self.compilation_target.take(),
}
}
+
+ #[inline]
+ pub(super) fn len(&self) -> usize {
+ self.predicates.len()
+ }
}
macro_rules! predicate_queue {
pub(super) clause_clauses: Vec<(Term, Term)>,
term_stream: TermStream,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
- pub(super) preprocessor: Preprocessor,
}
impl<'a, TS: TermStream> Loader<'a, TS> {
#[inline]
pub(super) fn new(term_stream: TS, wam: &'a mut Machine) -> Self {
- let flags = wam.machine_st.flags;
let load_state = LoadState {
compilation_target: CompilationTarget::User,
module_op_exports: vec![],
load_state,
term_stream,
non_counted_bt_preds: IndexSet::new(),
- preprocessor: Preprocessor::new(flags),
predicates: predicate_queue![],
clause_clauses: vec![],
}
self.compile_and_submit()?;
}
- let tl = self.preprocessor.try_term_to_tl(
- &mut self.load_state,
- term,
- CutContext::BlocksCuts,
- )?;
+ let term = match term {
+ Term::Clause(_, name, terms, _)
+ if name.as_str() == ":-" && terms.len() == 1 => {
+ return Ok(Some(setup_declaration(&self.load_state, terms)?));
+ },
+ term => term,
+ };
- match tl {
- TopLevel::Fact(fact) => self.predicates.push(PredicateClause::Fact(fact)),
- TopLevel::Rule(rule) => self.predicates.push(PredicateClause::Rule(rule)),
- TopLevel::Predicate(pred) => self.predicates.extend(pred.into_iter()),
- TopLevel::Declaration(decl) => return Ok(Some(decl)),
- TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact),
- }
+ self.predicates.push(term);
}
Ok(None)
pub(super) fn load_decl(&mut self, decl: Declaration) -> Result<(), SessionError> {
match decl {
Declaration::Dynamic(name, arity) => {
- self.add_dynamic_predicate(name, arity);
+ let compilation_target = self.load_state.compilation_target.clone();
+ self.add_dynamic_predicate(compilation_target, name, arity)?;
}
Declaration::MetaPredicate(module_name, name, meta_specs) => {
self.load_state
Ok(())
}
- fn add_dynamic_predicate(&mut self, name: ClauseName, arity: usize) {
+ fn add_extensible_predicate_declaration(
+ &mut self,
+ compilation_target: CompilationTarget,
+ name: ClauseName,
+ arity: usize,
+ flag_accessor: impl Fn(&mut PredicateSkeleton) -> &mut bool,
+ retraction_fn: impl Fn(CompilationTarget, PredicateKey) -> RetractionRecord,
+ ) -> Result<(), SessionError> {
let key = (name, arity);
+ let mut throw_permission_error = false;
- match &self.load_state.compilation_target {
+ match &compilation_target {
CompilationTarget::User => {
match self
.load_state
.get_mut(&key)
{
Some(ref mut skeleton) => {
- if !skeleton.is_dynamic {
- skeleton.is_dynamic = true;
+ if !*flag_accessor(skeleton) {
+ *flag_accessor(skeleton) = true;
self.load_state.retraction_info.push_record(
- RetractionRecord::AddedUserDynamicPredicate(key.clone()),
+ retraction_fn(compilation_target.clone(), key.clone()),
);
}
}
None => {
- self.load_state.add_extensible_predicate(
- key.clone(),
- PredicateSkeleton::new().set_dynamic(true),
- CompilationTarget::User,
- );
+ if self.load_state.compilation_target == compilation_target {
+ let mut skeleton = PredicateSkeleton::new();
+ *flag_accessor(&mut skeleton) = true;
+
+ self.load_state.add_extensible_predicate(
+ key.clone(),
+ skeleton,
+ CompilationTarget::User,
+ );
+ } else {
+ throw_permission_error = true;
+ }
}
}
}
match self.load_state.wam.indices.modules.get_mut(module_name) {
Some(ref mut module) => match module.extensible_predicates.get_mut(&key) {
Some(ref mut skeleton) => {
- if !skeleton.is_dynamic {
- skeleton.is_dynamic = true;
+ if !*flag_accessor(skeleton) {
+ *flag_accessor(skeleton) = true;
self.load_state.retraction_info.push_record(
- RetractionRecord::AddedModuleDynamicPredicate(
- module_name.clone(),
- key.clone(),
- ),
+ retraction_fn(compilation_target.clone(), key.clone()),
);
}
}
None => {
- self.load_state.add_extensible_predicate(
- key.clone(),
- PredicateSkeleton::new().set_dynamic(true),
- self.load_state.compilation_target.clone(),
- );
+ if self.load_state.compilation_target == compilation_target {
+ let mut skeleton = PredicateSkeleton::new();
+ *flag_accessor(&mut skeleton) = true;
+
+ self.load_state.add_extensible_predicate(
+ key.clone(),
+ skeleton,
+ compilation_target.clone(),
+ );
+ } else {
+ throw_permission_error = true;
+ }
}
},
None => {
- unreachable!();
+ self.load_state.add_dynamically_generated_module(module_name);
+
+ let mut skeleton = PredicateSkeleton::new();
+ *flag_accessor(&mut skeleton) = true;
+
+ self.load_state.add_extensible_predicate(
+ key.clone(),
+ skeleton,
+ compilation_target.clone(),
+ );
}
}
}
}
+ if !throw_permission_error {
+ match self.load_state.compilation_target.clone() {
+ CompilationTarget::User => {
+ match self
+ .load_state
+ .wam
+ .indices
+ .local_extensible_predicates
+ .get_mut(&(compilation_target.clone(), key.clone()))
+ {
+ Some(ref mut skeleton) => {
+ if !*flag_accessor(skeleton) {
+ *flag_accessor(skeleton) = true;
+ }
+ }
+ None => {
+ let mut skeleton = PredicateSkeleton::new();
+ *flag_accessor(&mut skeleton) = true;
+
+ self.load_state.add_local_extensible_predicate(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ );
+ }
+ }
+ }
+ CompilationTarget::Module(ref module_name) => {
+ match self.load_state.wam.indices.modules.get_mut(module_name) {
+ Some(ref mut module) =>
+ match module.local_extensible_predicates.get_mut(
+ &(compilation_target.clone(), key.clone()),
+ ) {
+ Some(ref mut skeleton) => {
+ if !*flag_accessor(skeleton) {
+ *flag_accessor(skeleton) = true;
+ }
+ }
+ None => {
+ let mut skeleton = PredicateSkeleton::new();
+ *flag_accessor(&mut skeleton) = true;
+
+ self.load_state.add_local_extensible_predicate(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ );
+ }
+ },
+ None => {
+ self.load_state.add_dynamically_generated_module(module_name);
+
+ let mut skeleton = PredicateSkeleton::new();
+ *flag_accessor(&mut skeleton) = true;
+
+ self.load_state.add_local_extensible_predicate(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ );
+ }
+ }
+ }
+ }
+
+ Ok(())
+ } else {
+ Err(SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key))
+ }
+ }
+
+ fn add_discontiguous_predicate(
+ &mut self,
+ compilation_target: CompilationTarget,
+ name: ClauseName,
+ arity: usize,
+ ) -> Result<(), SessionError> {
+ self.add_extensible_predicate_declaration(
+ compilation_target,
+ name,
+ arity,
+ |skeleton| &mut skeleton.is_discontiguous,
+ RetractionRecord::AddedDiscontiguousPredicate,
+ )
+ }
+
+ fn add_dynamic_predicate(
+ &mut self,
+ compilation_target: CompilationTarget,
+ name: ClauseName,
+ arity: usize,
+ ) -> Result<(), SessionError> {
+ self.add_extensible_predicate_declaration(
+ compilation_target.clone(),
+ name.clone(),
+ arity,
+ |skeleton| &mut skeleton.is_dynamic,
+ RetractionRecord::AddedDynamicPredicate,
+ )?;
+
let code_index = self.load_state.get_or_insert_code_index(
- key.clone(),
- self.load_state.compilation_target.clone(),
+ (name.clone(), arity),
+ compilation_target.clone(),
);
- set_code_index(
- &mut self.load_state.retraction_info,
- &self.load_state.compilation_target,
- key,
- &code_index,
- IndexPtr::DynamicUndefined,
- );
+ if let IndexPtr::Undefined = code_index.get() {
+ set_code_index(
+ &mut self.load_state.retraction_info,
+ &compilation_target,
+ (name, arity),
+ &code_index,
+ IndexPtr::DynamicUndefined,
+ );
+ }
+
+ Ok(())
+ }
+
+ fn add_multifile_predicate(
+ &mut self,
+ compilation_target: CompilationTarget,
+ name: ClauseName,
+ arity: usize,
+ ) -> Result<(), SessionError> {
+ self.add_extensible_predicate_declaration(
+ compilation_target,
+ name,
+ arity,
+ |skeleton| &mut skeleton.is_multifile,
+ RetractionRecord::AddedMultifilePredicate,
+ )
}
fn add_clause_clause_if_dynamic(&mut self, term: &Term) -> Result<(), SessionError> {
Ok(())
}
+
+ pub(super) fn retract_local_clauses(&mut self, key: &PredicateKey, is_dynamic: bool) {
+ let clause_locs = match self
+ .load_state
+ .wam
+ .indices
+ .get_local_predicate_skeleton_mut(
+ &self.load_state.compilation_target,
+ self.predicates.compilation_target.clone(),
+ key.clone(),
+ )
+ {
+ Some(skeleton) if !skeleton.clause_clause_locs.is_empty() =>
+ mem::replace(&mut skeleton.clause_clause_locs, sdeq![]),
+ _ =>
+ return,
+ };
+
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::RemovedLocalSkeletonClauseLocations(
+ self.load_state.compilation_target.clone(),
+ self.predicates.compilation_target.clone(),
+ key.clone(),
+ clause_locs.clone(),
+ ),
+ );
+
+ self.load_state.retract_local_clauses(
+ self.predicates.compilation_target.clone(),
+ key.clone(),
+ &clause_locs,
+ );
+
+ if is_dynamic {
+ let clause_clause_compilation_target = match &self.predicates.compilation_target {
+ CompilationTarget::User => CompilationTarget::Module(clause_name!("builtins")),
+ module_name => module_name.clone(),
+ };
+
+ self.load_state.retract_local_clause_clauses(
+ clause_clause_compilation_target,
+ &clause_locs,
+ );
+ }
+ }
}
impl Machine {
self.restore_load_state_payload(result, evacuable_h);
}
+ #[inline]
+ pub(crate) fn add_discontiguous_predicate(&mut self) {
+ self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| {
+ loader.add_discontiguous_predicate(compilation_target, clause_name, arity)
+ });
+ }
+
+ #[inline]
pub(crate) fn add_dynamic_predicate(&mut self) {
- let predicate_name = atom_from!(
+ self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| {
+ loader.add_dynamic_predicate(compilation_target, clause_name, arity)
+ });
+ }
+
+ #[inline]
+ pub(crate) fn add_multifile_predicate(&mut self) {
+ self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| {
+ loader.add_multifile_predicate(compilation_target, clause_name, arity)
+ });
+ }
+
+ fn add_extensible_predicate_declaration(
+ &mut self,
+ decl_adder: impl Fn(&mut Loader<LiveTermStream>, CompilationTarget, ClauseName, usize)
+ -> Result<(), SessionError>,
+ ) {
+ let module_name = atom_from!(
self.machine_st,
self.machine_st
.store(self.machine_st.deref(self.machine_st[temp_v!(1)]))
);
+ let compilation_target = match module_name.as_str() {
+ "user" => CompilationTarget::User,
+ _ => CompilationTarget::Module(module_name),
+ };
+
+ let predicate_name = atom_from!(
+ self.machine_st,
+ self.machine_st
+ .store(self.machine_st.deref(self.machine_st[temp_v!(2)]))
+ );
+
let arity = self
.machine_st
- .store(self.machine_st.deref(self.machine_st[temp_v!(2)]));
+ .store(self.machine_st.deref(self.machine_st[temp_v!(3)]));
let arity = match Number::try_from((arity, &self.machine_st.heap)) {
Ok(Number::Integer(n)) if &*n >= &0 && &*n <= &MAX_ARITY => Ok(n.to_usize().unwrap()),
_ => Err(SessionError::from(CompilationError::InvalidRuleHead)),
};
- let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3));
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(4));
- let add_dynamic_predicate = || {
- loader.add_dynamic_predicate(predicate_name, arity?);
+ let add_predicate_decl = || {
+ decl_adder(&mut loader, compilation_target, predicate_name, arity?)?;
LiveTermStream::evacuate(loader)
};
- let result = add_dynamic_predicate();
+ let result = add_predicate_decl();
self.restore_load_state_payload(result, evacuable_h);
}
let add_clause = || {
let term = loader.read_term_from_heap(temp_v!(1))?;
- loader.incremental_compile_clause(
+ loader.load_state.incremental_compile_clause(
(clause_name!("term_expansion"), 2),
term,
CompilationTarget::User,
let add_clause = || {
let term = loader.read_term_from_heap(temp_v!(2))?;
- loader.incremental_compile_clause(
+ loader.load_state.incremental_compile_clause(
(clause_name!("goal_expansion"), 2),
term,
compilation_target,
fetch_op_spec(clause_name!(":-"), 2, &loader.load_state.wam.indices.op_dir),
);
- loader.incremental_compile_clause(
+ loader.load_state.incremental_compile_clause(
key.clone(),
asserted_clause,
compilation_target.clone(),
}
};
- let mut clause_assert_margin = loader
- .load_state
- .wam
- .indices
- .modules
- .get(&clause_clause_compilation_target.module_name())
- .map(|module| module.clause_assert_margin)
- .unwrap();
-
let mut clause_clause_target_poses: Vec<_> = loader
.load_state
.wam
.map(|clause_clause_loc| {
clause_clause_skeleton.target_pos_of_clause_clause_loc(
*clause_clause_loc,
- clause_assert_margin,
- )
+ ).unwrap()
})
.collect()
})
.wam
.indices
.get_predicate_skeleton_mut(&loader.load_state.compilation_target, &key)
- .map(|skeleton| {
- skeleton.clauses.clear();
- skeleton.clause_clause_locs.clear();
- });
+ .map(|skeleton| skeleton.reset());
let code_index = loader.load_state.get_or_insert_code_index(
key,
while let Some(target_pos) = clause_clause_target_poses.pop() {
loader.load_state.retract_clause((clause_name!("$clause"), 2), target_pos);
-
- if target_pos < clause_assert_margin {
- clause_assert_margin -= 1;
- }
}
- loader
- .load_state
- .wam
- .indices
- .modules
- .get_mut(&loader.load_state.compilation_target.module_name())
- .map(|module| module.clause_assert_margin = clause_assert_margin);
-
LiveTermStream::evacuate(loader)
};
let clause_clause_loc = loader.load_state.retract_clause(key, target_pos);
- let clause_assert_margin = loader
- .load_state
- .wam
- .indices
- .modules
- .get(&clause_clause_compilation_target.module_name())
- .map(|module| module.clause_assert_margin)
- .unwrap();
-
let target_pos = match loader.load_state.wam.indices.get_predicate_skeleton(
&clause_clause_compilation_target,
&(clause_name!("$clause"), 2),
) {
Some(skeleton) => {
- let target_pos = skeleton.target_pos_of_clause_clause_loc(
+ skeleton.target_pos_of_clause_clause_loc(
clause_clause_loc,
- clause_assert_margin,
- );
-
- if target_pos < clause_assert_margin {
- loader
- .load_state
- .wam
- .indices
- .modules
- .get_mut(&clause_clause_compilation_target.module_name())
- .map(|module| module.clause_assert_margin -= 1);
- }
-
- target_pos
+ ).unwrap()
}
None => {
unreachable!();
&mut self.term_stream,
LiveTermStream::new(ListingSource::User),
),
- preprocessor: mem::replace(
- &mut self.preprocessor,
- Preprocessor::new(self.load_state.wam.machine_st.flags),
- ),
non_counted_bt_preds: mem::replace(&mut self.non_counted_bt_preds, IndexSet::new()),
compilation_target: self.load_state.compilation_target.take(),
retraction_info: mem::replace(
&mut payload.term_stream,
LiveTermStream::new(ListingSource::User),
),
- preprocessor: mem::replace(
- &mut payload.preprocessor,
- Preprocessor::new(MachineFlags::default()),
- ),
non_counted_bt_preds: mem::replace(&mut payload.non_counted_bt_preds, IndexSet::new()),
clause_clauses: mem::replace(&mut payload.clause_clauses, vec![]),
predicates: payload.predicates.take(),
}
}
- fn incremental_compile_clause(
- &mut self,
- key: PredicateKey,
- term: Term,
- compilation_target: CompilationTarget,
- non_counted_bt: bool,
- append_or_prepend: AppendOrPrepend,
- ) -> Result<(), SessionError> {
- let mut preprocessor = Preprocessor::new(self.load_state.wam.machine_st.flags);
-
- let tl = preprocessor.try_term_to_tl(
- &mut self.load_state,
- term,
- CutContext::BlocksCuts,
- )?;
-
- let queue = preprocessor.parse_queue(&mut self.load_state)?;
-
- let clause = match tl {
- TopLevel::Fact(fact) => PredicateClause::Fact(fact),
- TopLevel::Rule(rule) => PredicateClause::Rule(rule),
- _ => {
- unreachable!()
- }
- };
-
- self.load_state.incremental_compile_clause(
- key,
- clause,
- queue,
- compilation_target,
- non_counted_bt,
- append_or_prepend,
- )?;
-
- Ok(())
- }
-
fn read_and_enqueue_term(
mut self,
term_reg: RegType,
use crate::forms::{ModuleSource, Number}; //, PredicateKey};
use crate::machine::PredicateKey;
use crate::machine::heap::*;
+use crate::machine::loader::CompilationTarget;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
use crate::rug::Integer;
Self::permission_error(h, Permission::Create, "operator", functor!(clause_name(op)))
}
SessionError::CompilationError(err) => Self::syntax_error(h, err),
+ SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key) => {
+ let functor_stub = Self::functor_stub(key.0, key.1);
+ let stub = functor!(
+ ":",
+ SharedOpDesc::new(600, XFY),
+ [clause_name(compilation_target.module_name()), aux(h + 4, 0)],
+ [functor_stub]
+ );
+
+ Self::permission_error(
+ h,
+ Permission::Modify,
+ "not_declared_multifile_or_discontiguous",
+ stub,
+ )
+ }
SessionError::QueryCannotBeDefinedAsFact => Self::permission_error(
h,
Permission::Create,
ModuleCannotImportSelf(ClauseName),
NamelessEntry,
OpIsInfixAndPostFix(ClauseName),
+ PredicateNotMultifileOrDiscontiguous(CompilationTarget, PredicateKey),
QueryCannotBeDefinedAsFact,
}
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr {
+ AddDiscontiguousPredicate,
AddDynamicPredicate,
+ AddMultifilePredicate,
AddGoalExpansionClause,
AddTermExpansionClause,
ClauseToEvacuable,
}
}
+ pub fn get_local_predicate_skeleton_mut(
+ &mut self,
+ src_compilation_target: &CompilationTarget,
+ local_compilation_target: CompilationTarget,
+ key: PredicateKey,
+ ) -> Option<&mut PredicateSkeleton> {
+ match (key.0.as_str(), key.1) {
+ ("term_expansion", 2) => {
+ self.local_extensible_predicates.get_mut(
+ &(local_compilation_target, key),
+ )
+ }
+ _ => match src_compilation_target {
+ CompilationTarget::User => {
+ self.local_extensible_predicates.get_mut(
+ &(local_compilation_target, key),
+ )
+ }
+ CompilationTarget::Module(ref module_name) => {
+ if let Some(module) = self.modules.get_mut(module_name) {
+ module.local_extensible_predicates.get_mut(
+ &(local_compilation_target, key),
+ )
+ } else {
+ None
+ }
+ }
+ },
+ }
+ }
+
+ pub fn get_local_predicate_skeleton(
+ &self,
+ src_compilation_target: &CompilationTarget,
+ local_compilation_target: CompilationTarget,
+ key: PredicateKey,
+ ) -> Option<&PredicateSkeleton> {
+ match (key.0.as_str(), key.1) {
+ ("term_expansion", 2) => {
+ self.local_extensible_predicates.get(
+ &(local_compilation_target, key),
+ )
+ }
+ _ => match src_compilation_target {
+ CompilationTarget::User => {
+ self.local_extensible_predicates.get(
+ &(local_compilation_target, key),
+ )
+ }
+ CompilationTarget::Module(ref module_name) => {
+ if let Some(module) = self.modules.get(module_name) {
+ module.local_extensible_predicates.get(
+ &(local_compilation_target, key),
+ )
+ } else {
+ None
+ }
+ }
+ },
+ }
+ }
+
pub fn get_predicate_skeleton(
&self,
compilation_target: &CompilationTarget,
&mut self,
compilation_target: &CompilationTarget,
key: &PredicateKey,
- ) {
+ ) -> Option<PredicateSkeleton> {
match (key.0.as_str(), key.1) {
("term_expansion", 2) => {
- self.extensible_predicates.remove(key);
+ self.extensible_predicates.remove(key)
}
_ => match compilation_target {
CompilationTarget::User => {
- self.extensible_predicates.remove(key);
+ self.extensible_predicates.remove(key)
}
CompilationTarget::Module(ref module_name) => {
if let Some(module) = self.modules.get_mut(module_name) {
- module.extensible_predicates.remove(key);
+ module.extensible_predicates.remove(key)
+ } else {
+ None
}
}
},
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
match code_ptr {
+ REPLCodePtr::AddDiscontiguousPredicate => {
+ self.add_discontiguous_predicate();
+ }
REPLCodePtr::AddDynamicPredicate => {
self.add_dynamic_predicate();
}
+ REPLCodePtr::AddMultifilePredicate => {
+ self.add_multifile_predicate();
+ }
REPLCodePtr::AddGoalExpansionClause => {
self.add_goal_expansion_clause();
}
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => {
return Ok(tl);
}
- TopLevel::Declaration(_) if clauses.is_empty() => {
- return Ok(tl);
- }
TopLevel::Query(_) => {
return Err(CompilationError::InconsistentEntry);
}
clauses.push(clause);
}
TopLevel::Predicate(predicate) => clauses.extend(predicate.into_iter()),
- _ => {
- tls.push_front(tl);
- break;
- }
}
}
}
}
-fn setup_declaration<'a>(
+pub(super) fn setup_declaration<'a>(
load_state: &LoadState<'a>,
mut terms: Vec<Box<Term>>,
) -> Result<Declaration, CompilationError> {
terms,
cut_context,
)?))
- } else if name.as_str() == ":-" && terms.len() == 1 {
- Ok(TopLevel::Declaration(setup_declaration(load_state, terms)?))
} else {
let term = Term::Clause(r, name, terms, fixity);
Ok(TopLevel::Fact(self.setup_fact(term)?))
use prolog_parser::parser::*;
use crate::machine::machine_errors::CompilationError;
-use crate::machine::preprocessor::*;
use crate::machine::*;
use indexmap::IndexSet;
pub(super) retraction_info: RetractionInfo,
pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
- pub(super) preprocessor: Preprocessor,
pub(super) predicates: PredicateQueue,
pub(super) clause_clauses: Vec<(Term, Term)>,
}
retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
module_op_exports: vec![],
non_counted_bt_preds: IndexSet::new(),
- preprocessor: Preprocessor::new(wam.machine_st.flags),
predicates: predicate_queue![],
clause_clauses: vec![],
}
use crate::forms::*;
use crate::indexing::IndexingCodePtr;
use crate::instructions::*;
+use crate::machine::loader::CompilationTarget;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
+ REPLCodePtr::AddDiscontiguousPredicate =>
+ write!(f, "REPLCodePtr::AddDiscontiguousPredicate"),
REPLCodePtr::AddDynamicPredicate =>
write!(f, "REPLCodePtr::AddDynamicPredicate"),
+ REPLCodePtr::AddMultifilePredicate =>
+ write!(f, "REPLCodePtr::AddMultifilePredicate"),
REPLCodePtr::AddGoalExpansionClause =>
write!(f, "REPLCodePtr::AddGoalExpansionClause"),
REPLCodePtr::AddTermExpansionClause =>
}
}
+impl fmt::Display for CompilationTarget {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ CompilationTarget::User => write!(f, "user"),
+ CompilationTarget::Module(ref module_name) => write!(f, "{}", module_name),
+ }
+ }
+}
+
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
write!(f, "modules ({}, in this case) cannot import themselves.",
module_name)
}
+ &SessionError::PredicateNotMultifileOrDiscontiguous(ref compilation_target, ref key) => {
+ write!(f, "module {} does not define {}/{} as multifile or discontiguous.",
+ compilation_target.module_name(), key.0, key.1)
+ }
}
}
}