From da731ad1f9b1df8562f893230c85144d3122b4c2 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 5 Jan 2019 22:02:06 -0700 Subject: [PATCH] add module-level goal_expansion and term_expansion --- src/prolog/compile.rs | 84 ++++++++++++++++++++++++++++---------- src/prolog/instructions.rs | 19 +++++++++ src/prolog/machine/mod.rs | 6 +-- src/prolog/toplevel.rs | 38 +++++++++-------- 4 files changed, 105 insertions(+), 42 deletions(-) diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index cb8ba974..41c8b093 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -40,6 +40,8 @@ fn print_code(code: &Code) { } } +type PredicateCompileQueue = (Predicate, VecDeque); + // throw errors if declaration or query found. fn compile_relation(tl: &TopLevel, non_counted_bt: bool, flags: MachineFlags) -> Result @@ -97,9 +99,9 @@ impl CodeRepo { Some(preds) => { let mut cg = CodeGenerator::::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_results: Vec<(Predicate, VecDeque)>, + worker_results: Vec, + toplevel_results: Vec, toplevel_indices: IndexStore, addition_results: ExpansionAdditionResult } @@ -168,13 +170,15 @@ struct GatherResult { pub struct ListingCompiler { non_counted_bt_preds: HashSet, module: Option, + 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)>, + fn generate_code(&mut self, decls: Vec, wam: &Machine, code_dir: &mut CodeDir) -> Result { @@ -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) + -> (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(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore) -> Result { @@ -396,10 +433,15 @@ fn compile_listing(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 } diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index f9057795..fbfbd42e 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -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)] diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 8ca220d3..5f855973 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -132,12 +132,10 @@ impl CodeRepo { pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize) -> (Predicate, VecDeque) { - //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, diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 0fd65d30..a1541515 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -92,7 +92,7 @@ fn as_compile_time_hook(name: &str, arity: usize, terms: &Vec>) -> Opt } None - }, + }, _ => None } } @@ -106,8 +106,8 @@ fn is_compile_time_hook(name: &ClauseName, terms: &Vec>) -> Option); @@ -368,21 +368,25 @@ fn module_resolution_call(mod_name: Term, body: Term) -> Result 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(), + _ => {} } } -- 2.54.0