]> Repositorios git - scryer-prolog.git/commitdiff
separate constraint checks and code addition into separate phases in machine::compile
authorMark Thom <[email protected]>
Tue, 5 Mar 2019 07:17:56 +0000 (00:17 -0700)
committerMark Thom <[email protected]>
Tue, 5 Mar 2019 07:17:56 +0000 (00:17 -0700)
src/prolog/machine/compile.rs
src/prolog/machine/mod.rs

index 77a460b4e93ec97d079f24b245f3e8818be4c712..d1d20a594e478b675f414abc7aa0803540c98d25 100644 (file)
@@ -149,7 +149,8 @@ pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession
             let mut compiler = ListingCompiler::new(&wam.code_repo);
             let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
 
-            try_eval_session!(compiler.add_code(wam, vec![], indices));
+            try_eval_session!(wam.check_toplevel_code(&indices));
+            add_toplevel_code(wam, vec![], indices);
 
             EvalSession::EntrySuccess
         },
@@ -165,6 +166,57 @@ pub struct GatherResult {
     addition_results: ExpansionAdditionResult
 }
 
+pub struct ClauseCodeGenerator {
+    len_offset: usize,
+    code: Code,
+    pi_to_loc: HashMap<PredicateKey, usize>
+}
+
+impl ClauseCodeGenerator {
+    #[inline]
+    fn new(len_offset: usize) -> Self {
+        ClauseCodeGenerator { len_offset, code: vec![], pi_to_loc: HashMap::new() }
+    }
+
+    fn generate_clause_code(&mut self, dynamic_clause_map: DynamicClauseMap, wam: &Machine)
+                            -> Result<(), SessionError>
+    {
+        for ((name, arity), heads_and_tails) in dynamic_clause_map {
+            if heads_and_tails.is_empty() {
+                continue;
+            }
+
+            let predicate = Predicate(heads_and_tails.into_iter().map(|(head, tail)| {
+                let clause = Term::Clause(Cell::default(), clause_name!("clause"),
+                                          vec![Box::new(head), Box::new(tail)],
+                                          None);
+                PredicateClause::Fact(clause)
+            }).collect());
+
+            let p = self.code.len() + wam.code_size() + self.len_offset;
+            let mut decl_code = compile_relation(&TopLevel::Predicate(predicate), false,
+                                                 wam.machine_flags())?;
+
+            compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
+
+            self.pi_to_loc.insert((name, arity), p);
+            self.code.extend(decl_code.into_iter());
+        }
+
+        Ok(())
+    }
+
+    fn add_clause_code(self, wam: &mut Machine) {
+        wam.code_repo.code.extend(self.code.into_iter());
+
+        for ((name, arity), p) in self.pi_to_loc {
+            let entry = wam.indices.dynamic_code_dir.entry((name, arity))
+                           .or_insert(DynamicPredicateInfo::default());
+            entry.clauses_subsection_p = p;
+        }
+    }
+}
+
 pub struct ListingCompiler {
     non_counted_bt_preds: HashSet<PredicateKey>,
     module: Option<Module>,
@@ -173,6 +225,27 @@ pub struct ListingCompiler {
     orig_goal_expansion_lens: (usize, usize)
 }
 
+fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore)
+{
+    let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
+    let op_dir   = mem::replace(&mut indices.op_dir, OpDir::new());
+
+    wam.add_batched_code(code, code_dir);
+    wam.add_batched_ops(op_dir);
+}
+
+#[inline]
+fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, mut indices: IndexStore)
+{
+    let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
+    let op_dir   = mem::replace(&mut indices.op_dir, OpDir::new());
+
+    module.code_dir.extend(as_module_code_dir(code_dir));
+    module.op_dir.extend(op_dir.into_iter());
+
+    wam.add_module(module, code);
+}
+
 impl ListingCompiler {
     #[inline]
     pub fn new(code_repo: &CodeRepo) -> Self {
@@ -270,45 +343,6 @@ impl ListingCompiler {
             .unwrap_or(ClauseName::BuiltIn("user"))
     }
 
-    fn add_clause_code(&mut self, dynamic_clause_map: DynamicClauseMap, wam: &mut Machine)
-                       -> Result<(), SessionError>
-    {
-        let mut code = vec![];
-        let mut pi_to_loc = HashMap::new();
-
-        for ((name, arity), heads_and_tails) in dynamic_clause_map {
-            if heads_and_tails.is_empty() {
-                continue;
-            }
-
-            let predicate = Predicate(heads_and_tails.into_iter().map(|(head, tail)| {
-                let clause = Term::Clause(Cell::default(), clause_name!("clause"),
-                                          vec![Box::new(head), Box::new(tail)],
-                                          None);
-                PredicateClause::Fact(clause)
-            }).collect());
-
-            let p = code.len() + wam.code_size();
-            let mut decl_code = compile_relation(&TopLevel::Predicate(predicate), false,
-                                                 wam.machine_flags())?;
-
-            compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
-            
-            pi_to_loc.insert((name, arity), p);
-            code.extend(decl_code.into_iter());
-        }
-
-        wam.code_repo.code.extend(code.into_iter());
-
-        for ((name, arity), p) in pi_to_loc {
-            let entry = wam.indices.dynamic_code_dir.entry((name, arity))
-                           .or_insert(DynamicPredicateInfo::default());
-            entry.clauses_subsection_p = p;
-        }
-
-        Ok(())
-    }
-
     pub(crate)
     fn generate_code(&mut self, decls: Vec<PredicateCompileQueue>, wam: &Machine,
                      code_dir: &mut CodeDir)
@@ -336,25 +370,6 @@ impl ListingCompiler {
         Ok(code)
     }
 
-    fn add_code(&mut self, wam: &mut Machine, code: Code, mut indices: IndexStore)
-                -> Result<(), SessionError>
-    {
-        let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
-        let op_dir   = mem::replace(&mut indices.op_dir, OpDir::new());
-
-        if let Some(mut module) = self.module.take() {
-            module.code_dir.extend(as_module_code_dir(code_dir));
-            module.op_dir.extend(op_dir.into_iter());
-
-            wam.add_module(module, code);
-        } else {
-            wam.add_batched_code(code, code_dir)?;
-            wam.add_batched_ops(op_dir);
-        }
-
-        Ok(())
-    }
-
     fn add_non_counted_bt_flag(&mut self, name: ClauseName, arity: usize) {
         self.non_counted_bt_preds.insert((name, arity));
     }
@@ -525,11 +540,26 @@ fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine, src:
     try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion, flags));
     try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags));
 
