]> Repositorios git - scryer-prolog.git/commitdiff
correct module bugs
authorMark Thom <[email protected]>
Mon, 5 Mar 2018 04:35:30 +0000 (21:35 -0700)
committerMark Thom <[email protected]>
Mon, 5 Mar 2018 04:35:30 +0000 (21:35 -0700)
README.md
src/main.rs
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/io.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/mod.rs
src/prolog/parser

index 31444ff2665e61b5fbe5f6ac1d69de50c22c9d55..e081624b0093f0bfecfec18b60e680cc1a2e7e47 100644 (file)
--- a/README.md
+++ b/README.md
@@ -251,4 +251,15 @@ been exported to the toplevel. To export them, write
 ```
 prolog> :- use_module(library(lists)).
 prolog> :- use_module(library(control)).
+```
+
+To define modules inline at the REPL, use the ":{{"\"}}:" delimiters:
+
+```
+prolog> :{{
+:- module(test, [local_member/2]).
+:- use_module(library(lists)).
+
+local_member(X, Xs) :- member(X, Xs).
+}}:
 ```
\ No newline at end of file
index 4d99223ccd4b184485e4c54ed077e8f1661632d3..695e8c401d2bb591b8d516d117b20d0f967519ab 100644 (file)
@@ -15,7 +15,7 @@ mod tests;
 pub static LISTS: &str   = include_str!("./prolog/lib/lists.pl");
 pub static CONTROL: &str = include_str!("./prolog/lib/control.pl");
 
-fn process_buffer(wam: &mut Machine, buffer: &str)
+fn parse_and_compile_line(wam: &mut Machine, buffer: &str)
 {
     match parse_code(wam, buffer) {
         Ok(packet) => {
@@ -39,20 +39,22 @@ fn prolog_repl() {
 
     load_init_str(&mut wam, LISTS);
     load_init_str(&mut wam, CONTROL);
-    
+
     loop {
         print!("prolog> ");
 
-        let buffer = read();
-
-        if buffer == "quit\n" {
-            break;
-        } else if buffer == "clear\n" {
-            wam.clear();
-            continue;
-        }
+        match read() {
+            Input::Line(line) => parse_and_compile_line(&mut wam, line.as_str()),
+            Input::Batch(batch) => {
+                compile_listing(&mut wam, batch.as_str());
+            },
+            Input::Quit => break,
+            Input::Clear => {
+                wam.clear();
+                continue;
+            }
+        };
 
-        process_buffer(&mut wam, buffer.as_str());
         wam.reset();
     }
 }
index 6a434a3887f43d1f5792a3a297a475ce901dbb25..849c5d69da429cf9acd0f8d9a50732baf8d394f5 100644 (file)
@@ -133,18 +133,12 @@ impl PredicateClause {
 
 pub type OpDirKey = (ClauseName, Fixity);
 // name and fixity -> operator type and precedence.
-pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
+pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
 
-pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize, ClauseName)>;
+pub type CodeDir = HashMap<PredicateKey, (usize, ClauseName)>;
 
 pub type PredicateKey = (ClauseName, usize); // name, arity.
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub enum PredicateKeyType {
-    BuiltIn,
-    User
-}
-
 pub struct ModuleDecl {
     pub name: ClauseName,
     pub exports: Vec<PredicateKey>
@@ -377,7 +371,7 @@ impl From<ParserError> for EvalSession {
 pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
 
 impl OpDecl {
-    pub fn submit(&self, op_dir: &mut OpDir) -> Result<(), EvalError>
+    pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), EvalError>
     {
         let (prec, spec, name) = (self.0, self.1, self.2.clone());
 
@@ -398,9 +392,9 @@ impl OpDecl {
         if prec > 0 {
             match spec {
                 XFY | XFX | YFX => op_dir.insert((name.clone(), Fixity::In),
-                                                 (spec, prec)),
-                XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec)),
-                FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec,prec)),
+                                                 (spec, prec, module.clone())),
+                XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec, module.clone())),
+                FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec, prec, module.clone())),
                 _ => None
             };
         } else {
index 135eac8b234b5db768cfc3c004be79b86849b2e3..a2fe7e5d228e88d5cd2d418b2e644c815a6daaba 100644 (file)
@@ -628,154 +628,150 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
 {
     let mut code_dir = HashMap::new();
     let mut op_dir   = HashMap::new();
-
-    op_dir.insert((clause_name!(":-"), Fixity::In),   (XFX, 1200));
-    op_dir.insert((clause_name!(":-"), Fixity::Pre),  (FX, 1200));
-    op_dir.insert((clause_name!("?-"), Fixity::Pre),  (FX, 1200));
+    
+    let builtin = ClauseName::BuiltIn("builtin");
+    
+    op_dir.insert((clause_name!(":-"), Fixity::In),   (XFX, 1200, builtin.clone()));
+    op_dir.insert((clause_name!(":-"), Fixity::Pre),  (FX, 1200, builtin.clone()));
+    op_dir.insert((clause_name!("?-"), Fixity::Pre),  (FX, 1200, builtin.clone()));
 
     // control operators.
-    op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900));
-    op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900, builtin.clone()));
+    op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700, builtin.clone()));
 
     // arithmetic operators.
