]> Repositorios git - scryer-prolog.git/commitdiff
properly handle undefined predicates declared dynamic
authorMark Thom <[email protected]>
Thu, 3 Oct 2019 04:01:32 +0000 (22:01 -0600)
committerMark Thom <[email protected]>
Thu, 3 Oct 2019 04:01:32 +0000 (22:01 -0600)
src/prolog/machine/compile.rs
src/prolog/machine/dynamic_database.rs
src/prolog/machine/machine_indices.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/modules.rs
src/prolog/write.rs

index 079f7c12502daf6baa080423ae4ad1b882c1900d..58cbcfc593f1030adc2c9071069b1666338ac5af 100644 (file)
@@ -325,13 +325,13 @@ fn compile_into_module_impl<R: Read>(
     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<PredicateKey, usize>,
 }
 
 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((namearity), 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,
index 361ab1e6b200915ffcaa7569ab97b0ae019d1f37..b9ea7457b76baf30c38d28ef80373548d14e347d 100644 (file)
@@ -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),
index efdfa7a912a74705e8bc119e4bff5437ce3459dd..e311a50de1b520654a37bcade86c0eba370f9730 100644 (file)
@@ -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()
index d5f96d70a47260200292ce5b751c526ea765af46..a6e1da203721e5223ccfe5165f0d1561294bf329 100644 (file)
@@ -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)
             }
index c4e26449c21598736344de44eb9d5189a37698d0..b266bd656bdb83826cf723fdfbbc1aeaa4c4baab 100644 (file)
@@ -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<Atom>) -> Self {
+    pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self
+    {
         Module {
             module_decl,
             atom_tbl,
index e9f40996ec10f24d9ed25a06c8624cb233aa40e6..a4d6706c279219d7e3478145b05a6ee86f825e04 100644 (file)
@@ -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),
         }