do not add expansions behind module boundaries until the modules are added
This commit is contained in:
@@ -5,6 +5,7 @@ use prolog::instructions::*;
|
||||
use prolog::debray_allocator::*;
|
||||
use prolog::codegen::*;
|
||||
use prolog::machine::*;
|
||||
use prolog::machine::term_expansion::{ExpansionAdditionResult, TermStream};
|
||||
use prolog::toplevel::*;
|
||||
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
@@ -87,6 +88,30 @@ pub fn compile_appendix(code: &mut Code, queue: &VecDeque<TopLevel>, non_counted
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl CodeRepo {
|
||||
pub fn compile_hook(&mut self, hook: CompileTimeHook, flags: MachineFlags)
|
||||
-> Result<(), ParserError>
|
||||
{
|
||||
let key = (hook.name(), hook.arity());
|
||||
match self.term_dir.get(&key) {
|
||||
Some(preds) => {
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
|
||||
let mut code = cg.compile_predicate(&(preds.0).0)?;
|
||||
|
||||
compile_appendix(&mut code, &preds.1, false, flags)?;
|
||||
|
||||
Ok(match hook {
|
||||
CompileTimeHook::TermExpansion =>
|
||||
self.term_expanders = code,
|
||||
CompileTimeHook::GoalExpansion =>
|
||||
self.goal_expanders = code
|
||||
})
|
||||
},
|
||||
None => Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_query(terms: Vec<QueryTerm>, queue: VecDeque<TopLevel>, flags: MachineFlags)
|
||||
-> Result<(Code, AllocVarDict), ParserError>
|
||||
{
|
||||
@@ -136,7 +161,8 @@ pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
|
||||
struct GatherResult {
|
||||
worker_results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
||||
toplevel_results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
||||
toplevel_indices: IndexStore
|
||||
toplevel_indices: IndexStore,
|
||||
addition_results: ExpansionAdditionResult
|
||||
}
|
||||
|
||||
pub struct ListingCompiler {
|
||||
@@ -152,17 +178,19 @@ impl ListingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
fn use_module(&mut self, submodule: ClauseName, wam_indices: &mut IndexStore, indices: &mut IndexStore)
|
||||
fn use_module(&mut self, submodule: ClauseName, code_repo: &mut CodeRepo,
|
||||
flags: MachineFlags, wam_indices: &mut IndexStore,
|
||||
indices: &mut IndexStore)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
let mod_name = self.get_module_name();
|
||||
|
||||
if let Some(submodule) = wam_indices.take_module(submodule) {
|
||||
indices.use_module(&submodule)?;
|
||||
indices.use_module(code_repo, flags, &submodule)?;
|
||||
|
||||
if let &mut Some(ref mut module) = &mut self.module {
|
||||
module.remove_module(mod_name, &submodule);
|
||||
module.use_module(&submodule)?;
|
||||
module.use_module(code_repo, flags, &submodule)?;
|
||||
} else {
|
||||
wam_indices.remove_module(clause_name!("user"), &submodule);
|
||||
}
|
||||
@@ -173,18 +201,19 @@ impl ListingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, submodule: ClauseName, exports: &Vec<PredicateKey>,
|
||||
fn use_qualified_module(&mut self, submodule: ClauseName, code_repo: &mut CodeRepo,
|
||||
flags: MachineFlags, exports: &Vec<PredicateKey>,
|
||||
wam_indices: &mut IndexStore, indices: &mut IndexStore)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
let mod_name = self.get_module_name();
|
||||
|
||||
if let Some(submodule) = wam_indices.take_module(submodule) {
|
||||
indices.use_qualified_module(&submodule, exports)?;
|
||||
indices.use_qualified_module(code_repo, flags, &submodule, exports)?;
|
||||
|
||||
if let &mut Some(ref mut module) = &mut self.module {
|
||||
module.remove_module(mod_name, &submodule);
|
||||
module.use_qualified_module(&submodule, exports)?;
|
||||
module.use_qualified_module(code_repo, flags, &submodule, exports)?;
|
||||
} else {
|
||||
wam_indices.remove_module(clause_name!("user"), &submodule);
|
||||
}
|
||||
@@ -262,32 +291,26 @@ impl ListingCompiler {
|
||||
match decl {
|
||||
Declaration::Hook(hook, clause, queue) => {
|
||||
let key = (hook.name(), hook.arity());
|
||||
let preds = code_repo.term_dir.entry(key)
|
||||
.or_insert((Predicate(vec![]), VecDeque::from(vec![])));
|
||||
|
||||
(preds.0).0.push(clause);
|
||||
preds.1.extend(queue.into_iter());
|
||||
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
|
||||
let mut code = cg.compile_predicate(&(preds.0).0)?;
|
||||
|
||||
compile_appendix(&mut code, &preds.1, false, flags)?;
|
||||
|
||||
match hook {
|
||||
CompileTimeHook::TermExpansion =>
|
||||
Ok(code_repo.term_expanders = code),
|
||||
CompileTimeHook::GoalExpansion =>
|
||||
Ok(code_repo.goal_expanders = code)
|
||||
{
|
||||
let preds = code_repo.term_dir.entry(key)
|
||||
.or_insert((Predicate(vec![]), VecDeque::from(vec![])));
|
||||
|
||||
(preds.0).0.push(clause);
|
||||
preds.1.extend(queue.into_iter());
|
||||
}
|
||||
|
||||
code_repo.compile_hook(hook, flags)
|
||||
.map_err(SessionError::from)
|
||||
},
|
||||
Declaration::NonCountedBacktracking(name, arity) =>
|
||||
Ok(self.add_non_counted_bt_flag(name, arity)),
|
||||
Declaration::Op(op_decl) =>
|
||||
op_decl.submit(self.get_module_name(), &mut indices.op_dir),
|
||||
Declaration::UseModule(name) =>
|
||||
self.use_module(name, wam_indices, indices),
|
||||
self.use_module(name, code_repo, flags, wam_indices, indices),
|
||||
Declaration::UseQualifiedModule(name, exports) =>
|
||||
self.use_qualified_module(name, &exports, wam_indices, indices),
|
||||
self.use_qualified_module(name, code_repo, flags, &exports, wam_indices, indices),
|
||||
Declaration::Module(module_decl) =>
|
||||
if self.module.is_none() {
|
||||
let module_name = module_decl.name.clone();
|
||||
@@ -300,6 +323,20 @@ impl ListingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_and_commit_decl<'a, R: Read>(&mut self, decl: Declaration,
|
||||
term_stream: &mut TermStream<'a, R>,
|
||||
indices: &mut IndexStore, flags: MachineFlags)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
match &decl {
|
||||
&Declaration::Hook(hook, _, ref queue) if self.module.is_none() =>
|
||||
term_stream.incr_expansion_lens(hook, 1, queue.len()),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
self.process_decl(decl, term_stream.code_repo, term_stream.indices, indices, flags)
|
||||
}
|
||||
|
||||
fn gather_items<R: Read>(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore)
|
||||
-> Result<GatherResult, SessionError>
|
||||
{
|
||||
@@ -321,24 +358,25 @@ impl ListingCompiler {
|
||||
mem::swap(&mut worker.results, &mut toplevel_results);
|
||||
worker.in_module = true;
|
||||
|
||||
self.process_decl(decl, worker.term_stream.code_repo,
|
||||
worker.term_stream.indices,
|
||||
indices, flags)?;
|
||||
self.process_and_commit_decl(decl, &mut worker.term_stream,
|
||||
indices, flags)?;
|
||||
|
||||
if let &Some(ref module) = &self.module {
|
||||
worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
|
||||
}
|
||||
} else {
|
||||
self.process_decl(decl, worker.term_stream.code_repo,
|
||||
worker.term_stream.indices,
|
||||
indices, flags)?;
|
||||
self.process_and_commit_decl(decl, &mut worker.term_stream,
|
||||
indices, flags)?;
|
||||
}
|
||||
}
|
||||
|
||||
let addition_results = worker.term_stream.rollback_expansion_code()?;
|
||||
|
||||
Ok(GatherResult {
|
||||
worker_results: worker.results,
|
||||
toplevel_results,
|
||||
toplevel_indices
|
||||
toplevel_indices,
|
||||
addition_results
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -354,15 +392,24 @@ fn compile_listing<R: Read>(wam: &mut Machine, src: R, mut indices: IndexStore)
|
||||
let toplvl_code = try_eval_session!(compiler.generate_code(results.toplevel_results, wam,
|
||||
&mut results.toplevel_indices.code_dir));
|
||||
|
||||
if let Some(ref mut module) = &mut compiler.module {
|
||||
module.term_expansions = results.addition_results.take_term_expansions();
|
||||
module.goal_expansions = results.addition_results.take_goal_expansions();
|
||||
}
|
||||
|
||||
try_eval_session!(compiler.add_code(wam, module_code, indices));
|
||||
try_eval_session!(compiler.add_code(wam, toplvl_code, results.toplevel_indices));
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
fn setup_indices(wam: &Machine, indices: &mut IndexStore) -> Result<(), SessionError> {
|
||||
if let Some(ref builtins) = wam.indices.modules.get(&clause_name!("builtins")) {
|
||||
indices.use_module(builtins)
|
||||
fn setup_indices(wam: &mut Machine, indices: &mut IndexStore) -> Result<(), SessionError> {
|
||||
if let Some(builtins) = wam.indices.take_module(clause_name!("builtins")) {
|
||||
let flags = wam.machine_flags();
|
||||
let result = indices.use_module(&mut wam.code_repo, flags, &builtins);
|
||||
|
||||
wam.indices.insert_module(builtins);
|
||||
result
|
||||
} else {
|
||||
Err(SessionError::ModuleNotFound)
|
||||
}
|
||||
@@ -370,6 +417,6 @@ fn setup_indices(wam: &Machine, indices: &mut IndexStore) -> Result<(), SessionE
|
||||
|
||||
pub fn compile_user_module<R: Read>(wam: &mut Machine, src: R) -> EvalSession {
|
||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||
try_eval_session!(setup_indices(&wam, &mut indices));
|
||||
try_eval_session!(setup_indices(wam, &mut indices));
|
||||
compile_listing(wam, src, indices)
|
||||
}
|
||||
|
||||
@@ -125,6 +125,7 @@ impl CompareTermQT {
|
||||
// of vars (we get their adjoining cells this way).
|
||||
pub type JumpStub = Vec<Term>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum QueryTerm {
|
||||
// register, clause type, subterms, use default call policy.
|
||||
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>, bool),
|
||||
@@ -152,19 +153,26 @@ impl QueryTerm {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Rule {
|
||||
pub head: (ClauseName, Vec<Box<Term>>, QueryTerm),
|
||||
pub clauses: Vec<QueryTerm>
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Predicate(pub Vec<PredicateClause>);
|
||||
|
||||
impl Predicate {
|
||||
pub fn new() -> Self {
|
||||
Predicate(vec![])
|
||||
}
|
||||
|
||||
pub fn clauses(self) -> Vec<PredicateClause> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum PredicateClause {
|
||||
Fact(Term),
|
||||
Rule(Rule)
|
||||
@@ -203,6 +211,16 @@ pub type ModuleDir = HashMap<ClauseName, Module>;
|
||||
|
||||
pub type PredicateKey = (ClauseName, usize); // name, arity.
|
||||
|
||||
pub struct CodeRepo {
|
||||
pub(super) cached_query: Code,
|
||||
pub(super) goal_expanders: Code,
|
||||
pub(super) term_expanders: Code,
|
||||
pub(super) code: Code,
|
||||
pub(super) in_situ_code: Code,
|
||||
pub(super) term_dir: TermDir
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ModuleDecl {
|
||||
pub name: ClauseName,
|
||||
pub exports: Vec<PredicateKey>
|
||||
@@ -212,7 +230,9 @@ pub struct Module {
|
||||
pub atom_tbl: TabledData<Atom>,
|
||||
pub module_decl: ModuleDecl,
|
||||
pub code_dir: ModuleCodeDir,
|
||||
pub op_dir: OpDir
|
||||
pub op_dir: OpDir,
|
||||
pub term_expansions: (Predicate, VecDeque<TopLevel>),
|
||||
pub goal_expansions: (Predicate, VecDeque<TopLevel>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
@@ -1074,9 +1094,36 @@ impl<'a> TermIterState<'a> {
|
||||
impl Module {
|
||||
pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self {
|
||||
Module { module_decl, atom_tbl,
|
||||
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
code_dir: ModuleCodeDir::new(),
|
||||
op_dir: default_op_dir() }
|
||||
}
|
||||
|
||||
pub fn dump_expansions(&self, code_repo: &mut CodeRepo, flags: MachineFlags)
|
||||
-> Result<(), ParserError>
|
||||
{
|
||||
{
|
||||
let te = code_repo.term_dir.entry((clause_name!("term_expansion"), 2))
|
||||
.or_insert((Predicate::new(), VecDeque::from(vec![])));
|
||||
|
||||
(te.0).0.extend((self.term_expansions.0).0.iter().cloned());
|
||||
te.1.extend(self.term_expansions.1.iter().cloned());
|
||||
}
|
||||
|
||||
{
|
||||
let ge = code_repo.term_dir.entry((clause_name!("goal_expansion"), 2))
|
||||
.or_insert((Predicate::new(), VecDeque::from(vec![])));
|
||||
|
||||
(ge.0).0.extend((self.goal_expansions.0).0.iter().cloned());
|
||||
ge.1.extend(self.goal_expansions.1.iter().cloned());
|
||||
}
|
||||
|
||||
code_repo.compile_hook(CompileTimeHook::TermExpansion, flags)?;
|
||||
code_repo.compile_hook(CompileTimeHook::GoalExpansion, flags)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir {
|
||||
@@ -1171,31 +1218,39 @@ pub trait SubModuleUser {
|
||||
}
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
for (name, arity) in exports.iter().cloned() {
|
||||
if !submodule.module_decl.exports.contains(&(name.clone(), arity)) {
|
||||
continue;
|
||||
}
|
||||
fn use_qualified_module(&mut self, &mut CodeRepo, MachineFlags, &Module, &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>;
|
||||
fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module)
|
||||
-> Result<(), SessionError>;
|
||||
}
|
||||
|
||||
if !self.import_decl(name, arity, submodule) {
|
||||
return Err(SessionError::ModuleDoesNotContainExport);
|
||||
}
|
||||
pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
where User: SubModuleUser
|
||||
{
|
||||
for (name, arity) in exports.iter().cloned() {
|
||||
if !submodule.module_decl.exports.contains(&(name.clone(), arity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn use_module(&mut self, submodule: &Module) -> Result<(), SessionError> {
|
||||
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
||||
if !self.import_decl(name, arity, submodule) {
|
||||
return Err(SessionError::ModuleDoesNotContainExport);
|
||||
}
|
||||
if !user.import_decl(name, arity, submodule) {
|
||||
return Err(SessionError::ModuleDoesNotContainExport);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn use_module<User: SubModuleUser>(user: &mut User, submodule: &Module)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
||||
if !user.import_decl(name, arity, submodule) {
|
||||
return Err(SessionError::ModuleDoesNotContainExport);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl SubModuleUser for Module {
|
||||
@@ -1215,12 +1270,41 @@ impl SubModuleUser for Module {
|
||||
self.code_dir.remove(&key);
|
||||
}
|
||||
|
||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex)
|
||||
{
|
||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
|
||||
self.code_dir.insert((name, arity), idx);
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module,
|
||||
exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
use_qualified_module(self, submodule, exports)?;
|
||||
|
||||
(self.term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned());
|
||||
self.term_expansions.1.extend(submodule.term_expansions.1.iter().cloned());
|
||||
|
||||
(self.goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned());
|
||||
self.goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn use_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
use_module(self, submodule)?;
|
||||
|
||||
(self.term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned());
|
||||
self.term_expansions.1.extend(submodule.term_expansions.1.iter().cloned());
|
||||
|
||||
(self.goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned());
|
||||
self.goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Declaration {
|
||||
Hook(CompileTimeHook, PredicateClause, VecDeque<TopLevel>),
|
||||
Module(ModuleDecl),
|
||||
@@ -1237,6 +1321,7 @@ impl Declaration {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TopLevel {
|
||||
Declaration(Declaration),
|
||||
Fact(Term),
|
||||
@@ -1388,6 +1473,7 @@ impl From<ParserError> for EvalSession {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
|
||||
|
||||
impl OpDecl {
|
||||
|
||||
@@ -30,7 +30,7 @@ pub struct IndexStore {
|
||||
pub(super) code_dir: CodeDir,
|
||||
pub(super) in_situ_code_dir: InSituCodeDir,
|
||||
pub(super) op_dir: OpDir,
|
||||
pub(super) modules: ModuleDir
|
||||
pub(super) modules: ModuleDir,
|
||||
}
|
||||
|
||||
enum RefOrOwned<'a, T: 'a> {
|
||||
@@ -108,16 +108,7 @@ impl IndexStore {
|
||||
|
||||
pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
|
||||
|
||||
pub struct CodeRepo {
|
||||
cached_query: Code,
|
||||
pub(super) goal_expanders: Code,
|
||||
pub(super) term_expanders: Code,
|
||||
pub(super) code: Code,
|
||||
pub(super) in_situ_code: Code,
|
||||
pub(super) term_dir: TermDir
|
||||
}
|
||||
|
||||
impl CodeRepo {
|
||||
impl CodeRepo {
|
||||
#[inline]
|
||||
fn new() -> Self {
|
||||
CodeRepo {
|
||||
@@ -130,6 +121,25 @@ impl CodeRepo {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
|
||||
self.term_dir.get(&key)
|
||||
.map(|entry| ((entry.0).0.len(), entry.1.len()))
|
||||
.unwrap_or((0,0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize)
|
||||
-> (Predicate, VecDeque<TopLevel>)
|
||||
{
|
||||
//TODO: fix this! this is causing a test to fail. because term_expansions, when
|
||||
//removed by rollback_expansion_code, aren't jump-labeled properly by generate_code.
|
||||
self.term_dir.get_mut(&key)
|
||||
.map(|entry| (Predicate((entry.0).0.clone()[len ..].to_vec()), //drain(len ..).collect()),
|
||||
entry.1.drain(queue_len ..).collect()))
|
||||
.unwrap_or((Predicate(vec![]), VecDeque::from(vec![])))
|
||||
}
|
||||
|
||||
pub fn add_in_situ_result(&mut self, result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir,
|
||||
flags: MachineFlags)
|
||||
-> Result<(), SessionError>
|
||||
@@ -276,6 +286,21 @@ impl SubModuleUser for IndexStore {
|
||||
|
||||
self.code_dir.insert((name, arity), CodeIndex::from(idx));
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags,
|
||||
submodule: &Module, exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
use_qualified_module(self, submodule, exports)?;
|
||||
submodule.dump_expansions(code_repo, flags).map_err(SessionError::from)
|
||||
}
|
||||
|
||||
fn use_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags, submodule: &Module)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
use_module(self, submodule)?;
|
||||
submodule.dump_expansions(code_repo, flags).map_err(SessionError::from)
|
||||
}
|
||||
}
|
||||
|
||||
static LISTS: &str = include_str!("../lib/lists.pl");
|
||||
|
||||
@@ -50,6 +50,24 @@ pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
||||
term
|
||||
}
|
||||
|
||||
fn extract_from_list(head: Box<Term>, tail: Box<Term>)
|
||||
-> Result<Rev<IntoIter<Term>>, ParserError>
|
||||
{
|
||||
let mut terms = vec![*head];
|
||||
let mut tail = *tail;
|
||||
|
||||
while let Term::Cons(_, head, next_tail) = tail {
|
||||
terms.push(*head);
|
||||
tail = *next_tail;
|
||||
}
|
||||
|
||||
if let Term::Constant(_, Constant::EmptyList) = tail {
|
||||
Ok(terms.into_iter().rev())
|
||||
} else {
|
||||
Err(ParserError::ExpectedTopLevelTerm)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TermStream<'a, R: Read> {
|
||||
stack: Vec<Term>,
|
||||
pub(crate) indices: &'a mut IndexStore,
|
||||
@@ -57,13 +75,37 @@ pub struct TermStream<'a, R: Read> {
|
||||
pub(crate) code_repo: &'a mut CodeRepo,
|
||||
parser: Parser<R>,
|
||||
in_module: bool,
|
||||
pub(crate) flags: MachineFlags
|
||||
pub(crate) flags: MachineFlags,
|
||||
term_expansion_lens: (usize, usize),
|
||||
goal_expansion_lens: (usize, usize),
|
||||
}
|
||||
|
||||
pub struct ExpansionAdditionResult {
|
||||
term_expansion_additions: (Predicate, VecDeque<TopLevel>),
|
||||
goal_expansion_additions: (Predicate, VecDeque<TopLevel>)
|
||||
}
|
||||
|
||||
impl ExpansionAdditionResult {
|
||||
pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
||||
let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
|
||||
let teqs = mem::replace(&mut self.term_expansion_additions.1, VecDeque::from(vec![]));
|
||||
|
||||
(tes, teqs)
|
||||
}
|
||||
|
||||
pub fn take_goal_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
||||
let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
|
||||
let geqs = mem::replace(&mut self.goal_expansion_additions.1, VecDeque::from(vec![]));
|
||||
|
||||
(ges, geqs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: Read> Drop for TermStream<'a, R> {
|
||||
fn drop(&mut self) {
|
||||
self.indices.in_situ_code_dir.clear();
|
||||
self.code_repo.in_situ_code.clear();
|
||||
self.code_repo.in_situ_code.clear();
|
||||
discard_result!(self.rollback_expansion_code());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,15 +117,31 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
{
|
||||
TermStream {
|
||||
stack: Vec::new(),
|
||||
term_expansion_lens: code_repo.term_dir_entry_len((clause_name!("term_expansion"), 2)),
|
||||
goal_expansion_lens: code_repo.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
|
||||
code_repo,
|
||||
indices,
|
||||
policies,
|
||||
code_repo,
|
||||
parser: Parser::new(src, atom_tbl, flags),
|
||||
in_module: false,
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) {
|
||||
match hook {
|
||||
CompileTimeHook::TermExpansion => {
|
||||
self.term_expansion_lens.0 += len;
|
||||
self.term_expansion_lens.1 += queue_len;
|
||||
},
|
||||
CompileTimeHook::GoalExpansion => {
|
||||
self.goal_expansion_lens.0 += len;
|
||||
self.goal_expansion_lens.1 += queue_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_atom_tbl(&mut self, atom_tbl: TabledData<Atom>) {
|
||||
self.parser.set_atom_tbl(atom_tbl);
|
||||
@@ -99,28 +157,33 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
Ok(self.stack.is_empty() && self.parser.eof()?)
|
||||
}
|
||||
|
||||
fn extract_from_list(&mut self, head: Box<Term>, tail: Box<Term>)
|
||||
-> Result<Rev<IntoIter<Term>>, ParserError>
|
||||
{
|
||||
let mut terms = vec![*head];
|
||||
let mut tail = *tail;
|
||||
pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> {
|
||||
let te_len = self.term_expansion_lens.0;
|
||||
let te_queue_len = self.term_expansion_lens.1;
|
||||
|
||||
while let Term::Cons(_, head, next_tail) = tail {
|
||||
terms.push(*head);
|
||||
tail = *next_tail;
|
||||
}
|
||||
let ge_len = self.goal_expansion_lens.0;
|
||||
let ge_queue_len = self.goal_expansion_lens.1;
|
||||
|
||||
if let Term::Constant(_, Constant::EmptyList) = tail {
|
||||
Ok(terms.into_iter().rev())
|
||||
} else {
|
||||
Err(ParserError::ExpectedTopLevelTerm)
|
||||
}
|
||||
let term_expansion_additions =
|
||||
self.code_repo.truncate_terms((clause_name!("term_expansion"), 2),
|
||||
te_len, te_queue_len);
|
||||
let goal_expansion_additions =
|
||||
self.code_repo.truncate_terms((clause_name!("goal_expansion"), 2),
|
||||
ge_len, ge_queue_len);
|
||||
|
||||
self.code_repo.compile_hook(CompileTimeHook::TermExpansion, self.flags)?;
|
||||
self.code_repo.compile_hook(CompileTimeHook::GoalExpansion, self.flags)?;
|
||||
|
||||
Ok(ExpansionAdditionResult {
|
||||
term_expansion_additions,
|
||||
goal_expansion_additions
|
||||
})
|
||||
}
|
||||
|
||||
fn enqueue_term(&mut self, term: Term) -> Result<(), ParserError> {
|
||||
match term {
|
||||
Term::Cons(_, head, tail) => {
|
||||
let iter = self.extract_from_list(head, tail)?;
|
||||
let iter = extract_from_list(head, tail)?;
|
||||
Ok(self.stack.extend(iter))
|
||||
},
|
||||
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) =>
|
||||
@@ -208,7 +271,7 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
|
||||
match term {
|
||||
Term::Cons(_, head, tail) =>
|
||||
for term in self.extract_from_list(head, tail)? {
|
||||
for term in extract_from_list(head, tail)? {
|
||||
terms.push_front(term);
|
||||
},
|
||||
term =>
|
||||
|
||||
@@ -248,3 +248,11 @@ macro_rules! get_level_and_unify {
|
||||
Line::Cut(CutInstruction::GetLevelAndUnify($r))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! discard_result {
|
||||
($f: expr) => (
|
||||
match $f {
|
||||
_ => ()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ impl<'a, 'b> CompositeIndices<'a, 'b>
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_compile_time_hook(name: &str, arity: usize) -> Option<CompileTimeHook> {
|
||||
fn as_compile_time_hook(name: &str, arity: usize) -> Option<CompileTimeHook> {
|
||||
match (name, arity) {
|
||||
("term_expansion", 2) => Some(CompileTimeHook::TermExpansion),
|
||||
("goal_expansion", 2) => Some(CompileTimeHook::GoalExpansion),
|
||||
@@ -84,12 +84,12 @@ fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<Com
|
||||
if name.as_str() == ":-" {
|
||||
if let Some(ref term) = terms.first() {
|
||||
if let &Term::Clause(_, ref name, ref terms, None) = term.as_ref() {
|
||||
return get_compile_time_hook(name.as_str(), terms.len());
|
||||
return as_compile_time_hook(name.as_str(), terms.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_compile_time_hook(name.as_str(), terms.len())
|
||||
as_compile_time_hook(name.as_str(), terms.len())
|
||||
}
|
||||
|
||||
type CompileTimeHookCompileInfo = (CompileTimeHook, PredicateClause, VecDeque<TopLevel>);
|
||||
|
||||
Reference in New Issue
Block a user