-    op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500));
-    op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500));
-    op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500));
-    op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500));
-    op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500));
-    op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200));
-    op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400));
-    op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500, builtin.clone()));
+    op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500, builtin.clone()));
+    op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500, builtin.clone()));
+    op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500, builtin.clone()));
+    op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500, builtin.clone()));
+    op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200, builtin.clone()));
+    op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400, builtin.clone()));
+    op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400, builtin.clone()));
 
     // arithmetic comparison operators.
-    op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700, builtin.clone()));
 
     // control operators.
-    op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100));
-    op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050));
+    op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100, builtin.clone()));
+    op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050, builtin.clone()));
 
-    op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700));
-    op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700));
-
-    let builtin = ClauseName::BuiltIn("builtin");
+    op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700, builtin.clone()));
+    op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700, builtin.clone()));
 
     // there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
     // (an extra register is needed for the predicate name)
     for arity in 0 .. 63 {
-        code_dir.insert((clause_name!("call"), arity),
-                        (PredicateKeyType::BuiltIn, 0, builtin.clone()));
+        code_dir.insert((clause_name!("call"), arity), (0, builtin.clone()));
     }
 
-    code_dir.insert((clause_name!("atomic"), 1),
-                    (PredicateKeyType::BuiltIn, 1, builtin.clone()));
-    code_dir.insert((clause_name!("var"), 1),
-                    (PredicateKeyType::BuiltIn, 3, builtin.clone()));
-    code_dir.insert((clause_name!("false"), 0),
-                    (PredicateKeyType::BuiltIn, 61, builtin.clone()));
+    code_dir.insert((clause_name!("atomic"), 1), (1, builtin.clone()));
+    code_dir.insert((clause_name!("var"), 1), (3, builtin.clone()));
+    code_dir.insert((clause_name!("false"), 0), (61, builtin.clone()));
     code_dir.insert((clause_name!("\\+"), 1),
-                    (PredicateKeyType::BuiltIn, 62, builtin.clone()));
+                    (62, builtin.clone()));
     code_dir.insert((clause_name!("duplicate_term"), 2),
-                    (PredicateKeyType::BuiltIn, 71, builtin.clone()));
+                    (71, builtin.clone()));
     code_dir.insert((clause_name!("catch"), 3),
-                    (PredicateKeyType::BuiltIn, 5, builtin.clone()));
+                    (5, builtin.clone()));
     code_dir.insert((clause_name!("throw"), 1),
-                    (PredicateKeyType::BuiltIn, 59, builtin.clone()));
+                    (59, builtin.clone()));
     code_dir.insert((clause_name!("="), 2),
-                    (PredicateKeyType::BuiltIn, 73, builtin.clone()));
+                    (73, builtin.clone()));
     code_dir.insert((clause_name!("true"), 0),
-                    (PredicateKeyType::BuiltIn, 75, builtin.clone()));
+                    (75, builtin.clone()));
 
     code_dir.insert((clause_name!(","), 2),
-                    (PredicateKeyType::BuiltIn, 76, builtin.clone()));
+                    (76, builtin.clone()));
     code_dir.insert((clause_name!(";"), 2),
-                    (PredicateKeyType::BuiltIn, 120, builtin.clone()));
+                    (120, builtin.clone()));
     code_dir.insert((clause_name!("->"), 2),
-                    (PredicateKeyType::BuiltIn, 138, builtin.clone()));
+                    (138, builtin.clone()));
 
     code_dir.insert((clause_name!("functor"), 3),
-                    (PredicateKeyType::BuiltIn, 146, builtin.clone()));
+                    (146, builtin.clone()));
     code_dir.insert((clause_name!("arg"), 3),
-                    (PredicateKeyType::BuiltIn, 150, builtin.clone()));
+                    (150, builtin.clone()));
     code_dir.insert((clause_name!("integer"), 1),
-                    (PredicateKeyType::BuiltIn, 147, builtin.clone()));
+                    (147, builtin.clone()));
     code_dir.insert((clause_name!("display"), 1),
-                    (PredicateKeyType::BuiltIn, 192, builtin.clone()));
+                    (192, builtin.clone()));
 
     code_dir.insert((clause_name!("is"), 2),
-                    (PredicateKeyType::BuiltIn, 194, builtin.clone()));
+                    (194, builtin.clone()));
     code_dir.insert((clause_name!(">"), 2),
-                    (PredicateKeyType::BuiltIn, 196, builtin.clone()));
+                    (196, builtin.clone()));
     code_dir.insert((clause_name!("<"), 2),
-                    (PredicateKeyType::BuiltIn, 198, builtin.clone()));
+                    (198, builtin.clone()));
     code_dir.insert((clause_name!(">="), 2),
-                    (PredicateKeyType::BuiltIn, 200, builtin.clone()));
+                    (200, builtin.clone()));
     code_dir.insert((clause_name!("=<"), 2),
-                    (PredicateKeyType::BuiltIn, 202, builtin.clone()));
+                    (202, builtin.clone()));
     code_dir.insert((clause_name!("=\\="), 2),
-                    (PredicateKeyType::BuiltIn, 204, builtin.clone()));
+                    (204, builtin.clone()));
     code_dir.insert((clause_name!("=:="), 2),
-                    (PredicateKeyType::BuiltIn, 206, builtin.clone()));
+                    (206, builtin.clone()));
     code_dir.insert((clause_name!("=.."), 2),
-                    (PredicateKeyType::BuiltIn, 208, builtin.clone()));
+                    (208, builtin.clone()));
 
     code_dir.insert((clause_name!("length"), 2),
-                    (PredicateKeyType::BuiltIn, 261, builtin.clone()));
+                    (261, builtin.clone()));
     code_dir.insert((clause_name!("setup_call_cleanup"), 3),
-                    (PredicateKeyType::BuiltIn, 294, builtin.clone()));
+                    (294, builtin.clone()));
     code_dir.insert((clause_name!("call_with_inference_limit"), 3),
-                    (PredicateKeyType::BuiltIn, 393, builtin.clone()));
+                    (393, builtin.clone()));
 
     code_dir.insert((clause_name!("compound"), 1),
-                    (PredicateKeyType::BuiltIn, 372, builtin.clone()));
+                    (372, builtin.clone()));
     code_dir.insert((clause_name!("rational"), 1),
-                    (PredicateKeyType::BuiltIn, 374, builtin.clone()));
+                    (374, builtin.clone()));
     code_dir.insert((clause_name!("string"), 1),
-                    (PredicateKeyType::BuiltIn, 376, builtin.clone()));
+                    (376, builtin.clone()));
     code_dir.insert((clause_name!("float"), 1),
-                    (PredicateKeyType::BuiltIn, 378, builtin.clone()));
+                    (378, builtin.clone()));
     code_dir.insert((clause_name!("nonvar"), 1),
-                    (PredicateKeyType::BuiltIn, 380, builtin.clone()));
+                    (380, builtin.clone()));
 
     code_dir.insert((clause_name!("ground"), 1),
-                    (PredicateKeyType::BuiltIn, 384, builtin.clone()));
+                    (384, builtin.clone()));
     code_dir.insert((clause_name!("=="), 2),
-                    (PredicateKeyType::BuiltIn, 385, builtin.clone()));
+                    (385, builtin.clone()));
     code_dir.insert((clause_name!("\\=="), 2),
-                    (PredicateKeyType::BuiltIn, 386, builtin.clone()));
+                    (386, builtin.clone()));
     code_dir.insert((clause_name!("@>="), 2),
-                    (PredicateKeyType::BuiltIn, 387, builtin.clone()));
+                    (387, builtin.clone()));
     code_dir.insert((clause_name!("@=<"), 2),
-                    (PredicateKeyType::BuiltIn, 388, builtin.clone()));
+                    (388, builtin.clone()));
     code_dir.insert((clause_name!("@>"), 2),
-                    (PredicateKeyType::BuiltIn, 389, builtin.clone()));
+                    (389, builtin.clone()));
     code_dir.insert((clause_name!("@<"), 2),
-                    (PredicateKeyType::BuiltIn, 390, builtin.clone()));
+                    (390, builtin.clone()));
     code_dir.insert((clause_name!("=@="), 2),
-                    (PredicateKeyType::BuiltIn, 391, builtin.clone()));
+                    (391, builtin.clone()));
     code_dir.insert((clause_name!("\\=@="), 2),
-                    (PredicateKeyType::BuiltIn, 392, builtin.clone()));
+                    (392, builtin.clone()));
     code_dir.insert((clause_name!("compare"), 3),
-                    (PredicateKeyType::BuiltIn, 464, builtin.clone()));
+                    (464, builtin.clone()));
 
     (code_dir, op_dir)
 }
