remove need for taking code_dir
This commit is contained in:
@@ -97,16 +97,20 @@ fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>, flags: MachineFlag
|
||||
Ok((code, cg.take_vars()))
|
||||
}
|
||||
|
||||
fn package_term(wam: &mut Machine, term: Term) -> Result<TopLevelPacket, ParserError> {
|
||||
let mut code_dir = wam.take_code_dir();
|
||||
let packet = consume_term(&mut code_dir, term, &mut wam.indices)?;
|
||||
wam.swap_code_dir(&mut code_dir);
|
||||
Ok(packet)
|
||||
fn compile_decl(wam: &mut Machine, compiler: &mut ListingCompiler, decl: Declaration)
|
||||
-> Result<IndexStore, SessionError>
|
||||
{
|
||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||
let wam_indices = &mut wam.indices;
|
||||
|
||||
compiler.process_decl(decl, wam_indices, &mut indices)?;
|
||||
|
||||
Ok(indices)
|
||||
}
|
||||
|
||||
pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
|
||||
{
|
||||
let packet = try_eval_session!(package_term(wam, term));
|
||||
let packet = try_eval_session!(consume_term(term, &mut wam.indices));
|
||||
|
||||
match packet {
|
||||
TopLevelPacket::Query(terms, queue) =>
|
||||
@@ -116,9 +120,8 @@ pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
|
||||
},
|
||||
TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => {
|
||||
let mut compiler = ListingCompiler::new();
|
||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||
|
||||
try_eval_session!(compiler.process_decl(decl, wam, &mut indices));
|
||||
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
|
||||
try_eval_session!(compiler.add_code(wam, vec![], indices));
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
@@ -127,6 +130,12 @@ pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
|
||||
}
|
||||
}
|
||||
|
||||
struct GatherResult {
|
||||
worker_results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
||||
toplevel_results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
||||
toplevel_indices: IndexStore
|
||||
}
|
||||
|
||||
pub struct ListingCompiler {
|
||||
non_counted_bt_preds: HashSet<PredicateKey>,
|
||||
module: Option<Module>,
|
||||
@@ -140,41 +149,38 @@ impl ListingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
fn use_module(&mut self, submodule: Module, wam: &mut Machine, indices: &mut IndexStore)
|
||||
fn use_module(&mut self, submodule: &Module, indices: &mut IndexStore)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
let mod_name = self.get_module_name();
|
||||
|
||||
indices.use_module(&submodule)?;
|
||||
indices.use_module(submodule)?;
|
||||
|
||||
if let &mut Some(ref mut module) = &mut self.module {
|
||||
module.remove_module(mod_name, &submodule);
|
||||
module.use_module(&submodule)?;
|
||||
} else {
|
||||
wam.remove_module(&submodule);
|
||||
module.remove_module(mod_name, submodule);
|
||||
module.use_module(submodule)?;
|
||||
}
|
||||
|
||||
Ok(wam.insert_module(submodule))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, submodule: Module, wam: &mut Machine,
|
||||
exports: &Vec<PredicateKey>, indices: &mut IndexStore)
|
||||
fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec<PredicateKey>,
|
||||
indices: &mut IndexStore)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
let mod_name = self.get_module_name();
|
||||
|
||||
indices.use_qualified_module(&submodule, exports)?;
|
||||
indices.use_qualified_module(submodule, exports)?;
|
||||
|
||||
if let &mut Some(ref mut module) = &mut self.module {
|
||||
module.remove_module(mod_name, &submodule);
|
||||
module.use_qualified_module(&submodule, exports)?;
|
||||
} else {
|
||||
wam.remove_module(&submodule);
|
||||
module.remove_module(mod_name, submodule);
|
||||
module.use_qualified_module(submodule, exports)?;
|
||||
}
|
||||
|
||||
Ok(wam.insert_module(submodule))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_module_name(&self) -> ClauseName {
|
||||
self.module.as_ref()
|
||||
.map(|module| module.module_decl.name.clone())
|
||||
@@ -233,25 +239,26 @@ impl ListingCompiler {
|
||||
self.non_counted_bt_preds.insert((name, arity));
|
||||
}
|
||||
|
||||
fn process_decl(&mut self, decl: Declaration, wam: &mut Machine, indices: &mut IndexStore)
|
||||
fn process_decl(&mut self, decl: Declaration, wam_indices: &IndexStore, indices: &mut IndexStore)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
match decl {
|
||||
Declaration::Hook(CompileTimeHook::TermExpansion, clause) =>
|
||||
Ok(wam.add_term_expansion_clause(clause)?),
|
||||
//Ok(wam.add_term_expansion_clause(clause)?),
|
||||
Ok(()),
|
||||
Declaration::NonCountedBacktracking(name, arity) =>
|
||||
Ok(self.add_non_counted_bt_flag(name, arity)),
|
||||
Declaration::Op(op_decl) =>
|
||||
op_decl.submit(self.get_module_name(), &mut indices.op_dir),
|
||||
Declaration::UseModule(name) =>
|
||||
if let Some(submodule) = wam.take_module(name) {
|
||||
self.use_module(submodule, wam, indices)
|
||||
if let Some(ref submodule) = wam_indices.modules.get(&name) {
|
||||
self.use_module(submodule, indices)
|
||||
} else {
|
||||
Err(SessionError::ModuleNotFound)
|
||||
},
|
||||
Declaration::UseQualifiedModule(name, exports) =>
|
||||
if let Some(submodule) = wam.take_module(name) {
|
||||
self.use_qualified_module(submodule, wam, &exports, indices)
|
||||
if let Some(ref submodule) = wam_indices.modules.get(&name) {
|
||||
self.use_qualified_module(submodule, &exports, indices)
|
||||
} else {
|
||||
Err(SessionError::ModuleNotFound)
|
||||
},
|
||||
@@ -266,45 +273,60 @@ impl ListingCompiler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gather_items<R: Read>(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore)
|
||||
-> Result<GatherResult, SessionError>
|
||||
{
|
||||
let flags = wam.machine_flags();
|
||||
let machine_st = &mut wam.machine_st;
|
||||
let wam_indices = &mut wam.indices;
|
||||
|
||||
let atom_tbl = wam_indices.atom_tbl.clone();
|
||||
|
||||
let mut worker = TopLevelBatchWorker::new(src, atom_tbl.clone(), flags,
|
||||
wam_indices, &mut wam.policies,
|
||||
&mut wam.code_repo);
|
||||
|
||||
let mut toplevel_results = vec![];
|
||||
let mut toplevel_indices = default_index_store!(atom_tbl.clone());
|
||||
|
||||
while let Some(decl) = worker.consume(machine_st, indices)? {
|
||||
if decl.is_module_decl() {
|
||||
toplevel_indices.copy_and_swap(indices);
|
||||
mem::swap(&mut worker.results, &mut toplevel_results);
|
||||
worker.in_module = true;
|
||||
|
||||
self.process_decl(decl, worker.term_stream.indices, indices)?;
|
||||
|
||||
if let &Some(ref module) = &self.module {
|
||||
worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
|
||||
}
|
||||
} else {
|
||||
self.process_decl(decl, worker.term_stream.indices, indices)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(GatherResult {
|
||||
worker_results: worker.results,
|
||||
toplevel_results,
|
||||
toplevel_indices
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub
|
||||
fn compile_listing<R: Read>(wam: &mut Machine, src: R, mut indices: IndexStore) -> EvalSession
|
||||
{
|
||||
let code_dir = wam.take_code_dir();
|
||||
let mut worker = TopLevelBatchWorker::new(src, wam.indices.atom_tbl.clone(),
|
||||
wam.machine_flags(),
|
||||
code_dir);
|
||||
|
||||
let mut compiler = ListingCompiler::new();
|
||||
let mut toplevel_results = vec![];
|
||||
let mut toplevel_indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||
let mut results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
|
||||
|
||||
while let Some(decl) = try_eval_session!(worker.consume(wam, &mut indices)) {
|
||||
if decl.is_module_decl() {
|
||||
toplevel_indices.copy_and_swap(&mut indices);
|
||||
mem::swap(&mut worker.results, &mut toplevel_results);
|
||||
worker.in_module = true;
|
||||
|
||||
try_eval_session!(compiler.process_decl(decl, wam, &mut indices));
|
||||
|
||||
if let &Some(ref module) = &compiler.module {
|
||||
worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
|
||||
}
|
||||
} else {
|
||||
try_eval_session!(compiler.process_decl(decl, wam, &mut indices));
|
||||
}
|
||||
}
|
||||
|
||||
wam.swap_code_dir(&mut worker.static_code_dir);
|
||||
|
||||
let module_code = try_eval_session!(compiler.generate_code(worker.results, wam,
|
||||
let module_code = try_eval_session!(compiler.generate_code(results.worker_results, wam,
|
||||
&mut indices.code_dir));
|
||||
let toplvl_code = try_eval_session!(compiler.generate_code(toplevel_results, wam,
|
||||
&mut toplevel_indices.code_dir));
|
||||
let toplvl_code = try_eval_session!(compiler.generate_code(results.toplevel_results, wam,
|
||||
&mut results.toplevel_indices.code_dir));
|
||||
|
||||
try_eval_session!(compiler.add_code(wam, module_code, indices));
|
||||
try_eval_session!(compiler.add_code(wam, toplvl_code, toplevel_indices));
|
||||
try_eval_session!(compiler.add_code(wam, toplvl_code, results.toplevel_indices));
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
@@ -107,6 +107,14 @@ impl CodeRepo {
|
||||
code: Code::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_of_cached_query(&self) -> usize {
|
||||
match &self.cached_query {
|
||||
&Some(ref query) => query.len(),
|
||||
_ => 0
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_instr<'a>(&'a self, last_call: bool, p: &CodePtr) -> Option<RefOrOwned<'a, Line>>
|
||||
{
|
||||
@@ -138,29 +146,51 @@ impl CodeRepo {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Machine {
|
||||
ms: MachineState,
|
||||
pub struct MachinePolicies {
|
||||
call_policy: Box<CallPolicy>,
|
||||
cut_policy: Box<CutPolicy>,
|
||||
}
|
||||
|
||||
impl MachinePolicies {
|
||||
#[inline]
|
||||
fn new() -> Self {
|
||||
MachinePolicies {
|
||||
call_policy: Box::new(DefaultCallPolicy {}),
|
||||
cut_policy: Box::new(DefaultCutPolicy {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Machine {
|
||||
pub(super) machine_st: MachineState,
|
||||
pub(super) policies: MachinePolicies,
|
||||
pub(super) indices: IndexStore,
|
||||
term_dir: TermDir,
|
||||
pub(super) code_repo: CodeRepo
|
||||
}
|
||||
|
||||
impl Index<LocalCodePtr> for CodeRepo {
|
||||
type Output = Line;
|
||||
|
||||
fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
|
||||
match ptr {
|
||||
LocalCodePtr::TopLevel(_, p) => {
|
||||
match &self.cached_query {
|
||||
&Some(ref cq) => &cq[p],
|
||||
&None => panic!("Out-of-bounds top level index.")
|
||||
}
|
||||
},
|
||||
LocalCodePtr::DirEntry(p) => &self.code[p],
|
||||
LocalCodePtr::UserTermExpansion(p) => &self.term_expanders[p]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<LocalCodePtr> for Machine {
|
||||
type Output = Line;
|
||||
|
||||
fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
|
||||
match ptr {
|
||||
LocalCodePtr::TopLevel(_, p) => {
|
||||
match &self.code_repo.cached_query {
|
||||
&Some(ref cq) => &cq[p],
|
||||
&None => panic!("Out-of-bounds top level index.")
|
||||
}
|
||||
},
|
||||
LocalCodePtr::DirEntry(p) => &self.code_repo.code[p],
|
||||
LocalCodePtr::UserTermExpansion(p) => &self.code_repo.term_expanders[p]
|
||||
}
|
||||
&self.code_repo[ptr]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,9 +241,8 @@ static TERMS: &str = include_str!("../lib/terms.pl");
|
||||
impl Machine {
|
||||
pub fn new() -> Self {
|
||||
let mut wam = Machine {
|
||||
ms: MachineState::new(),
|
||||
call_policy: Box::new(DefaultCallPolicy {}),
|
||||
cut_policy: Box::new(DefaultCutPolicy {}),
|
||||
machine_st: MachineState::new(),
|
||||
policies: MachinePolicies::new(),
|
||||
indices: IndexStore::new(),
|
||||
term_dir: TermDir::new(),
|
||||
code_repo: CodeRepo::new()
|
||||
@@ -235,12 +264,12 @@ impl Machine {
|
||||
|
||||
#[inline]
|
||||
pub fn machine_flags(&self) -> MachineFlags {
|
||||
self.ms.flags
|
||||
self.machine_st.flags
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn failed(&self) -> bool {
|
||||
self.ms.fail
|
||||
self.machine_st.fail
|
||||
}
|
||||
|
||||
pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) -> Result<(), SessionError>
|
||||
@@ -305,16 +334,6 @@ impl Machine {
|
||||
pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
|
||||
self.indices.modules.remove(&name)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn take_code_dir(&mut self) -> CodeDir {
|
||||
mem::replace(&mut self.indices.code_dir, CodeDir::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn swap_code_dir(&mut self, code_dir: &mut CodeDir) {
|
||||
mem::swap(&mut self.indices.code_dir, code_dir);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn insert_module(&mut self, module: Module) {
|
||||
@@ -347,159 +366,19 @@ impl Machine {
|
||||
|
||||
preds.0.push(clause);
|
||||
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, self.ms.flags);
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, self.machine_st.flags);
|
||||
let code = cg.compile_predicate(&preds.0)?;
|
||||
|
||||
Ok(self.code_repo.term_expanders = code)
|
||||
}
|
||||
|
||||
fn execute_instr(&mut self)
|
||||
{
|
||||
let instr = match self.code_repo.lookup_instr(self.ms.last_call, &self.ms.p) {
|
||||
Some(instr) => instr,
|
||||
None => return
|
||||
};
|
||||
|
||||
match instr.as_ref() {
|
||||
&Line::Arithmetic(ref arith_instr) =>
|
||||
self.ms.execute_arith_instr(arith_instr),
|
||||
&Line::Choice(ref choice_instr) =>
|
||||
self.ms.execute_choice_instr(choice_instr, &mut self.call_policy),
|
||||
&Line::Cut(ref cut_instr) =>
|
||||
self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
|
||||
&Line::Control(ref control_instr) =>
|
||||
self.ms.execute_ctrl_instr(&mut self.indices, &mut self.call_policy,
|
||||
&mut self.cut_policy, control_instr),
|
||||
&Line::Fact(ref fact) => {
|
||||
for fact_instr in fact {
|
||||
if self.failed() {
|
||||
break;
|
||||
}
|
||||
|
||||
self.ms.execute_fact_instr(&fact_instr);
|
||||
}
|
||||
|
||||
self.ms.p += 1;
|
||||
},
|
||||
&Line::Indexing(ref indexing_instr) =>
|
||||
self.ms.execute_indexing_instr(&indexing_instr),
|
||||
&Line::IndexedChoice(ref choice_instr) =>
|
||||
self.ms.execute_indexed_choice_instr(choice_instr, &mut self.call_policy),
|
||||
&Line::Query(ref query) => {
|
||||
for query_instr in query {
|
||||
if self.failed() {
|
||||
break;
|
||||
}
|
||||
|
||||
self.ms.execute_query_instr(&query_instr);
|
||||
}
|
||||
|
||||
self.ms.p += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn backtrack(&mut self)
|
||||
{
|
||||
if self.ms.b > 0 {
|
||||
let b = self.ms.b - 1;
|
||||
|
||||
self.ms.b0 = self.ms.or_stack[b].b0;
|
||||
self.ms.p = self.ms.or_stack[b].bp.clone();
|
||||
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.ms.p {
|
||||
self.ms.fail = p == 0;
|
||||
} else {
|
||||
self.ms.fail = false;
|
||||
}
|
||||
} else {
|
||||
self.ms.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
fn query_stepper<'a>(&mut self)
|
||||
{
|
||||
loop {
|
||||
self.execute_instr();
|
||||
|
||||
if self.failed() {
|
||||
self.backtrack();
|
||||
}
|
||||
|
||||
match self.ms.p {
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < self.code_repo.code.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < self.code_repo.term_expanders.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.ms.fail = true,
|
||||
CodePtr::Local(_) => break,
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
|
||||
heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
for (var, var_data) in alloc_locs {
|
||||
match var_data {
|
||||
&VarData::Perm(p) if p > 0 => {
|
||||
let e = self.ms.e;
|
||||
let r = var_data.as_reg_type().reg_num();
|
||||
let addr = self.ms.and_stack[e][r].clone();
|
||||
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
},
|
||||
&VarData::Temp(cn, _, _) if cn == chunk_num => {
|
||||
let r = var_data.as_reg_type();
|
||||
|
||||
if r.reg_num() != 0 {
|
||||
let addr = self.ms[r].clone();
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_query(&mut self, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
let end_ptr = top_level_code_ptr!(0, self.cached_query_size());
|
||||
|
||||
while self.ms.p < end_ptr {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.ms.p {
|
||||
match &self[LocalCodePtr::TopLevel(cn, p)] {
|
||||
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
|
||||
self.record_var_places(cn, alloc_locs, heap_locs);
|
||||
cn += 1;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.ms.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
self.query_stepper();
|
||||
|
||||
match self.ms.p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
_ => {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn fail(&mut self, heap_locs: &HeapVarDict) -> EvalSession
|
||||
{
|
||||
if self.ms.ball.stub.len() > 0 {
|
||||
let h = self.ms.heap.h;
|
||||
self.ms.copy_and_align_ball_to_heap();
|
||||
if self.machine_st.ball.stub.len() > 0 {
|
||||
let h = self.machine_st.heap.h;
|
||||
self.machine_st.copy_and_align_ball_to_heap();
|
||||
|
||||
let error_str = self.ms.print_exception(Addr::HeapCell(h),
|
||||
let error_str = self.machine_st.print_exception(Addr::HeapCell(h),
|
||||
&heap_locs,
|
||||
TermFormatter {},
|
||||
PrinterOutputter::new())
|
||||
@@ -516,9 +395,9 @@ impl Machine {
|
||||
let mut heap_locs = HashMap::new();
|
||||
|
||||
self.code_repo.cached_query = Some(code);
|
||||
self.run_query(&alloc_locs, &mut heap_locs);
|
||||
self.machine_st.run_query(&mut self.indices, &mut self.policies, &self.code_repo, &alloc_locs, &mut heap_locs);
|
||||
|
||||
if self.failed() {
|
||||
if self.machine_st.fail {
|
||||
self.fail(&heap_locs)
|
||||
} else {
|
||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs)
|
||||
@@ -528,16 +407,17 @@ impl Machine {
|
||||
pub fn continue_query(&mut self, alloc_l: &AllocVarDict, heap_l: &mut HeapVarDict) -> EvalSession
|
||||
{
|
||||
if !self.or_stack_is_empty() {
|
||||
let b = self.ms.b - 1;
|
||||
self.ms.p = self.ms.or_stack[b].bp.clone();
|
||||
let b = self.machine_st.b - 1;
|
||||
self.machine_st.p = self.machine_st.or_stack[b].bp.clone();
|
||||
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.ms.p {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
|
||||
return EvalSession::from(SessionError::QueryFailure);
|
||||
}
|
||||
|
||||
self.run_query(alloc_l, heap_l);
|
||||
|
||||
if self.failed() {
|
||||
self.machine_st.run_query(&mut self.indices, &mut self.policies, &self.code_repo,
|
||||
alloc_l, heap_l);
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.fail(&heap_l)
|
||||
} else {
|
||||
EvalSession::SubsequentQuerySuccess
|
||||
@@ -555,14 +435,14 @@ impl Machine {
|
||||
|
||||
for (var, addr) in sorted_vars {
|
||||
let fmt = TermFormatter {};
|
||||
output = self.ms.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output);
|
||||
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output);
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn or_stack_is_empty(&self) -> bool {
|
||||
self.ms.b == 0
|
||||
self.machine_st.b == 0
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
@@ -571,7 +451,154 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.cut_policy = Box::new(DefaultCutPolicy {});
|
||||
self.ms.reset();
|
||||
self.policies.cut_policy = Box::new(DefaultCutPolicy {});
|
||||
self.machine_st.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl MachineState {
|
||||
fn execute_instr(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
code_repo: &CodeRepo)
|
||||
{
|
||||
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
||||
Some(instr) => instr,
|
||||
None => return
|
||||
};
|
||||
|
||||
match instr.as_ref() {
|
||||
&Line::Arithmetic(ref arith_instr) =>
|
||||
self.execute_arith_instr(arith_instr),
|
||||
&Line::Choice(ref choice_instr) =>
|
||||
self.execute_choice_instr(choice_instr, &mut policies.call_policy),
|
||||
&Line::Cut(ref cut_instr) =>
|
||||
self.execute_cut_instr(cut_instr, &mut policies.cut_policy),
|
||||
&Line::Control(ref control_instr) =>
|
||||
self.execute_ctrl_instr(indices, &mut policies.call_policy,
|
||||
&mut policies.cut_policy, control_instr),
|
||||
&Line::Fact(ref fact) => {
|
||||
for fact_instr in fact {
|
||||
if self.fail {
|
||||
break;
|
||||
}
|
||||
|
||||
self.execute_fact_instr(&fact_instr);
|
||||
}
|
||||
|
||||
self.p += 1;
|
||||
},
|
||||
&Line::Indexing(ref indexing_instr) =>
|
||||
self.execute_indexing_instr(&indexing_instr),
|
||||
&Line::IndexedChoice(ref choice_instr) =>
|
||||
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy),
|
||||
&Line::Query(ref query) => {
|
||||
for query_instr in query {
|
||||
if self.fail {
|
||||
break;
|
||||
}
|
||||
|
||||
self.execute_query_instr(&query_instr);
|
||||
}
|
||||
|
||||
self.p += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn backtrack(&mut self)
|
||||
{
|
||||
if self.b > 0 {
|
||||
let b = self.b - 1;
|
||||
|
||||
self.b0 = self.or_stack[b].b0;
|
||||
self.p = self.or_stack[b].bp.clone();
|
||||
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
|
||||
self.fail = p == 0;
|
||||
} else {
|
||||
self.fail = false;
|
||||
}
|
||||
} else {
|
||||
self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
fn query_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, code_repo: &CodeRepo)
|
||||
{
|
||||
loop {
|
||||
self.execute_instr(indices, policies, code_repo);
|
||||
|
||||
if self.fail {
|
||||
self.backtrack();
|
||||
}
|
||||
|
||||
match self.p {
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < code_repo.code.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < code_repo.term_expanders.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.fail = true,
|
||||
CodePtr::Local(_) => break,
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
for (var, var_data) in alloc_locs {
|
||||
match var_data {
|
||||
&VarData::Perm(p) if p > 0 => {
|
||||
let e = self.e;
|
||||
let r = var_data.as_reg_type().reg_num();
|
||||
let addr = self.and_stack[e][r].clone();
|
||||
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
},
|
||||
&VarData::Temp(cn, _, _) if cn == chunk_num => {
|
||||
let r = var_data.as_reg_type();
|
||||
|
||||
if r.reg_num() != 0 {
|
||||
let addr = self[r].clone();
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn run_query(&mut self, indices: &mut IndexStore,
|
||||
policies: &mut MachinePolicies, code_repo: &CodeRepo,
|
||||
alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
let end_ptr = top_level_code_ptr!(0, code_repo.size_of_cached_query());
|
||||
|
||||
while self.p < end_ptr {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.p {
|
||||
match &code_repo[LocalCodePtr::TopLevel(cn, p)] {
|
||||
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
|
||||
self.record_var_places(cn, alloc_locs, heap_locs);
|
||||
cn += 1;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
self.query_stepper(indices, policies, code_repo);
|
||||
|
||||
match self.p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
_ => {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,26 @@ use prolog::read::*;
|
||||
use std::cell::Cell;
|
||||
use std::io::Read;
|
||||
|
||||
pub struct TermStream<R: Read> {
|
||||
pub struct TermStream<'a, R: Read> {
|
||||
stack: Vec<Term>,
|
||||
pub(crate) indices: &'a mut IndexStore,
|
||||
policies: &'a mut MachinePolicies,
|
||||
code_repo: &'a mut CodeRepo,
|
||||
parser: Parser<R>,
|
||||
in_module: bool
|
||||
}
|
||||
|
||||
impl<R: Read> TermStream<R> {
|
||||
pub fn new(src: R, atom_tbl: TabledData<Atom>, flags: MachineFlags) -> Self {
|
||||
impl<'a, R: Read> TermStream<'a, R> {
|
||||
pub fn new(src: R, atom_tbl: TabledData<Atom>, flags: MachineFlags,
|
||||
indices: &'a mut IndexStore, policies: &'a mut MachinePolicies,
|
||||
code_repo: &'a mut CodeRepo)
|
||||
-> Self
|
||||
{
|
||||
TermStream {
|
||||
stack: Vec::new(),
|
||||
indices,
|
||||
policies,
|
||||
code_repo,
|
||||
parser: Parser::new(src, atom_tbl, flags),
|
||||
in_module: false
|
||||
}
|
||||
@@ -67,40 +77,47 @@ impl<R: Read> TermStream<R> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_term(&mut self, wam: &mut Machine, op_dir: &OpDir) -> Result<Term, ParserError>
|
||||
pub fn read_term(&mut self, machine_st: &mut MachineState, op_dir: &OpDir)
|
||||
-> Result<Term, ParserError>
|
||||
{
|
||||
loop {
|
||||
while let Some(term) = self.stack.pop() {
|
||||
match wam.try_expand_term(&term)? {
|
||||
match machine_st.try_expand_term(self.indices, self.policies, self.code_repo, &term)? {
|
||||
Some(term) => self.enqueue_term(term)?,
|
||||
None => return Ok(term)
|
||||
};
|
||||
}
|
||||
|
||||
let term = self.parser.read_term(composite_op!(self.in_module, &wam.indices.op_dir,
|
||||
let term = self.parser.read_term(composite_op!(self.in_module,
|
||||
&self.indices.op_dir,
|
||||
op_dir))?;
|
||||
self.stack.push(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
fn try_expand_term(&mut self, term: &Term) -> Result<Option<Term>, ParserError> {
|
||||
let term_h = write_term_to_heap(term, &mut self.ms);
|
||||
let h = self.ms.heap.h;
|
||||
impl MachineState {
|
||||
fn try_expand_term(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
code_repo: &mut CodeRepo, term: &Term)
|
||||
-> Result<Option<Term>, ParserError>
|
||||
{
|
||||
let term_h = write_term_to_heap(term, self);
|
||||
let h = self.heap.h;
|
||||
|
||||
self.ms[temp_v!(1)] = Addr::HeapCell(term_h);
|
||||
self.ms.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||
self.ms[temp_v!(2)] = Addr::HeapCell(h);
|
||||
self[temp_v!(1)] = Addr::HeapCell(term_h);
|
||||
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||
self[temp_v!(2)] = Addr::HeapCell(h);
|
||||
|
||||
let code = vec![call_clause!(ClauseType::Hook(CompileTimeHook::TermExpansion), 2, 0, true)];
|
||||
self.submit_query(code, AllocVarDict::new());
|
||||
|
||||
if self.failed() {
|
||||
code_repo.cached_query = Some(code);
|
||||
self.run_query(indices, policies, code_repo, &AllocVarDict::new(), &mut HeapVarDict::new());
|
||||
|
||||
if self.fail {
|
||||
self.reset();
|
||||
Ok(None)
|
||||
} else {
|
||||
let term = read_term_from_heap(&self.ms, Addr::HeapCell(h))?;
|
||||
let term = read_term_from_heap(&self, Addr::HeapCell(h))?;
|
||||
self.reset();
|
||||
Ok(Some(term))
|
||||
}
|
||||
|
||||
@@ -46,10 +46,11 @@ pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {
|
||||
},
|
||||
_ => {
|
||||
let mut term_stream = TermStream::new(stdin.lock(), wam.indices.atom_tbl.clone(),
|
||||
wam.machine_flags());
|
||||
wam.machine_flags(), &mut wam.indices,
|
||||
&mut wam.policies, &mut wam.code_repo);
|
||||
|
||||
term_stream.add_to_top(buffer.as_str());
|
||||
|
||||
Ok(Input::Term(term_stream.read_term(wam, &OpDir::new())?))
|
||||
Ok(Input::Term(term_stream.read_term(&mut wam.machine_st, &OpDir::new())?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use prolog_parser::tabled_rc::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::iterators::*;
|
||||
use prolog::machine::*;
|
||||
use prolog::machine::machine_state::MachineState;
|
||||
use prolog::machine::term_expansion::*;
|
||||
use prolog::num::*;
|
||||
|
||||
@@ -15,7 +16,7 @@ use std::rc::Rc;
|
||||
|
||||
struct CompositeIndices<'a, 'b> {
|
||||
local: &'a mut IndexStore,
|
||||
static_code_dir: Option<&'b mut CodeDir>
|
||||
static_code_dir: Option<&'b CodeDir>
|
||||
}
|
||||
|
||||
macro_rules! composite_indices {
|
||||
@@ -720,11 +721,11 @@ pub fn parse_term<R: Read>(wam: &Machine, buf: R) -> Result<Term, ParserError>
|
||||
}
|
||||
|
||||
pub
|
||||
fn consume_term(static_code_dir: &mut CodeDir, term: Term, indices: &mut IndexStore)
|
||||
-> Result<TopLevelPacket, ParserError>
|
||||
fn consume_term(term: Term, indices: &mut IndexStore) -> Result<TopLevelPacket, ParserError>
|
||||
{
|
||||
let mut rel_worker = RelationWorker::new();
|
||||
let mut indices = composite_indices!(false, indices, static_code_dir);
|
||||
let mut _code_dir = CodeDir::new();
|
||||
let mut indices = composite_indices!(false, indices, &mut _code_dir);
|
||||
|
||||
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
||||
let results = rel_worker.parse_queue(&mut indices)?;
|
||||
@@ -732,49 +733,52 @@ fn consume_term(static_code_dir: &mut CodeDir, term: Term, indices: &mut IndexSt
|
||||
Ok(deque_to_packet(tl, results))
|
||||
}
|
||||
|
||||
pub struct TopLevelBatchWorker<R: Read> {
|
||||
pub(crate) term_stream: TermStream<R>,
|
||||
pub struct TopLevelBatchWorker<'a, R: Read> {
|
||||
pub(crate) term_stream: TermStream<'a, R>,
|
||||
rel_worker: RelationWorker,
|
||||
pub(super) static_code_dir: CodeDir,
|
||||
pub(crate) results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
||||
pub(crate) in_module: bool
|
||||
}
|
||||
|
||||
impl<R: Read> TopLevelBatchWorker<R> {
|
||||
pub fn new(inner: R, atom_tbl: TabledData<Atom>, flags: MachineFlags, static_code_dir: CodeDir)
|
||||
impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
||||
pub fn new(inner: R,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
flags: MachineFlags,
|
||||
indices: &'a mut IndexStore,
|
||||
policies: &'a mut MachinePolicies,
|
||||
code_repo: &'a mut CodeRepo)
|
||||
-> Self
|
||||
{
|
||||
TopLevelBatchWorker { term_stream: TermStream::new(inner, atom_tbl, flags),
|
||||
let term_stream = TermStream::new(inner, atom_tbl, flags,
|
||||
indices, policies, code_repo);
|
||||
|
||||
TopLevelBatchWorker { term_stream,
|
||||
rel_worker: RelationWorker::new(),
|
||||
static_code_dir,
|
||||
results: vec![],
|
||||
in_module: false }
|
||||
}
|
||||
|
||||
pub
|
||||
fn consume(&mut self, wam: &mut Machine, indices: &mut IndexStore)
|
||||
fn consume(&mut self, machine_st: &mut MachineState, indices: &mut IndexStore)
|
||||
-> Result<Option<Declaration>, SessionError>
|
||||
{
|
||||
let mut preds = vec![];
|
||||
|
||||
while !self.term_stream.eof()? {
|
||||
self.term_stream.empty_tokens(); // empty the parser stack of token descriptions.
|
||||
// empty the parser stack of token descriptions.
|
||||
self.term_stream.empty_tokens();
|
||||
|
||||
let mut new_rel_worker = RelationWorker::new();
|
||||
|
||||
let term = {
|
||||
wam.swap_code_dir(&mut self.static_code_dir);
|
||||
self.term_stream.read_term(wam, &indices.op_dir)?
|
||||
};
|
||||
|
||||
self.static_code_dir = wam.take_code_dir();
|
||||
|
||||
let mut indices = composite_indices!(self.in_module, indices,
|
||||
&mut self.static_code_dir);
|
||||
let term = self.term_stream.read_term(machine_st, &indices.op_dir)?;
|
||||
|
||||
let mut indices =
|
||||
composite_indices!(self.in_module, indices,
|
||||
&mut self.term_stream.indices.code_dir);
|
||||
|
||||
let tl = new_rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
||||
|
||||
if !is_consistent(&tl, &preds) { // if is_consistent returns false, preds is non-empty.
|
||||
// if is_consistent returns false, preds is non-empty.
|
||||
if !is_consistent(&tl, &preds) {
|
||||
let result_queue = self.rel_worker.parse_queue(&mut indices)?;
|
||||
self.results.push((append_preds(&mut preds), result_queue));
|
||||
}
|
||||
@@ -791,8 +795,9 @@ impl<R: Read> TopLevelBatchWorker<R> {
|
||||
}
|
||||
|
||||
if !preds.is_empty() {
|
||||
let mut indices = composite_indices!(self.in_module, indices,
|
||||
&mut self.static_code_dir);
|
||||
let mut indices =
|
||||
composite_indices!(self.in_module, indices,
|
||||
&mut self.term_stream.indices.code_dir);
|
||||
|
||||
let result_queue = self.rel_worker.parse_queue(&mut indices)?;
|
||||
self.results.push((append_preds(&mut preds), result_queue));
|
||||
|
||||
Reference in New Issue
Block a user