compile scoped clauses from loader.pl

This commit is contained in:
Mark Thom
2021-02-13 19:41:04 -07:00
parent b24f68eee7
commit e2a413df78
12 changed files with 313 additions and 142 deletions

View File

@@ -557,7 +557,7 @@ impl<'a> Drop for LoadState<'a> {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CompilationTarget {
Module(ClauseName),
User,
@@ -587,9 +587,58 @@ impl CompilationTarget {
}
}
pub struct PredicateQueue {
pub(super) predicates: Vec<PredicateClause>,
pub(super) compilation_target: CompilationTarget,
}
impl PredicateQueue {
#[inline]
pub(super) fn push(&mut self, clause: PredicateClause) {
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> {
self.predicates.first()
}
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.predicates.is_empty()
}
#[inline]
pub(super) fn take(&mut self) -> Self {
Self {
predicates: mem::replace(&mut self.predicates, vec![]),
compilation_target: self.compilation_target.take(),
}
}
}
macro_rules! predicate_queue {
[$($v:expr),*] => (
PredicateQueue {
predicates: vec![$($v,)*],
compilation_target: CompilationTarget::default(),
}
)
}
pub(crate) struct Loader<'a, TermStream> {
pub(super) load_state: LoadState<'a>,
pub(super) predicates: Vec<PredicateClause>,
pub(super) predicates: PredicateQueue,
pub(super) clause_clauses: Vec<(Term, Term)>,
term_stream: TermStream,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
@@ -612,7 +661,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
term_stream,
non_counted_bt_preds: IndexSet::new(),
preprocessor: Preprocessor::new(flags),
predicates: vec![],
predicates: predicate_queue![],
clause_clauses: vec![],
}
}
@@ -643,7 +692,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
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),
TopLevel::Predicate(pred) => self.predicates.extend(pred.into_iter()),
TopLevel::Declaration(decl) => return Ok(Some(decl)),
TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact),
}
@@ -665,6 +714,9 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
self.load_state.compilation_target =
CompilationTarget::Module(module_decl.name.clone());
self.predicates.compilation_target =
self.load_state.compilation_target.clone();
self.load_state
.add_module(module_decl, self.term_stream.listing_src().clone());
}
@@ -827,14 +879,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
}
}
None => {
self.load_state
.wam
.indices
.extensible_predicates
.insert(key.clone(), PredicateSkeleton::new().set_dynamic(true));
self.load_state.retraction_info.push_record(
RetractionRecord::AddedUserExtensiblePredicate(key.clone()),
self.load_state.add_extensible_predicate(
key.clone(),
PredicateSkeleton::new().set_dynamic(true),
CompilationTarget::User,
);
}
}
@@ -855,15 +903,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
}
}
None => {
module
.extensible_predicates
.insert(key.clone(), PredicateSkeleton::new().set_dynamic(true));
self.load_state.retraction_info.push_record(
RetractionRecord::AddedModuleExtensiblePredicate(
module_name.clone(),
key.clone(),
),
self.load_state.add_extensible_predicate(
key.clone(),
PredicateSkeleton::new().set_dynamic(true),
self.load_state.compilation_target.clone(),
);
}
},
@@ -874,7 +917,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
}
}
let code_index = self.load_state.get_or_insert_code_index(key.clone());
let code_index = self.load_state.get_or_insert_code_index(
key.clone(),
self.load_state.compilation_target.clone(),
);
set_code_index(
&mut self.load_state.retraction_info,
@@ -884,6 +930,29 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
IndexPtr::DynamicUndefined,
);
}
fn add_clause_clause_if_dynamic(&mut self, term: &Term) -> Result<(), SessionError> {
if let Some(predicate_name) = ClauseInfo::name(term) {
let arity = ClauseInfo::arity(term);
let is_dynamic = self
.load_state
.wam
.indices
.get_predicate_skeleton(
&self.predicates.compilation_target,
&(predicate_name, arity),
)
.map(|skeleton| skeleton.is_dynamic)
.unwrap_or(false);
if is_dynamic {
self.add_clause_clause(term.clone())?;
}
}
Ok(())
}
}
impl Machine {
@@ -1180,36 +1249,29 @@ impl Machine {
}
}
pub(crate) fn clause_to_evacuable(&mut self) {
let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2));
pub(crate) fn scoped_clause_to_evacuable(&mut self) {
let module_name = atom_from!(
self.machine_st,
self.machine_st
.store(self.machine_st.deref(self.machine_st[temp_v!(1)]))
);
let enqueue_term = || {
let term = loader.read_term_from_heap(temp_v!(1))?;
let (loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3));
if let Some(predicate_name) = ClauseInfo::name(&term) {
let arity = ClauseInfo::arity(&term);
let is_dynamic = loader
.load_state
.wam
.indices
.get_predicate_skeleton(
&loader.load_state.compilation_target,
&(predicate_name, arity),
)
.map(|skeleton| skeleton.is_dynamic)
.unwrap_or(false);
if is_dynamic {
loader.add_clause_clause(term.clone())?;
}
}
loader.enqueue_term(term);
loader.load()
let compilation_target = match module_name.as_str() {
"user" => CompilationTarget::User,
_ => CompilationTarget::Module(module_name),
};
let result = enqueue_term();
let result = loader.read_and_enqueue_term(temp_v!(2), compilation_target);
self.restore_load_state_payload(result, evacuable_h);
}
pub(crate) fn clause_to_evacuable(&mut self) {
let (loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2));
let compilation_target = loader.load_state.compilation_target.clone();
let result = loader.read_and_enqueue_term(temp_v!(1), compilation_target);
self.restore_load_state_payload(result, evacuable_h);
}
@@ -1470,7 +1532,11 @@ impl Machine {
skeleton.clause_clause_locs.clear();
});
let code_index = loader.load_state.get_or_insert_code_index(key);
let code_index = loader.load_state.get_or_insert_code_index(
key,
loader.load_state.compilation_target.clone(),
);
code_index.set(IndexPtr::DynamicUndefined);
loader.load_state.compilation_target = clause_clause_compilation_target;
@@ -1778,7 +1844,7 @@ impl<'a> Loader<'a, LiveTermStream> {
&mut self.load_state.retraction_info,
RetractionInfo::new(self.load_state.wam.code_repo.code.len()),
),
predicates: mem::replace(&mut self.predicates, vec![]),
predicates: self.predicates.take(),
clause_clauses: mem::replace(&mut self.clause_clauses, vec![]),
module_op_exports: mem::replace(&mut self.load_state.module_op_exports, vec![]),
}
@@ -1799,7 +1865,7 @@ impl<'a> Loader<'a, LiveTermStream> {
),
non_counted_bt_preds: mem::replace(&mut payload.non_counted_bt_preds, IndexSet::new()),
clause_clauses: mem::replace(&mut payload.clause_clauses, vec![]),
predicates: mem::replace(&mut payload.predicates, vec![]),
predicates: payload.predicates.take(),
load_state: LoadState {
compilation_target: payload.compilation_target.take(),
module_op_exports: mem::replace(&mut payload.module_op_exports, vec![]),
@@ -1819,7 +1885,11 @@ impl<'a> Loader<'a, LiveTermStream> {
) -> 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 tl = preprocessor.try_term_to_tl(
&mut self.load_state,
term,
CutContext::BlocksCuts,
)?;
let queue = preprocessor.parse_queue(&mut self.load_state)?;
@@ -1831,26 +1901,37 @@ impl<'a> Loader<'a, LiveTermStream> {
}
};
let compilation_target =
mem::replace(&mut self.load_state.compilation_target, compilation_target);
let result = self.load_state.incremental_compile_clause(
self.load_state.incremental_compile_clause(
key,
clause,
queue,
compilation_target,
non_counted_bt,
append_or_prepend,
);
self.load_state.compilation_target = compilation_target;
result?;
)?;
Ok(())
}
#[inline]
fn enqueue_term(&mut self, term: Term) {
fn read_and_enqueue_term(
mut self,
term_reg: RegType,
compilation_target: CompilationTarget,
) -> Result<LoadStatePayload, SessionError> {
if self.predicates.compilation_target != compilation_target {
if !self.predicates.is_empty() {
self.compile_and_submit()?;
}
self.predicates.compilation_target = compilation_target;
}
let term = self.read_term_from_heap(term_reg)?;
self.add_clause_clause_if_dynamic(&term)?;
self.term_stream.term_queue.push_back(term);
self.load()
}
}