index d5a42981d23e577cc06822f777c62a7452fca29d..32b94f88d1c448b1d8521628eafd9d2ac59597ca 100644 (file)
@@ -446,32 +446,45 @@ pub fn parse_code(wam: &Machine, buffer: &str) -> Result<TopLevelPacket, ParserE
     worker.parse_code(&wam.op_dir)
 }
 
-pub fn read() -> String {
-    let _ = stdout().flush();
+pub enum Input {
+    Quit,
+    Clear,
+    Line(String),
+    Batch(String)
+}
 
-    let mut buffer = String::new();
+fn read_lines(buffer: &mut String, end_delim: &str) -> String {
     let mut result = String::new();
-
     let stdin = stdin();
-    stdin.read_line(&mut buffer).unwrap();
-
-    if &*buffer.trim() == ":{" {
-        buffer.clear();
 
-        stdin.read_line(&mut buffer).unwrap();
+    buffer.clear();
+    stdin.read_line(buffer).unwrap();
 
-        while &*buffer.trim() != "}:" {
-            result += buffer.as_str();
-            buffer.clear();
-            stdin.read_line(&mut buffer).unwrap();
-        }
-    } else {
-        result = buffer;
+    while &*buffer.trim() != end_delim {
+        result += buffer.as_str();
+        buffer.clear();
+        stdin.read_line(buffer).unwrap();
     }
 
     result
 }
 
+pub fn read() -> Input {
+    let _ = stdout().flush();
+    let mut buffer = String::new();
+
+    let stdin = stdin();
+    stdin.read_line(&mut buffer).unwrap();
+
+    match &*buffer.trim() {
+        ":{"    => Input::Line(read_lines(&mut buffer, "}:")),
+        ":{{"   => Input::Batch(read_lines(&mut buffer, "}}:")),
+        "quit"  => Input::Quit,
+        "clear" => Input::Clear,
+        _       => Input::Line(buffer)
+    }
+}
+
 // throw errors if declaration or query found.
 fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
 {
@@ -533,7 +546,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
 {
     match tl {
         TopLevel::Declaration(Declaration::Op(op_decl)) => {
-            try_eval_session!(op_decl.submit(&mut wam.op_dir));
+            try_eval_session!(op_decl.submit(clause_name!("user"), &mut wam.op_dir));
             EvalSession::EntrySuccess
         },
         TopLevel::Declaration(Declaration::UseModule(name)) =>
@@ -585,8 +598,10 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
     let mut code = Vec::new();
 
     let mut worker = TopLevelWorker::new(src_str.as_bytes(), wam.atom_tbl());
-    let tls = try_eval_session!(worker.parse_batch(&mut op_dir));
+
     
+    let tls = try_eval_session!(worker.parse_batch(&mut op_dir));
+
     for tl in tls {
         match tl {
             TopLevelPacket::Query(..) =>
@@ -622,15 +637,14 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
                 try_eval_session!(compile_appendix(&mut decl_code, queue));
 
                 code.extend(decl_code.into_iter());
-                code_dir.insert((decl.name().unwrap(), decl.arity()),
-                                (PredicateKeyType::User, p, get_module_name(&module)));
+                code_dir.insert((decl.name().unwrap(), decl.arity()), (p, get_module_name(&module)));
             }
         }
     }
 
     if let Some(mut module) = module {
-        module.code_dir = code_dir;
-        module.op_dir = op_dir;
+        module.code_dir.extend(code_dir.into_iter());
+        module.op_dir.extend(op_dir.into_iter());
 
         wam.add_module(module, code);
     } else {
index d2e6bc065035bbf1f1785755b41faf3b7c3579d6..b52565aca3263882f5c518e9954da64f39048b9b 100644 (file)
@@ -37,7 +37,7 @@ impl<'a> CodeDirs<'a> {
                       -> Option<(usize, ClauseName)>
     {
         let code_dir = self.get_current_code_dir(p);        
-        code_dir.get(&(name, arity)).map(|idx| (idx.1, idx.2.clone()))
+        code_dir.get(&(name, arity)).cloned()
     }
 }
 
index 6377e17e17c1c737ee90dcab82caa537af6a1cd3..7afe46eac9aabe718ff436f627d88efa1323f059 100644 (file)
@@ -17,7 +17,7 @@ use std::rc::Rc;
 
 struct MachineCodeIndex<'a> {
     code_dir: &'a mut CodeDir,
-    op_dir: &'a mut OpDir
+    op_dir: &'a mut OpDir,
 }
 
 pub struct Machine {
@@ -54,7 +54,7 @@ impl<'a> SubModuleUser for MachineCodeIndex<'a> {
 
     fn code_dir(&mut self) -> &mut CodeDir {
         self.code_dir
-    }
+    }   
 }
 
 impl Machine {
@@ -73,7 +73,50 @@ impl Machine {
             cached_query: None
         }
     }
-
+    
+    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((_, ref mod_name)) if mod_name == &module_name => {
+                    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));
+                            }
+                        }
+                    }
+                },
+                _ => {}
+            };
+        }
+    }
+    
     pub fn failed(&self) -> bool {
         self.ms.fail
     }
