]> Repositorios git - scryer-prolog.git/commitdiff
add preliminary multifile declaration support
authorMark Thom <[email protected]>
Mon, 27 Jan 2020 03:17:52 +0000 (20:17 -0700)
committerMark Thom <[email protected]>
Mon, 27 Jan 2020 03:17:52 +0000 (20:17 -0700)
src/prolog/forms.rs
src/prolog/lib/builtins.pl
src/prolog/machine/compile.rs
src/prolog/machine/dynamic_database.rs
src/prolog/machine/modules.rs
src/prolog/machine/toplevel.rs

index e60e1b4a8c4ed0546b6235484420996bbd2d3127..d0c02028886db95c05868aaeb779b267a2a2f270 100644 (file)
@@ -203,6 +203,7 @@ pub enum Declaration {
     Hook(CompileTimeHook, PredicateClause, VecDeque<TopLevel>),
     ModuleInitialization(Vec<QueryTerm>, VecDeque<TopLevel>), // goal
     Module(ModuleDecl),
+    MultiFile(ClauseName, usize),
     NonCountedBacktracking(ClauseName, usize), // name, arity
     Op(OpDecl),
     UseModule(ModuleSource),
@@ -371,6 +372,7 @@ pub struct Module {
     pub module_decl: ModuleDecl,
     pub code_dir: CodeDir,
     pub op_dir: OpDir,
+    pub term_dir: TermDir, // this contains multifile predicates.
     pub term_expansions: (Predicate, VecDeque<TopLevel>),
     pub goal_expansions: (Predicate, VecDeque<TopLevel>),
     pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope.
index d6e524dc1dda214ac4beee1cf701dc4b134121ce..38a5fe39959fa23566f286085ea68b647eedf620 100644 (file)
@@ -614,9 +614,11 @@ assertz_clause(Head, Body) :-
         arg(1, Head, Module),
         arg(2, Head, F),
         module_assertz_clause(F, Body, Module)
-       ; '$no_such_predicate'(Head) -> call_assertz(Head, Body, Name, Arity)
-       ; '$head_is_dynamic'(Head) -> call_assertz(Head, Body, Name, Arity)
-       ;  throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
+       ; '$no_such_predicate'(Head) ->
+        call_assertz(Head, Body, Name, Arity)
+       ; '$head_is_dynamic'(Head) ->
+        call_assertz(Head, Body, Name, Arity)
+       ; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
        )
     ;  throw(error(type_error(callable, Head), assertz/1))
     ).
index fcdaf90aff19033fa41cc9d445aa619c3c99eb90..e026b25dc92b8f231254ad179074f6f9d3c654c0 100644 (file)
@@ -374,7 +374,17 @@ fn compile_into_module_impl<R: Read>(
     let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len(), module_name.clone());
 
     clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?;
-    add_module_code(wam, compiler.module.take().unwrap(), module_code, indices);
+
+    let top_level_term_dir = results.top_level_term_dirs.consolidate();
+    
+    add_module_code(
+        wam,
+        compiler.module.take().unwrap(),
+        module_code,
+        indices,
+        top_level_term_dir,
+    );
+    
     clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
 
     Ok(compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo))
