Merge branch 'master' into library-use-case

This commit is contained in:
Nicolas Luck
2023-08-07 16:42:48 +02:00
6 changed files with 74 additions and 53 deletions

View File

@@ -36,6 +36,7 @@
integer_si/1, integer_si/1,
atomic_si/1, atomic_si/1,
list_si/1, list_si/1,
character_si/1,
chars_si/1, chars_si/1,
dif_si/2]). dif_si/2]).
@@ -62,9 +63,29 @@ list_si(L0) :-
; throw(error(instantiation_error, list_si/1)) ; throw(error(instantiation_error, list_si/1))
). ).
chars_si(Cs) :- character_si(Ch) :-
list_si(Cs), functor(Ch,Ch,0),
'$is_partial_string'(Cs). atom(Ch),
atom_length(Ch,1).
chars_si(Chs0) :-
'$skip_max_list'(_,_, Chs0,Chs),
( nonvar(Chs) -> Chs == [] ; true ), % fails for infinite lists too
failnochars(Chs0, Uninstantiated),
( nonvar(Uninstantiated)
-> throw(error(instantiation_error, chars_si/1))
; true
).
failnochars(Chs0, U) :-
( var(Chs0) -> U = true
; Chs0 == [] -> true
; Chs0 = [Ch|Chs1],
( nonvar(Ch) -> atom(Ch), atom_length(Ch,1)
; U = true
),
failnochars(Chs1, U)
).
dif_si(X, Y) :- dif_si(X, Y) :-
X \== Y, X \== Y,

View File

