address issues #143, #150, #155

This commit is contained in:
Mark Thom
2019-09-02 16:53:31 -04:00
parent 07412b9d34
commit 2c880b2bc0
25 changed files with 314 additions and 210 deletions

View File

@@ -14,8 +14,10 @@ use prolog::machine::toplevel::*;
use std::cell::Cell;
use std::collections::{HashMap, HashSet, VecDeque};
use std::fs::File;
use std::io::Read;
use std::mem;
use std::path::PathBuf;
#[allow(dead_code)]
fn print_code(code: &Code) {
@@ -41,6 +43,59 @@ fn print_code(code: &Code) {
}
}
fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, SessionError>
{
let mut path = PathBuf::from(filename);
if !path.is_file() {
if path.extension().is_none() {
path.set_extension("pl");
}
if !path.is_file() {
let filename = clause_name!(path.to_string_lossy().to_string(), atom_tbl);
return Err(SessionError::InvalidFileName(filename));
}
}
Ok(path)
}
fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName, SessionError>
{
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
let file_handle = File::open(&path).or_else(|_| {
let filename = clause_name!(path.to_string_lossy().to_string(), wam.indices.atom_tbl);
Err(SessionError::InvalidFileName(filename))
})?;
let file_src = parsing_stream(file_handle);
// follow the operation of compile_user_module, but before
// compiling, check that a module is declared in the file. if not,
// throw an exception.
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
let mut compiler = ListingCompiler::new(&wam.code_repo);
let results = compiler.gather_items(wam, file_src, &mut indices)?;
let module_name = if let Some(ref module) = &compiler.module {
module.module_decl.name.clone()
} else {
let module_name = path.to_string_lossy().to_string();
let module_name = clause_name!(module_name, wam.indices.atom_tbl);
return Err(SessionError::NoModuleDeclaration(module_name));
};
match compile_work_impl(&mut compiler, wam, indices, results) {
EvalSession::Error(e) => return Err(e),
_ => Ok(module_name)
}
}
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
// throw errors if declaration or query found.
@@ -96,6 +151,7 @@ impl CodeRepo {
-> Result<(), ParserError>
{
let key = (hook.name(), hook.arity());
match self.term_dir.get(&key) {
Some(preds) => {
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
@@ -131,10 +187,9 @@ fn compile_decl(wam: &mut Machine, compiler: &mut ListingCompiler, decl: Declara
{
let flags = wam.machine_flags();
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
let wam_indices = &mut wam.indices;
compiler.process_decl(decl, &mut wam.code_repo, wam_indices, &mut indices, flags)?;
compiler.process_decl(decl, wam, &mut indices, flags)?;
Ok(indices)
}
@@ -407,19 +462,18 @@ impl ListingCompiler {
}
}
fn use_module(&mut self, submodule: ClauseName, code_repo: &mut CodeRepo,
flags: MachineFlags, 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();
let module_name = self.get_module_name();
if let Some(mut submodule) = wam_indices.take_module(submodule) {
unwind_protect!(indices.use_module(code_repo, flags, &submodule),
wam_indices.insert_module(submodule));
if let &mut Some(ref mut module) = &mut self.module {
module.remove_module(mod_name, &submodule);
module.remove_module(module_name, &submodule);
unwind_protect!(module.use_module(code_repo, flags, &submodule),
wam_indices.insert_module(submodule));
} else {
@@ -438,14 +492,14 @@ impl ListingCompiler {
wam_indices: &mut IndexStore, indices: &mut IndexStore)
-> Result<(), SessionError>
{
let mod_name = self.get_module_name();
let module_name = self.get_module_name();
if let Some(mut submodule) = wam_indices.take_module(submodule) {
unwind_protect!(indices.use_qualified_module(code_repo, flags, &submodule, exports),
wam_indices.insert_module(submodule));
if let &mut Some(ref mut module) = &mut self.module {
module.remove_module(mod_name, &submodule);
module.remove_module(module_name, &submodule);
unwind_protect!(module.use_qualified_module(code_repo, flags, &submodule, exports),
wam_indices.insert_module(submodule));
} else {
@@ -536,19 +590,20 @@ impl ListingCompiler {
(len, queue_len)
}
fn process_decl(&mut self, decl: Declaration, code_repo: &mut CodeRepo,
wam_indices: &mut IndexStore, indices: &mut IndexStore,
fn process_decl(&mut self, decl: Declaration, wam: &mut Machine, indices: &mut IndexStore,
flags: MachineFlags)
-> Result<(), SessionError>
{
match decl {
Declaration::EndOfFile =>
return Ok(()),
Declaration::Hook(hook, clause, queue) => {
let key = (hook.name(), hook.arity());
let (len, queue_len) = self.add_term_dir_terms(hook, code_repo, key.clone(),
clause, queue);
let (len, queue_len) = self.add_term_dir_terms(hook, &mut wam.code_repo,
key.clone(), clause, queue);
let result = code_repo.compile_hook(hook, flags).map_err(SessionError::from);
code_repo.truncate_terms(key, len, queue_len);
let result = wam.code_repo.compile_hook(hook, flags).map_err(SessionError::from);
wam.code_repo.truncate_terms(key, len, queue_len);
result
},
@@ -556,15 +611,17 @@ impl ListingCompiler {
Ok(self.add_non_counted_bt_flag(name, arity)),
Declaration::Op(op_decl) => {
let spec = get_desc(op_decl.name(), composite_op!(self.module.is_some(),
&wam_indices.op_dir,
&wam.indices.op_dir,
&mut indices.op_dir));
op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
},
Declaration::UseModule(name) =>
self.use_module(name, code_repo, flags, wam_indices, indices),
Declaration::UseQualifiedModule(name, exports) =>
self.use_qualified_module(name, code_repo, flags, &exports, wam_indices, indices),
Declaration::UseModule(ModuleSource::Library(name)) =>
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices,
indices),
Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) =>
self.use_qualified_module(name, &mut wam.code_repo, flags, &exports,
&mut wam.indices, indices),
Declaration::Module(module_decl) =>
if self.module.is_none() {
let module_name = module_decl.name.clone();
@@ -574,6 +631,15 @@ impl ListingCompiler {
} else {
Err(SessionError::from(ParserError::InvalidModuleDecl))
},
Declaration::UseModule(ModuleSource::File(filename)) => {
let name = load_module_from_file(wam, filename.as_str())?;
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
},
Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
let name = load_module_from_file(wam, filename.as_str())?;
self.use_qualified_module(name, &mut wam.code_repo, flags, &exports,
&mut wam.indices, indices)
},
Declaration::Dynamic(..) => Ok(())
}
}
@@ -583,6 +649,8 @@ impl ListingCompiler {
indices: &mut IndexStore, flags: MachineFlags)
-> Result<(), SessionError>
{
let mut update_expansion_lengths = false;
match &decl {
&Declaration::Dynamic(ref name, arity) => {
worker.dynamic_clause_map.entry((name.clone(), arity)).or_insert(vec![]);
@@ -591,11 +659,19 @@ impl ListingCompiler {
worker.term_stream.incr_expansion_lens(hook.user_scope(), 1, queue.len()),
&Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() =>
worker.term_stream.incr_expansion_lens(hook, 1, queue.len()),
&Declaration::UseModule(ModuleSource::File(_))
| &Declaration::UseQualifiedModule(ModuleSource::File(_), _) =>
update_expansion_lengths = true,
_ => {}
};
self.process_decl(decl, &mut worker.term_stream.code_repo,
&mut worker.term_stream.indices, indices, flags)
let result = self.process_decl(decl, &mut worker.term_stream.wam, indices, flags);
if update_expansion_lengths {
worker.term_stream.update_expansion_lens();
}
result
}
pub(crate)
@@ -605,9 +681,7 @@ impl ListingCompiler {
{
let flags = wam.machine_flags();
let atom_tbl = indices.atom_tbl.clone();
let mut worker = TopLevelBatchWorker::new(&mut src, atom_tbl.clone(), flags,
&mut wam.indices, &mut wam.policies,
&mut wam.code_repo);
let mut worker = TopLevelBatchWorker::new(&mut src, atom_tbl.clone(), flags, wam);
let mut toplevel_results = vec![];
let mut toplevel_indices = default_index_store!(atom_tbl.clone());
@@ -623,6 +697,8 @@ impl ListingCompiler {
if let &Some(ref module) = &self.module {
worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
}
} else if decl.is_end_of_file() {
break;
} else {
self.process_and_commit_decl(decl, &mut worker, indices, flags)?;
}
@@ -652,12 +728,10 @@ impl ListingCompiler {
}
}
fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine,
src: ParsingStream<R>, mut indices: IndexStore)
-> EvalSession
fn compile_work_impl(compiler: &mut ListingCompiler, wam: &mut Machine,
mut indices: IndexStore, mut results: GatherResult)
-> EvalSession
{
let mut results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
let module_code = try_eval_session!(compiler.generate_code(results.worker_results, wam,
&mut indices.code_dir, 0));
let toplvl_code = try_eval_session!(compiler.generate_code(results.toplevel_results, wam,
@@ -693,6 +767,14 @@ fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine,
EvalSession::EntrySuccess
}
fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine,
src: ParsingStream<R>, mut indices: IndexStore)
-> EvalSession
{
let results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
compile_work_impl(compiler, wam, indices, results)
}
/* This is a truncated version of compile_user_module, used for
compiling code composing special forms, ie. the code that calls
M:verify_attributes on attributed variables. */