]> Repositorios git - scryer-prolog.git/commitdiff
add module-level goal_expansion and term_expansion
authorMark Thom <[email protected]>
Sun, 6 Jan 2019 05:02:06 +0000 (22:02 -0700)
committerMark Thom <[email protected]>
Sun, 6 Jan 2019 05:02:06 +0000 (22:02 -0700)
src/prolog/compile.rs
src/prolog/instructions.rs
src/prolog/machine/mod.rs
src/prolog/toplevel.rs

index cb8ba974e89436c7548d551d07052fed1d91897e..41c8b0938d515c4498ce92068536f7fa8e9e5661 100644 (file)
@@ -40,6 +40,8 @@ fn print_code(code: &Code) {
     }
 }
 
+type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
+
 // throw errors if declaration or query found.
 fn compile_relation(tl: &TopLevel, non_counted_bt: bool, flags: MachineFlags)
                     -> Result<Code, ParserError>
@@ -97,9 +99,9 @@ impl CodeRepo {
             Some(preds) => {
                 let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
                 let mut code = cg.compile_predicate(&(preds.0).0)?;
-                
+
                 compile_appendix(&mut code, &preds.1, false, flags)?;
-                
+
                 Ok(match hook {
                     CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion =>
                         self.term_expanders = code,
@@ -159,8 +161,8 @@ pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
 }
 
 struct GatherResult {
-    worker_results: Vec<(Predicate, VecDeque<TopLevel>)>,
-    toplevel_results: Vec<(Predicate, VecDeque<TopLevel>)>,
+    worker_results: Vec<PredicateCompileQueue>,
+    toplevel_results: Vec<PredicateCompileQueue>,
     toplevel_indices: IndexStore,
     addition_results: ExpansionAdditionResult
 }
@@ -168,13 +170,15 @@ struct GatherResult {
 pub struct ListingCompiler {
     non_counted_bt_preds: HashSet<PredicateKey>,
     module: Option<Module>,
+    user_term_dir: TermDir
 }
 
 impl ListingCompiler {
     #[inline]
     pub fn new() -> Self {
         ListingCompiler {
-            module: None, non_counted_bt_preds: HashSet::new()
+            module: None, non_counted_bt_preds: HashSet::new(),
+            user_term_dir: TermDir::new()
         }
     }
 
@@ -231,7 +235,7 @@ impl ListingCompiler {
             .unwrap_or(ClauseName::BuiltIn("user"))
     }
 
-    fn generate_code(&mut self, decls: Vec<(Predicate, VecDeque<TopLevel>)>,
+    fn generate_code(&mut self, decls: Vec<PredicateCompileQueue>,
                      wam: &Machine, code_dir: &mut CodeDir)
                      -> Result<Code, SessionError>
     {
@@ -250,7 +254,7 @@ impl ListingCompiler {
                                                  wam.machine_flags())?;
 
             compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
-            
+
             let idx = code_dir.entry((name, arity)).or_insert(CodeIndex::default());
             set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
 
@@ -283,6 +287,41 @@ impl ListingCompiler {
         self.non_counted_bt_preds.insert((name, arity));
     }
 
+    fn add_term_dir_terms(&mut self, hook: CompileTimeHook, code_repo: &mut CodeRepo,
+                          key: PredicateKey, clause: PredicateClause, queue: VecDeque<TopLevel>)
+                          -> (usize, usize)
+    {
+        let preds = code_repo.term_dir.entry(key.clone())
+            .or_insert((Predicate::new(), VecDeque::from(vec![])));
+
+        let (mut len, mut queue_len) = ((preds.0).0.len(), preds.1.len());
+
+        if self.module.is_some() && hook.has_module_scope() {
+            let module_preds = self.user_term_dir.entry(key.clone())
+                .or_insert((Predicate::new(), VecDeque::from(vec![])));
+
+            (module_preds.0).0.push(clause);
+            module_preds.1.extend(queue.into_iter());
+
+            (preds.0).0.extend((module_preds.0).0.iter().cloned());
+            preds.1.extend(module_preds.1.iter().cloned());
+        } else {
+            let module_preds = self.user_term_dir.entry(key.clone())
+                .or_insert((Predicate::new(), VecDeque::from(vec![])));
+
+            len += 1;
+            queue_len += queue_len;
+
+            (preds.0).0.push(clause);
+            preds.1.extend(queue.into_iter());
+
+            (preds.0).0.extend((module_preds.0).0.iter().cloned());
+            preds.1.extend(module_preds.1.iter().cloned());
+        }
+
+        (len, queue_len)
+    }
+
     fn process_decl(&mut self, decl: Declaration, code_repo: &mut CodeRepo,
                     wam_indices: &mut IndexStore, indices: &mut IndexStore,
                     flags: MachineFlags)
@@ -291,17 +330,13 @@ impl ListingCompiler {
         match decl {
             Declaration::Hook(hook, clause, queue) => {
                 let key = (hook.name(), hook.arity());
+                let (len, queue_len) = self.add_term_dir_terms(hook, code_repo, key.clone(),
+                                                               clause, queue);
 
-                {
-                    let preds = code_repo.term_dir.entry(key)
-                        .or_insert((Predicate(vec![]), VecDeque::from(vec![])));
-                    
-                    (preds.0).0.push(clause);
-                    preds.1.extend(queue.into_iter());
-                }
-                
-                code_repo.compile_hook(hook, flags)
-                         .map_err(SessionError::from)
+                let result = code_repo.compile_hook(hook, flags).map_err(SessionError::from);
+                code_repo.truncate_terms(key, len, queue_len);
+
+                result
             },
             Declaration::NonCountedBacktracking(name, arity) =>
                 Ok(self.add_non_counted_bt_flag(name, arity)),
@@ -330,13 +365,15 @@ impl ListingCompiler {
     {
         match &decl {
             &Declaration::Hook(hook, _, ref queue) if self.module.is_none() =>
-                term_stream.incr_expansion_lens(hook, 1, queue.len()),            
+                term_stream.incr_expansion_lens(hook.user_scope(), 1, queue.len()),
+            &Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() =>
+                term_stream.incr_expansion_lens(hook, 1, queue.len()),
             _ => {}
         };
 
         self.process_decl(decl, term_stream.code_repo, term_stream.indices, indices, flags)
     }
-    
+
     fn gather_items<R: Read>(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore)
                              -> Result<GatherResult, SessionError>
     {
@@ -396,10 +433,15 @@ fn compile_listing<R: Read>(wam: &mut Machine, src: R, mut indices: IndexStore)
         module.term_expansions = results.addition_results.take_term_expansions();
         module.goal_expansions = results.addition_results.take_goal_expansions();
     }
-    
+
     try_eval_session!(compiler.add_code(wam, module_code, indices));
     try_eval_session!(compiler.add_code(wam, toplvl_code, results.toplevel_indices));
-  
+
+    let flags = wam.machine_flags();
+
+    try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion, flags));
+    try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags));
+
     EvalSession::EntrySuccess
 }
 
index f90577951709c79a7a90ec19d202d1797c00d154..fbfbd42ead09db473a43ea7c4eb217118edd6a60 100644 (file)
@@ -386,6 +386,7 @@ impl CompileTimeHook {
         }
     }
 
+    #[inline]
     pub fn arity(self) -> usize {
         match self {
             CompileTimeHook::UserGoalExpansion
@@ -394,6 +395,24 @@ impl CompileTimeHook {
           | CompileTimeHook::TermExpansion => 2
         }
     }
+
+    #[inline]
+    pub fn user_scope(self) -> Self {
+        match self {
+            CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion =>
+                CompileTimeHook::UserGoalExpansion,
+            CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion =>
+                CompileTimeHook::UserTermExpansion,
+        }
+    }
+
+    #[inline]
+    pub fn has_module_scope(self) -> bool {
+        match self {
+            CompileTimeHook::UserTermExpansion | CompileTimeHook::UserGoalExpansion => false,
+            _ => true
+        }
+    }
 }
 
 #[derive(Clone)]
index 8ca220d3bd3c0591927cfc3011575559930620fc..5f8559735caa30f525084449e7b2540e8a258349 100644 (file)
@@ -132,12 +132,10 @@ impl CodeRepo {
     pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize) 
                           -> (Predicate, VecDeque<TopLevel>)
     {
-        //TODO: fix this! this is causing a test to fail. because term_expansions, when
-        //removed by rollback_expansion_code, aren't jump-labeled properly by generate_code.
         self.term_dir.get_mut(&key)
-            .map(|entry| (Predicate((entry.0).0.clone()[len ..].to_vec()), //drain(len ..).collect()),
+            .map(|entry| (Predicate((entry.0).0.drain(len ..).collect()),
                           entry.1.drain(queue_len ..).collect()))
-            .unwrap_or((Predicate(vec![]), VecDeque::from(vec![])))
+            .unwrap_or((Predicate::new(), VecDeque::from(vec![])))
     }    
 
     pub fn add_in_situ_result(&mut self, result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir,
index 0fd65d307d0869c0c7092571f56baf5af1585b05..a1541515736ad76d1236c62fff26b793216755b5 100644 (file)
@@ -92,7 +92,7 @@ fn as_compile_time_hook(name: &str, arity: usize, terms: &Vec<Box<Term>>) -> Opt
             }
 
             None
-        },                
+        },
         _ => None
     }
 }
@@ -106,8 +106,8 @@ fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<Com
             }
         }
     }
