]> Repositorios git - scryer-prolog.git/commitdiff
make module code entries immutable (re: issue #27)
authorMark Thom <[email protected]>
Thu, 19 Apr 2018 01:24:32 +0000 (19:24 -0600)
committerMark Thom <[email protected]>
Thu, 19 Apr 2018 01:24:32 +0000 (19:24 -0600)
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/io.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/parser

index bee150641f1ccf9e93249f79a5e10ba8340a08a0..47edbdcba476bbce05ffada49d66626d88180685 100644 (file)
@@ -139,6 +139,8 @@ pub type OpDirKey = (ClauseName, Fixity);
 // name and fixity -> operator type and precedence.
 pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
 
+pub type ModuleCodeDir = HashMap<PredicateKey, ModuleCodeIndex>;
+
 pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
 
 pub type TermDir = HashMap<PredicateKey, Predicate>;
@@ -152,68 +154,63 @@ pub struct ModuleDecl {
 
 pub struct Module {
     pub module_decl: ModuleDecl,
-    pub code_dir: CodeDir,
+    pub code_dir: ModuleCodeDir,
     pub op_dir: OpDir
 }
 
 impl Module {
     pub fn new(module_decl: ModuleDecl) -> Self {
         Module { module_decl,
-                 code_dir: CodeDir::new(),
+                 code_dir: ModuleCodeDir::new(),
                  op_dir: OpDir::new() }
     }
 }
 
+pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir {
+    code_dir.into_iter()
+        .map(|(k, code_idx)| (k, ModuleCodeIndex(code_idx.0.get(), code_idx.1)))        
+        .collect()        
+}
+
 impl SubModuleUser for Module {
     fn op_dir(&mut self) -> &mut OpDir {
         &mut self.op_dir
     }
 
-    fn code_dir(&mut self) -> &mut CodeDir {
-        &mut self.code_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 code_dir(&mut self) -> &mut CodeDir;
+    fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex);
 
     // returns true on successful import.
     fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
         let name = name.defrock_brackets();
-
-        if arity == 1 {
-            if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Pre)) {
-                self.op_dir().insert((name.clone(), Fixity::Pre), op_data.clone());
-            }
-
-            if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Post)) {
-                self.op_dir().insert((name.clone(), Fixity::Post), op_data.clone());
-            }
-        } else if arity == 2 {
-            if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::In)) {
-                self.op_dir().insert((name.clone(), Fixity::In), op_data.clone());
+        
+        {
+            let mut insert_op_dir = |fix| {
+                if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) {
+                    self.op_dir().insert((name.clone(), fix), op_data.clone());
+                }
+            };
+            
+            if arity == 1 {
+                insert_op_dir(Fixity::Pre);
+                insert_op_dir(Fixity::Post);
+            } else if arity == 2 {
+                insert_op_dir(Fixity::In);
             }
         }
-
-        if self.code_dir().contains_key(&(name.clone(), arity)) {
-            println!("warning: overwriting {}/{}", &name, arity);
-        }
-
+        
         if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
-            if let Some(ref mut global_code_data) = self.code_dir().get_mut(&(name.clone(), arity)) {
-                global_code_data.1 = code_data.1.clone();
-                global_code_data.0.set(code_data.0.get());
-
-                return true; // done to appease the borrow checker.
-            }
-
-            self.code_dir().insert((name, arity), code_data.clone());
+            self.insert_dir_entry(name, arity, code_data.clone());
+            true
         } else {
-            return false;
+            false
         }
-
-        true
     }
 
     fn use_qualified_module(&mut self, submodule: &Module, exports: Vec<PredicateKey>) -> EvalSession
@@ -1397,6 +1394,15 @@ pub enum IndexPtr {
 #[derive(Clone)]
 pub struct CodeIndex(pub Rc<Cell<IndexPtr>>, pub ClauseName);
 
+#[derive(Clone)]
+pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName);
+
+impl From<ModuleCodeIndex> for CodeIndex {
+    fn from(value: ModuleCodeIndex) -> Self {
+        CodeIndex(Rc::new(Cell::new(value.0)), value.1.clone())
+    }
+}
+
 impl Default for CodeIndex {
     fn default() -> Self {
         CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)), clause_name!(""))
index 71d4c7e3ec7e299b3ca5d7d633348aac87d57049..bb88d6bf8d549b4074f028176a19f1d96172975c 100644 (file)
@@ -832,5 +832,5 @@ pub fn builtin_module() -> Module
         module_decl.exports.push((clause_name!("call"), arity));
     }
 
-    Module { module_decl, code_dir, op_dir }
+    Module { module_decl, code_dir: as_module_code_dir(code_dir), op_dir }
 }
index 1b005bd349b00f11c6c54b91b5abe37e43f7966b..9259054fd1f91a7d7cac102b294745709ab44d90 100644 (file)
@@ -642,7 +642,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
                 } else {
                     return EvalSession::from(EvalError::ModuleNotFound);
                 }
