From: Mark Thom Date: Mon, 2 Sep 2019 20:53:31 +0000 (-0400) Subject: address issues #143, #150, #155 X-Git-Tag: v0.8.110~52 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=2c880b2bc0bd75d5f273d5df5db5bec4df37a678;p=scryer-prolog.git address issues #143, #150, #155 --- diff --git a/Cargo.toml b/Cargo.toml index 3fd047d8..8593888a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.86" +version = "0.8.87" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." diff --git a/README.md b/README.md index 9462e399..9cc5d8be 100644 --- a/README.md +++ b/README.md @@ -359,16 +359,12 @@ been exported to the toplevel. To export them, write ?- use_module(library(lists)). ``` -The [user] prompt can also be used to define modules inline at the -REPL: +To load modules contained in files, the `library` functor can be +omitted, prompting Scryer to search for the file (specified as an +atom) from its home directory: ``` -?- [user]. -(type Enter + Ctrl-D to terminate the stream when finished) -:- module(test, [local_member/2]). -:- use_module(library(lists)). - -local_member(X, Xs) :- member(X, Xs). +?- use_module('file.pl'). ``` `use_module` directives can be qualified by adding a list of imports: @@ -386,3 +382,18 @@ imported to the current working namespace: ``` ?- lists:member(X, Xs). ``` + +The [user] prompt can also be used to define modules inline at the +REPL: + +``` +?- [user]. +(type Enter + Ctrl-D to terminate the stream when finished) +:- module(test, [local_member/2]). +:- use_module(library(lists)). + +local_member(X, Xs) :- member(X, Xs). +``` + +The user listing can also be terminated by placing `end_of_file.` at +the end of the stream. \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index bc7d295a..412dff66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,6 @@ extern crate termion; mod prolog; use prolog::machine::*; -use prolog::machine::machine_errors::*; use prolog::read::*; #[cfg(test)] diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs index cb2c7a87..0ac6ecfd 100644 --- a/src/prolog/forms.rs +++ b/src/prolog/forms.rs @@ -50,6 +50,15 @@ impl TopLevel { &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() } } + + pub fn is_end_of_file_atom(&self) -> bool { + match self { + &TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _))) => + return name.as_str() == "end_of_file", + _ => + false + } + } } #[derive(Clone, Copy)] @@ -152,15 +161,22 @@ impl PredicateClause { } } +#[derive(Clone)] +pub enum ModuleSource { + Library(ClauseName), + File(ClauseName) +} + #[derive(Clone)] pub enum Declaration { Dynamic(ClauseName, usize), // name, arity + EndOfFile, Hook(CompileTimeHook, PredicateClause, VecDeque), Module(ModuleDecl), NonCountedBacktracking(ClauseName, usize), // name, arity Op(OpDecl), - UseModule(ClauseName), - UseQualifiedModule(ClauseName, Vec) + UseModule(ModuleSource), + UseQualifiedModule(ModuleSource, Vec) } impl Declaration { @@ -168,6 +184,11 @@ impl Declaration { pub fn is_module_decl(&self) -> bool { if let &Declaration::Module(_) = self { true } else { false } } + + #[inline] + pub fn is_end_of_file(&self) -> bool { + if let &Declaration::EndOfFile = self { true } else { false } + } } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/prolog/lib/assoc.pl b/src/prolog/lib/assoc.pl index b99b1c4b..7880a9e6 100644 --- a/src/prolog/lib/assoc.pl +++ b/src/prolog/lib/assoc.pl @@ -52,7 +52,7 @@ del_max_assoc/4 % +Assoc0, ?Key, ?Value, ?Assoc ]). -:- use_module(library(lists)). +:- use_module('src/prolog/lib/lists.pl'). /** Binary associations diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl index 6f3b109b..1ea94277 100644 --- a/src/prolog/lib/atts.pl +++ b/src/prolog/lib/atts.pl @@ -4,8 +4,8 @@ '$add_to_list'/3, '$del_attr'/3, '$del_attr_step'/3, '$del_attr_buried'/4]). -:- use_module(library(dcgs)). -:- use_module(library(terms)). +:- use_module('src/prolog/lib/dcgs.pl'). +:- use_module('src/prolog/lib/terms.pl'). :- op(1199, fx, attribute). diff --git a/src/prolog/lib/between.pl b/src/prolog/lib/between.pl index 16c73145..90090986 100644 --- a/src/prolog/lib/between.pl +++ b/src/prolog/lib/between.pl @@ -2,8 +2,8 @@ %% TODO: numlist/5. -:- use_module(library(lists), [length/2]). -:- use_module(library(error)). +:- use_module('src/prolog/lib/lists.pl', [length/2]). +:- use_module('src/prolog/lib/error.pl'). between(Lower, Upper, X) :- must_be(integer, Lower), diff --git a/src/prolog/lib/dcgs.pl b/src/prolog/lib/dcgs.pl index 60fe7126..fabd67b0 100644 --- a/src/prolog/lib/dcgs.pl +++ b/src/prolog/lib/dcgs.pl @@ -2,8 +2,8 @@ :- module(dcgs, [phrase/2, phrase/3]). -:- use_module(library(lists), [append/3]). -:- use_module(library(terms)). +:- use_module('src/prolog/lib/lists.pl', [append/3]). +:- use_module('src/prolog/lib/terms.pl'). phrase(G, G) :- nonvar(G), G = [_|_], !. diff --git a/src/prolog/lib/dif.pl b/src/prolog/lib/dif.pl index 991db075..cd779375 100644 --- a/src/prolog/lib/dif.pl +++ b/src/prolog/lib/dif.pl @@ -1,7 +1,7 @@ :- module(dif, [dif/2]). -:- use_module(library(atts)). -:- use_module(library(lists), [append/3]). +:- use_module('src/prolog/lib/atts.pl'). +:- use_module('src/prolog/lib/lists.pl', [append/3]). :- attribute dif/1. diff --git a/src/prolog/lib/freeze.pl b/src/prolog/lib/freeze.pl index d3a92eaf..3fa4ef91 100644 --- a/src/prolog/lib/freeze.pl +++ b/src/prolog/lib/freeze.pl @@ -1,6 +1,6 @@ :- module(freeze, [freeze/2]). -:- use_module(library(atts)). +:- use_module('src/prolog/lib/atts.pl'). :- attribute frozen/1. diff --git a/src/prolog/lib/ordsets.pl b/src/prolog/lib/ordsets.pl index ff080962..a97c609b 100644 --- a/src/prolog/lib/ordsets.pl +++ b/src/prolog/lib/ordsets.pl @@ -52,7 +52,7 @@ ord_intersection/2 % +PowerSet, -Intersection ]). -:- use_module(library(lists)). +:- use_module('src/prolog/lib/lists.pl'). /** Ordered set manipulation Ordered sets are lists with unique elements sorted to the standard order diff --git a/src/prolog/lib/reif.pl b/src/prolog/lib/reif.pl index 0e958356..603d1188 100644 --- a/src/prolog/lib/reif.pl +++ b/src/prolog/lib/reif.pl @@ -2,7 +2,7 @@ memberd_t/3, tfilter/3, tmember/2, tmember_t/3, tpartition/4]). -:- use_module(library(dif)). +:- use_module('src/prolog/lib/dif.pl'). if_(If_1, Then_0, Else_0) :- call(If_1, T), diff --git a/src/prolog/lib/terms.pl b/src/prolog/lib/terms.pl index 8391457b..9b394460 100644 --- a/src/prolog/lib/terms.pl +++ b/src/prolog/lib/terms.pl @@ -1,6 +1,6 @@ :- module(terms, [numbervars/3]). -:- use_module(library(error)). +:- use_module('src/prolog/lib/error.pl'). numbervars(Term, N0, N) :- catch(internal_numbervars(Term, N0, N), error(E,Ctx), diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 172d1008..33d05cbf 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -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, filename: &str) -> Result +{ + 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 +{ + 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); // 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::::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(compiler: &mut ListingCompiler, wam: &mut Machine, - src: ParsingStream, 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(compiler: &mut ListingCompiler, wam: &mut Machine, EvalSession::EntrySuccess } +fn compile_work(compiler: &mut ListingCompiler, wam: &mut Machine, + src: ParsingStream, 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. */ diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 34011f69..0945a9e0 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -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 diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index ac72ffa5..7e6ad97b 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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)); } }, diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 31e29642..8c33f0a6 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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; }, diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs index d3f7f175..c66a8f62 100644 --- a/src/prolog/machine/modules.rs +++ b/src/prolog/machine/modules.rs @@ -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) -> 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: &mut User, submodule: &Module, exports: &Vec) diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 55baf3e6..d6015741 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -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(); diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 2797399c..ed6707bf 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -71,9 +71,7 @@ fn extract_from_list(head: Box, tail: Box) pub struct TermStream<'a, R: Read> { stack: Vec, - 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, atom_tbl: TabledData, flags: MachineFlags, - indices: &'a mut IndexStore, policies: &'a mut MachinePolicies, - code_repo: &'a mut CodeRepo) + pub fn new(src: &'a mut ParsingStream, atom_tbl: TabledData, 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) { 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 { + pub fn rollback_expansion_code(&mut self) -> Result + { 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 @@ -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 { 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()) diff --git a/src/prolog/machine/toplevel.rs b/src/prolog/machine/toplevel.rs index 93335a54..ed37b5be 100644 --- a/src/prolog/machine/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -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>) -> Result>) -> Result +fn setup_use_module_decl(mut terms: Vec>) -> Result { 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); +type UseModuleExport = (ModuleSource, Vec); fn setup_qualified_import(mut terms: Vec>) -> Result { 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>) -> Result(term_stream: &mut TermStream, 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(mut buffer: ParsingStream, 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, atom_tbl: TabledData, - 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, SessionError> + pub fn consume(&mut self, indices: &mut IndexStore) -> Result, 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) { diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 0ad08597..6af0794d 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -136,13 +136,6 @@ pub mod readline bind_keyseq_rl("\\C-d", bind_end_chord); } - pub fn read_batch(prompt: &str) -> Result, ::SessionError> { - match readline_rl(prompt) { - Some(input) => Ok(Vec::from(input.as_bytes())), - None => Err(::SessionError::UserPrompt) - } - } - #[inline] pub fn input_stream() -> ::PrologStream { let reader: Box = Box::new(ReadlineStream::new(String::from(""))); diff --git a/src/prolog/toplevel.pl b/src/prolog/toplevel.pl index df0f808a..15a3cc80 100644 --- a/src/prolog/toplevel.pl +++ b/src/prolog/toplevel.pl @@ -2,7 +2,7 @@ repl :- catch(read_and_match, E, '$print_exception'(E)), false. %% this is for GC, until we get actual GC. repl :- repl. - + read_and_match :- write_term('?- ', [quoted(false)]), read_term(Term, [variable_names(VarList)]), diff --git a/src/prolog/write.rs b/src/prolog/write.rs index df259884..df2400e6 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -261,9 +261,13 @@ impl fmt::Display for SessionError { write!(f, "cannot overwrite {}", msg), &SessionError::CannotOverwriteImport(ref msg) => write!(f, "cannot overwrite import {}", msg), + &SessionError::InvalidFileName(ref filename) => + write!(f, "filename {} is invalid", filename), &SessionError::ModuleNotFound => write!(f, "module not found."), &SessionError::ModuleDoesNotContainExport => write!(f, "module does not contain claimed export."), + &SessionError::NoModuleDeclaration(ref name) => + write!(f, "file {}.pl lacks an expected module declaration.", name), &SessionError::OpIsInfixAndPostFix(_) => write!(f, "cannot define an op to be both postfix and infix."), &SessionError::NamelessEntry => diff --git a/src/tests.rs b/src/tests.rs index c4f8e0e1..6bebd3c5 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1366,11 +1366,11 @@ fn test_queries_on_modules() { let mut wam = Machine::new(readline::input_stream()); - submit(&mut wam, ":- use_module(library(lists))."); + submit(&mut wam, ":- use_module('src/prolog/lib/lists.pl')."); submit_code(&mut wam, " :- module(my_lists, [local_member/2, reverse/2]). -:- use_module(library(lists), [member/2]). +:- use_module('src/prolog/lib/lists.pl', [member/2]). local_member(X, Xs) :- member(X, Xs). @@ -1387,13 +1387,13 @@ reverse(Xs, Ys) :- lists:reverse(Xs, Ys)."); assert_prolog_success!(&mut wam, "catch(local_member(X, Xs), error(E, _), true).", [["X = _1", "E = existence_error(procedure,local_member/2)", "Xs = _2"]]); - submit(&mut wam, ":- use_module(library(lists), [reverse/2])."); + submit(&mut wam, ":- use_module('src/prolog/lib/lists.pl', [reverse/2])."); assert_prolog_success!(&mut wam, "catch(member(_, _), error(existence_error(procedure, P), _), true).", [["P = member/2"]]); assert_prolog_success!(&mut wam, "reverse(_, _)."); - submit(&mut wam, ":- use_module(library(lists), [])."); + submit(&mut wam, ":- use_module('src/prolog/lib/lists.pl', [])."); assert_prolog_success!(&mut wam, "catch(reverse(_, _), error(existence_error(procedure, P), _), true).", [["P = reverse/2"]]); @@ -1404,8 +1404,7 @@ fn test_queries_on_builtins() { let mut wam = Machine::new(readline::input_stream()); - submit(&mut wam, ":- use_module(library(lists))."); - submit(&mut wam, ":- use_module(library(control))."); + submit(&mut wam, ":- use_module('src/prolog/lib/lists.pl')."); assert_prolog_failure!(&mut wam, "atom(X)."); assert_prolog_success!(&mut wam, "atom(a)."); @@ -1611,7 +1610,7 @@ fn test_queries_on_builtins() assert_prolog_success!(&mut wam, "1.0 @=< 1."); assert_prolog_success!(&mut wam, "1 @=< 1.0."); - submit(&mut wam, ":- use_module(library(non_iso))."); + submit(&mut wam, ":- use_module('src/prolog/lib/non_iso.pl')."); assert_prolog_success!(&mut wam, "variant(X, Y)."); assert_prolog_failure!(&mut wam, "variant(f(X), f(x))."); @@ -1662,8 +1661,6 @@ fn test_queries_on_builtins() assert_prolog_success!(&mut wam, "call(((G = 2 ; fail),B=3,!)).", [["G = 2","B = 3"]]); - submit(&mut wam, ":- use_module(library(non_iso))."); - assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)),B=3,!),135,R).", [["G = 2","B = 3","R = !","S = 1"]]); assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)),B=3,!),10,R).", @@ -1802,8 +1799,6 @@ fn test_queries_on_builtins() assert_prolog_success!(&mut wam, "setof(X,Y^((X = 1 ; Y = 1) ; (X = 2,Y = 2)),S).", [["S = [_126,1,2]","X = _0","Y = _5"]]); - submit(&mut wam, ":- use_module(library(non_iso))."); - assert_prolog_failure!(&mut wam, "forall(true,false)."); assert_prolog_success!(&mut wam, "forall(false,true)."); assert_prolog_success!(&mut wam, "catch(forall(_,true),error(instantiation_error,_),true)."); @@ -1971,7 +1966,7 @@ fn test_queries_on_setup_call_cleanup() { let mut wam = Machine::new(readline::input_stream()); - submit(&mut wam, ":- use_module(library(non_iso))."); + submit(&mut wam, ":- use_module('src/prolog/lib/non_iso.pl')."); // Test examples from the ISO Prolog page for setup_call_catch. assert_prolog_failure!(&mut wam, "setup_call_cleanup(false, _, _)."); @@ -2024,7 +2019,7 @@ fn test_queries_on_setup_call_cleanup() // fails here. assert_prolog_success!(&mut wam, -"setup_call_cleanup(true, (X=1;X=2), writeq(a)), setup_call_cleanup(true,(Y=1;Y=2),writeq(b)), !.", + "setup_call_cleanup(true, (X=1;X=2), writeq(a)), setup_call_cleanup(true,(Y=1;Y=2),writeq(b)), !.", [["Y = 1", "X = 1"]]); } @@ -2033,7 +2028,7 @@ fn test_queries_on_call_with_inference_limit() { let mut wam = Machine::new(readline::input_stream()); - submit(&mut wam, ":- use_module(library(non_iso))."); + submit(&mut wam, ":- use_module('src/prolog/lib/non_iso.pl')."); assert_prolog_success!(&mut wam, "call_with_inference_limit(throw(error), 0, R).", [["R = inference_limit_exceeded"]]); @@ -2155,7 +2150,7 @@ fn test_queries_on_dcgs() { let mut wam = Machine::new(readline::input_stream()); - submit(&mut wam, ":- use_module(library(dcgs))."); + submit(&mut wam, ":- use_module('src/prolog/lib/dcgs.pl')."); // test case by YeGoblynQueene from hacker news. submit_code(&mut wam, @@ -2186,7 +2181,7 @@ fn test_queries_on_string_lists() { let mut wam = Machine::new(readline::input_stream()); - submit(&mut wam, ":- use_module(library(non_iso))."); + submit(&mut wam, ":- use_module('src/prolog/lib/non_iso.pl')."); // double_quotes is chars by default. assert_prolog_success!(&mut wam, "variant(\"\", [])."); @@ -2399,7 +2394,7 @@ fn test_queries_on_attributed_variables() submit(&mut wam, " :- module(my_mod, []). -:- use_module(library(atts)). +:- use_module('src/prolog/lib/atts.pl'). :- attribute dif/1, frozen/1."); @@ -2441,8 +2436,7 @@ fn test_queries_on_attributed_variables() put_atts(V, my_mod, -dif(A)), get_atts(V, my_mod, Ls).", [["A = _114", "Ls = [frozen(b)]", "V = _29"]]); - submit(&mut wam, include_str!("./prolog/examples/minatotask.pl")); - submit(&mut wam, ":- use_module(library(zdd))."); + submit(&mut wam, ":- use_module('src/prolog/examples/minatotask.pl')."); assert_prolog_failure!(&mut wam, "ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), Vs = [X,Y],