]> Repositorios git - scryer-prolog.git/commitdiff
add dynamic module resolution calls
authorMark Thom <[email protected]>
Sun, 6 Jan 2019 07:15:32 +0000 (00:15 -0700)
committerMark Thom <[email protected]>
Sun, 6 Jan 2019 07:15:32 +0000 (00:15 -0700)
src/prolog/instructions.rs
src/prolog/lib/builtins.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs
src/prolog/toplevel.rs
src/prolog/write.rs

index fbfbd42ead09db473a43ea7c4eb217118edd6a60..9a84037c68e60a1b2502a1db236632d062a3d9c3 100644 (file)
@@ -238,6 +238,7 @@ pub struct Module {
 #[derive(Copy, Clone, PartialEq)]
 pub enum SystemClauseType {
     CheckCutPoint,
+    DynamicModuleResolution,
     ExpandGoal,
     ExpandTerm,
     GetBValue,
@@ -276,6 +277,7 @@ impl SystemClauseType {
     pub fn name(&self) -> ClauseName {
         match self {
             &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
+            &SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
             &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
             &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
             &SystemClauseType::GetBValue => clause_name!("$get_b_value"),
@@ -313,6 +315,7 @@ impl SystemClauseType {
     pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
         match (name, arity) {
             ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
+            ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
             ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
             ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
             ("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
@@ -857,8 +860,6 @@ impl HeapCellValue {
 pub enum IndexPtr {
     Undefined,
     Index(usize),
-    Module /* This is a resolved module call. The module
-        targeted is in the wrapping CodeIndex, and the name is in the ClauseType. */
 }
 
 #[derive(Clone)]
index 2c90076b3241c68afbf560372337f179ef1b6a4c..4f35ac657bcf03f985903bfd8e4c38a6f4f56157 100644 (file)
@@ -60,6 +60,13 @@ true.
 
 false :- '$fail'.
 
+% dynamic module resolution.
+
+Module : Predicate :-
+    ( atom(Module) -> '$module_call'(Module, Predicate)
+    ; throw(error(type_error(atom, Module), (:)))
+    ).
+
 % flags.
 
 current_prolog_flag(Flag, false) :- Flag == bounded, !.
index 8e3c157d27733d919538bbb2f3dbd16d9e9e5294..e7366ac0a838d91f73f3571341558201a9435535 100644 (file)
@@ -224,19 +224,48 @@ pub struct MachineState {
     pub(crate) flags: MachineFlags
 }
 
-fn call_at_index(machine_st: &mut MachineState, arity: usize, p: usize)
-{
-    machine_st.cp.assign_if_local(machine_st.p.clone() + 1);
-    machine_st.num_of_args = arity;
-    machine_st.b0 = machine_st.b;
-    machine_st.p  = dir_entry!(p);
-}
+impl MachineState {
+    fn call_at_index(&mut self, arity: usize, p: usize)
+    {
+        self.cp.assign_if_local(self.p.clone() + 1);
+        self.num_of_args = arity;
+        self.b0 = self.b;
+        self.p  = dir_entry!(p);
+    }
 
-fn execute_at_index(machine_st: &mut MachineState, arity: usize, p: usize)
-{
-    machine_st.num_of_args = arity;
-    machine_st.b0 = machine_st.b;
-    machine_st.p  = dir_entry!(p);
+    fn execute_at_index(&mut self, arity: usize, p: usize)
+    {
+        self.num_of_args = arity;
+        self.b0 = self.b;
+        self.p  = dir_entry!(p);
+    }
+
+    pub(super)
+    fn module_lookup(&mut self, indices: &IndexStore, key: PredicateKey, module_name: ClauseName,
+                     last_call: bool)
+                     -> CallResult
+    {
+        let (name, arity) = key;        
+        
+        if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
+        {
+            if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
+                if last_call {
+                    self.execute_at_index(arity, compiled_tl_index);
+                } else {
+                    self.call_at_index(arity, compiled_tl_index);
+                }
+                
+                return Ok(());
+            }
+        }
+
+        let h = self.heap.h;
+        let stub = MachineError::functor_stub(name.clone(), arity);        
+        let err = MachineError::module_resolution_error(h, module_name, name, arity);        
+        
+        return Err(self.error_form(err, stub));
+    }
 }
 
 fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore)
@@ -261,9 +290,9 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
 {
     if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
         if last_call {
-            execute_at_index(machine_st, arity, p);
+            machine_st.execute_at_index(arity, p);
         } else {
-            call_at_index(machine_st, arity, p);
+            machine_st.call_at_index(arity, p);
         }
 
         machine_st.p = in_situ_dir_entry!(p);
@@ -451,26 +480,10 @@ pub(crate) trait CallPolicy: Any {
                 -> CallResult
     {
         match idx.0.borrow().0 {
-            IndexPtr::Module => {
-                let stub = MachineError::functor_stub(name.clone(), arity);
-                let module_name = idx.0.borrow().1.clone();
-                let h = machine_st.heap.h;
-
-                if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
-                {
-                    if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
-                        call_at_index(machine_st, arity, compiled_tl_index);
-                        return Ok(());
-                    }
-                }
-
-                let err = MachineError::module_resolution_error(h, module_name, name, arity);
-                return Err(machine_st.error_form(err, stub));
-            },
             IndexPtr::Undefined =>
                 return try_in_situ(machine_st, name, arity, indices, false),
             IndexPtr::Index(compiled_tl_index) =>
-                call_at_index(machine_st, arity, compiled_tl_index)
+                machine_st.call_at_index(arity, compiled_tl_index)
         }
 
         Ok(())
@@ -481,26 +494,10 @@ pub(crate) trait CallPolicy: Any {
                    -> CallResult
     {
         match idx.0.borrow().0 {
-            IndexPtr::Module => {
-                let stub = MachineError::functor_stub(name.clone(), arity);
-                let module_name = idx.0.borrow().1.clone();
-                let h = machine_st.heap.h;
-
-                if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
-                {
-                    if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
-                        execute_at_index(machine_st, arity, compiled_tl_index);
-                        return Ok(());
-                    }
-                }
-
-                let err = MachineError::module_resolution_error(h, module_name, name, arity);
-                return Err(machine_st.error_form(err, stub));
-            },
             IndexPtr::Undefined =>
                 return try_in_situ(machine_st, name, arity, indices, true),
             IndexPtr::Index(compiled_tl_index) =>
-                execute_at_index(machine_st, arity, compiled_tl_index)
+                machine_st.execute_at_index(arity, compiled_tl_index)
         }
 
         Ok(())
@@ -923,9 +920,9 @@ impl SCCCutPolicy {
                 };
 
                 if machine_st.last_call {
-                    execute_at_index(machine_st, arity, idx);
+                    machine_st.execute_at_index(arity, idx);
                 } else {
-                    call_at_index(machine_st, arity, idx);
+                    machine_st.call_at_index(arity, idx);
                 }
 
                 return true;
index 5f8559735caa30f525084449e7b2540e8a258349..3da31e29af4aa29eebefa119549e7583b67a7617 100644 (file)
@@ -79,6 +79,7 @@ impl IndexStore {
         mem::swap(&mut self.modules, &mut other.modules);
     }
 
+    #[inline]
     fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName)
                     -> Option<ModuleCodeIndex>
     {
@@ -86,7 +87,7 @@ impl IndexStore {
             .and_then(|ref module| module.code_dir.get(&(name, arity)))
             .cloned()
     }
-
+    
     pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
         let r_w_h  = clause_name!("run_cleaners_with_handling");
         let r_wo_h = clause_name!("run_cleaners_without_handling");
index a4fab360aa9cc3cd060d1f1555967c192d52d6fe..00c7dd722730795e5d482f68a6a362e034473f06 100644 (file)
@@ -203,6 +203,32 @@ impl MachineState {
                     _ => self.fail = true
                 };
             },
+            &SystemClauseType::DynamicModuleResolution => {
+                let module_name = self.store(self.deref(self[temp_v!(1)].clone()));
+
+                if let Addr::Con(Constant::Atom(module_name, _)) = module_name {
+                    match self.store(self.deref(self[temp_v!(2)].clone())) {
+                        Addr::Str(a) =>
+                            if let HeapCellValue::NamedStr(arity, name, _) = self.heap[a].clone() {
+                                for i in 1 .. arity + 1 {
+                                    self.registers[i] = self.heap[a+i].as_addr(a+i);
+                                }
+                                
+                                return self.module_lookup(indices, (name, arity), module_name, true);
+                            },
+                        Addr::Con(Constant::Atom(name, _)) =>
+                            return self.module_lookup(indices, (name, 0), module_name, true),
+                        addr => {
+                            let stub = MachineError::functor_stub(clause_name!("(:)"), 2);
+                            
+                            let type_error = MachineError::type_error(ValidType::Callable, addr);
+                            let type_error = self.error_form(type_error, stub);
+
+                            return Err(type_error);
+                        }
+                    }
+                };
+            },
             &SystemClauseType::ExpandGoal => {
                 self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
                 return Ok(());
index a1541515736ad76d1236c62fff26b793216755b5..55d8f82a7bb5ba3b55879d3a9c9f29ea77875220 100644 (file)
@@ -10,7 +10,7 @@ use prolog::num::*;
 
 use std::borrow::BorrowMut;
 use std::collections::{HashSet, VecDeque};
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
 use std::io::Read;
 use std::mem;
 use std::rc::Rc;
@@ -355,18 +355,6 @@ fn mark_cut_variables(terms: &mut Vec<Term>) -> bool {
     found_cut_var
 }
 
-fn module_resolution_call(mod_name: Term, body: Term) -> Result<QueryTerm, ParserError> {
-    if let Term::Constant(_, Constant::Atom(mod_name, _)) = mod_name {
-        if let Term::Clause(_, name, terms, _) = body {
-            let idx = CodeIndex(Rc::new(RefCell::new((IndexPtr::Module, mod_name))));
-            return Ok(QueryTerm::Clause(Cell::default(), ClauseType::Named(name, idx), terms,
-                                        false));
-        }
-    }
-
-    Err(ParserError::InvalidModuleResolution)
-}
-
 fn flatten_hook(mut term: Term) -> Term {
     if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
         match (name.as_str(), terms.len()) {
@@ -517,12 +505,6 @@ impl RelationWorker {
                         self.queue.push_back(clauses);
                         Ok(QueryTerm::Jump(stub))
                     },
-                    (":", 2) => {
-                        let callee   = *terms.pop().unwrap();
-                        let mod_name = *terms.pop().unwrap();
-
-                        module_resolution_call(mod_name, callee)
-                    },
                     ("->", 2) => {
                         let conq = *terms.pop().unwrap();
                         let prec = *terms.pop().unwrap();
index edb390b0b43151caf144af19a90f8f4770eb7a38..956b221c306a3a40403eea3703f1a6b5685a8cec 100644 (file)
@@ -16,8 +16,6 @@ fn error_string(e: &String) -> String {
 impl fmt::Display for IndexPtr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            &IndexPtr::Module =>
-                write!(f, ""),
             &IndexPtr::Undefined =>
                 write!(f, "undefined"),
             &IndexPtr::Index(i)  =>