From: Mark Thom Date: Sun, 6 Jan 2019 07:15:32 +0000 (-0700) Subject: add dynamic module resolution calls X-Git-Tag: v0.8.110~299 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=c9f6ab984fc8ecae4e47d64b75e9c91dec4055ce;p=scryer-prolog.git add dynamic module resolution calls --- diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index fbfbd42e..9a84037c 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -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 { 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)] diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 2c90076b..4f35ac65 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -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, !. diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 8e3c157d..e7366ac0 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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; diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 5f855973..3da31e29 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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 { @@ -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"); diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index a4fab360..00c7dd72 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -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(()); diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index a1541515..55d8f82a 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -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) -> bool { found_cut_var } -fn module_resolution_call(mod_name: Term, body: Term) -> Result { - 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(); diff --git a/src/prolog/write.rs b/src/prolog/write.rs index edb390b0..956b221c 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -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) =>