-
+                
                 wam.use_module_in_toplevel(name);
             },
             TopLevelPacket::Decl(TopLevel::Declaration(Declaration::UseQualifiedModule(name, exports)), _) => {
@@ -689,7 +689,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
     }
 
     if let Some(mut module) = module {
-        module.code_dir.extend(code_dir.into_iter());
+        module.code_dir.extend(as_module_code_dir(code_dir));
         module.op_dir.extend(op_dir.into_iter());
 
         wam.add_module(module, code);
index c76edba2a6e3a5c025e29dd48724c653460ef2f2..81cff9c9dbc662a444672b9a5064e7c3409e5d5c 100644 (file)
@@ -24,19 +24,17 @@ impl<'a> CodeDirs<'a> {
         CodeDirs { code_dir, modules }
     }
 
-    fn get_current_code_dir(&self, p: &CodePtr) -> &CodeDir {
-        let module_name = p.module_name();
-
-        match module_name {
-            ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") => self.code_dir,
-            _ => &self.modules.get(&module_name).unwrap().code_dir
+    pub(super) fn get(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
+    {
+        match in_mod.as_str() {
+            "user" | "builtin" => self.code_dir.get(&(name, arity)).cloned(),
+            _ => match self.modules.get(&in_mod) {
+                Some(&Module { ref code_dir, .. }) =>
+                    code_dir.get(&(name, arity)).cloned().map(CodeIndex::from),
+                None => None
+            }
         }
     }
-
-    pub(super) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr) -> Option<CodeIndex> {
-        let code_dir = self.get_current_code_dir(p);
-        code_dir.get(&(name, arity)).cloned()
-    }
 }
 
 pub(super) struct DuplicateTerm<'a> {
@@ -428,7 +426,8 @@ pub(crate) trait CallPolicy: Any {
             },
             &ClauseType::CallN =>
                 if let Some((name, arity)) = machine_st.setup_call_n(arity) {
-                    if let Some(idx) = code_dirs.get(name.clone(), arity, &machine_st.p.clone()) {
+                    if let Some(idx) = code_dirs.get(name.clone(), arity, machine_st.p.module_name())
+                    {
                         self.context_call(machine_st, name, arity, idx, lco)
                     } else {
                         Err(predicate_existence_error(name, arity, machine_st.heap.h))
index 3d893e87350520305e77c0eae10559492c18d370..6d1b33f04a2138c04668d77f28c0e7e2d2455ca5 100644 (file)
@@ -909,7 +909,7 @@ impl MachineState {
             self.registers[arity - 1] = pred;
 
             if let Some((name, arity)) = self.setup_call_n(arity - 1) {
-                if let Some(idx) = code_dirs.get(name.clone(), arity, &self.p.clone()) {
+                if let Some(idx) = code_dirs.get(name.clone(), arity, self.p.module_name()) {
                     try_or_fail!(self, call_policy.try_execute(self, name, arity, idx));
                     return;
                 }
index 10ed207472f191e362f19b73556a82a6d4d631ab..8c4b977e4ac42b602f380f83d534c1782823ceb3 100644 (file)
@@ -53,8 +53,17 @@ impl<'a> SubModuleUser for MachineCodeIndex<'a> {
         self.op_dir
     }
 
-    fn code_dir(&mut self) -> &mut CodeDir {
-        self.code_dir
+    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)) {
+            println!("warning: overwriting {}/{}", &name, arity);
+            
+            code_idx.0.set(idx.0);
+            code_idx.1 = idx.1;
+
+            return;
+        }
+        
+        self.code_dir.insert((name, arity), CodeIndex::from(idx));
     }
 }
 
@@ -132,8 +141,8 @@ impl Machine {
     {
         self.remove_module(name.clone());
 
-        match self.modules.get(&name) {
-            Some(ref module) => {
+        match self.modules.get_mut(&name) {
+            Some(ref mut module) => {
                 let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
                                                      op_dir: &mut self.op_dir };
 
@@ -146,8 +155,8 @@ 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) => {
+        match self.modules.get_mut(&name) {
+            Some(ref mut module) => {
                 let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
                                                      op_dir: &mut self.op_dir };
 
@@ -196,7 +205,7 @@ impl Machine {
 
         entry.0.set(IndexPtr::Index(offset));
         entry.1 = clause_name!("user");
-        
+
         EvalSession::EntrySuccess
     }
 
@@ -312,8 +321,8 @@ impl Machine {
                     let e = self.ms.e;
                     let r = var_data.as_reg_type().reg_num();
                     let addr = self.ms.and_stack[e][r].clone();
-                    
-                    heap_locs.insert(var.clone(), addr);                    
+
+                    heap_locs.insert(var.clone(), addr);
                 },
                 &VarData::Temp(cn, _, _) if cn == chunk_num => {
                     let r = var_data.as_reg_type();
index 0e9dd3a01f21c6457bd1bcb35518ccdb502c82bd..1b3bcc77f2b9d264c9753653ae87bfa3b4c11081 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0e9dd3a01f21c6457bd1bcb35518ccdb502c82bd
+Subproject commit 1b3bcc77f2b9d264c9753653ae87bfa3b4c11081