separate constraint checks and code addition into separate phases in machine::compile
This commit is contained in:
@@ -149,7 +149,8 @@ pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession
|
|||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
||||||
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
|
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
|
EvalSession::EntrySuccess
|
||||||
},
|
},
|
||||||
@@ -165,6 +166,57 @@ pub struct GatherResult {
|
|||||||
addition_results: ExpansionAdditionResult
|
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 {
|
pub struct ListingCompiler {
|
||||||
non_counted_bt_preds: HashSet<PredicateKey>,
|
non_counted_bt_preds: HashSet<PredicateKey>,
|
||||||
module: Option<Module>,
|
module: Option<Module>,
|
||||||
@@ -173,6 +225,27 @@ pub struct ListingCompiler {
|
|||||||
orig_goal_expansion_lens: (usize, usize)
|
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 {
|
impl ListingCompiler {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(code_repo: &CodeRepo) -> Self {
|
pub fn new(code_repo: &CodeRepo) -> Self {
|
||||||
@@ -270,45 +343,6 @@ impl ListingCompiler {
|
|||||||
.unwrap_or(ClauseName::BuiltIn("user"))
|
.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)
|
pub(crate)
|
||||||
fn generate_code(&mut self, decls: Vec<PredicateCompileQueue>, wam: &Machine,
|
fn generate_code(&mut self, decls: Vec<PredicateCompileQueue>, wam: &Machine,
|
||||||
code_dir: &mut CodeDir)
|
code_dir: &mut CodeDir)
|
||||||
@@ -336,25 +370,6 @@ impl ListingCompiler {
|
|||||||
Ok(code)
|
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) {
|
fn add_non_counted_bt_flag(&mut self, name: ClauseName, arity: usize) {
|
||||||
self.non_counted_bt_preds.insert((name, arity));
|
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::UserTermExpansion, flags));
|
||||||
try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags));
|
try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags));
|
||||||
|
|
||||||
try_eval_session!(compiler.add_code(wam, module_code, indices));
|
if let Some(module) = compiler.module.take() {
|
||||||
try_eval_session!(compiler.add_code(wam, toplvl_code, results.toplevel_indices));
|
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
|
EvalSession::EntrySuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,9 +208,9 @@ impl Machine {
|
|||||||
self.machine_st.flags
|
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) {
|
match ClauseType::from(key.0.clone(), key.1, None) {
|
||||||
ClauseType::Named(..) | ClauseType::Op(..) => {},
|
ClauseType::Named(..) | ClauseType::Op(..) => {},
|
||||||
_ => {
|
_ => {
|
||||||
@@ -234,12 +234,18 @@ impl Machine {
|
|||||||
let err_str = format!("{}/{} from module {}", key.0, key.1,
|
let err_str = format!("{}/{} from module {}", key.0, key.1,
|
||||||
existing_idx.module_name().as_str());
|
existing_idx.module_name().as_str());
|
||||||
let err_str = clause_name!(err_str, self.indices.atom_tbl());
|
let err_str = clause_name!(err_str, self.indices.atom_tbl());
|
||||||
|
|
||||||
return Err(SessionError::CannotOverwriteImport(err_str));
|
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.
|
// error detection has finished, so update the master index of keys.
|
||||||
for (key, idx) in code_dir {
|
for (key, idx) in code_dir {
|
||||||
if let Some(ref mut master_idx) = self.indices.code_dir.get_mut(&key) {
|
if let Some(ref mut master_idx) = self.indices.code_dir.get_mut(&key) {
|
||||||
@@ -252,11 +258,10 @@ impl Machine {
|
|||||||
continue;
|
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());
|
self.code_repo.code.extend(code.into_iter());
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
Reference in New Issue
Block a user