-    try_eval_session!(compiler.add_code(wam, module_code, indices));
-    try_eval_session!(compiler.add_code(wam, toplvl_code, results.toplevel_indices));
+    if let Some(module) = compiler.module.take() {
+        let mut clause_code_generator = ClauseCodeGenerator::new(toplvl_code.len());
+
+        try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam));
+        try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices));
+
+        add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
+        clause_code_generator.add_clause_code(wam);
+        add_module_code(wam, module, module_code, indices);
+    } else {
+        let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len());
+
+        try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam));
+        try_eval_session!(wam.check_toplevel_code(&indices));
+
+        // yes, in this case, module_code is actually toplevel code.
+        add_toplevel_code(wam, module_code, indices);
+        clause_code_generator.add_clause_code(wam);
+    }
 
-    try_eval_session!(compiler.add_clause_code(results.dynamic_clause_map, wam));    
-    
     EvalSession::EntrySuccess
 }
 
index b65eea0926e3861be7c3c317f68bf46a1dd5eb1d..bee136315b0b56315570d164ce93185b7253466f 100644 (file)
@@ -208,9 +208,9 @@ impl Machine {
         self.machine_st.flags
     }
 
-    pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) -> Result<(), SessionError>
+    pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError>
     {
-        for (ref key, ref idx) in code_dir.iter() {
+        for (key, idx) in &indices.code_dir {
             match ClauseType::from(key.0.clone(), key.1, None) {
                 ClauseType::Named(..) | ClauseType::Op(..) => {},
                 _ => {
@@ -234,12 +234,18 @@ impl Machine {
                         let err_str = format!("{}/{} from module {}", key.0, key.1,
                                               existing_idx.module_name().as_str());
                         let err_str = clause_name!(err_str, self.indices.atom_tbl());
+                        
                         return Err(SessionError::CannotOverwriteImport(err_str));
                     }
                 }
             }
         }
 
+        Ok(())
+    }
+    
+    pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir)
+    {
         // error detection has finished, so update the master index of keys.
         for (key, idx) in code_dir {
             if let Some(ref mut master_idx) = self.indices.code_dir.get_mut(&key) {
@@ -252,11 +258,10 @@ impl Machine {
                 continue;
             }
 
-            self.indices.code_dir.insert(key.clone(), idx.clone());
+            self.indices.code_dir.insert(key, idx);
         }
 
         self.code_repo.code.extend(code.into_iter());
-        Ok(())
     }
 
     #[inline]