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. */

View File

@@ -52,22 +52,32 @@ impl MachineError {
MachineError { stub, from: ErrorProvenance::Constructed }
}
pub(super) fn existence_error(h: usize, name: ClauseName, arity: usize) -> Self {
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
stub.append(&mut Self::functor_stub(name, arity));
pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self
{
match err {
ExistenceError::Procedure(name, arity) => {
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
stub.append(&mut Self::functor_stub(name, arity));
MachineError { stub, from: ErrorProvenance::Constructed }
MachineError { stub, from: ErrorProvenance::Constructed }
},
ExistenceError::Module(name) => {
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
let mut stub = functor!("existence_error", 2, [heap_atom!("module"), name]);
MachineError { stub, from: ErrorProvenance::Constructed }
}
}
}
// so far, this function is only called wrt dynamic database
// transactions. their inapplicable error cases have been left
// unhandled.
pub(super) fn session_error(h: usize, err: SessionError) -> Self {
match err {
SessionError::ParserError(err) => Self::syntax_error(h, err),
SessionError::CannotOverwriteBuiltIn(pred_str)
| SessionError::CannotOverwriteImport(pred_str) =>
Self::permission_error(PermissionError::Modify, "private_procedure", pred_str),
SessionError::InvalidFileName(filename) =>
Self::existence_error(h, ExistenceError::Module(filename)),
SessionError::ModuleDoesNotContainExport =>
Self::permission_error(PermissionError::Access,
"private_procedure",
@@ -76,6 +86,8 @@ impl MachineError {
Self::permission_error(PermissionError::Access,
"private_procedure",
clause_name!("module_does_not_exist")),
SessionError::NoModuleDeclaration(name) =>
Self::existence_error(h, ExistenceError::Module(name)),
SessionError::OpIsInfixAndPostFix(op) =>
Self::permission_error(PermissionError::Create,
"operator",
@@ -396,12 +408,19 @@ impl MachineState {
}
}
pub enum ExistenceError {
Module(ClauseName),
Procedure(ClauseName, usize)
}
pub enum SessionError {
CannotOverwriteBuiltIn(ClauseName),
CannotOverwriteImport(ClauseName),
ModuleDoesNotContainExport,
InvalidFileName(ClauseName),
ModuleDoesNotContainExport,
ModuleNotFound,
NamelessEntry,
NoModuleDeclaration(ClauseName),
OpIsInfixAndPostFix(ClauseName),
ParserError(ParserError),
UserPrompt

View File

@@ -376,9 +376,9 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
} else {
let stub = MachineError::functor_stub(name.clone(), arity);
let h = machine_st.heap.h;
let key = ExistenceError::Procedure(name, arity);
Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
stub))
Err(machine_st.error_form(MachineError::existence_error(h, key), stub))
}
}
@@ -797,8 +797,9 @@ pub(crate) trait CallPolicy: Any {
} else {
let h = machine_st.heap.h;
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
let key = ExistenceError::Procedure(name, arity);
return Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
return Err(machine_st.error_form(MachineError::existence_error(h, key),
stub));
}
},

View File

@@ -152,21 +152,8 @@ impl SubModuleUser for IndexStore {
}
static BUILTINS: &str = include_str!("../lib/builtins.pl");
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
static LISTS: &str = include_str!("../lib/lists.pl");
static QUEUES: &str = include_str!("../lib/queues.pl");
static ERROR: &str = include_str!("../lib/error.pl");
static BETWEEN: &str = include_str!("../lib/between.pl");
static TERMS: &str = include_str!("../lib/terms.pl");
static DCGS: &str = include_str!("../lib/dcgs.pl");
static ATTS: &str = include_str!("../lib/atts.pl");
static DIF: &str = include_str!("../lib/dif.pl");
static FREEZE: &str = include_str!("../lib/freeze.pl");
static REIF: &str = include_str!("../lib/reif.pl");
static ASSOC: &str = include_str!("../lib/assoc.pl");
static ORDSETS: &str = include_str!("../lib/ordsets.pl");
static TOPLEVEL: &str = include_str!("../toplevel.pl");
static ERROR: &str = include_str!("../lib/error.pl");
impl Machine {
fn compile_special_forms(&mut self) {
@@ -192,22 +179,6 @@ impl Machine {
compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()));
}
fn compile_libraries(&mut self) {
compile_user_module(self, parsing_stream(NON_ISO.as_bytes()));
compile_user_module(self, parsing_stream(LISTS.as_bytes()));
compile_user_module(self, parsing_stream(QUEUES.as_bytes()));
compile_user_module(self, parsing_stream(ERROR.as_bytes()));
compile_user_module(self, parsing_stream(BETWEEN.as_bytes()));
compile_user_module(self, parsing_stream(TERMS.as_bytes()));
compile_user_module(self, parsing_stream(DCGS.as_bytes()));
compile_user_module(self, parsing_stream(ATTS.as_bytes()));
compile_user_module(self, parsing_stream(ORDSETS.as_bytes()));
compile_user_module(self, parsing_stream(DIF.as_bytes()));
compile_user_module(self, parsing_stream(FREEZE.as_bytes()));
compile_user_module(self, parsing_stream(REIF.as_bytes()));
compile_user_module(self, parsing_stream(ASSOC.as_bytes()));
}
#[cfg(test)]
pub fn reset(&mut self) {
self.prolog_stream = readline::input_stream();
@@ -235,10 +206,11 @@ impl Machine {
compile_listing(&mut wam, parsing_stream(BUILTINS.as_bytes()),
default_index_store!(atom_tbl.clone()));
wam.compile_libraries();
wam.compile_special_forms();
wam.compile_top_level();
compile_user_module(&mut wam, parsing_stream(ERROR.as_bytes()));
wam
}
@@ -344,20 +316,13 @@ impl Machine {
#[cfg(feature = "readline_rs_compat")]
readline::set_line_mode(readline::LineMode::Multi);
let src = match readline::read_batch("") {
Ok(src) => src,
Err(e) => {
self.throw_session_error(e, (clause_name!("repl"), 0));
return;
}
};
let src = readline::input_stream();
#[cfg(feature = "readline_rs_compat")]
readline::set_line_mode(readline::LineMode::Single);
match compile_user_module(self, parsing_stream(&src[0 ..])) {
EvalSession::Error(e) =>
self.throw_session_error(e, (clause_name!("repl"), 0)),
match compile_user_module(self, src) {
EvalSession::Error(e) => self.throw_session_error(e, (clause_name!("repl"), 0)),
_ => {}
};
},
@@ -387,7 +352,7 @@ impl Machine {
self.machine_st.heap_locs = var_dict;
let term_output = self.machine_st.print_query(term, &self.indices.op_dir);
term_output.result()
},
Err(err_stub) => {
@@ -439,7 +404,7 @@ impl Machine {
if !(self.machine_st.b > 0) {
if bindings.is_empty() {
let space = if requires_space(&attr_goals, ".") { " " } else { "" };
if !attr_goals.is_empty() {
println!("{}{}.", attr_goals, space);
} else {
@@ -511,7 +476,7 @@ impl Machine {
} else {
if requires_space(&bindings, ".") { " " } else { "" }
};
write!(raw_stdout, "{}.\r\n", space).unwrap();
}
@@ -647,9 +612,8 @@ impl Machine {
}
}
impl MachineState {
fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict)
fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict)
{
for (var, var_data) in alloc_locs {
match var_data {
@@ -673,16 +637,16 @@ impl MachineState {
}
}
}
fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter
{
let flags = self.flags;
let mut output = {
self.flags = MachineFlags { double_quotes: DoubleQuotes::Atom };
let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.quoted = true;
printer.numbervars = false;
@@ -774,8 +738,8 @@ impl MachineState {
return false,
CodePtr::DynamicTransaction(..) => {
// prevent use of dynamic transactions from
// succeeding in expansions. this will be toggled
// back to true later.
// succeeding in expansions. self.fail will be toggled
// back to false later.
self.fail = true;
return false;
},

View File

@@ -117,7 +117,7 @@ pub trait SubModuleUser
};
}
}
// returns true on successful import.
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool
{
@@ -155,8 +155,7 @@ pub trait SubModuleUser
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>;
fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module) -> Result<(), SessionError>;
}
pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports: &Vec<PredicateKey>)

View File

@@ -282,7 +282,7 @@ impl MachineState {
self.fail = true;
return;
}
if let Some(r) = a2.as_var() {
let spec = get_clause_spec(name.clone(), *arity,
composite_op!(&indices.op_dir));
@@ -308,7 +308,7 @@ impl MachineState {
self.fail = true;
return;
}
if let Some(r) = a2.as_var() {
let spec = get_clause_spec(name.clone(), *arity,
composite_op!(&indices.op_dir));
@@ -1589,6 +1589,10 @@ impl MachineState {
self.unify(list_offset, a2);
},
Err(err) => {
if let ParserError::UnexpectedEOF = err {
std::process::exit(0);
}
// reset the input stream after an input failure.
*current_input_stream = readline::input_stream();

View File

@@ -71,9 +71,7 @@ fn extract_from_list(head: Box<Term>, tail: Box<Term>)
pub struct TermStream<'a, R: Read> {
stack: Vec<Term>,
pub(crate) indices: &'a mut IndexStore,
policies: &'a mut MachinePolicies,
pub(crate) code_repo: &'a mut CodeRepo,
pub(crate) wam: &'a mut Machine,
parser: Parser<'a, R>,
in_module: bool,
pub(crate) flags: MachineFlags,
@@ -104,25 +102,21 @@ impl ExpansionAdditionResult {
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.wam.indices.in_situ_code_dir.clear();
self.wam.code_repo.in_situ_code.clear();
discard_result!(self.rollback_expansion_code());
}
}
impl<'a, R: Read> TermStream<'a, R> {
pub fn new(src: &'a mut ParsingStream<R>, atom_tbl: TabledData<Atom>, flags: MachineFlags,
indices: &'a mut IndexStore, policies: &'a mut MachinePolicies,
code_repo: &'a mut CodeRepo)
pub fn new(src: &'a mut ParsingStream<R>, atom_tbl: TabledData<Atom>, flags: MachineFlags, wam: &'a mut Machine)
-> Self
{
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,
term_expansion_lens: wam.code_repo.term_dir_entry_len((clause_name!("term_expansion"), 2)),
goal_expansion_lens: wam.code_repo.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
wam,
parser: Parser::new(src, atom_tbl, flags),
in_module: false,
flags
@@ -149,6 +143,22 @@ impl<'a, R: Read> TermStream<'a, R> {
}
}
#[inline]
pub fn update_expansion_lens(&mut self) {
let te_key = (clause_name!("term_expansion"), 2);
let ge_key = (clause_name!("goal_expansion"), 2);
let (tes_len, tes_q_len) = self.wam.code_repo.term_dir_entry_len(te_key);
self.term_expansion_lens.0 = tes_len;
self.term_expansion_lens.1 = tes_q_len;
let (ges_len, ges_q_len) = self.wam.code_repo.term_dir_entry_len(ge_key);
self.goal_expansion_lens.0 = ges_len;
self.goal_expansion_lens.1 = ges_q_len;
}
#[inline]
pub fn set_atom_tbl(&mut self, atom_tbl: TabledData<Atom>) {
self.parser.set_atom_tbl(atom_tbl);
@@ -159,7 +169,8 @@ impl<'a, R: Read> TermStream<'a, R> {
Ok(self.stack.is_empty() && self.parser.eof()?)
}
pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> {
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;
@@ -167,14 +178,14 @@ impl<'a, R: Read> TermStream<'a, R> {
let ge_queue_len = self.goal_expansion_lens.1;
let term_expansion_additions =
self.code_repo.truncate_terms((clause_name!("term_expansion"), 2),
te_len, te_queue_len);
self.wam.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.wam.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)?;
self.wam.code_repo.compile_hook(CompileTimeHook::TermExpansion, self.flags)?;
self.wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion, self.flags)?;
Ok(ExpansionAdditionResult {
term_expansion_additions,
@@ -200,7 +211,7 @@ impl<'a, R: Read> TermStream<'a, R> {
let mut stream = parsing_stream(term_string.trim().as_bytes());
let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags);
parser.read_term(composite_op!(self.in_module, &self.indices.op_dir, op_dir))
parser.read_term(composite_op!(self.in_module, &self.wam.indices.op_dir, op_dir))
}
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError>
@@ -209,8 +220,7 @@ impl<'a, R: Read> TermStream<'a, R> {
loop {
while let Some(term) = self.stack.pop() {
match machine_st.try_expand_term(self.indices, self.policies, self.code_repo,
&term, CompileTimeHook::TermExpansion)
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion)
{
Some(term_string) => {
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
@@ -224,7 +234,7 @@ impl<'a, R: Read> TermStream<'a, R> {
}
self.parser.reset();
let term = self.parser.read_term(composite_op!(self.in_module, &self.indices.op_dir,
let term = self.parser.read_term(composite_op!(self.in_module, &self.wam.indices.op_dir,
op_dir))?;
self.stack.push(term);
}
@@ -242,8 +252,7 @@ impl<'a, R: Read> TermStream<'a, R> {
let comma_term = *terms.pop().unwrap();
unfold_by_str(comma_term, ",")
},
("?-", 1) =>
unfold_by_str(*terms.pop().unwrap(), ","),
("?-", 1) => unfold_by_str(*terms.pop().unwrap(), ","),
_ => return Ok(Term::Clause(cell, name, terms, arity))
};
@@ -266,10 +275,10 @@ impl<'a, R: Read> TermStream<'a, R> {
let mut results = vec![];
while let Some(term) = terms.pop_front() {
match machine_st.try_expand_term(self.indices, self.policies, self.code_repo,
&term, CompileTimeHook::GoalExpansion)
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion)
{
Some(term_string) => {
println!("trying to goal expand {}", term_string);
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
match term {
@@ -318,8 +327,7 @@ impl MachineState {
output
}
fn try_expand_term(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
code_repo: &mut CodeRepo, term: &Term, hook: CompileTimeHook)
fn try_expand_term(&mut self, wam: &mut Machine, term: &Term, hook: CompileTimeHook)
-> Option<String>
{
let term_write_result = write_term_to_heap(term, self);
@@ -331,17 +339,17 @@ impl MachineState {
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
code_repo.cached_query = code;
self.query_stepper(indices, policies, code_repo, &mut readline::input_stream());
wam.code_repo.cached_query = code;
self.query_stepper(&mut wam.indices, &mut wam.policies, &mut wam.code_repo, &mut readline::input_stream());
if self.fail {
self.reset();
None
} else {
let TermWriteResult { var_dict, .. } = term_write_result;
self.heap_locs = var_dict;
let output = self.print_with_locs(Addr::HeapCell(h), &indices.op_dir);
let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
self.reset();
Some(output.result())

View File

@@ -4,7 +4,6 @@ use prolog_parser::tabled_rc::*;
use prolog::forms::*;
use prolog::iterators::*;
use prolog::machine::*;
use prolog::machine::code_repo::*;
use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*;
use prolog::machine::machine_state::MachineState;
@@ -193,31 +192,37 @@ fn setup_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleDecl, ParserErro
}
}
fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ClauseName, ParserError>
fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, ParserError>
{
match *terms.pop().unwrap() {
Term::Clause(_, ref name, ref mut terms, None)
if name.as_str() == "library" && terms.len() == 1 => {
terms.pop().unwrap().to_constant()
.and_then(|c| c.to_atom())
.ok_or(ParserError::InvalidUseModuleDecl)
.and_then(|c| c.to_atom())
.map(|c| ModuleSource::Library(c))
.ok_or(ParserError::InvalidUseModuleDecl)
},
Term::Constant(_, Constant::Atom(ref name, _)) =>
Ok(ModuleSource::File(name.clone())),
_ => Err(ParserError::InvalidUseModuleDecl)
}
}
type UseModuleExport = (ClauseName, Vec<PredicateKey>);
type UseModuleExport = (ModuleSource, Vec<PredicateKey>);
fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport, ParserError>
{
let mut export_list = *terms.pop().unwrap();
let name = match *terms.pop().unwrap() {
let module_src = match *terms.pop().unwrap() {
Term::Clause(_, ref name, ref mut terms, None)
if name.as_str() == "library" && terms.len() == 1 => {
terms.pop().unwrap().to_constant()
.and_then(|c| c.to_atom())
.map(|c| ModuleSource::Library(c))
.ok_or(ParserError::InvalidUseModuleDecl)
},
Term::Constant(_, Constant::Atom(ref name, _)) =>
Ok(ModuleSource::File(name.clone())),
_ => Err(ParserError::InvalidUseModuleDecl)
}?;
@@ -231,7 +236,7 @@ fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport,
if export_list.to_constant() != Some(Constant::EmptyList) {
Err(ParserError::InvalidModuleDecl)
} else {
Ok((name, exports))
Ok((module_src, exports))
}
}
@@ -768,7 +773,7 @@ fn term_to_toplevel<R>(term_stream: &mut TermStream<R>, code_dir: &mut CodeDir,
where R: Read
{
let mut rel_worker = RelationWorker::new(flags);
let mut indices = composite_indices!(false, term_stream.indices, code_dir);
let mut indices = composite_indices!(false, &mut term_stream.wam.indices, code_dir);
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
@@ -781,18 +786,17 @@ fn stream_to_toplevel<R: Read>(mut buffer: ParsingStream<R>, wam: &mut Machine)
{
let flags = wam.machine_flags();
let mut term_stream = TermStream::new(&mut buffer, wam.indices.atom_tbl(),
wam.machine_flags(), &mut wam.indices,
&mut wam.policies, &mut wam.code_repo);
wam.machine_flags(), wam);
term_stream.add_to_top("?- ");
let term = term_stream.read_term(&OpDir::new())?;
let mut code_dir = CodeDir::new();
let mut code_dir = CodeDir::new();
let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term, flags)?;
rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?;
let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir);
let mut indices = composite_indices!(false, &mut term_stream.wam.indices, &mut code_dir);
let queue = rel_worker.parse_queue(&mut indices)?;
Ok(deque_to_packet(tl, queue))
@@ -811,12 +815,10 @@ pub struct TopLevelBatchWorker<'a, R: Read> {
impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
pub fn new(inner: &'a mut ParsingStream<R>, atom_tbl: TabledData<Atom>,
flags: MachineFlags, indices: &'a mut IndexStore,
policies: &'a mut MachinePolicies, code_repo: &'a mut CodeRepo)
flags: MachineFlags, wam: &'a mut Machine)
-> Self
{
let term_stream = TermStream::new(inner, atom_tbl, flags,
indices, policies, code_repo);
let term_stream = TermStream::new(inner, atom_tbl, flags, wam);
TopLevelBatchWorker { term_stream,
rel_worker: RelationWorker::new(flags),
@@ -830,7 +832,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
{
let mut new_rel_worker = RelationWorker::new(self.rel_worker.flags);
let mut indices = composite_indices!(self.in_module, indices,
&self.term_stream.indices.code_dir);
&self.term_stream.wam.indices.code_dir);
Ok((new_rel_worker.try_term_to_tl(&mut indices, term, true)?, new_rel_worker))
}
@@ -841,15 +843,15 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
self.rel_worker.expand_queue_contents(&mut self.term_stream, &indices.op_dir)?;
let mut indices = composite_indices!(self.in_module, indices,
&mut self.term_stream.indices.code_dir);
&mut self.term_stream.wam.indices.code_dir);
let queue = self.rel_worker.parse_queue(&mut indices)?;
let result = (append_preds(preds), queue);
let in_situ_code_dir = &mut self.term_stream.indices.in_situ_code_dir;
let in_situ_code_dir = &mut self.term_stream.wam.indices.in_situ_code_dir;
self.term_stream.code_repo.add_in_situ_result(&result, in_situ_code_dir,
self.term_stream.flags)?;
self.term_stream.wam.code_repo.add_in_situ_result(&result, in_situ_code_dir,
self.term_stream.flags)?;
Ok(self.results.push(result))
}
@@ -873,14 +875,17 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
}
}
pub fn consume(&mut self, indices: &mut IndexStore)
-> Result<Option<Declaration>, SessionError>
pub fn consume(&mut self, indices: &mut IndexStore) -> Result<Option<Declaration>, SessionError>
{
let mut preds = vec![];
while !self.term_stream.eof()? {
let term = self.term_stream.read_term(&indices.op_dir)?;
let (tl, new_rel_worker) = self.try_term_to_tl(indices, term)?;
let (mut tl, new_rel_worker) = self.try_term_to_tl(indices, term)?;
if tl.is_end_of_file_atom() {
tl = TopLevel::Declaration(Declaration::EndOfFile);
}
// if is_consistent is false, preds is non-empty.
if !is_consistent(&tl, &preds) {