make module code entries immutable (re: issue #27)
This commit is contained in:
@@ -139,6 +139,8 @@ pub type OpDirKey = (ClauseName, Fixity);
|
|||||||
// name and fixity -> operator type and precedence.
|
// name and fixity -> operator type and precedence.
|
||||||
pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
|
pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
|
||||||
|
|
||||||
|
pub type ModuleCodeDir = HashMap<PredicateKey, ModuleCodeIndex>;
|
||||||
|
|
||||||
pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
|
pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
|
||||||
|
|
||||||
pub type TermDir = HashMap<PredicateKey, Predicate>;
|
pub type TermDir = HashMap<PredicateKey, Predicate>;
|
||||||
@@ -152,68 +154,63 @@ pub struct ModuleDecl {
|
|||||||
|
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub module_decl: ModuleDecl,
|
pub module_decl: ModuleDecl,
|
||||||
pub code_dir: CodeDir,
|
pub code_dir: ModuleCodeDir,
|
||||||
pub op_dir: OpDir
|
pub op_dir: OpDir
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn new(module_decl: ModuleDecl) -> Self {
|
pub fn new(module_decl: ModuleDecl) -> Self {
|
||||||
Module { module_decl,
|
Module { module_decl,
|
||||||
code_dir: CodeDir::new(),
|
code_dir: ModuleCodeDir::new(),
|
||||||
op_dir: OpDir::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 {
|
impl SubModuleUser for Module {
|
||||||
fn op_dir(&mut self) -> &mut OpDir {
|
fn op_dir(&mut self) -> &mut OpDir {
|
||||||
&mut self.op_dir
|
&mut self.op_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code_dir(&mut self) -> &mut CodeDir {
|
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
|
||||||
&mut self.code_dir
|
self.code_dir.insert((name, arity), idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SubModuleUser {
|
pub trait SubModuleUser {
|
||||||
fn op_dir(&mut self) -> &mut OpDir;
|
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.
|
// returns true on successful import.
|
||||||
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
|
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
|
||||||
let name = name.defrock_brackets();
|
let name = name.defrock_brackets();
|
||||||
|
|
||||||
if arity == 1 {
|
{
|
||||||
if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Pre)) {
|
let mut insert_op_dir = |fix| {
|
||||||
self.op_dir().insert((name.clone(), Fixity::Pre), op_data.clone());
|
if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) {
|
||||||
}
|
self.op_dir().insert((name.clone(), fix), op_data.clone());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Post)) {
|
if arity == 1 {
|
||||||
self.op_dir().insert((name.clone(), Fixity::Post), op_data.clone());
|
insert_op_dir(Fixity::Pre);
|
||||||
|
insert_op_dir(Fixity::Post);
|
||||||
|
} else if arity == 2 {
|
||||||
|
insert_op_dir(Fixity::In);
|
||||||
}
|
}
|
||||||
} 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(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)) {
|
self.insert_dir_entry(name, arity, code_data.clone());
|
||||||
global_code_data.1 = code_data.1.clone();
|
true
|
||||||
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());
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_qualified_module(&mut self, submodule: &Module, exports: Vec<PredicateKey>) -> EvalSession
|
fn use_qualified_module(&mut self, submodule: &Module, exports: Vec<PredicateKey>) -> EvalSession
|
||||||
@@ -1397,6 +1394,15 @@ pub enum IndexPtr {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CodeIndex(pub Rc<Cell<IndexPtr>>, pub ClauseName);
|
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 {
|
impl Default for CodeIndex {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)), clause_name!(""))
|
CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)), clause_name!(""))
|
||||||
|
|||||||
@@ -832,5 +832,5 @@ pub fn builtin_module() -> Module
|
|||||||
module_decl.exports.push((clause_name!("call"), arity));
|
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 }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -689,7 +689,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut module) = module {
|
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());
|
module.op_dir.extend(op_dir.into_iter());
|
||||||
|
|
||||||
wam.add_module(module, code);
|
wam.add_module(module, code);
|
||||||
|
|||||||
@@ -24,19 +24,17 @@ impl<'a> CodeDirs<'a> {
|
|||||||
CodeDirs { code_dir, modules }
|
CodeDirs { code_dir, modules }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_code_dir(&self, p: &CodePtr) -> &CodeDir {
|
pub(super) fn get(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
|
||||||
let module_name = p.module_name();
|
{
|
||||||
|
match in_mod.as_str() {
|
||||||
match module_name {
|
"user" | "builtin" => self.code_dir.get(&(name, arity)).cloned(),
|
||||||
ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") => self.code_dir,
|
_ => match self.modules.get(&in_mod) {
|
||||||
_ => &self.modules.get(&module_name).unwrap().code_dir
|
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> {
|
pub(super) struct DuplicateTerm<'a> {
|
||||||
@@ -428,7 +426,8 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
},
|
},
|
||||||
&ClauseType::CallN =>
|
&ClauseType::CallN =>
|
||||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
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)
|
self.context_call(machine_st, name, arity, idx, lco)
|
||||||
} else {
|
} else {
|
||||||
Err(predicate_existence_error(name, arity, machine_st.heap.h))
|
Err(predicate_existence_error(name, arity, machine_st.heap.h))
|
||||||
|
|||||||
@@ -909,7 +909,7 @@ impl MachineState {
|
|||||||
self.registers[arity - 1] = pred;
|
self.registers[arity - 1] = pred;
|
||||||
|
|
||||||
if let Some((name, arity)) = self.setup_call_n(arity - 1) {
|
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));
|
try_or_fail!(self, call_policy.try_execute(self, name, arity, idx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,17 @@ impl<'a> SubModuleUser for MachineCodeIndex<'a> {
|
|||||||
self.op_dir
|
self.op_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code_dir(&mut self) -> &mut CodeDir {
|
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
|
||||||
self.code_dir
|
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());
|
self.remove_module(name.clone());
|
||||||
|
|
||||||
match self.modules.get(&name) {
|
match self.modules.get_mut(&name) {
|
||||||
Some(ref module) => {
|
Some(ref mut module) => {
|
||||||
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
|
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
|
||||||
op_dir: &mut self.op_dir };
|
op_dir: &mut self.op_dir };
|
||||||
|
|
||||||
@@ -146,8 +155,8 @@ impl Machine {
|
|||||||
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
|
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
|
||||||
self.remove_module(name.clone());
|
self.remove_module(name.clone());
|
||||||
|
|
||||||
match self.modules.get(&name) {
|
match self.modules.get_mut(&name) {
|
||||||
Some(ref module) => {
|
Some(ref mut module) => {
|
||||||
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
|
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
|
||||||
op_dir: &mut self.op_dir };
|
op_dir: &mut self.op_dir };
|
||||||
|
|
||||||
|
|||||||
Submodule src/prolog/parser updated: 0e9dd3a01f...1b3bcc77f2
Reference in New Issue
Block a user