]> Repositorios git - scryer-prolog.git/commitdiff
provisional changes to module insertion
authorMark Thom <[email protected]>
Thu, 13 Sep 2018 02:46:15 +0000 (20:46 -0600)
committerMark Thom <[email protected]>
Thu, 13 Sep 2018 02:46:15 +0000 (20:46 -0600)
src/main.rs
src/prolog/compile.rs
src/prolog/instructions.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/mod.rs
src/prolog/machine/term_writer.rs [new file with mode: 0644]
src/prolog/macros.rs
src/prolog/read.rs
src/prolog/toplevel.rs
src/prolog/write.rs

index a4fce5f1e242d41fdfb45eb088613e8db9b0f038..fd910dee738c56a3f696fced094fef0d7d6386eb 100644 (file)
@@ -11,22 +11,11 @@ use prolog::machine::*;
 use prolog::read::*;
 use prolog::write::*;
 
-use std::io::{Write, stdout};
+use std::io::{Write, stdin, stdout};
 
 #[cfg(test)]
 mod tests;
 
-fn parse_and_compile_line(wam: &mut Machine, buffer: &str)
-{
-    match parse_code(wam, buffer) {
-        Ok(packet) => {
-            let result = compile_packet(wam, packet);
-            print(wam, result);
-        },
-        Err(e) => print(wam, EvalSession::from(e))
-    }
-}
-
 fn prolog_repl() {
     let mut wam = Machine::new();
 
@@ -35,17 +24,14 @@ fn prolog_repl() {
         stdout().flush().unwrap();
         
         match read_toplevel(&mut wam) {
-            Ok(Input::Term(term)) =>
-                match compile_term(&mut wam, term) {
-                    Ok(packet) => {
-                        let result = compile_packet(&mut wam, packet);
-                        print(&mut wam, result);
-                    },
-                    Err(e) => print(&mut wam, EvalSession::from(e))
-                },
-            Ok(Input::Line(line)) => parse_and_compile_line(&mut wam, line.as_str()),
-            Ok(Input::Batch(batch)) => {
-                let result = compile_user_module(&mut wam, batch.as_bytes());
+            Ok(Input::Term(term)) => {
+                let result = compile_term(&mut wam, term);
+                print(&mut wam, result)
+            },
+            Ok(Input::Batch) => {
+                let stdin  = stdin();
+                let result = compile_user_module(&mut wam, stdin.lock());
+                
                 print(&mut wam, result);
             },
             Ok(Input::Quit) => break,
@@ -53,7 +39,8 @@ fn prolog_repl() {
                 wam.clear();
                 continue;
             },
-            Err(e) => print(&mut wam, EvalSession::from(e))
+            Err(e) =>
+                print(&mut wam, EvalSession::from(e))
         };
 
         wam.reset();
index 9c6183ff4d43717b3bbe4c4e0934c5b08411c0d7..94feb8359b7711a389dc5dccd269597585996ee0 100644 (file)
@@ -38,22 +38,6 @@ fn print_code(code: &Code) {
     }
 }
 
-pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result<TopLevelPacket, ParserError>
-{
-    let atom_tbl = wam.atom_tbl();
-    let flags = wam.machine_flags();
-
-    let indices = machine_code_indices!(&mut wam.code_dir, &mut wam.op_dir, &mut HashMap::new());
-
-    let mut worker = TopLevelWorker::new(buffer.as_bytes(), atom_tbl, flags, indices);
-    worker.parse_code()
-}
-
-pub fn compile_term(wam: &mut Machine, term: Term) -> Result<TopLevelPacket, ParserError> {
-    let indices = machine_code_indices!(&mut wam.code_dir, &mut wam.op_dir, &mut HashMap::new());
-    parse_term(term, indices)
-}
-
 // throw errors if declaration or query found.
 fn compile_relation(tl: &TopLevel, non_counted_bt: bool, flags: MachineFlags) -> Result<Code, ParserError>
 {
@@ -112,78 +96,89 @@ fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>, flags: MachineFlag
     Ok((code, cg.take_vars()))
 }
 
-fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSession
-{
-    match tl {
-        TopLevel::Declaration(Declaration::Op(op_decl)) => {
-            try_eval_session!(op_decl.submit(clause_name!("user"), &mut wam.op_dir));
-            EvalSession::EntrySuccess
-        },
-        TopLevel::Declaration(Declaration::UseModule(name)) =>
-            wam.use_module_in_toplevel(name),
-        TopLevel::Declaration(Declaration::UseQualifiedModule(name, exports)) =>
-            wam.use_qualified_module_in_toplevel(name, exports),
-        TopLevel::Declaration(_) =>
-            EvalSession::from(ParserError::InvalidModuleDecl),
-        _ => {
-            let name = try_eval_session!(if let Some(name) = tl.name() {
-                match ClauseType::from(name.clone(), tl.arity(), None) {
-                    ClauseType::Named(..) | ClauseType::Op(..) =>
-                        Ok(name),
-                    _ => {
-                        let err_str = format!("{}/{}", name.as_str(), tl.arity());
-                        Err(SessionError::ImpermissibleEntry(err_str))
-                    }
-                }
-            } else {
-                Err(SessionError::NamelessEntry)
-            });
-
-            let mut code = try_eval_session!(compile_relation(&tl, false, wam.machine_flags()));
-            try_eval_session!(compile_appendix(&mut code, queue, false, wam.machine_flags()));
-
-            if !code.is_empty() {
-                wam.add_user_code(name, tl.arity(), code)
-            } else {
-                EvalSession::from(SessionError::ImpermissibleEntry(String::from("no code generated.")))
-            }
-        }
-    }
+fn package_term(wam: &mut Machine, term: Term) -> Result<TopLevelPacket, ParserError> {
+    let indices = machine_code_indices!(&mut wam.code_dir, &mut wam.op_dir, &mut wam.modules);
+    parse_term(term, indices)
 }
 
-pub fn compile_packet(wam: &mut Machine, tl: TopLevelPacket) -> EvalSession
+pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
 {
-    match tl {
+    let packet = try_eval_session!(package_term(wam, term));
+
+    match packet {
         TopLevelPacket::Query(terms, queue) =>
             match compile_query(terms, queue, wam.machine_flags()) {
                 Ok((mut code, vars)) => wam.submit_query(code, vars),
                 Err(e) => EvalSession::from(e)
             },
-        TopLevelPacket::Decl(tl, queue) =>
-            compile_decl(wam, tl, queue)
+        TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => {
+            let mut compiler = ListingCompiler::new();
+            let mut indices = default_machine_code_indices!();
+
+            try_eval_session!(compiler.process_decl(decl, wam, &mut indices));
+            try_eval_session!(compiler.add_code(wam, vec![], indices));
+
+            EvalSession::EntrySuccess
+        },
+        _ => EvalSession::from(SessionError::UserPrompt)
     }
 }
 
-pub struct ListingCompiler<'a> {
-    wam: &'a mut Machine,
+pub struct ListingCompiler {
     non_counted_bt_preds: HashSet<PredicateKey>,
-    module: Option<Module>
+    module: Option<Module>,
 }
 
-impl<'a> ListingCompiler<'a> {
-    pub fn new(wam: &'a mut Machine) -> Self {
-        ListingCompiler { wam,
-                          module: None,
-                          non_counted_bt_preds: HashSet::new() }
+impl ListingCompiler {
+    pub fn new() -> Self {
+        ListingCompiler { module: None, non_counted_bt_preds: HashSet::new() }
+    }
+    
+    fn use_module(&mut self, submodule: Module, wam: &mut Machine,
+                  indices: &mut MachineCodeIndices) -> Result<(), SessionError>
+    {
+        let mod_name = self.get_module_name();
+                
+        indices.use_module(&submodule)?;
+
+        if let &mut Some(ref mut module) = &mut self.module {
+            module.remove_module(mod_name, &submodule);
+            module.use_module(&submodule)?;
+        } else {
+            wam.remove_module(&submodule);
+        }
+
+        wam.insert_module(submodule);
+        Ok(())
     }
 
+    fn use_qualified_module(&mut self, submodule: Module, wam: &mut Machine,
+                            exports: &Vec<PredicateKey>, indices: &mut MachineCodeIndices)
+                            -> Result<(), SessionError>
+    {
+        let mod_name = self.get_module_name();
+                
+        indices.use_qualified_module(&submodule, exports)?;
+
+        if let &mut Some(ref mut module) = &mut self.module {
+            module.remove_module(mod_name, &submodule);
+            module.use_qualified_module(&submodule, exports)?;
+        } else {
+            wam.remove_module(&submodule);
+        }
+
+        wam.insert_module(submodule);
+        Ok(())
+    }
+    
     fn get_module_name(&self) -> ClauseName {
         self.module.as_ref()
             .map(|module| module.module_decl.name.clone())
             .unwrap_or(ClauseName::BuiltIn("user"))
     }
 
-    fn generate_code(&mut self, decls: Vec<(Predicate, VecDeque<TopLevel>)>, code_dir: &mut CodeDir)
+    fn generate_code(&mut self, decls: Vec<(Predicate, VecDeque<TopLevel>)>,
+                     wam: &Machine, code_dir: &mut CodeDir)
                      -> Result<Code, SessionError>
     {
         let mut code = vec![];
@@ -196,12 +191,11 @@ impl<'a> ListingCompiler<'a> {
 
             let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity));
 
-            let p = code.len() + self.wam.code_size();
+            let p = code.len() + wam.code_size();
             let mut decl_code = compile_relation(&TopLevel::Predicate(decl), non_counted_bt,
-                                                 self.wam.machine_flags())?;
+                                                 wam.machine_flags())?;
 
-            compile_appendix(&mut decl_code, Vec::from(queue), non_counted_bt,
-                             self.wam.machine_flags())?;
+            compile_appendix(&mut decl_code, Vec::from(queue), non_counted_bt, wam.machine_flags())?;
 
             let idx = code_dir.entry((name, arity)).or_insert(CodeIndex::default());
             set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
@@ -212,26 +206,30 @@ impl<'a> ListingCompiler<'a> {
         Ok(code)
     }
 
-    fn add_code(self, code: Code, indices: MachineCodeIndices) {
+    fn add_code(&mut self, wam: &mut Machine, code: Code, indices: MachineCodeIndices)
+                -> Result<(), SessionError>
+    {
         let code_dir = mem::replace(indices.code_dir, HashMap::new());
         let op_dir   = mem::replace(indices.op_dir, HashMap::new());
 
-        if let Some(mut module) = self.module {
+        if let Some(mut module) = self.module.take() {
             module.code_dir.extend(as_module_code_dir(code_dir));
             module.op_dir.extend(op_dir.into_iter());
 
-            self.wam.add_module(module, code);
+            wam.add_module(module, code);
         } else {
-            self.wam.add_batched_code(code, code_dir);
-            self.wam.add_batched_ops(op_dir);
+            wam.add_batched_code(code, code_dir)?;
+            wam.add_batched_ops(op_dir);
         }
+
+        Ok(())
     }
 
     fn add_non_counted_bt_flag(&mut self, name: ClauseName, arity: usize) {
         self.non_counted_bt_preds.insert((name, arity));
     }
 
-    fn process_decl(&mut self, decl: Declaration, indices: &mut MachineCodeIndices)
+    fn process_decl(&mut self, decl: Declaration, wam: &mut Machine, indices: &mut MachineCodeIndices)
                     -> Result<(), SessionError>
     {
         match decl {
@@ -240,22 +238,20 @@ impl<'a> ListingCompiler<'a> {
             Declaration::Op(op_decl) =>
                 op_decl.submit(self.get_module_name(), &mut indices.op_dir),
             Declaration::UseModule(name) =>
-                if let Some(ref submodule) = self.wam.get_module(name.clone()) {
-                    Ok(use_module(&mut self.module, submodule, indices))
+                if let Some(submodule) = wam.take_module(name) {
+                    self.use_module(submodule, wam, indices)
                 } else {
                     Err(SessionError::ModuleNotFound)
                 },
             Declaration::UseQualifiedModule(name, exports) =>
-                if let Some(ref submodule) = self.wam.get_module(name.clone()) {
-                    Ok(use_qualified_module(&mut self.module, submodule, &exports, indices))
+                if let Some(submodule) = wam.take_module(name) {
+                    self.use_qualified_module(submodule, wam, &exports, indices)
                 } else {
                     Err(SessionError::ModuleNotFound)
                 },
             Declaration::Module(module_decl) =>
                 if self.module.is_none() {
-                    // worker.source_mod = module_decl.name.clone();
-                    self.module = Some(Module::new(module_decl));
-                    Ok(())
+                    Ok(self.module = Some(Module::new(module_decl)))
                 } else {
                     Err(SessionError::from(ParserError::InvalidModuleDecl))
                 }
@@ -263,50 +259,46 @@ impl<'a> ListingCompiler<'a> {
     }
 }
 
-fn use_module(module: &mut Option<Module>, submodule: &Module, indices: &mut MachineCodeIndices)
-{
-    indices.use_module(submodule);
-
-    if let &mut Some(ref mut module) = module {
-        module.use_module(submodule);
-    }
-}
-
-fn use_qualified_module(module: &mut Option<Module>, submodule: &Module, exports: &Vec<PredicateKey>,
-                        indices: &mut MachineCodeIndices)
-{
-    indices.use_qualified_module(submodule, exports);
-
-    if let &mut Some(ref mut module) = module {
-        module.use_qualified_module(submodule, exports);
-    }
-}
-
-pub
-fn compile_listing<R: Read>(wam: &mut Machine, src: R, mut indices: MachineCodeIndices) -> EvalSession
+pub fn compile_listing<'a, R>(wam: &mut Machine, src: R, mut indices: MachineCodeIndices<'a>,
+                              mut toplevel_indices: MachineCodeIndices<'a>)
+                              -> EvalSession
+    where R: Read
 {
     let mut worker = TopLevelBatchWorker::new(src, wam.atom_tbl(), wam.machine_flags());
-    let mut compiler = ListingCompiler::new(wam);
+    let mut compiler = ListingCompiler::new();
+    let mut toplevel_results = vec![];
 
     while let Some(decl) = try_eval_session!(worker.consume(&mut indices)) {
-        try_eval_session!(compiler.process_decl(decl, &mut indices));
+        if decl.is_module_decl() {
+            toplevel_indices.copy_and_swap(&mut indices);
+            mem::swap(&mut worker.results, &mut toplevel_results);
+        }
+
+        try_eval_session!(compiler.process_decl(decl, wam, &mut indices));
     }
 
-    let code = try_eval_session!(compiler.generate_code(worker.results, &mut indices.code_dir));
-    compiler.add_code(code, indices);
+    let module_code = try_eval_session!(compiler.generate_code(worker.results, wam,
+                                                               &mut indices.code_dir));
+    let toplvl_code = try_eval_session!(compiler.generate_code(toplevel_results, wam,
+                                                               &mut toplevel_indices.code_dir));
+
+    try_eval_session!(compiler.add_code(wam, module_code, indices));
+    try_eval_session!(compiler.add_code(wam, toplvl_code, toplevel_indices));
 
     EvalSession::EntrySuccess
 }
 
-pub fn compile_user_module<R: Read>(wam: &mut Machine, src: R) -> EvalSession {
-    let mut indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(),
-                                            &mut HashMap::new());
-
+fn setup_indices(wam: &Machine, indices: &mut MachineCodeIndices) -> Result<(), SessionError> {
     if let Some(ref builtins) = wam.modules.get(&clause_name!("builtins")) {
-        indices.use_module(builtins);
+        indices.use_module(builtins)
     } else {
-        return EvalSession::from(SessionError::ModuleNotFound);
+        Err(SessionError::ModuleNotFound)
     }
+}
+
+pub fn compile_user_module<R: Read>(wam: &mut Machine, src: R) -> EvalSession {
+    let mut indices = default_machine_code_indices!();
+    try_eval_session!(setup_indices(&wam, &mut indices));
 
-    compile_listing(wam, src, indices)
+    compile_listing(wam, src, indices, default_machine_code_indices!())
 }
index 1563648b826f07008baf407de9077c2af45e70a0..a19642dc3c38a02927bc921436910c399027d07c 100644 (file)
@@ -791,6 +791,11 @@ impl CodeIndex {
             false
         }
     }
+
+    #[inline]
+    pub fn module_name(&self) -> ClauseName {
+        self.0.borrow().1.clone()
+    }
 }
 
 #[derive(Clone)]
@@ -1033,20 +1038,54 @@ pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir {
         .collect()
 }
 
-impl SubModuleUser for Module {
-    fn op_dir(&mut self) -> &mut OpDir {
-        &mut self.op_dir
-    }
-
-    fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
-        self.code_dir.insert((name, arity), idx);
-    }
-}
-
 pub trait SubModuleUser {
     fn op_dir(&mut self) -> &mut OpDir;
+    fn remove_code_index(&mut self, key: PredicateKey);
+    fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex>;
+    
     fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex);
 
+    fn remove_module(&mut self, mod_name: ClauseName, module: &Module) {
+        for (name, arity) in module.module_decl.exports.iter().cloned() {
+            let name = name.defrock_brackets();
+
+            match self.get_code_index((name.clone(), arity), mod_name.clone()) {
+                Some(CodeIndex (ref code_idx)) => {
+                    if &code_idx.borrow().1 != &module.module_decl.name {
+                        continue;
+                    }
+
+                    self.remove_code_index((name.clone(), arity));
+
+                    // remove or respecify ops.
+                    if arity == 2 {
+                        if let Some((_, _, mod_name)) = self.op_dir().get(&(name.clone(), Fixity::In)).cloned()
+                        {
+                            if mod_name == module.module_decl.name {
+                                self.op_dir().remove(&(name.clone(), Fixity::In));
+                            }
+                        }
+                    } else if arity == 1 {
+                        if let Some((_, _, mod_name)) = self.op_dir().get(&(name.clone(), Fixity::Pre)).cloned()
+                        {
+                            if mod_name == module.module_decl.name {
+                                self.op_dir().remove(&(name.clone(), Fixity::Pre));
+                            }
+                        }
+
+                        if let Some((_, _, mod_name)) = self.op_dir().get(&(name.clone(), Fixity::Post)).cloned()
+                        {
+                            if mod_name == module.module_decl.name {
+                                self.op_dir().remove(&(name.clone(), Fixity::Post));
+                            }
+                        }
+                    }
+                },
+                _ => {}
+            };
+        }
+    }
+    
     // returns true on successful import.
     fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
         let name = name.defrock_brackets();
@@ -1076,7 +1115,8 @@ pub trait SubModuleUser {
         }
     }
 
-    fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec<PredicateKey>) -> EvalSession
+    fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec<PredicateKey>)
+                            -> Result<(), SessionError>
     {
         for (name, arity) in exports.iter().cloned() {
             if !submodule.module_decl.exports.contains(&(name.clone(), arity)) {
@@ -1084,21 +1124,39 @@ pub trait SubModuleUser {
             }
 
             if !self.import_decl(name, arity, submodule) {
-                return EvalSession::from(SessionError::ModuleDoesNotContainExport);
+                return Err(SessionError::ModuleDoesNotContainExport);
             }
         }
 
-        EvalSession::EntrySuccess
+        Ok(())
     }
 
-    fn use_module(&mut self, submodule: &Module) -> EvalSession {
+    fn use_module(&mut self, submodule: &Module) -> Result<(), SessionError> {
         for (name, arity) in submodule.module_decl.exports.iter().cloned() {
             if !self.import_decl(name, arity, submodule) {
-                return EvalSession::from(SessionError::ModuleDoesNotContainExport);
+                return Err(SessionError::ModuleDoesNotContainExport);
             }
         }
 
-        EvalSession::EntrySuccess
+        Ok(())
+    }
+}
+
+impl SubModuleUser for Module {
+    fn op_dir(&mut self) -> &mut OpDir {
+        &mut self.op_dir
+    }
+
+    fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option<CodeIndex> {
+        self.code_dir.get(&key).cloned().map(CodeIndex::from)
+    }
+
+    fn remove_code_index(&mut self, key: PredicateKey) {
+        self.code_dir.remove(&key);
+    }
+    
+    fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
+        self.code_dir.insert((name, arity), idx);
     }
 }
 
@@ -1110,6 +1168,13 @@ pub enum Declaration {
     UseQualifiedModule(ClauseName, Vec<PredicateKey>)
 }
 
+impl Declaration {
+    #[inline]
+    pub fn is_module_decl(&self) -> bool {
+        if let &Declaration::Module(_) = self { true } else { false }
+    }
+}
+
 pub enum TopLevel {
     Declaration(Declaration),
     Fact(Term),
@@ -1224,14 +1289,16 @@ pub type HeapVarDict  = HashMap<Rc<Var>, Addr>;
 pub type AllocVarDict = HashMap<Rc<Var>, VarData>;
 
 pub enum SessionError {
-    ImpermissibleEntry(String),
+    CannotOverwriteBuiltIn(String),
+    CannotOverwriteImport(String),
     ModuleDoesNotContainExport,
     ModuleNotFound,
     NamelessEntry,
     OpIsInfixAndPostFix,
     ParserError(ParserError),
     QueryFailure,
-    QueryFailureWithException(String)    
+    QueryFailureWithException(String),
+    UserPrompt
 }
 
 pub enum EvalSession {
index a2a4c09e7b6f40cfdbb334ee4745bdbc21fc9719..c48748b84ffd700233687f83e5731a9001ca15bd 100644 (file)
@@ -12,7 +12,6 @@ use prolog::or_stack::*;
 
 use downcast::Any;
 
-use std::cell::RefCell;
 use std::cmp::Ordering;
 use std::io::stdin;
 use std::mem::swap;
@@ -68,67 +67,6 @@ impl<'a> CodeDirs<'a> {
     }
 }
 
-pub trait CodeDirsAdapter<'a> {
-    fn get_code_index(&self, PredicateKey, ClauseName) -> Option<CodeIndex>;
-    fn get_op(&self, OpDirKey) -> Option<(Specifier, usize, ClauseName)>;
-    fn op_dir(&self) -> &OpDir;
-}
-
-fn get_code_index(code_dir: &CodeDir, modules: &ModuleDir, key: PredicateKey, module: ClauseName)
-                  -> Option<CodeIndex>
-{
-    match module.as_str() {
-        "user" | "builtin" => code_dir.get(&key).cloned(),
-        _ => modules.get(&module).and_then(|ref module| {
-            module.code_dir.get(&key).cloned().map(CodeIndex::from)
-        })
-    }
-}
-
-impl<'a> CodeDirsAdapter<'a> for MachineCodeIndices<'a> {
-    fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
-        get_code_index(&self.code_dir, &self.modules, key, module)
-    }
-
-    fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
-        self.op_dir.get(&key).cloned()
-    }
-
-    fn op_dir(&self) -> &OpDir {
-        &self.op_dir
-    }
-}
-
-impl<'a> CodeDirsAdapter<'a> for CodeDirs<'a> {
-    fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
-        get_code_index(&self.code_dir, &self.modules, key, module)
-    }
-
-    fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
-        self.op_dir.get(&key).cloned()
-    }
-
-    fn op_dir(&self) -> &OpDir {
-        &self.op_dir
-    }
-}
-
-impl<'a> CodeDirsAdapter<'a> for &'a Module {
-    fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option<CodeIndex> {
-        self.code_dir.get(&key)
-            .cloned()
-            .map(|ModuleCodeIndex(ptr, module)| CodeIndex(Rc::new(RefCell::new((ptr, module)))))
-    }
-
-    fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
-        self.op_dir.get(&key).cloned()
-    }
-
-    fn op_dir(&self) -> &OpDir {
-        &self.op_dir
-    }
-}
-
 pub(super) struct DuplicateTerm<'a> {
     state: &'a mut MachineState
 }
