]> Repositorios git - scryer-prolog.git/commitdiff
address issues #143, #150, #155
authorMark Thom <[email protected]>
Mon, 2 Sep 2019 20:53:31 +0000 (16:53 -0400)
committerMark Thom <[email protected]>
Mon, 2 Sep 2019 20:53:31 +0000 (16:53 -0400)
25 files changed:
Cargo.toml
README.md
src/main.rs
src/prolog/forms.rs
src/prolog/lib/assoc.pl
src/prolog/lib/atts.pl
src/prolog/lib/between.pl
src/prolog/lib/dcgs.pl
src/prolog/lib/dif.pl
src/prolog/lib/freeze.pl
src/prolog/lib/ordsets.pl
src/prolog/lib/reif.pl
src/prolog/lib/terms.pl
src/prolog/machine/compile.rs
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/mod.rs
src/prolog/machine/modules.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/prolog/machine/toplevel.rs
src/prolog/read.rs
src/prolog/toplevel.pl
src/prolog/write.rs
src/tests.rs

index 3fd047d82832f3f0922bce650dccaabf28d5cab0..8593888a8034efb0a7a30f4644f360f7226f64e9 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.86"
+version = "0.8.87"
 authors = ["Mark Thom <[email protected]>"]
 repository = "https://github.com/mthom/scryer-prolog"
 description = "A modern Prolog implementation written mostly in Rust."
index 9462e399d46d3483dcf57f5308b75e721e157ce8..9cc5d8bee68c1d0466ad322aa802a662566c3c0d 100644 (file)
--- 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
index bc7d295a36dac16cdcbd2adec4b0dc7ec0b9c90d..412dff66565f31be22b6a599672de2432a57c429 100644 (file)
@@ -15,7 +15,6 @@ extern crate termion;
 mod prolog;
 
 use prolog::machine::*;
-use prolog::machine::machine_errors::*;
 use prolog::read::*;
 
 #[cfg(test)]
index cb2c7a8712501bdecf863f0ae1d0721f4df53fc4..0ac6ecfd100080b3e750f61b6df593585476cf04 100644 (file)
@@ -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<TopLevel>),
     Module(ModuleDecl),
     NonCountedBacktracking(ClauseName, usize), // name, arity
     Op(OpDecl),
-    UseModule(ClauseName),
-    UseQualifiedModule(ClauseName, Vec<PredicateKey>)
+    UseModule(ModuleSource),
+    UseQualifiedModule(ModuleSource, Vec<PredicateKey>)
 }
 
 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)]
index b99b1c4b0ec0e69aa39fd777f6cbd8d57a54e106..7880a9e664fb50950b9264d2df10a5af857b506b 100644 (file)
@@ -52,7 +52,7 @@
             del_max_assoc/4             % +Assoc0, ?Key, ?Value, ?Assoc
           ]).
 
-:- use_module(library(lists)).
+:- use_module('src/prolog/lib/lists.pl').
 
 /** <module> Binary associations
 
index 6f3b109b924f73d7a1cd4e0fed357536855b8f89..1ea94277c8c2a760941e8762240455eeb2e92fa2 100644 (file)
@@ -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).
 
index 16c7314591f506be79898a2e5ebbc5373cfd1fea..900909862772dfe765320b7c06b2761775871a1c 100644 (file)
@@ -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),
index 60fe71264f4dbe5089b1af094064f788f5bc108f..fabd67b016680735b2b633964bd72a3fc50d8762 100644 (file)
@@ -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 = [_|_], !.
index 991db075f6ed1d9ff32de014bcf0ea8cedf1d440..cd779375ad50c4409df70a37ec5b1ac32d056058 100644 (file)
@@ -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.
 
index d3a92eaf24535515d460143955bbe79612f9c1ef..3fa4ef9149371eb933038cbbd9c31308215e1187 100644 (file)
@@ -1,6 +1,6 @@
 :- module(freeze, [freeze/2]).
 
-:- use_module(library(atts)).
+:- use_module('src/prolog/lib/atts.pl').
 
 :- attribute frozen/1.
 
index ff08096295e7c30bab404bddb2a67f531338cf79..a97c609b8bb35fc2a5bd0c3058fce12d13e4f0c4 100644 (file)
@@ -52,7 +52,7 @@
             ord_intersection/2          % +PowerSet, -Intersection
           ]).
 
-:- use_module(library(lists)).
+:- use_module('src/prolog/lib/lists.pl').
 
 /** <module> Ordered set manipulation
 Ordered sets are lists with unique elements sorted to the standard order
index 0e958356995c5491a297cefc0963a69735cd519d..603d1188d431b04a611bc1d955e145cac05f445e 100644 (file)
@@ -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),
index 8391457b9c0b4b25ea6647432da019cbcf9e86f2..9b3944600eb763fbab9545ba67b47cd91d2aa764 100644 (file)
@@ -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),
index 172d10089cfa816402ceb897ca40c5db8284d462..33d05cbfd7175b6dfe774d01a9590ff2b5edc56a 100644 (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. */
index 34011f69b08f47c8eed7cfa4b62bc9e683c598c0..0945a9e0fa92ec237167d145cac0be200fdd44ae 100644 (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
index ac72ffa576c546fd83f5a3a03269941884887d97..7e6ad97b3381bcc239b09c0a2bcb3540bbb63666 100644 (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));
                     }
                 },
index 31e2964237cc553d072223071ecace757b2ab48b..8c33f0a6bfecefdba2ff6ea3b8efd2e85eb47d88 100644 (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;
             },
index d3f7f1752d8eddc3cd5bbb7001c22a9979864b6e..c66a8f6249429ed09299d3fd5a64d46cfaf0fb09 100644 (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>)
index 55baf3e6011a1bf76da584b28c9e0c20d27d2571..d60157418de092367ce9a1eaf205e72a814eefe3 100644 (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();
 
index 2797399cccb591d450c1da72ad7d07c04b8e0a79..ed6707bfd1293db4c6d8f4bd33a7010e4f7c590c 100644 (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())
index 93335a544c0b2cef1fc7f768ba7b488e618e7538..ed37b5be6f95f7e91d4e204431e1d5ad09de7cde 100644 (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) {
index 0ad08597e45ab80e495d254ed675941bc0fe9512..6af0794d02583eb6e90d3a0b68ab304d2a13ddb6 100644 (file)
@@ -136,13 +136,6 @@ pub mod readline
         bind_keyseq_rl("\\C-d", bind_end_chord);
     }
 
-    pub fn read_batch(prompt: &str) -> Result<Vec<u8>, ::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<Read> = Box::new(ReadlineStream::new(String::from("")));
index df0f808a964cadc5e3b3bbb2b85723dbbb0389fc..15a3cc80a0ca871c65345e84f7a33309b6cd807d 100644 (file)
@@ -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)]),
index df2598845dc3d0068c349e95e1f065ac930d2f30..df2400e671bd2fad752a5a6c898d31ace4801a19 100644 (file)
@@ -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 =>
index c4f8e0e121581b84f08d5c3cc38307de40b42652..6bebd3c5922bc948498647609a0d27e569d73487 100644 (file)
@@ -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],