separate constraint checks and code addition into separate phases in machine::compile

This commit is contained in:
Mark Thom
2019-03-05 00:17:56 -07:00
parent e51e816178
commit 14f05a67e3
2 changed files with 102 additions and 67 deletions

View 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
}