index 8c9f16a492bd29f55e4a5afaaa077cce3989443c..d07bf29bc558128424a4c8a07d7afb20e5e58e7d 100644 (file)
@@ -27,8 +27,18 @@ pub struct MachineCodeIndices<'a> {
 }
 
 impl<'a> MachineCodeIndices<'a> {
+    #[inline]
+    pub(super) fn copy_and_swap(&mut self, other: &mut MachineCodeIndices<'a>) {
+        *self.code_dir = other.code_dir.clone();
+        *self.op_dir = other.op_dir.clone();
+
+        swap(&mut self.code_dir, &mut other.code_dir);
+        swap(&mut self.op_dir, &mut other.op_dir);
+        swap(&mut self.modules, &mut other.modules);
+    }
+
     pub(super)
-    fn lookup(&mut self, name: ClauseName, arity: usize, fixity: Option<Fixity>) -> ClauseType
+    fn get_clause_type(&mut self, name: ClauseName, arity: usize, fixity: Option<Fixity>) -> ClauseType
     {
         match ClauseType::from(name, arity, fixity) {
             ClauseType::Named(name, _) => {
@@ -67,6 +77,17 @@ pub struct Machine {
     cached_query: Option<Code>
 }
 
+fn get_code_index(code_dir: &CodeDir, modules: &ModuleDir, key: PredicateKey, module: ClauseName)
+                  -> Option<CodeIndex>
+{
+    match module.as_str() {
+        "user" | "builtin" => code_dir.get(&key).cloned(),
+        _ => modules.get(&module).and_then(|ref module| {
+            module.code_dir.get(&key).cloned().map(CodeIndex::from)
+        })
+    }
+}
+
 impl Index<LocalCodePtr> for Machine {
     type Output = Line;
 
@@ -88,6 +109,14 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> {
         self.op_dir
     }
 
+    fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
+        get_code_index(&self.code_dir, &self.modules, key, module)
+    }
+
+    fn remove_code_index(&mut self, key: PredicateKey) {
+        self.code_dir.remove(&key);
+    }
+
     fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
         if let Some(ref mut code_idx) = self.code_dir.get_mut(&(name.clone(), arity)) {
             if !code_idx.is_undefined() {
@@ -116,22 +145,19 @@ impl Machine {
             code: Code::new(),
             code_dir: CodeDir::new(),
             op_dir: default_op_dir(),
-            // term_dir: TermDir::new(),            
+            // term_dir: TermDir::new(),
             modules: HashMap::new(),
             cached_query: None
         };
 
-        let indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(),
-                                            &mut HashMap::new());
-        
-        compile_listing(&mut wam, BUILTINS.as_bytes(), indices);
+        compile_listing(&mut wam, BUILTINS.as_bytes(),
+                        default_machine_code_indices!(),
+                        default_machine_code_indices!());
 
         compile_user_module(&mut wam, LISTS.as_bytes());
         compile_user_module(&mut wam, CONTROL.as_bytes());
         compile_user_module(&mut wam, QUEUES.as_bytes());
 
-        wam.use_module_in_toplevel(clause_name!("builtins"));
-
         wam
     }
 
@@ -139,53 +165,6 @@ impl Machine {
     pub fn machine_flags(&self) -> MachineFlags {
         self.ms.flags
     }
-    
-    fn remove_module(&mut self, module_name: ClauseName) {
-        let iter = if let Some(submodule) = self.modules.get(&module_name) {
-            submodule.module_decl.exports.iter().cloned()
-        } else {
-            return;
-        };
-
-        for (name, arity) in iter {
-            let name = name.defrock_brackets();
-
-            match self.code_dir.get(&(name.clone(), arity)).cloned() {
-                Some(CodeIndex (ref code_idx)) => {
-                    if &code_idx.borrow().1 != &module_name {
-                        continue;
-                    }
-
-                    self.code_dir.remove(&(name.clone(), arity));
-
-                    // remove or respecify ops.
-                    if arity == 2 {
-                        if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::In)).cloned()
-                        {
-                            if mod_name == module_name {
-                                self.op_dir.remove(&(name.clone(), Fixity::In));
-                            }
-                        }
-                    } else if arity == 1 {
-                        if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::Pre)).cloned()
-                        {
-                            if mod_name == module_name {
-                                self.op_dir.remove(&(name.clone(), Fixity::Pre));
-                            }
-                        }
-
-                        if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::Post)).cloned()
-                        {
-                            if mod_name == module_name {
-                                self.op_dir.remove(&(name.clone(), Fixity::Post));
-                            }
-                        }
-                    }
-                },
-                _ => {}
-            };
-        }
-    }
 
     #[inline]
     pub fn failed(&self) -> bool {
@@ -196,84 +175,68 @@ impl Machine {
     pub fn atom_tbl(&self) -> TabledData<Atom> {
         self.ms.atom_tbl.clone()
     }
-    
-    pub fn use_qualified_module_in_toplevel(&mut self, name: ClauseName, exports: Vec<PredicateKey>)
-                                            -> EvalSession
-    {
-        self.remove_module(name.clone());
-
-        if let Some(mut module) = self.modules.remove(&name) {
-            let result = {
-                let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
-                                                        &mut self.modules);
-                indices.use_qualified_module(&mut module, &exports)
-            };
 
-            self.modules.insert(name, module);
-            result
-        } else {
-            EvalSession::from(SessionError::ModuleNotFound)
-        }
+    pub fn get_module(&self, name: ClauseName) -> Option<&Module> {
+        self.modules.get(&name)
     }
 
-    pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession
+    pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) -> Result<(), SessionError>
     {
-        self.remove_module(name.clone());
-
-        if let Some(mut module) = self.modules.remove(&name) {
-            let result = {
-                let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
-                                                        &mut self.modules);
-                indices.use_module(&mut module)
+        for (ref key, ref idx) in code_dir.iter() {
+            match ClauseType::from(key.0.clone(), key.1, None) {
+                ClauseType::Named(..) | ClauseType::Op(..) => {},
+                _ => {
+                    // ensure we don't try to overwrite the name/arity of a builtin.
+                    let err_str = format!("{}/{}", key.0, key.1);
+                    return Err(SessionError::CannotOverwriteBuiltIn(err_str));
+                }
             };
 
-            self.modules.insert(name, module);
-            result
-        } else {
-            EvalSession::from(SessionError::ModuleNotFound)
-        }
-    }
+            if idx.module_name().as_str() == "builtins" {
+                continue;
+            }
 
-    pub fn get_module(&self, name: ClauseName) -> Option<&Module> {
-        self.modules.get(&name)
-    }
+            if let Some(ref existing_idx) = self.code_dir.get(&key) {
+                // ensure we don't try to overwrite an existing predicate from a different module.
+                if !existing_idx.is_undefined() {
+                    if existing_idx.module_name() != idx.module_name() {
+                        let err_str = format!("{}/{} from module {}", key.0, key.1,
+                                              existing_idx.module_name().as_str());
+                        return Err(SessionError::CannotOverwriteImport(err_str));
+                    }
+                }
+            }
+        }
 
-    pub fn add_batched_code(&mut self, mut code: Code, code_dir: CodeDir) {
-        self.code.append(&mut code);
-        self.code_dir.extend(code_dir.into_iter());
+        self.code.extend(code.into_iter());
+        Ok(self.code_dir.extend(code_dir.into_iter()))
     }
 
+    #[inline]
     pub fn add_batched_ops(&mut self, op_dir: OpDir) {
         self.op_dir.extend(op_dir.into_iter());
     }
 
-    pub fn add_module(&mut self, module: Module, code: Code) {
-        self.modules.insert(module.module_decl.name.clone(), module);
-        self.code.extend(code.into_iter());
+    #[inline]
+    pub fn remove_module(&mut self, module: &Module) {
+        let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir, &mut self.modules);
+        indices.remove_module(clause_name!("user"), module);
     }
 
-    pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code) -> EvalSession
-    {
-        match self.code_dir.get(&(name.clone(), arity)) {
-            Some(&CodeIndex (ref idx)) if idx.borrow().1 != clause_name!("user") =>
-                if !(&CodeIndex(idx.clone())).is_undefined() {
-                    return EvalSession::from(SessionError::ImpermissibleEntry(format!("{}/{}",
-                                                                                      name,
-                                                                                      arity)))
-                },
-            _ => {}
-        };
-
-        let offset = self.code.len();
+    #[inline]
+    pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
+        self.modules.remove(&name)
+    }
 