@@ -1258,7 +1258,7 @@ fn print_overwrite_warning(
_ => {} _ => {}
} }
println!("Warning: overwriting {}/{}", key.0.as_str(), key.1); println!("Warning: overwriting {}/{} because the clauses are discontiguous", key.0.as_str(), key.1);
} }
impl<'a, LS: LoadState<'a>> Loader<'a, LS> { impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
@@ -2220,7 +2220,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let payload_compilation_target = self.payload.compilation_target; let payload_compilation_target = self.payload.compilation_target;
let local_predicate_info = self let mut local_predicate_info = self
.wam_prelude .wam_prelude
.indices .indices
.get_local_predicate_skeleton( .get_local_predicate_skeleton(
@@ -2242,6 +2242,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let is_cross_module_clause = let is_cross_module_clause =
payload_compilation_target != self.payload.predicates.compilation_target; payload_compilation_target != self.payload.predicates.compilation_target;
local_predicate_info.is_discontiguous = predicate_info.is_discontiguous;
if local_predicate_info.must_retract_local_clauses(is_cross_module_clause) { if local_predicate_info.must_retract_local_clauses(is_cross_module_clause) {
self.retract_local_clauses(&key, predicate_info.is_dynamic); self.retract_local_clauses(&key, predicate_info.is_dynamic);
} }

View File

@@ -530,7 +530,36 @@ impl VariableClassifier {
} }
}; };
let mut add_chunk = |classifier: &mut Self, name: Atom, terms: Vec<Term>| {
if update_chunk_data(classifier, name, terms.len()) {
build_stack.add_chunk();
}
for (arg_c, term) in terms.iter().enumerate() {
classifier.probe_body_term(arg_c + 1, terms.len(), term);
}
build_stack.push_chunk_term(
clause_to_query_term(
loader,
name,
terms,
classifier.call_policy,
),
);
};
match term { match term {
Term::Clause(_, name @ (atom!("->") | atom!(";") | atom!(",")), mut terms) if terms.len() == 3 => {
if let Some(last_arg) = terms.last() {
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
terms.pop();
state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), name, terms)));
} else {
add_chunk(self, name, terms);
}
}
}
Term::Clause(_, atom!(","), mut terms) if terms.len() == 2 => { Term::Clause(_, atom!(","), mut terms) if terms.len() == 2 => {
let tail = terms.pop().unwrap(); let tail = terms.pop().unwrap();
let head = terms.pop().unwrap(); let head = terms.pop().unwrap();
@@ -700,22 +729,7 @@ impl VariableClassifier {
self.call_policy = CallPolicy::Counted; self.call_policy = CallPolicy::Counted;
} }
Term::Clause(_, name, terms) => { Term::Clause(_, name, terms) => {
if update_chunk_data(self, name, terms.len()) { add_chunk(self, name, terms);
build_stack.add_chunk();
}
for (arg_c, term) in terms.iter().enumerate() {
self.probe_body_term(arg_c + 1, terms.len(), term);
}
build_stack.push_chunk_term(
clause_to_query_term(
loader,
name,
terms,
self.call_policy,
),
);
} }
var @ Term::Var(..) => { var @ Term::Var(..) => {
if update_chunk_data(self, atom!("call"), 1) { if update_chunk_data(self, atom!("call"), 1) {

View File

@@ -32,8 +32,7 @@ use std::ops::{Deref, DerefMut};
* loader.pl does a few high-level things more easily handled from * loader.pl does a few high-level things more easily handled from
* Prolog that are not supported (or needed) during bootstrapping: * Prolog that are not supported (or needed) during bootstrapping:
* term and goal expansion, loading modules from different streams, * term and goal expansion, loading modules from different streams,
* verifying certain kinds of declarations, perhaps (in the future?) * and verifying certain kinds of declarations.
* compiling inline disjunctions.
* *
* Since the loader can operate incrementally, it uses an intermittent * Since the loader can operate incrementally, it uses an intermittent
* structure to rebuild the loader between invocations. Preprocessor * structure to rebuild the loader between invocations. Preprocessor
@@ -1279,6 +1278,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
name: Atom, name: Atom,
arity: usize, arity: usize,
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let key = (name, arity);
let predicate_info = self
.wam_prelude
.indices
.get_predicate_skeleton(&self.payload.predicates.compilation_target, &key)
.map(|skeleton| skeleton.predicate_info())
.unwrap_or_default();
self.retract_local_clauses(&key, predicate_info.is_dynamic);
self.add_extensible_predicate_declaration( self.add_extensible_predicate_declaration(
compilation_target, compilation_target,
name, name,

View File

@@ -9,6 +9,7 @@ use crate::read::devour_whitespace;
use crate::predicate_queue; use crate::predicate_queue;
use fxhash::FxBuildHasher;
use indexmap::IndexSet; use indexmap::IndexSet;
use std::collections::VecDeque; use std::collections::VecDeque;
@@ -19,7 +20,7 @@ pub struct LoadStatePayload<TS> {
pub(super) compilation_target: CompilationTarget, pub(super) compilation_target: CompilationTarget,
pub(super) retraction_info: RetractionInfo, pub(super) retraction_info: RetractionInfo,
pub(super) module_op_exports: ModuleOpExports, pub(super) module_op_exports: ModuleOpExports,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>, pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>,
pub(super) predicates: PredicateQueue, pub(super) predicates: PredicateQueue,
pub(super) clause_clauses: Vec<(Term, Term)>, pub(super) clause_clauses: Vec<(Term, Term)>,
} }
@@ -97,7 +98,7 @@ impl<TS> LoadStatePayload<TS> {
compilation_target: CompilationTarget::default(), compilation_target: CompilationTarget::default(),
retraction_info: RetractionInfo::new(code_repo_len), retraction_info: RetractionInfo::new(code_repo_len),
module_op_exports: vec![], module_op_exports: vec![],
non_counted_bt_preds: IndexSet::new(), non_counted_bt_preds: IndexSet::with_hasher(FxBuildHasher::default()),
predicates: predicate_queue![], predicates: predicate_queue![],
clause_clauses: vec![], clause_clauses: vec![],
} }

View File

@@ -830,30 +830,3 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
terms.push(term); terms.push(term);
terms terms
} }
fn unfold_by_str_ref_once(term: &Term, s: Atom) -> Option<(&Term, &Term)> {
if let Term::Clause(_, ref name, ref subterms) = term {
if name == &s && subterms.len() == 2 {
let fst = &subterms[0];
let snd = &subterms[1];
return Some((fst, snd));
}
}
None
}
pub fn unfold_by_str_ref(mut term: &Term, s: Atom) -> Vec<&Term> {
let mut terms = vec![];
while let Some((fst, snd)) = unfold_by_str_ref_once(&term, s) {
terms.push(fst);
term = snd;
}
terms.push(term);
terms
}