-    
-    as_compile_time_hook(name.as_str(), terms.len(), terms)    
+
+    as_compile_time_hook(name.as_str(), terms.len(), terms)
 }
 
 type CompileTimeHookCompileInfo = (CompileTimeHook, PredicateClause, VecDeque<TopLevel>);
@@ -368,21 +368,25 @@ fn module_resolution_call(mod_name: Term, body: Term) -> Result<QueryTerm, Parse
 }
 
 fn flatten_hook(mut term: Term) -> Term {
-    if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {        
-        if name.as_str() == ":-" && terms.len() == 2 {
-            let inner_term = match terms.first_mut().map(|term| term.borrow_mut()) {
-                Some(&mut Term::Clause(_, ref name, ref mut inner_terms, _)) =>
-                    if name.as_str() == ":" && inner_terms.len() == 2 {
-                        Some(*inner_terms.pop().unwrap())
-                    } else {
-                        None
-                    },
-                _ => None
-            };
+    if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
+        match (name.as_str(), terms.len()) {
+            (":-", 2) => {
+                let inner_term = match terms.first_mut().map(|term| term.borrow_mut()) {
+                    Some(&mut Term::Clause(_, ref name, ref mut inner_terms, _)) =>
+                        if name.as_str() == ":" && inner_terms.len() == 2 {
+                            Some(*inner_terms.pop().unwrap())
+                        } else {
+                            None
+                        },
+                    _ => None
+                };
 
-            if let Some(mut inner_term) = inner_term {                
-                mem::swap(&mut terms[0], &mut Box::new(inner_term));
-            }
+                if let Some(mut inner_term) = inner_term {
+                    mem::swap(&mut terms[0], &mut Box::new(inner_term));
+                }
+            },
+            (":", 2) => return *terms.pop().unwrap(),
+            _ => {}
         }
     }