@@ -83,10 +126,13 @@ impl Machine {
     }
 
     pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
+        self.remove_module(name.clone());
+        
         match self.modules.get(&name) {
             Some(ref module) => {
                 let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
                                                      op_dir: &mut self.op_dir };
+                                
                 indices.use_module(module)
             },
             None => EvalSession::from(EvalError::ModuleNotFound)
@@ -114,7 +160,7 @@ impl Machine {
     pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code) -> EvalSession
     {
         match self.code_dir.get(&(name.clone(), arity)) {
-            Some(&(PredicateKeyType::BuiltIn, _, _)) =>
+            Some(&(_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
                 return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}", name, arity))),
             _ => {}
         };
@@ -122,7 +168,7 @@ impl Machine {
         let offset = self.code.len();
 
         self.code.extend(code.into_iter());
-        self.code_dir.insert((name, arity), (PredicateKeyType::User, offset, clause_name!("user")));
+        self.code_dir.insert((name, arity), (offset, clause_name!("user")));
 
         EvalSession::EntrySuccess
     }
index efb52afa2cb121bf0f81ea381510baccf8359773..e95c45f411a278f6bacf2aca5ee2f1448fd1a915 160000 (submodule)
@@ -1 +1 @@
-Subproject commit efb52afa2cb121bf0f81ea381510baccf8359773
+Subproject commit e95c45f411a278f6bacf2aca5ee2f1448fd1a915