+    #[inline]
+    pub fn insert_module(&mut self, module: Module) {
+        self.modules.insert(module.module_decl.name.clone(), module);
+    }
+    
+    #[inline]
+    pub fn add_module(&mut self, module: Module, code: Code) {
+        self.modules.insert(module.module_decl.name.clone(), module);
         self.code.extend(code.into_iter());
-        //self.term_dir.insert((name.clone(), arity), pred);
-
-        let idx = self.code_dir.entry((name, arity))
-            .or_insert(CodeIndex::from((offset, clause_name!("user"))));
-
-        set_code_index!(idx, IndexPtr::Index(offset), clause_name!("user"));
-        EvalSession::EntrySuccess
     }
 
     pub fn code_size(&self) -> usize {
@@ -422,7 +385,7 @@ impl Machine {
         while self.ms.p < end_ptr {
             if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.ms.p {
                 match &self[LocalCodePtr::TopLevel(cn, p)] {
-                    &Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {                        
+                    &Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
                         self.record_var_places(cn, alloc_locs, heap_locs);
                         cn += 1;
                     },
@@ -506,7 +469,7 @@ impl Machine {
     {
         let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = var_dir.iter().collect();
         sorted_vars.sort_by_key(|ref v| v.0);
-        
+
         for (var, addr) in sorted_vars {
             let fmt = TermFormatter {};
             output = self.ms.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output);
diff --git a/src/prolog/machine/term_writer.rs b/src/prolog/machine/term_writer.rs
new file mode 100644 (file)
index 0000000..d094a23
--- /dev/null
@@ -0,0 +1,54 @@
+use prolog_parser::ast::*;
+
+use prolog::heap_iter::*;
+use prolog::instructions::*;
+use prolog::machine::machine_state::MachineState;
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+pub fn term_write(machine_st: &MachineState, addr: Addr) -> Result<Term, ParserError>
+{
+    let pre_order_iter  = HCPreOrderIterator::new(machine_st, addr);
+    let post_order_iter = HCPostOrderIterator::new(pre_order_iter);
+
+    let mut stack = vec![];
+
+    for value in post_order_iter {
+        match value {
+            HeapCellValue::NamedStr(arity, ref name, fixity)
+                if stack.len() >= arity => {
+                    let stack_len = stack.len();
+                    let subterms: Vec<_> = stack.drain(stack_len - arity ..).collect();
+
+                    stack.push(Box::new(Term::Clause(Cell::default(), name.clone(), subterms,
+                                                     fixity)));
+                },
+            HeapCellValue::Addr(Addr::Con(constant)) =>
+                stack.push(Box::new(Term::Constant(Cell::default(), constant))),
+            HeapCellValue::Addr(Addr::Lis(_))
+                if stack.len() >= 2 => {
+                    let stack_len = stack.len();                    
+                    let mut iter  = stack.drain(stack_len - 2 ..);
+                    
+                    let head = iter.next().unwrap();
+                    let tail = iter.next().unwrap();
+
+                    stack.push(Box::new(Term::Cons(Cell::default(), head, tail)));
+                },
+            HeapCellValue::Addr(Addr::HeapCell(h)) =>
+                stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}", h))))),
+            HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
+                stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}_{}", sc, fr))))),
+            _ => return Err(ParserError::IncompleteReduction)
+        }
+    }
+
+    if let Some(term) = stack.pop() {
+        if stack.is_empty() {
+            return Ok(*term);
+        }
+    }
+
+    Err(ParserError::IncompleteReduction)
+}
index 48712dfc7b5edb1e01d349dac1be9de24bc61dca..69f86b3ba602069ddfd3b9c007673751e09dada0 100644 (file)
@@ -216,6 +216,13 @@ macro_rules! machine_code_indices {
     )
 }
 
+macro_rules! default_machine_code_indices {
+    () => (
+        machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(),
+                              &mut HashMap::new());
+    )
+}
+
 macro_rules! put_constant {
     ($lvl:expr, $cons:expr, $r:expr) => (
         QueryInstruction::PutConstant($lvl, $cons, $r)
index 7432ec654991b404db2241326e8f15fb88de5436..b079eef29bb999df6574601268f6e028bf5f0daf 100644 (file)
@@ -25,27 +25,10 @@ impl<'a> TermRef<'a> {
 pub enum Input {
     Quit,
     Clear,
-    Line(String),
-    Batch(String),
+    Batch,
     Term(Term)
 }
 
-fn read_lines(buffer: &mut String, end_delim: &str) -> String {
-    let mut result = String::new();
-    let stdin = stdin();
-
-    buffer.clear();
-    stdin.read_line(buffer).unwrap();
-
-    while &*buffer.trim() != end_delim {
-        result += buffer.as_str();
-        buffer.clear();
-        stdin.read_line(buffer).unwrap();
-    }
-
-    result
-}
-
 pub fn read_toplevel(wam: &Machine) -> Result<Input, ParserError> {    
     let mut buffer = String::new();
 
@@ -53,16 +36,15 @@ pub fn read_toplevel(wam: &Machine) -> Result<Input, ParserError> {
     stdin.read_line(&mut buffer).unwrap();
 
     match &*buffer.trim() {
-        ":{"    => Ok(Input::Line(read_lines(&mut buffer, "}:"))),
-        ":{{"   => Ok(Input::Batch(read_lines(&mut buffer, "}}:"))),
-        "quit"  => Ok(Input::Quit),
-        "clear" => Ok(Input::Clear),
-        _       => {
+        "quit"   => Ok(Input::Quit),
+        "clear"  => Ok(Input::Clear),
+        "[user]" => Ok(Input::Batch),
+        _        => {
             let mut parser = Parser::new(stdin.lock(), wam.atom_tbl(), wam.machine_flags());
             
             parser.add_to_top(buffer.as_str());
             Ok(Input::Term(parser.read_term(&wam.op_dir)?))
-        }
+        }        
     }
 }
 
index c731d2e0d3f3caea0d2d8672104b33cee5c6f4db..267695f680ddbbff5e10ecb5b2cb5ac4f881c3c8 100644 (file)
@@ -416,7 +416,7 @@ impl RelationWorker {
                 if name.as_str() == "!" || name.as_str() == "blocked_!" {
                     Ok(QueryTerm::BlockedCut)
                 } else {
-                    let ct = indices.lookup(name, 0, None);
+                    let ct = indices.get_clause_type(name, 0, None);
                     Ok(QueryTerm::Clause(r, ct, vec![], false))
                 },
             Term::Var(_, ref v) if v.as_str() == "!" =>
@@ -462,7 +462,7 @@ impl RelationWorker {
                         Err(ParserError::InadmissibleQueryTerm)
                     },
                     _ => {
-                        let ct = indices.lookup(name, terms.len(), fixity);
+                        let ct = indices.get_clause_type(name, terms.len(), fixity);
                         Ok(QueryTerm::Clause(Cell::default(), ct, terms, false))
                     }
                 },
@@ -496,24 +496,24 @@ impl RelationWorker {
         }
     }
 
-    fn pre_query_term(&mut self, idx: &mut MachineCodeIndices, term: Term) -> Result<QueryTerm, ParserError>
+    fn pre_query_term(&mut self, indices: &mut MachineCodeIndices, term: Term) -> Result<QueryTerm, ParserError>
     {
         match term {
             Term::Clause(r, name, mut subterms, fixity) =>
                 if subterms.len() == 1 && name.as_str() == "$call_with_default_policy" {
-                    self.to_query_term(idx, *subterms.pop().unwrap())
+                    self.to_query_term(indices, *subterms.pop().unwrap())
                         .map(|mut query_term| {
                             query_term.set_default_caller();
                             query_term
                         })
                 } else {
-                    self.to_query_term(idx, Term::Clause(r, name, subterms, fixity))
+                    self.to_query_term(indices, Term::Clause(r, name, subterms, fixity))
                 },
-            _ => self.to_query_term(idx, term)
+            _ => self.to_query_term(indices, term)
         }
     }
 
-    fn setup_query(&mut self, idx: &mut MachineCodeIndices, terms: Vec<Box<Term>>, blocks_cuts: bool)
+    fn setup_query(&mut self, indices: &mut MachineCodeIndices, terms: Vec<Box<Term>>, blocks_cuts: bool)
                    -> Result<Vec<QueryTerm>, ParserError>
     {
         let mut query_terms = vec![];
@@ -541,18 +541,18 @@ impl RelationWorker {
                     mark_cut_variable(&mut subterm);
                 }
 
-                query_terms.push(self.pre_query_term(idx, subterm)?);
+                query_terms.push(self.pre_query_term(indices, subterm)?);
             }
         }
 
         Ok(query_terms)
     }
 
-    fn setup_rule(&mut self, idx: &mut MachineCodeIndices, mut terms: Vec<Box<Term>>, blocks_cuts: bool)
+    fn setup_rule(&mut self, indices: &mut MachineCodeIndices, mut terms: Vec<Box<Term>>, blocks_cuts: bool)
                   -> Result<Rule, ParserError>
     {
         let post_head_terms = terms.drain(1..).collect();
-        let mut query_terms = try!(self.setup_query(idx, post_head_terms, blocks_cuts));
+        let mut query_terms = try!(self.setup_query(indices, post_head_terms, blocks_cuts));
         let clauses = query_terms.drain(1 ..).collect();
         let qt = query_terms.pop().unwrap();
 
@@ -565,15 +565,15 @@ impl RelationWorker {
         }
     }
 
-    fn try_term_to_tl(&mut self, idx: &mut MachineCodeIndices, term: Term, blocks_cuts: bool)
+    fn try_term_to_tl(&mut self, indices: &mut MachineCodeIndices, term: Term, blocks_cuts: bool)
                       -> Result<TopLevel, ParserError>
     {
         match term {
             Term::Clause(r, name, mut terms, fixity) =>
                 if name.as_str() == "?-" {
-                    Ok(TopLevel::Query(try!(self.setup_query(idx, terms, blocks_cuts))))
+                    Ok(TopLevel::Query(try!(self.setup_query(indices, terms, blocks_cuts))))
                 } else if name.as_str() == ":-" && terms.len() > 1 {
-                    Ok(TopLevel::Rule(try!(self.setup_rule(idx, terms, blocks_cuts))))
+                    Ok(TopLevel::Rule(try!(self.setup_rule(indices, terms, blocks_cuts))))
                 } else if name.as_str() == ":-" && terms.len() == 1 {
                     let term = *terms.pop().unwrap();
                     Ok(TopLevel::Declaration(try!(setup_declaration(term))))
@@ -584,25 +584,25 @@ impl RelationWorker {
         }
     }
 
-    fn try_terms_to_tls<Iter>(&mut self, idx: &mut MachineCodeIndices, terms: Iter, blocks_cuts: bool)
-                              -> Result<VecDeque<TopLevel>, ParserError>
-        where Iter: IntoIterator<Item=Term>
+    fn try_terms_to_tls<I>(&mut self, indices: &mut MachineCodeIndices, terms: I, blocks_cuts: bool)
+                           -> Result<VecDeque<TopLevel>, ParserError>
+        where I: IntoIterator<Item=Term>
     {
         let mut results = VecDeque::new();
 
         for term in terms.into_iter() {
-            results.push_back(self.try_term_to_tl(idx, term, blocks_cuts)?);
+            results.push_back(self.try_term_to_tl(indices, term, blocks_cuts)?);
         }
 
         Ok(results)
     }
 
-    fn parse_queue(&mut self, idx: &mut MachineCodeIndices) -> Result<VecDeque<TopLevel>, ParserError>
+    fn parse_queue(&mut self, indices: &mut MachineCodeIndices) -> Result<VecDeque<TopLevel>, ParserError>
     {
         let mut queue = VecDeque::new();
 
         while let Some(terms) = self.queue.pop_front() {
-            let clauses = merge_clauses(&mut self.try_terms_to_tls(idx, terms, false)?)?;
+            let clauses = merge_clauses(&mut self.try_terms_to_tls(indices, terms, false)?)?;
             queue.push_back(clauses);
         }
 
@@ -614,37 +614,6 @@ impl RelationWorker {
     }
 }
 
-pub struct TopLevelWorker<'a, R: Read> {
-    pub parser: Parser<R>,
-    indices: MachineCodeIndices<'a>
-}
-
-impl<'a, R: Read> TopLevelWorker<'a, R> {
-    pub fn new(inner: R, atom_tbl: TabledData<Atom>, flags: MachineFlags,
-               indices: MachineCodeIndices<'a>)
-               -> Self
-    {
-        TopLevelWorker { parser: Parser::new(inner, atom_tbl, flags), indices }
-    }
-
-    pub fn parse_code(&mut self) -> Result<TopLevelPacket, ParserError>
-    {
-        let mut rel_worker = RelationWorker::new();
-
-        let terms   = self.parser.read(self.indices.op_dir)?;
-        let mut tls = rel_worker.try_terms_to_tls(&mut self.indices, terms, true)?;
-        let results = rel_worker.parse_queue(&mut self.indices)?;
-
-        let tl = merge_clauses(&mut tls)?;
-
-        if tls.is_empty() {
-            Ok(deque_to_packet(tl, results))
-        } else {
-            Err(ParserError::InconsistentEntry)
-        }
-    }
-}
-
 pub fn parse_term(term: Term, mut indices: MachineCodeIndices) -> Result<TopLevelPacket, ParserError>
 {
     let mut rel_worker = RelationWorker::new();
@@ -667,7 +636,7 @@ impl<R: Read> TopLevelBatchWorker<R> {
         TopLevelBatchWorker { parser: Parser::new(inner, atom_tbl, flags),
                               rel_worker: RelationWorker::new(),
                               results: vec![] }
-    }
+    }    
 
     pub
     fn consume(&mut self, indices: &mut MachineCodeIndices) -> Result<Option<Declaration>, SessionError>
index c9259dab30d165989dbefdb20f3890cbbf42d7fb..c39da26a00dac7cc06baf1249c3c9811ac836267 100644 (file)
@@ -193,15 +193,19 @@ impl fmt::Display for IndexingInstruction {
 impl fmt::Display for SessionError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
+            &SessionError::CannotOverwriteBuiltIn(ref msg) =>
+                write!(f, "cannot overwrite {}", msg),
+            &SessionError::CannotOverwriteImport(ref msg) =>
+                write!(f, "cannot overwrite import {}", msg),
             &SessionError::ModuleNotFound => write!(f, "module not found."),
             &SessionError::ModuleDoesNotContainExport => write!(f, "module does not contain claimed export."),
             &SessionError::QueryFailure => write!(f, "false."),
             &SessionError::QueryFailureWithException(ref e) => write!(f, "{}", error_string(e)),
-            &SessionError::ImpermissibleEntry(ref msg) => write!(f, "cannot overwrite {}.", msg),
             &SessionError::OpIsInfixAndPostFix =>
                 write!(f, "cannot define an op to be both postfix and infix."),
             &SessionError::NamelessEntry => write!(f, "the predicate head is not an atom or clause."),
             &SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()),
+            &SessionError::UserPrompt => write!(f, "enter predicate at [user] prompt")
         }
     }
 }