@@ -386,7 +396,9 @@ pub struct GatherResult {
     toplevel_results: Vec<PredicateCompileQueue>,
     toplevel_indices: IndexStore,
     addition_results: ExpansionAdditionResult,
-    top_level_terms: Vec<(Term, usize, usize)>
+    top_level_terms: Vec<(Term, usize, usize)>,
+    top_level_term_dirs: TermDirQuantum,
+    module_term_dirs: TermDirQuantum,
 }
 
 pub struct ClauseCodeGenerator {
@@ -489,16 +501,29 @@ pub struct ListingCompiler {
     listing_src: ListingSource, // a file? a module?
 }
 
-fn add_toplevel_code(wam: &mut Machine, code: Code, indices: IndexStore) {
+fn add_toplevel_code(
+    wam: &mut Machine,
+    code: Code,
+    indices: IndexStore,
+    term_dir: TermDir,    
+) {
     wam.add_batched_code(code, indices.code_dir);
     wam.add_batched_ops(indices.op_dir);
+
+    wam.code_repo.term_dir.extend(term_dir.into_iter());
 }
 
 #[inline]
-fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, indices: IndexStore)
-{
+fn add_module_code(
+    wam: &mut Machine,
+    mut module: Module,
+    code: Code,
+    indices: IndexStore,
+    term_dir: TermDir,
+) {
     module.code_dir.extend(indices.code_dir);
     module.op_dir.extend(indices.op_dir.into_iter());
+    module.term_dir.extend(term_dir.into_iter());
 
     wam.add_module(module, code);
 }
@@ -508,13 +533,14 @@ fn add_non_module_code(
     dynamic_clause_map: DynamicClauseMap,
     code: Code,
     indices: IndexStore,
+    term_dir: TermDir,
 ) -> Result<(), SessionError> {
     wam.check_toplevel_code(&indices)?;
 
     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);
+    add_toplevel_code(wam, code, indices, term_dir);
     clause_code_generator.add_clause_code(wam, dynamic_clause_map);
 
     Ok(())
@@ -532,7 +558,7 @@ fn load_library(
 
             lib_path.pop();
             lib_path.push("lib");
-            
+
             let listing_src = ListingSource::from_file_and_path(name, lib_path);
 
             load_module(
@@ -694,6 +720,7 @@ impl ListingCompiler {
             let (name, arity) = decl
                 .predicate_indicator()
                 .ok_or(SessionError::NamelessEntry)?;
+            
             let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity));
 
             let p = code.len() + wam.code_repo.code.len() + code_offset;
@@ -797,7 +824,12 @@ impl ListingCompiler {
         flags: MachineFlags,
     ) -> Result<(), SessionError> {
         match decl {
-            Declaration::EndOfFile => Ok(()),
+            Declaration::Dynamic(..) => {
+                Ok(())
+            }
+            Declaration::EndOfFile => {
+                Ok(())
+            }
             Declaration::Hook(hook, clause, queue) => {
                 let key = (hook.name(), hook.arity());
                 let (len, queue_len) =
@@ -812,6 +844,33 @@ impl ListingCompiler {
 
                 result
             }
+            Declaration::Module(module_decl) => {
+                if self.module.is_none() {
+                    let module_name = module_decl.name.clone();
+                    let atom_tbl = TabledData::new(module_name.to_rc());
+
+                    for export in module_decl.exports.iter() {
+                        if let ModuleExport::OpDecl(ref op_decl) = export {
+                            self.submit_op(wam, indices, op_decl)?;
+                        }
+                    }
+
+                    let listing_src = self.listing_src.clone();
+
+                    Ok(self.module = Some(Module::new(module_decl, atom_tbl, listing_src)))
+                } else {
+                    Err(SessionError::from(ParserError::InvalidModuleDecl))
+                }
+            }
+           Declaration::ModuleInitialization(query_terms, queue) => {
+               self.initialization_goals.0.extend(query_terms.into_iter());
+               self.initialization_goals.1.extend(queue.into_iter());
+
+               Ok(())
+           }
+            Declaration::MultiFile(..) => {
+                Ok(())
+            }
             Declaration::NonCountedBacktracking(name, arity) => {
                 Ok(self.add_non_counted_bt_flag(name, arity))
             }
@@ -827,6 +886,13 @@ impl ListingCompiler {
 
                 self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
             }
+            Declaration::UseModule(ModuleSource::File(filename)) => {
+                let mut path_buf = self.listing_src.path();
+                path_buf.push(filename.as_str());
+
+                let name = load_module_from_file(wam, path_buf, true)?;
+                self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
+            }
             Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => {
                 let name = if !wam.indices.modules.contains_key(&name) {
                     load_library(wam, name, true)?
@@ -842,31 +908,6 @@ impl ListingCompiler {
                     &mut wam.indices,
                     indices
                 )
-            },
-            Declaration::Module(module_decl) => {
-                if self.module.is_none() {
-                    let module_name = module_decl.name.clone();
-                    let atom_tbl = TabledData::new(module_name.to_rc());
-
-                    for export in module_decl.exports.iter() {
-                        if let ModuleExport::OpDecl(ref op_decl) = export {
-                            self.submit_op(wam, indices, op_decl)?;
-                        }
-                    }
-
-                    let listing_src = self.listing_src.clone();
-
-                    Ok(self.module = Some(Module::new(module_decl, atom_tbl, listing_src)))
-                } else {
-                    Err(SessionError::from(ParserError::InvalidModuleDecl))
-                }
-            }
-            Declaration::UseModule(ModuleSource::File(filename)) => {
-                let mut path_buf = self.listing_src.path();
-                path_buf.push(filename.as_str());
-
-                let name = load_module_from_file(wam, path_buf, true)?;
-                self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
             }
             Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
                 let mut path_buf = self.listing_src.path();
@@ -883,16 +924,57 @@ impl ListingCompiler {
                     indices,
                 )
             }
-           Declaration::ModuleInitialization(query_terms, queue) => {
-               self.initialization_goals.0.extend(query_terms.into_iter());
-               self.initialization_goals.1.extend(queue.into_iter());
-
-               Ok(())
-           }
-            Declaration::Dynamic(..) => Ok(()),
         }
     }
 
+    fn setup_multifile_decl<R: Read>(
+        &self,
+        name: ClauseName,
+        arity: usize,
+        worker: &mut TopLevelBatchWorker<R>
+    ) -> Result<(), SessionError> {
+        let module_name = name.owning_module();
+
+        let term_dir = match module_name.as_str() {
+            "user" => {
+                &worker.term_stream.wam.code_repo.term_dir
+            }
+            _ => {
+                if let Some(ref module) = self.module {
+                    &module.term_dir
+                } else {
+                    match worker.term_stream.wam.indices.modules.get(&module_name) {
+                        Some(ref module) => {
+                            &module.term_dir
+                        }
+                        None => {
+                            return Err(SessionError::ModuleNotFound);
+                        }
+                    }
+                }
+            }
+        };
+
+        Ok(match term_dir.get(&(name.clone(), arity)) {
+            Some((ref preds, ref queue)) => {
+                let (preds, queue) = (preds.clone(), queue.clone());
+
+                worker.term_dirs.set_old(
+                    (name.clone(), arity),
+                    preds,
+                    queue,
+                );
+            }
+            None => {
+                worker.term_dirs.set_old(
+                    (name.clone(), arity),
+                    Predicate::new(),
+                    VecDeque::new(),                        
+                );
+            }
+        })
+    }
+
     fn process_and_commit_decl<R: Read>(
         &mut self,
         decl: Declaration,
@@ -919,6 +1001,9 @@ impl ListingCompiler {
             &Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() => {
                 worker.term_stream.incr_expansion_lens(hook, 1, queue.len())
             }
+            &Declaration::MultiFile(ref name, arity) => {
+                self.setup_multifile_decl(name.clone(), arity, worker)?;
+            }
             &Declaration::UseModule(_) | &Declaration::UseQualifiedModule(..) => {
                 update_expansion_lengths = true
             }
@@ -933,7 +1018,7 @@ impl ListingCompiler {
 
         result
     }
-
+    
     pub(crate) fn gather_items<R: Read>(
         &mut self,
         wam: &mut Machine,
@@ -947,16 +1032,22 @@ impl ListingCompiler {
         let mut toplevel_results = vec![];
         let mut toplevel_indices = default_index_store!(atom_tbl.clone());
 
+        let mut top_level_term_dirs = TermDirQuantum::new();
+
         while let Some(decl) = worker.consume(indices)? {
             if decl.is_module_decl() {
                 toplevel_indices.copy_and_swap(indices);
                 mem::swap(&mut worker.results, &mut toplevel_results);
                 worker.in_module = true;
 
-                self.process_and_commit_decl(decl, &mut worker, indices, flags)?;
-
+                self.process_and_commit_decl(decl, &mut worker, indices, flags)?;                
+                
                 if let Some(ref module) = &self.module {
                     worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
+                    top_level_term_dirs = mem::replace(
+                        &mut worker.term_dirs,
+                        TermDirQuantum::new(),
+                    );
                 }
             } else if decl.is_end_of_file() {
                 break;
@@ -965,8 +1056,15 @@ impl ListingCompiler {
             }
         }
 
-        let addition_results = worker.term_stream.rollback_expansion_code()?;
+        let addition_results = worker.term_stream.rollback_expansion_code()?;        
 
+        let module_term_dirs = if self.module.is_some() {
+            worker.term_dirs
+        } else {
+            top_level_term_dirs = worker.term_dirs;
+            TermDirQuantum::new()
+        };
+        
         Ok(GatherResult {
             worker_results: worker.results,
             dynamic_clause_map: worker.dynamic_clause_map,
@@ -974,6 +1072,8 @@ impl ListingCompiler {
             toplevel_indices,
             addition_results,
             top_level_terms: worker.term_stream.top_level_terms(),
+            top_level_term_dirs,
+            module_term_dirs,
         })
     }
 
@@ -1016,6 +1116,9 @@ fn compile_work_impl(
         }
     }
 
+    let top_level_term_dir = results.top_level_term_dirs.consolidate();
+    let module_term_dir = results.module_term_dirs.consolidate();
+
     let module_code = compiler.generate_code(
         results.worker_results,
         wam,
@@ -1062,24 +1165,25 @@ fn compile_work_impl(
         }
 
         if module.is_impromptu_module {
-            add_module_code(wam, module, module_code, indices);
+            add_module_code(wam, module, module_code, indices, module_term_dir);
 
             let module = wam.indices.take_module(compiler.listing_src.name()).unwrap();
 
             wam.indices.use_module(&mut wam.code_repo, wam.machine_st.flags, &module)?;
             wam.indices.insert_module(module);
         } else {
-            add_module_code(wam, module, module_code, indices);
+            add_module_code(wam, module, module_code, indices, module_term_dir);
         }
 
-        add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
+        add_toplevel_code(wam, toplvl_code, results.toplevel_indices, top_level_term_dir);
         clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
     } else {
         add_non_module_code(
             wam,
             results.dynamic_clause_map,
             module_code,
-            indices
+            indices,
+            top_level_term_dir,
         )?;
     }
 
@@ -1132,7 +1236,9 @@ pub fn compile_special_form<R: Read>(
     let code = compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)?;
     let p = wam.code_repo.code.len();
 
-    add_toplevel_code(wam, code, indices);
+    let top_level_term_dir = results.top_level_term_dirs.consolidate();
+    
+    add_toplevel_code(wam, code, indices, top_level_term_dir);
 
     Ok(p)
 }
index d6ffd1a3319cf71ecab286600ba0784e1f247593..f76601bf20e93c7122508225632f605d27413825 100644 (file)
@@ -270,8 +270,12 @@ impl Machine {
         p: LocalCodePtr,
     ) {
         match trans_type {
-            DynamicTransactionType::Abolish => self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
-            DynamicTransactionType::Assert(place) => self.recompile_dynamic_predicate(place),
+            DynamicTransactionType::Abolish => {
+                self.abolish_dynamic_clause(temp_v!(1), temp_v!(2))
+            }
+            DynamicTransactionType::Assert(place) => {
+                self.recompile_dynamic_predicate(place)
+            }
             DynamicTransactionType::ModuleAbolish => {
                 self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3))
             }
@@ -281,7 +285,9 @@ impl Machine {
             DynamicTransactionType::ModuleRetract => {
                 self.retract_from_dynamic_predicate_in_module()
             }
-            DynamicTransactionType::Retract => self.retract_from_dynamic_predicate(),
+            DynamicTransactionType::Retract => {
+                self.retract_from_dynamic_predicate()
+            }
         }
 
         self.machine_st.p = CodePtr::Local(p);
index 17c5136f69cae494f61ac5ef55042f3fc501f325..8f5e39c16ad007c21aa2b3cf4452916004b88500 100644 (file)
@@ -18,8 +18,9 @@ impl Module {
     ) -> Self
     {
         Module {
-            module_decl,
             atom_tbl,
+            module_decl,
+            term_dir: TermDir::new(),
             user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
             user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
             term_expansions: (Predicate::new(), VecDeque::from(vec![])),
index 872d0e5b7f516661bc7fc46fbfb481390275127b..cbe0ff2133a8dc64204d1c759d3927b5c428c752 100644 (file)
@@ -377,10 +377,6 @@ fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, ParserError>
     }
 }
 
-fn append_preds(preds: &mut Vec<PredicateClause>) -> Predicate {
-    Predicate(mem::replace(preds, vec![]))
-}
-
 fn mark_cut_variables_as(terms: &mut Vec<Term>, name: ClauseName) {
     for term in terms.iter_mut() {
         match term {
@@ -493,20 +489,6 @@ fn setup_declaration<'a, 'b, 'c, R: Read>(
     match term {
         Term::Clause(_, name, mut terms, _) =>
            match (name.as_str(), terms.len()) {
-               ("op", 3) =>
-                   Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
-               ("module", 2) =>
-                   Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
-               ("use_module", 1) =>
-                   Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
-               ("use_module", 2) => {
-                   let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
-                   Ok(Declaration::UseQualifiedModule(name, exports))
-               }
-               ("non_counted_backtracking", 1) => {
-                   let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
-                   Ok(Declaration::NonCountedBacktracking(name, arity))
-               }
                ("dynamic", 1) => {
                    let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
                    Ok(Declaration::Dynamic(name, arity))
@@ -518,10 +500,30 @@ fn setup_declaration<'a, 'b, 'c, R: Read>(
 
                    Ok(Declaration::ModuleInitialization(query_terms, queue))
                }
-               _ =>
+               ("module", 2) =>
+                   Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
+               ("op", 3) =>
+                   Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
+               ("non_counted_backtracking", 1) => {
+                   let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
+                   Ok(Declaration::NonCountedBacktracking(name, arity))
+               }
+                ("multifile", 1) => {
+                    let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
+                    Ok(Declaration::MultiFile(name, arity))
+                }
+               ("use_module", 1) => {
+                   Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
+                }
+               ("use_module", 2) => {
+                   let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
+                   Ok(Declaration::UseQualifiedModule(name, exports))
+               }
+               _ => {
                    Err(ParserError::InconsistentEntry)
+                }
            },
-        _ => return Err(ParserError::InconsistentEntry),
+        _ => Err(ParserError::InconsistentEntry),
     }
 }
 
@@ -688,7 +690,7 @@ impl RelationWorker {
                         Cell::default(),
                         Constant::Atom(clause_name!("true"), None)
                     );
-                    
+
                     let prec = Term::Clause(Cell::default(), clause_name!("->"), terms, None);
                     let terms = vec![Box::new(prec), Box::new(conq)];
 
@@ -943,7 +945,64 @@ impl RelationWorker {
     }
 }
 
-pub type DynamicClauseMap = IndexMap<(ClauseName, usize), Vec<(Term, Term)>>;
+pub type DynamicClause = Vec<(Term, Term)>;
+
+pub type DynamicClauseMap = IndexMap<(ClauseName, usize), DynamicClause>;
+
+pub struct TermDirQuantum {
+    old_term_dir: TermDir,
+    new_term_dir: TermDir,
+}
+
+impl TermDirQuantum {
+    pub fn new() -> Self {
+        Self {
+            old_term_dir: TermDir::new(),
+            new_term_dir: TermDir::new()
+        }
+    }
+
+    #[inline]
+    fn get_old(&self, name: ClauseName, arity: usize) -> Option<&(Predicate, VecDeque<TopLevel>)>
+    {
+        self.old_term_dir.get(&(name, arity))
+    }
+
+    #[inline]
+    fn add_new(
+        &mut self,
+        key: PredicateKey,
+        preds: &mut Vec<PredicateClause>,
+        queue: VecDeque<TopLevel>
+    ) {
+        let preds = Predicate(mem::replace(preds, vec![]));
+        self.new_term_dir.insert(key, (preds, queue));
+    }
+
+    pub fn consolidate(self) -> TermDir {
+        let mut term_dir = self.old_term_dir;
+
+        for (key, (preds, queue)) in self.new_term_dir {
+            let (prev_preds, prev_queue) =
+                term_dir.entry(key).or_insert((Predicate::new(), VecDeque::new()));
+
+            prev_preds.0.extend(preds.0.into_iter());
+            prev_queue.extend(queue.into_iter());
+        }
+
+        term_dir
+    }
+
+    #[inline]
+    pub fn set_old(
+        &mut self,
+        key: PredicateKey,
+        pred: Predicate,
+        queue: VecDeque<TopLevel>
+    ) {
+        self.old_term_dir.insert(key, (pred, queue));
+    }
+}
 
 pub struct TopLevelBatchWorker<'a, R: Read> {
     pub(crate) term_stream: TermStream<'a, R>,
@@ -951,6 +1010,7 @@ pub struct TopLevelBatchWorker<'a, R: Read> {
     pub(crate) results: Vec<(Predicate, VecDeque<TopLevel>)>,
     pub(crate) dynamic_clause_map: DynamicClauseMap,
     pub(crate) in_module: bool,
+    pub(crate) term_dirs: TermDirQuantum
 }
 
 impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
@@ -971,6 +1031,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
             results: vec![],
             dynamic_clause_map: IndexMap::new(),
             in_module: false,
+            term_dirs: TermDirQuantum::new(),
         }
     }
 
@@ -999,15 +1060,29 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
         &mut self,
         indices: &mut IndexStore,
         preds: &mut Vec<PredicateClause>,
-    ) -> Result<(), SessionError> {       
+    ) -> Result<(), SessionError> {
         let mut indices = CompositeIndices::new(
             &mut self.term_stream,
             IndexSource::Local(indices),
             if self.in_module { None } else { Some(IndexSource::TermStream) }
         );
 
-        let queue  = self.rel_worker.parse_queue(&mut indices)?;
-        let result = (append_preds(preds), queue);
+        let (name, arity) = (preds[0].name().unwrap(), preds[0].arity());
+
+        let (mut prev_preds, mut prev_queue) =
+            match self.term_dirs.get_old(name.clone(), arity).cloned() {
+                Some((preds, queue)) => (preds, queue),
+                None => (Predicate::new(), VecDeque::new()),
+            };
+
+        let queue = self.rel_worker.parse_queue(&mut indices)?;
+
+        prev_preds.0.extend(preds.iter().cloned());
+        prev_queue.extend(queue.iter().cloned());
+
+        let result = (prev_preds, prev_queue);
+
+        self.term_dirs.add_new((name, arity), preds, queue);
 
         let in_situ_code_dir = &mut indices.term_stream.wam.indices.in_situ_code_dir;
 
@@ -1045,18 +1120,18 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
 
         while !self.term_stream.eof()? {
             let term = self.term_stream.read_term(&indices.op_dir)?;
-            
+
             // if is_consistent is false, preds is non-empty.
             if !is_consistent(term.predicate_name(), term.predicate_arity(), &preds) {
                 self.process_result(indices, &mut preds)?;
                 self.take_dynamic_clauses();
             }
-            
+
             let (mut tl, new_rel_worker) = self.try_term_to_tl(indices, term)?;
 
             if tl.is_end_of_file_atom() {
                 tl = TopLevel::Declaration(Declaration::EndOfFile);
-            }            
+            }
 
             self.rel_worker.absorb(new_rel_worker);