support discontiguous and multifile declarations
This commit is contained in:
@@ -340,9 +340,15 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
|
&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
|
||||||
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
|
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
|
||||||
&SystemClauseType::FileTime => clause_name!("$file_time"),
|
&SystemClauseType::FileTime => clause_name!("$file_time"),
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate) => {
|
||||||
|
clause_name!("$add_discontiguous_predicate")
|
||||||
|
}
|
||||||
&SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) => {
|
&SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) => {
|
||||||
clause_name!("$add_dynamic_predicate")
|
clause_name!("$add_dynamic_predicate")
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate) => {
|
||||||
|
clause_name!("$add_multifile_predicate")
|
||||||
|
}
|
||||||
&SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) => {
|
&SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) => {
|
||||||
clause_name!("$add_goal_expansion_clause")
|
clause_name!("$add_goal_expansion_clause")
|
||||||
}
|
}
|
||||||
@@ -582,9 +588,15 @@ impl SystemClauseType {
|
|||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$abolish_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)),
|
("$abolish_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)),
|
||||||
("$add_dynamic_predicate", 3) => {
|
("$add_dynamic_predicate", 4) => {
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate))
|
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) => {
|
("$add_goal_expansion_clause", 4) => {
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause))
|
Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause))
|
||||||
}
|
}
|
||||||
|
|||||||
122
src/forms.rs
122
src/forms.rs
@@ -28,7 +28,6 @@ pub type JumpStub = Vec<Term>;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TopLevel {
|
pub enum TopLevel {
|
||||||
Declaration(Declaration),
|
|
||||||
Fact(Term), // Term, line_num, col_num
|
Fact(Term), // Term, line_num, col_num
|
||||||
Predicate(Predicate),
|
Predicate(Predicate),
|
||||||
Query(Vec<QueryTerm>),
|
Query(Vec<QueryTerm>),
|
||||||
@@ -117,7 +116,7 @@ impl ListingSource {
|
|||||||
pub trait ClauseInfo {
|
pub trait ClauseInfo {
|
||||||
fn is_consistent(&self, clauses: &PredicateQueue) -> bool {
|
fn is_consistent(&self, clauses: &PredicateQueue) -> bool {
|
||||||
match clauses.first() {
|
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,
|
None => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,33 +211,6 @@ impl PredicateClause {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -447,7 +419,6 @@ pub struct Module {
|
|||||||
pub local_extensible_predicates: LocalExtensiblePredicates,
|
pub local_extensible_predicates: LocalExtensiblePredicates,
|
||||||
pub is_impromptu_module: bool,
|
pub is_impromptu_module: bool,
|
||||||
pub listing_src: ListingSource,
|
pub listing_src: ListingSource,
|
||||||
pub clause_assert_margin: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module's and related types are defined in forms.
|
// Module's and related types are defined in forms.
|
||||||
@@ -462,7 +433,6 @@ impl Module {
|
|||||||
extensible_predicates: ExtensiblePredicates::new(),
|
extensible_predicates: ExtensiblePredicates::new(),
|
||||||
local_extensible_predicates: LocalExtensiblePredicates::new(),
|
local_extensible_predicates: LocalExtensiblePredicates::new(),
|
||||||
listing_src,
|
listing_src,
|
||||||
clause_assert_margin: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,7 +613,7 @@ impl AddAssign<usize> for OptArgIndexKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ClauseIndexInfo {
|
pub struct ClauseIndexInfo {
|
||||||
pub clause_start: usize,
|
pub clause_start: usize,
|
||||||
pub opt_arg_index_key: OptArgIndexKey,
|
pub opt_arg_index_key: OptArgIndexKey,
|
||||||
@@ -660,6 +630,41 @@ impl ClauseIndexInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)]
|
#[derive(Debug)]
|
||||||
pub struct PredicateSkeleton {
|
pub struct PredicateSkeleton {
|
||||||
pub is_discontiguous: bool,
|
pub is_discontiguous: bool,
|
||||||
@@ -667,6 +672,7 @@ pub struct PredicateSkeleton {
|
|||||||
pub is_multifile: bool,
|
pub is_multifile: bool,
|
||||||
pub clauses: SliceDeque<ClauseIndexInfo>,
|
pub clauses: SliceDeque<ClauseIndexInfo>,
|
||||||
pub clause_clause_locs: SliceDeque<usize>,
|
pub clause_clause_locs: SliceDeque<usize>,
|
||||||
|
pub clause_assert_margin: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PredicateSkeleton {
|
impl PredicateSkeleton {
|
||||||
@@ -678,57 +684,41 @@ impl PredicateSkeleton {
|
|||||||
is_multifile: false,
|
is_multifile: false,
|
||||||
clauses: sdeq![],
|
clauses: sdeq![],
|
||||||
clause_clause_locs: sdeq![],
|
clause_clause_locs: sdeq![],
|
||||||
|
clause_assert_margin: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_discontiguous(self, is_discontiguous: bool) -> Self {
|
pub fn predicate_info(&self) -> PredicateInfo {
|
||||||
PredicateSkeleton {
|
PredicateInfo {
|
||||||
is_discontiguous,
|
is_extensible: true,
|
||||||
is_dynamic: self.is_dynamic,
|
|
||||||
is_multifile: self.is_multifile,
|
|
||||||
clauses: self.clauses,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn set_dynamic(self, is_dynamic: bool) -> Self {
|
|
||||||
PredicateSkeleton {
|
|
||||||
is_discontiguous: self.is_discontiguous,
|
is_discontiguous: self.is_discontiguous,
|
||||||
is_dynamic,
|
is_dynamic: self.is_dynamic,
|
||||||
is_multifile: self.is_multifile,
|
is_multifile: self.is_multifile,
|
||||||
clauses: self.clauses,
|
has_clauses: !self.clauses.is_empty(),
|
||||||
clause_clause_locs: self.clause_clause_locs,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_multifile(self, is_multifile: bool) -> Self {
|
pub fn reset(&mut self) {
|
||||||
PredicateSkeleton {
|
self.clauses.clear();
|
||||||
is_discontiguous: self.is_discontiguous,
|
self.clause_clause_locs.clear();
|
||||||
is_dynamic: self.is_dynamic,
|
self.clause_assert_margin = 0;
|
||||||
is_multifile,
|
|
||||||
clauses: self.clauses,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn target_pos_of_clause_clause_loc(
|
pub fn target_pos_of_clause_clause_loc(
|
||||||
&self,
|
&self,
|
||||||
clause_clause_loc: usize,
|
clause_clause_loc: usize,
|
||||||
clause_assert_margin: usize,
|
) -> Option<usize> {
|
||||||
) -> usize {
|
let search_result = self.clause_clause_locs[0..self.clause_assert_margin]
|
||||||
let search_result = self.clause_clause_locs[0..clause_assert_margin]
|
|
||||||
.binary_search_by(|loc| clause_clause_loc.cmp(&loc));
|
.binary_search_by(|loc| clause_clause_loc.cmp(&loc));
|
||||||
|
|
||||||
search_result.unwrap_or_else(|_| {
|
match search_result {
|
||||||
self.clause_clause_locs[clause_assert_margin..]
|
Ok(loc) => Some(loc),
|
||||||
|
Err(_) => self.clause_clause_locs[self.clause_assert_margin..]
|
||||||
.binary_search_by(|loc| loc.cmp(&clause_clause_loc))
|
.binary_search_by(|loc| loc.cmp(&clause_clause_loc))
|
||||||
.unwrap()
|
.map(|loc| loc + self.clause_assert_margin)
|
||||||
+ clause_assert_margin
|
.ok()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,9 +257,38 @@ compile_declaration(module(Module, Exports), Evacuable) :-
|
|||||||
type_error(atom, Module, load/1)
|
type_error(atom, Module, load/1)
|
||||||
).
|
).
|
||||||
compile_declaration(dynamic(Name/Arity), Evacuable) :-
|
compile_declaration(dynamic(Name/Arity), Evacuable) :-
|
||||||
|
!,
|
||||||
must_be(atom, Name),
|
must_be(atom, Name),
|
||||||
must_be(integer, Arity),
|
must_be(integer, Arity),
|
||||||
'$add_dynamic_predicate'(Name, Arity, Evacuable).
|
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_discontiguous_predicate'(Module, Name, Arity, Evacuable).
|
||||||
compile_declaration(initialization(Goal), Evacuable) :-
|
compile_declaration(initialization(Goal), Evacuable) :-
|
||||||
prolog_load_context(module, Module),
|
prolog_load_context(module, Module),
|
||||||
assertz(Module:'$initialization_goals'(Goal)).
|
assertz(Module:'$initialization_goals'(Goal)).
|
||||||
@@ -388,7 +417,7 @@ check_predicate_property(dynamic, Module, Name, Arity, dynamic) :-
|
|||||||
'$cpp_dynamic_property'(Module, Name, Arity).
|
'$cpp_dynamic_property'(Module, Name, Arity).
|
||||||
check_predicate_property(multifile, Module, Name, Arity, multifile) :-
|
check_predicate_property(multifile, Module, Name, Arity, multifile) :-
|
||||||
'$cpp_multifile_property'(Module, Name, Arity).
|
'$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).
|
'$cpp_discontiguous_property'(Module, Name, Arity).
|
||||||
|
|
||||||
|
|
||||||
@@ -408,7 +437,7 @@ load_context(Module) :-
|
|||||||
predicate_property(Callable, Property) :-
|
predicate_property(Callable, Property) :-
|
||||||
( var(Callable) ->
|
( var(Callable) ->
|
||||||
instantiation_error(load/1)
|
instantiation_error(load/1)
|
||||||
; functor(Callable, (:), 2), % Callable =.. [(:), Module, Callable0],
|
; functor(Callable, (:), 2),
|
||||||
arg(1, Callable, Module),
|
arg(1, Callable, Module),
|
||||||
arg(2, Callable, Callable0),
|
arg(2, Callable, Callable0),
|
||||||
atom(Module) ->
|
atom(Module) ->
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ use prolog_parser::clause_name;
|
|||||||
use crate::codegen::*;
|
use crate::codegen::*;
|
||||||
use crate::debray_allocator::*;
|
use crate::debray_allocator::*;
|
||||||
use crate::indexing::{merge_clause_index, remove_index};
|
use crate::indexing::{merge_clause_index, remove_index};
|
||||||
use crate::machine::load_state::set_code_index;
|
use crate::machine::load_state::*;
|
||||||
use crate::machine::load_state::LoadState;
|
|
||||||
use crate::machine::loader::*;
|
use crate::machine::loader::*;
|
||||||
|
use crate::machine::preprocessor::*;
|
||||||
use crate::machine::term_stream::*;
|
use crate::machine::term_stream::*;
|
||||||
use crate::machine::*;
|
use crate::machine::*;
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ pub(super) fn compile_relation(
|
|||||||
tl: &TopLevel,
|
tl: &TopLevel,
|
||||||
) -> Result<Code, CompilationError> {
|
) -> Result<Code, CompilationError> {
|
||||||
match tl {
|
match tl {
|
||||||
&TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
|
&TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
|
||||||
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses),
|
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses),
|
||||||
&TopLevel::Fact(ref fact, ..) => Ok(cg.compile_fact(fact)),
|
&TopLevel::Fact(ref fact, ..) => Ok(cg.compile_fact(fact)),
|
||||||
&TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
|
&TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
|
||||||
@@ -54,16 +54,15 @@ pub(super) fn compile_relation(
|
|||||||
|
|
||||||
pub(super) fn compile_appendix(
|
pub(super) fn compile_appendix(
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
queue: &VecDeque<TopLevel>,
|
mut queue: VecDeque<TopLevel>,
|
||||||
jmp_by_locs: Vec<usize>,
|
jmp_by_locs: Vec<usize>,
|
||||||
non_counted_bt: bool,
|
non_counted_bt: bool,
|
||||||
atom_tbl: TabledData<Atom>,
|
atom_tbl: TabledData<Atom>,
|
||||||
) -> Result<(), CompilationError> {
|
) -> Result<(), CompilationError> {
|
||||||
let mut jmp_by_locs = VecDeque::from(jmp_by_locs);
|
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 code_len = code.len();
|
||||||
let jmp_by_offset = jmp_by_locs.pop_front().unwrap();
|
|
||||||
|
|
||||||
match &mut code[jmp_by_offset] {
|
match &mut code[jmp_by_offset] {
|
||||||
&mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => {
|
&mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => {
|
||||||
@@ -76,9 +75,10 @@ pub(super) fn compile_appendix(
|
|||||||
|
|
||||||
// false because the inner predicate is a one-off, hence not extensible.
|
// false because the inner predicate is a one-off, hence not extensible.
|
||||||
let settings = CodeGenSettings::new(false, non_counted_bt);
|
let settings = CodeGenSettings::new(false, non_counted_bt);
|
||||||
|
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(atom_tbl.clone(), settings);
|
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()));
|
jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len()));
|
||||||
code.extend(decl_code.into_iter());
|
code.extend(decl_code.into_iter());
|
||||||
@@ -109,29 +109,6 @@ fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize)
|
|||||||
0
|
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(
|
fn derelictize_try_me_else(
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
index: usize,
|
index: usize,
|
||||||
@@ -341,17 +318,21 @@ fn merge_indexed_subsequences(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_from_dynamic_skeleton(
|
fn delete_from_skeleton(
|
||||||
compilation_target: CompilationTarget,
|
compilation_target: CompilationTarget,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
skeleton: &mut PredicateSkeleton,
|
skeleton: &mut PredicateSkeleton,
|
||||||
target_pos: usize,
|
target_pos: usize,
|
||||||
retraction_info: &mut RetractionInfo,
|
retraction_info: &mut RetractionInfo,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let clause_clause_loc = skeleton.clause_clause_locs.remove(target_pos);
|
|
||||||
let clause_index_info = skeleton.clauses.remove(target_pos);
|
let clause_index_info = skeleton.clauses.remove(target_pos);
|
||||||
|
let clause_clause_loc = skeleton.clause_clause_locs.remove(target_pos);
|
||||||
|
|
||||||
retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause(
|
if target_pos < skeleton.clause_assert_margin {
|
||||||
|
skeleton.clause_assert_margin -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
retraction_info.push_record(RetractionRecord::RemovedSkeletonClause(
|
||||||
compilation_target,
|
compilation_target,
|
||||||
key,
|
key,
|
||||||
target_pos,
|
target_pos,
|
||||||
@@ -585,7 +566,7 @@ fn finalize_retract(
|
|||||||
index_ptr_opt: Option<IndexPtr>,
|
index_ptr_opt: Option<IndexPtr>,
|
||||||
retraction_info: &mut RetractionInfo,
|
retraction_info: &mut RetractionInfo,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let clause_clause_loc = delete_from_dynamic_skeleton(
|
let clause_clause_loc = delete_from_skeleton(
|
||||||
compilation_target.clone(),
|
compilation_target.clone(),
|
||||||
key.clone(),
|
key.clone(),
|
||||||
skeleton,
|
skeleton,
|
||||||
@@ -1007,13 +988,40 @@ fn mergeable_indexed_subsequences(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LoadState<'a> {
|
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(
|
fn compile(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
predicates: &PredicateQueue, // &Vec<PredicateClause>,
|
predicates: &mut PredicateQueue,
|
||||||
queue: &VecDeque<TopLevel>,
|
|
||||||
settings: CodeGenSettings,
|
settings: CodeGenSettings,
|
||||||
) -> Result<IndexPtr, SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
let code_index = self.get_or_insert_code_index(
|
let code_index = self.get_or_insert_code_index(
|
||||||
key.clone(),
|
key.clone(),
|
||||||
predicates.compilation_target.clone(),
|
predicates.compilation_target.clone(),
|
||||||
@@ -1025,7 +1033,15 @@ impl<'a> LoadState<'a> {
|
|||||||
let mut cg =
|
let mut cg =
|
||||||
CodeGenerator::<DebrayAllocator>::new(self.wam.machine_st.atom_tbl.clone(), settings);
|
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(
|
compile_appendix(
|
||||||
&mut code,
|
&mut code,
|
||||||
@@ -1036,9 +1052,13 @@ impl<'a> LoadState<'a> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
if settings.is_extensible {
|
if settings.is_extensible {
|
||||||
|
let mut clause_clause_locs = sdeq![];
|
||||||
|
|
||||||
for clause_index_info in cg.skeleton.clauses.iter_mut() {
|
for clause_index_info in cg.skeleton.clauses.iter_mut() {
|
||||||
clause_index_info.clause_start += code_len;
|
clause_index_info.clause_start += code_len;
|
||||||
clause_index_info.opt_arg_index_key += 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] {
|
match &mut code[0] {
|
||||||
@@ -1062,8 +1082,15 @@ impl<'a> LoadState<'a> {
|
|||||||
));
|
));
|
||||||
|
|
||||||
skeleton.clauses.extend(cg.skeleton.clauses.into_iter());
|
skeleton.clauses.extend(cg.skeleton.clauses.into_iter());
|
||||||
|
skeleton.clause_clause_locs.extend_from_slice(
|
||||||
|
&clause_clause_locs[0 ..]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
cg.skeleton.clause_clause_locs.extend_from_slice(
|
||||||
|
&clause_clause_locs[0 ..]
|
||||||
|
);
|
||||||
|
|
||||||
self.add_extensible_predicate(
|
self.add_extensible_predicate(
|
||||||
key.clone(),
|
key.clone(),
|
||||||
cg.skeleton,
|
cg.skeleton,
|
||||||
@@ -1071,6 +1098,15 @@ impl<'a> LoadState<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
set_code_index(
|
||||||
@@ -1082,7 +1118,7 @@ impl<'a> LoadState<'a> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.wam.code_repo.code.extend(code.into_iter());
|
self.wam.code_repo.code.extend(code.into_iter());
|
||||||
Ok(code_index.get())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn record_incremental_compile(
|
fn record_incremental_compile(
|
||||||
@@ -1119,24 +1155,23 @@ impl<'a> LoadState<'a> {
|
|||||||
pub(super) fn incremental_compile_clause(
|
pub(super) fn incremental_compile_clause(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
clause: PredicateClause,
|
clause: Term,
|
||||||
queue: VecDeque<TopLevel>,
|
|
||||||
compilation_target: CompilationTarget,
|
compilation_target: CompilationTarget,
|
||||||
non_counted_bt: bool,
|
non_counted_bt: bool,
|
||||||
append_or_prepend: AppendOrPrepend,
|
append_or_prepend: AppendOrPrepend,
|
||||||
) -> Result<IndexPtr, SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
self.record_incremental_compile(
|
self.record_incremental_compile(
|
||||||
key.clone(),
|
key.clone(),
|
||||||
compilation_target.clone(),
|
compilation_target.clone(),
|
||||||
append_or_prepend,
|
append_or_prepend,
|
||||||
);
|
);
|
||||||
|
|
||||||
let skeleton = match self
|
match self
|
||||||
.wam
|
.wam
|
||||||
.indices
|
.indices
|
||||||
.get_predicate_skeleton_mut(&compilation_target, &key)
|
.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.
|
// true because this predicate is extensible.
|
||||||
let settings = CodeGenSettings::new(true, non_counted_bt);
|
let settings = CodeGenSettings::new(true, non_counted_bt);
|
||||||
@@ -1144,7 +1179,7 @@ impl<'a> LoadState<'a> {
|
|||||||
let mut predicate_queue = predicate_queue![clause];
|
let mut predicate_queue = predicate_queue![clause];
|
||||||
predicate_queue.compilation_target = compilation_target;
|
predicate_queue.compilation_target = compilation_target;
|
||||||
|
|
||||||
return self.compile(key, &predicate_queue, &queue, settings);
|
return self.compile(key, &mut predicate_queue, settings);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1154,13 +1189,25 @@ impl<'a> LoadState<'a> {
|
|||||||
let StandaloneCompileResult {
|
let StandaloneCompileResult {
|
||||||
clause_code,
|
clause_code,
|
||||||
mut standalone_skeleton,
|
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 {
|
match append_or_prepend {
|
||||||
AppendOrPrepend::Append => {
|
AppendOrPrepend::Append => {
|
||||||
skeleton
|
let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap();
|
||||||
.clauses
|
skeleton.clauses.push_back(clause_index_info);
|
||||||
.push_back(standalone_skeleton.clauses.pop_back().unwrap());
|
|
||||||
|
skeleton.clause_clause_locs.push_back(code_len);
|
||||||
|
|
||||||
self.retraction_info
|
self.retraction_info
|
||||||
.push_record(RetractionRecord::SkeletonClausePopBack(
|
.push_record(RetractionRecord::SkeletonClausePopBack(
|
||||||
@@ -1175,6 +1222,38 @@ impl<'a> LoadState<'a> {
|
|||||||
&mut self.retraction_info,
|
&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(
|
let code_index = self.get_or_insert_code_index(
|
||||||
key.clone(),
|
key.clone(),
|
||||||
compilation_target.clone(),
|
compilation_target.clone(),
|
||||||
@@ -1190,12 +1269,14 @@ impl<'a> LoadState<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(code_index.get())
|
Ok(())
|
||||||
}
|
}
|
||||||
AppendOrPrepend::Prepend => {
|
AppendOrPrepend::Prepend => {
|
||||||
skeleton
|
let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap();
|
||||||
.clauses
|
skeleton.clauses.push_front(clause_index_info);
|
||||||
.push_front(standalone_skeleton.clauses.pop_back().unwrap());
|
|
||||||
|
skeleton.clause_clause_locs.push_front(code_len);
|
||||||
|
skeleton.clause_assert_margin += 1;
|
||||||
|
|
||||||
self.retraction_info
|
self.retraction_info
|
||||||
.push_record(RetractionRecord::SkeletonClausePopFront(
|
.push_record(RetractionRecord::SkeletonClausePopFront(
|
||||||
@@ -1212,6 +1293,38 @@ impl<'a> LoadState<'a> {
|
|||||||
&mut self.retraction_info,
|
&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(
|
let code_index = self.get_or_insert_code_index(
|
||||||
key.clone(),
|
key.clone(),
|
||||||
compilation_target.clone(),
|
compilation_target.clone(),
|
||||||
@@ -1225,7 +1338,7 @@ impl<'a> LoadState<'a> {
|
|||||||
IndexPtr::Index(threaded_choice_instr_loc),
|
IndexPtr::Index(threaded_choice_instr_loc),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(IndexPtr::Index(threaded_choice_instr_loc))
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1309,7 +1422,7 @@ impl<'a> LoadState<'a> {
|
|||||||
skeleton.clauses[target_pos + 1].clause_start =
|
skeleton.clauses[target_pos + 1].clause_start =
|
||||||
skeleton.clauses[target_pos].clause_start;
|
skeleton.clauses[target_pos].clause_start;
|
||||||
|
|
||||||
return delete_from_dynamic_skeleton(
|
return delete_from_skeleton(
|
||||||
self.compilation_target.clone(),
|
self.compilation_target.clone(),
|
||||||
key,
|
key,
|
||||||
skeleton,
|
skeleton,
|
||||||
@@ -1530,12 +1643,12 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
|
|||||||
append_or_prepend: AppendOrPrepend,
|
append_or_prepend: AppendOrPrepend,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
let clause_predicates = clause_clauses.map(|(head, body)| {
|
let clause_predicates = clause_clauses.map(|(head, body)| {
|
||||||
PredicateClause::Fact(Term::Clause(
|
Term::Clause(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
clause_name!("$clause"),
|
clause_name!("$clause"),
|
||||||
vec![Box::new(head), Box::new(body)],
|
vec![Box::new(head), Box::new(body)],
|
||||||
None,
|
None,
|
||||||
))
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let clause_clause_compilation_target = match compilation_target {
|
let clause_clause_compilation_target = match compilation_target {
|
||||||
@@ -1543,49 +1656,64 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
|
|||||||
_ => compilation_target.clone(),
|
_ => compilation_target.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut clause_clause_locs = sdeq![];
|
let mut num_clause_predicates = 0;
|
||||||
|
|
||||||
for clause_predicate in clause_predicates {
|
|
||||||
clause_clause_locs.push_back(self.load_state.wam.code_repo.code.len());
|
|
||||||
|
|
||||||
|
for clause_term in clause_predicates {
|
||||||
self.load_state.incremental_compile_clause(
|
self.load_state.incremental_compile_clause(
|
||||||
(clause_name!("$clause"), 2),
|
(clause_name!("$clause"), 2),
|
||||||
clause_predicate,
|
clause_term,
|
||||||
VecDeque::new(),
|
|
||||||
clause_clause_compilation_target.clone(),
|
clause_clause_compilation_target.clone(),
|
||||||
false, // non_counted_bt is false.
|
false, // non_counted_bt is false.
|
||||||
append_or_prepend,
|
append_or_prepend,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
num_clause_predicates += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() => {
|
||||||
|
let tail_num = skeleton.clause_clause_locs.len() - num_clause_predicates;
|
||||||
|
skeleton.clause_clause_locs[tail_num ..]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
Some(skeleton) => {
|
||||||
|
skeleton.clause_clause_locs[0 .. num_clause_predicates]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match self.load_state.wam.indices.get_predicate_skeleton_mut(
|
match self.load_state.wam.indices.get_predicate_skeleton_mut(
|
||||||
&clause_clause_compilation_target,
|
&clause_clause_compilation_target,
|
||||||
&(clause_name!("$clause"), 2),
|
&(clause_name!("$clause"), 2),
|
||||||
) {
|
) {
|
||||||
Some(skeleton) if append_or_prepend.is_append() => {
|
Some(skeleton) if append_or_prepend.is_append() => {
|
||||||
self.load_state.retraction_info.push_record(
|
for _ in 0 .. num_clause_predicates {
|
||||||
RetractionRecord::SkeletonClauseClausesTruncateBack(
|
skeleton.clause_clause_locs.pop_back();
|
||||||
clause_clause_compilation_target.clone(),
|
}
|
||||||
(clause_name!("$clause"), 2),
|
|
||||||
skeleton.clause_clause_locs.len(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
skeleton
|
for loc in locs_vec {
|
||||||
.clause_clause_locs
|
skeleton.clause_clause_locs.push_back(loc);
|
||||||
.extend_from_slice(&clause_clause_locs[0..]);
|
}
|
||||||
}
|
}
|
||||||
Some(skeleton) => {
|
Some(skeleton) => {
|
||||||
self.load_state.retraction_info.push_record(
|
for _ in 0 .. num_clause_predicates {
|
||||||
RetractionRecord::SkeletonClauseClausesTruncateFront(
|
skeleton.clause_clause_locs.pop_front();
|
||||||
clause_clause_compilation_target.clone(),
|
}
|
||||||
(clause_name!("$clause"), 2),
|
|
||||||
skeleton.clause_clause_locs.len(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
for loc in clause_clause_locs.iter() {
|
for loc in locs_vec.into_iter().rev() {
|
||||||
skeleton.clause_clause_locs.push_front(*loc);
|
skeleton.clause_clause_locs.push_front(loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -1593,82 +1721,128 @@ impl<'a, TS: TermStream> Loader<'a, TS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
|
||||||
compilation_target.clone(),
|
|
||||||
key.clone(),
|
|
||||||
skeleton.clause_clause_locs.len(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
skeleton.clause_clause_locs.append(&mut clause_clause_locs);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.load_state.increment_clause_assert_margin(
|
|
||||||
clause_clause_compilation_target,
|
|
||||||
clause_clause_locs.len(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
|
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
|
||||||
let queue = self.preprocessor.parse_queue(&mut self.load_state)?;
|
|
||||||
|
|
||||||
let key = self
|
let key = self
|
||||||
.predicates
|
.predicates
|
||||||
.first()
|
.first()
|
||||||
.and_then(|cl| {
|
.and_then(|cl| {
|
||||||
let arity = cl.arity();
|
let arity = ClauseInfo::arity(cl);
|
||||||
cl.name().map(|name| (name, arity))
|
ClauseInfo::name(cl).map(|name| (name, arity))
|
||||||
})
|
})
|
||||||
.ok_or(SessionError::NamelessEntry)?;
|
.ok_or(SessionError::NamelessEntry)?;
|
||||||
|
|
||||||
let (is_dynamic, is_extensible) = self
|
let mut predicate_info = self
|
||||||
.load_state
|
.load_state
|
||||||
.wam
|
.wam
|
||||||
.indices
|
.indices
|
||||||
.get_predicate_skeleton(&self.predicates.compilation_target, &key)
|
.get_predicate_skeleton(&self.predicates.compilation_target, &key)
|
||||||
.map(|skeleton| (skeleton.is_dynamic, true))
|
.map(|skeleton| skeleton.predicate_info())
|
||||||
.unwrap_or((false, false));
|
.unwrap_or_default();
|
||||||
|
|
||||||
let non_counted_bt = self.non_counted_bt_preds.contains(&key);
|
let local_predicate_info = self
|
||||||
let settings = CodeGenSettings::new(is_extensible, non_counted_bt);
|
.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();
|
||||||
|
|
||||||
self.load_state
|
if predicate_info.must_retract_local_clauses() {
|
||||||
.compile(key.clone(), &self.predicates, &queue, settings)?;
|
self.retract_local_clauses(&key, predicate_info.is_dynamic);
|
||||||
|
|
||||||
if is_dynamic {
|
|
||||||
let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter();
|
|
||||||
let compilation_target = self.predicates.compilation_target.clone();
|
|
||||||
|
|
||||||
self.compile_clause_clauses(key, compilation_target, iter, AppendOrPrepend::Append)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.predicates.clear())
|
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);
|
||||||
|
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
self.predicates.compilation_target.clone(),
|
||||||
|
clauses_vec.into_iter(),
|
||||||
|
AppendOrPrepend::Append,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
|
use crate::machine::preprocessor::*;
|
||||||
use crate::machine::*;
|
use crate::machine::*;
|
||||||
|
use crate::machine::term_stream::*;
|
||||||
|
|
||||||
use prolog_parser::clause_name;
|
use prolog_parser::clause_name;
|
||||||
|
|
||||||
use crate::machine::term_stream::*;
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
use ref_thread_local::RefThreadLocal;
|
use ref_thread_local::RefThreadLocal;
|
||||||
|
use slice_deque::{sdeq, SliceDeque};
|
||||||
|
|
||||||
type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>;
|
type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>;
|
||||||
|
|
||||||
@@ -328,28 +330,120 @@ fn import_qualified_module_exports_into_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LoadState<'a> {
|
impl<'a> LoadState<'a> {
|
||||||
#[inline]
|
pub(super) fn retract_local_clauses(
|
||||||
pub(super) fn increment_clause_assert_margin(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
compilation_target: CompilationTarget,
|
compilation_target: CompilationTarget,
|
||||||
incr: usize,
|
key: PredicateKey,
|
||||||
|
clause_locs: &SliceDeque<usize>,
|
||||||
) {
|
) {
|
||||||
match compilation_target {
|
let clause_target_poses: Vec<_> = self
|
||||||
CompilationTarget::User => {}
|
.wam
|
||||||
CompilationTarget::Module(module_name) => {
|
.indices
|
||||||
self.wam
|
.get_predicate_skeleton(&compilation_target, &key)
|
||||||
.indices
|
.map(|skeleton| {
|
||||||
.modules
|
clause_locs
|
||||||
.get_mut(&module_name)
|
.iter()
|
||||||
.map(|module| module.clause_assert_margin += incr);
|
.map(|clause_clause_loc| {
|
||||||
|
skeleton.target_pos_of_clause_clause_loc(
|
||||||
|
*clause_clause_loc,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
self.retraction_info
|
self.retract_local_clauses_by_locs(
|
||||||
.push_record(RetractionRecord::IncreasedClauseAssertMargin(
|
compilation_target,
|
||||||
module_name,
|
key,
|
||||||
incr,
|
clause_target_poses,
|
||||||
));
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
#[inline]
|
||||||
@@ -451,16 +545,51 @@ impl<'a> LoadState<'a> {
|
|||||||
.extensible_predicates
|
.extensible_predicates
|
||||||
.insert(key.clone(), skeleton);
|
.insert(key.clone(), skeleton);
|
||||||
|
|
||||||
self.retraction_info
|
let record = RetractionRecord::AddedExtensiblePredicate(
|
||||||
.push_record(RetractionRecord::AddedUserExtensiblePredicate(key));
|
CompilationTarget::User,
|
||||||
|
key,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.retraction_info.push_record(record);
|
||||||
}
|
}
|
||||||
CompilationTarget::Module(module_name) => {
|
CompilationTarget::Module(module_name) => {
|
||||||
if let Some(module) = self.wam.indices.modules.get_mut(&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(
|
let record = RetractionRecord::AddedExtensiblePredicate(
|
||||||
RetractionRecord::AddedModuleExtensiblePredicate(module_name, key),
|
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 {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -604,32 +733,40 @@ impl<'a> LoadState<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let module_decl = ModuleDecl {
|
self.add_dynamically_generated_module(&module_name);
|
||||||
name: module_name.clone(),
|
|
||||||
exports: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
let listing_src = ListingSource::DynamicallyGenerated;
|
if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
|
||||||
let mut module = Module::new(module_decl, listing_src);
|
module.meta_predicates.insert(key.clone(), meta_specs);
|
||||||
|
} else {
|
||||||
module.meta_predicates.insert(key.clone(), meta_specs);
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
self.retraction_info
|
self.retraction_info
|
||||||
.push_record(RetractionRecord::AddedMetaPredicate(
|
.push_record(RetractionRecord::AddedMetaPredicate(
|
||||||
module_name.clone(),
|
module_name.clone(),
|
||||||
key,
|
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(
|
fn import_builtins_in_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
code_dir: &mut CodeDir,
|
code_dir: &mut CodeDir,
|
||||||
@@ -651,16 +788,57 @@ impl<'a> LoadState<'a> {
|
|||||||
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
|
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
|
||||||
let module_name = module_decl.name.clone();
|
let module_name = module_decl.name.clone();
|
||||||
|
|
||||||
|
match self.wam.indices.modules.get_mut(&module_name) {
|
||||||
|
Some(module) => {
|
||||||
|
let old_module_decl = mem::replace(&mut module.module_decl, module_decl.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) {
|
let mut module = match self.wam.indices.modules.remove(&module_name) {
|
||||||
Some(mut module) => {
|
Some(mut module) => {
|
||||||
let old_module_decl = mem::replace(&mut module.module_decl, module_decl);
|
|
||||||
|
|
||||||
self.retraction_info
|
|
||||||
.push_record(RetractionRecord::ReplacedModule(
|
|
||||||
old_module_decl,
|
|
||||||
listing_src.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
module.listing_src = listing_src;
|
module.listing_src = listing_src;
|
||||||
module
|
module
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ use prolog_parser::{clause_name, temp_v};
|
|||||||
use crate::forms::{ModuleSource, Number}; //, PredicateKey};
|
use crate::forms::{ModuleSource, Number}; //, PredicateKey};
|
||||||
use crate::machine::PredicateKey;
|
use crate::machine::PredicateKey;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
|
use crate::machine::loader::CompilationTarget;
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
use crate::machine::machine_state::*;
|
use crate::machine::machine_state::*;
|
||||||
use crate::rug::Integer;
|
use crate::rug::Integer;
|
||||||
@@ -344,6 +345,22 @@ impl MachineError {
|
|||||||
Self::permission_error(h, Permission::Create, "operator", functor!(clause_name(op)))
|
Self::permission_error(h, Permission::Create, "operator", functor!(clause_name(op)))
|
||||||
}
|
}
|
||||||
SessionError::CompilationError(err) => Self::syntax_error(h, err),
|
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(
|
SessionError::QueryCannotBeDefinedAsFact => Self::permission_error(
|
||||||
h,
|
h,
|
||||||
Permission::Create,
|
Permission::Create,
|
||||||
@@ -808,6 +825,7 @@ pub enum SessionError {
|
|||||||
ModuleCannotImportSelf(ClauseName),
|
ModuleCannotImportSelf(ClauseName),
|
||||||
NamelessEntry,
|
NamelessEntry,
|
||||||
OpIsInfixAndPostFix(ClauseName),
|
OpIsInfixAndPostFix(ClauseName),
|
||||||
|
PredicateNotMultifileOrDiscontiguous(CompilationTarget, PredicateKey),
|
||||||
QueryCannotBeDefinedAsFact,
|
QueryCannotBeDefinedAsFact,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -417,7 +417,9 @@ impl Default for CodeIndex {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
pub enum REPLCodePtr {
|
pub enum REPLCodePtr {
|
||||||
|
AddDiscontiguousPredicate,
|
||||||
AddDynamicPredicate,
|
AddDynamicPredicate,
|
||||||
|
AddMultifilePredicate,
|
||||||
AddGoalExpansionClause,
|
AddGoalExpansionClause,
|
||||||
AddTermExpansionClause,
|
AddTermExpansionClause,
|
||||||
ClauseToEvacuable,
|
ClauseToEvacuable,
|
||||||
@@ -743,6 +745,68 @@ impl IndexStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
pub fn get_predicate_skeleton(
|
||||||
&self,
|
&self,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
@@ -767,18 +831,20 @@ impl IndexStore {
|
|||||||
&mut self,
|
&mut self,
|
||||||
compilation_target: &CompilationTarget,
|
compilation_target: &CompilationTarget,
|
||||||
key: &PredicateKey,
|
key: &PredicateKey,
|
||||||
) {
|
) -> Option<PredicateSkeleton> {
|
||||||
match (key.0.as_str(), key.1) {
|
match (key.0.as_str(), key.1) {
|
||||||
("term_expansion", 2) => {
|
("term_expansion", 2) => {
|
||||||
self.extensible_predicates.remove(key);
|
self.extensible_predicates.remove(key)
|
||||||
}
|
}
|
||||||
_ => match compilation_target {
|
_ => match compilation_target {
|
||||||
CompilationTarget::User => {
|
CompilationTarget::User => {
|
||||||
self.extensible_predicates.remove(key);
|
self.extensible_predicates.remove(key)
|
||||||
}
|
}
|
||||||
CompilationTarget::Module(ref module_name) => {
|
CompilationTarget::Module(ref module_name) => {
|
||||||
if let Some(module) = self.modules.get_mut(module_name) {
|
if let Some(module) = self.modules.get_mut(module_name) {
|
||||||
module.extensible_predicates.remove(key);
|
module.extensible_predicates.remove(key)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -412,9 +412,15 @@ impl Machine {
|
|||||||
|
|
||||||
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
|
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
|
||||||
match code_ptr {
|
match code_ptr {
|
||||||
|
REPLCodePtr::AddDiscontiguousPredicate => {
|
||||||
|
self.add_discontiguous_predicate();
|
||||||
|
}
|
||||||
REPLCodePtr::AddDynamicPredicate => {
|
REPLCodePtr::AddDynamicPredicate => {
|
||||||
self.add_dynamic_predicate();
|
self.add_dynamic_predicate();
|
||||||
}
|
}
|
||||||
|
REPLCodePtr::AddMultifilePredicate => {
|
||||||
|
self.add_multifile_predicate();
|
||||||
|
}
|
||||||
REPLCodePtr::AddGoalExpansionClause => {
|
REPLCodePtr::AddGoalExpansionClause => {
|
||||||
self.add_goal_expansion_clause();
|
self.add_goal_expansion_clause();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,9 +394,6 @@ fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, CompilationEr
|
|||||||
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => {
|
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => {
|
||||||
return Ok(tl);
|
return Ok(tl);
|
||||||
}
|
}
|
||||||
TopLevel::Declaration(_) if clauses.is_empty() => {
|
|
||||||
return Ok(tl);
|
|
||||||
}
|
|
||||||
TopLevel::Query(_) => {
|
TopLevel::Query(_) => {
|
||||||
return Err(CompilationError::InconsistentEntry);
|
return Err(CompilationError::InconsistentEntry);
|
||||||
}
|
}
|
||||||
@@ -409,10 +406,6 @@ fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, CompilationEr
|
|||||||
clauses.push(clause);
|
clauses.push(clause);
|
||||||
}
|
}
|
||||||
TopLevel::Predicate(predicate) => clauses.extend(predicate.into_iter()),
|
TopLevel::Predicate(predicate) => clauses.extend(predicate.into_iter()),
|
||||||
_ => {
|
|
||||||
tls.push_front(tl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +490,7 @@ fn check_for_internal_if_then(terms: &mut Vec<Term>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_declaration<'a>(
|
pub(super) fn setup_declaration<'a>(
|
||||||
load_state: &LoadState<'a>,
|
load_state: &LoadState<'a>,
|
||||||
mut terms: Vec<Box<Term>>,
|
mut terms: Vec<Box<Term>>,
|
||||||
) -> Result<Declaration, CompilationError> {
|
) -> Result<Declaration, CompilationError> {
|
||||||
@@ -883,8 +876,6 @@ impl Preprocessor {
|
|||||||
terms,
|
terms,
|
||||||
cut_context,
|
cut_context,
|
||||||
)?))
|
)?))
|
||||||
} else if name.as_str() == ":-" && terms.len() == 1 {
|
|
||||||
Ok(TopLevel::Declaration(setup_declaration(load_state, terms)?))
|
|
||||||
} else {
|
} else {
|
||||||
let term = Term::Clause(r, name, terms, fixity);
|
let term = Term::Clause(r, name, terms, fixity);
|
||||||
Ok(TopLevel::Fact(self.setup_fact(term)?))
|
Ok(TopLevel::Fact(self.setup_fact(term)?))
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use prolog_parser::ast::*;
|
|||||||
use prolog_parser::parser::*;
|
use prolog_parser::parser::*;
|
||||||
|
|
||||||
use crate::machine::machine_errors::CompilationError;
|
use crate::machine::machine_errors::CompilationError;
|
||||||
use crate::machine::preprocessor::*;
|
|
||||||
use crate::machine::*;
|
use crate::machine::*;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
@@ -100,7 +99,6 @@ pub struct LoadStatePayload {
|
|||||||
pub(super) retraction_info: RetractionInfo,
|
pub(super) retraction_info: RetractionInfo,
|
||||||
pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>,
|
pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>,
|
||||||
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
|
pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
|
||||||
pub(super) preprocessor: Preprocessor,
|
|
||||||
pub(super) predicates: PredicateQueue,
|
pub(super) predicates: PredicateQueue,
|
||||||
pub(super) clause_clauses: Vec<(Term, Term)>,
|
pub(super) clause_clauses: Vec<(Term, Term)>,
|
||||||
}
|
}
|
||||||
@@ -119,7 +117,6 @@ impl LoadStatePayload {
|
|||||||
retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
|
retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
|
||||||
module_op_exports: vec![],
|
module_op_exports: vec![],
|
||||||
non_counted_bt_preds: IndexSet::new(),
|
non_counted_bt_preds: IndexSet::new(),
|
||||||
preprocessor: Preprocessor::new(wam.machine_st.flags),
|
|
||||||
predicates: predicate_queue![],
|
predicates: predicate_queue![],
|
||||||
clause_clauses: vec![],
|
clause_clauses: vec![],
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/write.rs
18
src/write.rs
@@ -2,6 +2,7 @@ use crate::clause_types::*;
|
|||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::indexing::IndexingCodePtr;
|
use crate::indexing::IndexingCodePtr;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
|
use crate::machine::loader::CompilationTarget;
|
||||||
use crate::machine::machine_errors::*;
|
use crate::machine::machine_errors::*;
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
|
|
||||||
@@ -20,8 +21,12 @@ impl fmt::Display for LocalCodePtr {
|
|||||||
impl fmt::Display for REPLCodePtr {
|
impl fmt::Display for REPLCodePtr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
REPLCodePtr::AddDiscontiguousPredicate =>
|
||||||
|
write!(f, "REPLCodePtr::AddDiscontiguousPredicate"),
|
||||||
REPLCodePtr::AddDynamicPredicate =>
|
REPLCodePtr::AddDynamicPredicate =>
|
||||||
write!(f, "REPLCodePtr::AddDynamicPredicate"),
|
write!(f, "REPLCodePtr::AddDynamicPredicate"),
|
||||||
|
REPLCodePtr::AddMultifilePredicate =>
|
||||||
|
write!(f, "REPLCodePtr::AddMultifilePredicate"),
|
||||||
REPLCodePtr::AddGoalExpansionClause =>
|
REPLCodePtr::AddGoalExpansionClause =>
|
||||||
write!(f, "REPLCodePtr::AddGoalExpansionClause"),
|
write!(f, "REPLCodePtr::AddGoalExpansionClause"),
|
||||||
REPLCodePtr::AddTermExpansionClause =>
|
REPLCodePtr::AddTermExpansionClause =>
|
||||||
@@ -88,6 +93,15 @@ impl fmt::Display for IndexPtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
impl fmt::Display for FactInstruction {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -404,6 +418,10 @@ impl fmt::Display for SessionError {
|
|||||||
write!(f, "modules ({}, in this case) cannot import themselves.",
|
write!(f, "modules ({}, in this case) cannot import themselves.",
|
||||||
module_name)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user