From 516c66a47d65e89bff4a7fadbb7a46b0bad783d8 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 2 Oct 2019 22:01:32 -0600 Subject: [PATCH] properly handle undefined predicates declared dynamic --- src/prolog/machine/compile.rs | 44 +++++++++++++++++--------- src/prolog/machine/dynamic_database.rs | 14 ++------ src/prolog/machine/machine_indices.rs | 16 +++++++--- src/prolog/machine/machine_state.rs | 31 ++++++++++++------ src/prolog/machine/modules.rs | 3 +- src/prolog/write.rs | 1 + 6 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 079f7c12..58cbcfc5 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -325,13 +325,13 @@ fn compile_into_module_impl( let module_code = compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)?; - let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len()); - clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam)?; + let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len(), module_name.clone()); + clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?; update_module_indices(wam, module_name, indices); wam.code_repo.code.extend(module_code.into_iter()); - clause_code_generator.add_clause_code(wam); + clause_code_generator.add_clause_code(wam, results.dynamic_clause_map); Ok(compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo)) } @@ -347,22 +347,24 @@ pub struct GatherResult { pub struct ClauseCodeGenerator { len_offset: usize, code: Code, + module_name: ClauseName, pi_to_loc: IndexMap, } impl ClauseCodeGenerator { #[inline] - fn new(len_offset: usize) -> Self { + fn new(len_offset: usize, module_name: ClauseName) -> Self { ClauseCodeGenerator { len_offset, code: vec![], + module_name, pi_to_loc: IndexMap::new(), } } fn generate_clause_code( &mut self, - dynamic_clause_map: DynamicClauseMap, + dynamic_clause_map: &DynamicClauseMap, wam: &Machine, ) -> Result<(), SessionError> { for ((name, arity), heads_and_tails) in dynamic_clause_map { @@ -372,12 +374,12 @@ impl ClauseCodeGenerator { let predicate = Predicate( heads_and_tails - .into_iter() + .iter() .map(|(head, tail)| { let clause = Term::Clause( Cell::default(), clause_name!("clause"), - vec![Box::new(head), Box::new(tail)], + vec![Box::new(head.clone()), Box::new(tail.clone())], None, ); PredicateClause::Fact(clause) @@ -391,16 +393,24 @@ impl ClauseCodeGenerator { compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?; - self.pi_to_loc.insert((name, arity), p); + self.pi_to_loc.insert((name.clone(), *arity), p); self.code.extend(decl_code.into_iter()); } Ok(()) } - fn add_clause_code(self, wam: &mut Machine) { + fn add_clause_code(self, wam: &mut Machine, dynamic_code_dir: DynamicClauseMap) + { wam.code_repo.code.extend(self.code.into_iter()); + for ((name, arity), _) in dynamic_code_dir { + wam.indices.dynamic_code_dir.insert((name.owning_module(), name.clone(), arity), + DynamicPredicateInfo::default()); + wam.indices.code_dir.entry((name, arity)) + .or_insert(CodeIndex::dynamic_undefined(self.module_name.clone())); + } + for ((name, arity), p) in self.pi_to_loc { let entry = wam .indices @@ -457,11 +467,11 @@ fn add_non_module_code( ) -> Result<(), SessionError> { wam.check_toplevel_code(&indices)?; - let mut clause_code_generator = ClauseCodeGenerator::new(code.len()); - clause_code_generator.generate_clause_code(dynamic_clause_map, wam)?; + let mut clause_code_generator = ClauseCodeGenerator::new(code.len(), clause_name!("user")); + clause_code_generator.generate_clause_code(&dynamic_clause_map, wam)?; add_toplevel_code(wam, code, indices); - clause_code_generator.add_clause_code(wam); + clause_code_generator.add_clause_code(wam, dynamic_clause_map); Ok(()) } @@ -818,6 +828,9 @@ impl ListingCompiler { .dynamic_clause_map .entry((name.clone(), arity)) .or_insert(vec![]); + + indices.code_dir.insert((name.clone(), arity), + CodeIndex::dynamic_undefined(self.get_module_name())); } &Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker .term_stream @@ -929,17 +942,18 @@ fn compile_work_impl( if let Some(module) = compiler.module.take() { let mut clause_code_generator = - ClauseCodeGenerator::new(module_code.len() + toplvl_code.len()); + ClauseCodeGenerator::new(module_code.len() + toplvl_code.len(), + module.module_decl.name.clone()); try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices)); try_eval_session!( - clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam) + clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam) ); add_module_code(wam, module, module_code, indices); add_toplevel_code(wam, toplvl_code, results.toplevel_indices); - clause_code_generator.add_clause_code(wam); + clause_code_generator.add_clause_code(wam, results.dynamic_clause_map); } else { try_eval_session!(add_non_module_code( wam, diff --git a/src/prolog/machine/dynamic_database.rs b/src/prolog/machine/dynamic_database.rs index 361ab1e6..b9ea7457 100644 --- a/src/prolog/machine/dynamic_database.rs +++ b/src/prolog/machine/dynamic_database.rs @@ -78,7 +78,7 @@ impl Machine { let (name, arity) = self.get_predicate_key(name, arity); if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) { - set_code_index!(idx, IndexPtr::Undefined, clause_name!("user")); + set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user")); } self.indices.remove_code_index((name.clone(), arity)); @@ -106,7 +106,7 @@ impl Machine { if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) { if idx.module_name() == module_name { - set_code_index!(idx, IndexPtr::Undefined, clause_name!("user")); + set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user")); } } @@ -208,11 +208,6 @@ impl Machine { let mut addrs = VecDeque::from(addrs); addrs.remove(index); - if addrs.is_empty() { - self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(5)); - return; - } - self.print_new_dynamic_clause(addrs, name.clone(), arity) } Err(err) => return self.machine_st.throw_exception(err), @@ -242,11 +237,6 @@ impl Machine { let mut addrs = VecDeque::from(addrs); addrs.remove(index); - if addrs.is_empty() { - self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)); - return; - } - self.print_new_dynamic_clause(addrs, name.clone(), arity) } Err(err) => return self.machine_st.throw_exception(err), diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index efdfa7a9..e311a50d 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -206,6 +206,7 @@ impl HeapCellValue { #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] pub enum IndexPtr { + DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined. Undefined, Index(usize), } @@ -218,13 +219,20 @@ impl CodeIndex { pub fn is_undefined(&self) -> bool { let index_ptr = &self.0.borrow().0; - if let &IndexPtr::Undefined = index_ptr { - true - } else { - false + match index_ptr { + &IndexPtr::Undefined | &IndexPtr::DynamicUndefined => true, + _ => false } } + #[inline] + pub fn dynamic_undefined(module_name: ClauseName) -> Self { + CodeIndex(Rc::new(RefCell::new(( + IndexPtr::DynamicUndefined, + module_name + )))) + } + #[inline] pub fn module_name(&self) -> ClauseName { self.0.borrow().1.clone() diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index d5f96d70..a6e1da20 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -325,14 +325,21 @@ impl MachineState { 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); - } + match idx.0.borrow().0 { + IndexPtr::Index(compiled_tl_index) => { + if last_call { + self.execute_at_index(arity, compiled_tl_index); + } else { + self.call_at_index(arity, compiled_tl_index); + } - return Ok(()); + return Ok(()); + } + IndexPtr::DynamicUndefined => { + self.fail = true; + return Ok(()); + } + _ => {} } } @@ -586,7 +593,10 @@ pub(crate) trait CallPolicy: Any { indices: &IndexStore, ) -> CallResult { match idx.0.borrow().0 { - IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, false), + IndexPtr::DynamicUndefined => + machine_st.fail = true, + IndexPtr::Undefined => + return try_in_situ(machine_st, name, arity, indices, false), IndexPtr::Index(compiled_tl_index) => { machine_st.call_at_index(arity, compiled_tl_index) } @@ -604,7 +614,10 @@ pub(crate) trait CallPolicy: Any { indices: &IndexStore, ) -> CallResult { match idx.0.borrow().0 { - IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, true), + IndexPtr::DynamicUndefined => + machine_st.fail = true, + IndexPtr::Undefined => + return try_in_situ(machine_st, name, arity, indices, true), IndexPtr::Index(compiled_tl_index) => { machine_st.execute_at_index(arity, compiled_tl_index) } diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs index c4e26449..b266bd65 100644 --- a/src/prolog/machine/modules.rs +++ b/src/prolog/machine/modules.rs @@ -10,7 +10,8 @@ use std::collections::VecDeque; // Module's and related types are defined in forms. impl Module { - pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData) -> Self { + pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData) -> Self + { Module { module_decl, atom_tbl, diff --git a/src/prolog/write.rs b/src/prolog/write.rs index e9f40996..a4d6706c 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -48,6 +48,7 @@ impl fmt::Display for REPLCodePtr { impl fmt::Display for IndexPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + &IndexPtr::DynamicUndefined => write!(f, "undefined"), &IndexPtr::Undefined => write!(f, "undefined"), &IndexPtr::Index(i) => write!(f, "{}", i), } -- 2.54.0