From: Mark Thom Date: Sat, 6 Oct 2018 22:25:10 +0000 (-0600) Subject: remove need for taking code_dir X-Git-Tag: v0.8.110~345 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=c85eba0e2244fda15ee3ba8c138603c086854fb4;p=scryer-prolog.git remove need for taking code_dir --- diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index aa09b1b7..ecbb1b8c 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -97,16 +97,20 @@ fn compile_query(terms: Vec, queue: Vec, flags: MachineFlag Ok((code, cg.take_vars())) } -fn package_term(wam: &mut Machine, term: Term) -> Result { - 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 +{ + 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_results: Vec<(Predicate, VecDeque)>, + toplevel_indices: IndexStore +} + pub struct ListingCompiler { non_counted_bt_preds: HashSet, module: Option, @@ -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, indices: &mut IndexStore) + fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec, + 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 { } } } -} -pub -fn compile_listing(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); + fn gather_items(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore) + -> Result + { + let flags = wam.machine_flags(); + let machine_st = &mut wam.machine_st; + let wam_indices = &mut wam.indices; - let mut compiler = ListingCompiler::new(); - let mut toplevel_results = vec![]; - let mut toplevel_indices = default_index_store!(wam.indices.atom_tbl.clone()); + 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); - 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; + let mut toplevel_results = vec![]; + let mut toplevel_indices = default_index_store!(atom_tbl.clone()); - try_eval_session!(compiler.process_decl(decl, wam, &mut indices)); + 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; - if let &Some(ref module) = &compiler.module { - worker.term_stream.set_atom_tbl(module.atom_tbl.clone()); + 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)?; } - } else { - try_eval_session!(compiler.process_decl(decl, wam, &mut indices)); } + + Ok(GatherResult { + worker_results: worker.results, + toplevel_results, + toplevel_indices + }) } +} - wam.swap_code_dir(&mut worker.static_code_dir); +pub +fn compile_listing(wam: &mut Machine, src: R, mut indices: IndexStore) -> EvalSession +{ + let mut compiler = ListingCompiler::new(); + let mut results = try_eval_session!(compiler.gather_items(wam, src, &mut indices)); - 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 } diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 30dd0870..e192b4fc 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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> { @@ -138,32 +146,54 @@ impl CodeRepo { } } -pub struct Machine { - ms: MachineState, +pub struct MachinePolicies { call_policy: Box, cut_policy: Box, +} + +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 for Machine { +impl Index for CodeRepo { type Output = Line; fn index(&self, ptr: LocalCodePtr) -> &Self::Output { match ptr { LocalCodePtr::TopLevel(_, p) => { - match &self.code_repo.cached_query { + match &self.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] + LocalCodePtr::DirEntry(p) => &self.code[p], + LocalCodePtr::UserTermExpansion(p) => &self.term_expanders[p] } } } +impl Index for Machine { + type Output = Line; + + fn index(&self, ptr: LocalCodePtr) -> &Self::Output { + &self.code_repo[ptr] + } +} + impl SubModuleUser for IndexStore { fn atom_tbl(&self) -> TabledData { self.atom_tbl.clone() @@ -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 { 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,104 +366,190 @@ impl Machine { preds.0.push(clause); - let mut cg = CodeGenerator::::new(false, self.ms.flags); + let mut cg = CodeGenerator::::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) + fn fail(&mut self, heap_locs: &HeapVarDict) -> EvalSession { - let instr = match self.code_repo.lookup_instr(self.ms.last_call, &self.ms.p) { + 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.machine_st.print_exception(Addr::HeapCell(h), + &heap_locs, + TermFormatter {}, + PrinterOutputter::new()) + .result(); + + EvalSession::from(SessionError::QueryFailureWithException(error_str)) + } else { + EvalSession::from(SessionError::QueryFailure) + } + } + + pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession + { + let mut heap_locs = HashMap::new(); + + self.code_repo.cached_query = Some(code); + self.machine_st.run_query(&mut self.indices, &mut self.policies, &self.code_repo, &alloc_locs, &mut heap_locs); + + if self.machine_st.fail { + self.fail(&heap_locs) + } else { + EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) + } + } + + pub fn continue_query(&mut self, alloc_l: &AllocVarDict, heap_l: &mut HeapVarDict) -> EvalSession + { + if !self.or_stack_is_empty() { + 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.machine_st.p { + return EvalSession::from(SessionError::QueryFailure); + } + + 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 + } + } else { + EvalSession::from(SessionError::QueryFailure) + } + } + + pub fn heap_view(&self, var_dir: &HeapVarDict, mut output: Outputter) -> Outputter + where Outputter: HCValueOutputter + { + let mut sorted_vars: Vec<(&Rc, &Addr)> = var_dir.iter().collect(); + sorted_vars.sort_by_key(|ref v| v.0); + + for (var, addr) in sorted_vars { + let fmt = TermFormatter {}; + 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.machine_st.b == 0 + } + + pub fn clear(&mut self) { + let mut machine = Machine::new(); + mem::swap(self, &mut machine); + } + + pub fn reset(&mut self) { + 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.ms.execute_arith_instr(arith_instr), + self.execute_arith_instr(arith_instr), &Line::Choice(ref choice_instr) => - self.ms.execute_choice_instr(choice_instr, &mut self.call_policy), + self.execute_choice_instr(choice_instr, &mut policies.call_policy), &Line::Cut(ref cut_instr) => - self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy), + self.execute_cut_instr(cut_instr, &mut policies.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), + 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.failed() { + if self.fail { break; } - self.ms.execute_fact_instr(&fact_instr); + self.execute_fact_instr(&fact_instr); } - self.ms.p += 1; + self.p += 1; }, &Line::Indexing(ref indexing_instr) => - self.ms.execute_indexing_instr(&indexing_instr), + self.execute_indexing_instr(&indexing_instr), &Line::IndexedChoice(ref choice_instr) => - self.ms.execute_indexed_choice_instr(choice_instr, &mut self.call_policy), + self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy), &Line::Query(ref query) => { for query_instr in query { - if self.failed() { + if self.fail { break; } - self.ms.execute_query_instr(&query_instr); + self.execute_query_instr(&query_instr); } - self.ms.p += 1; + self.p += 1; } } } fn backtrack(&mut self) { - if self.ms.b > 0 { - let b = self.ms.b - 1; + if self.b > 0 { + let b = self.b - 1; - self.ms.b0 = self.ms.or_stack[b].b0; - self.ms.p = self.ms.or_stack[b].bp.clone(); + self.b0 = self.or_stack[b].b0; + self.p = self.or_stack[b].bp.clone(); - if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.ms.p { - self.ms.fail = p == 0; + if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p { + self.fail = p == 0; } else { - self.ms.fail = false; + self.fail = false; } } else { - self.ms.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0)); + self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0)); } } - fn query_stepper<'a>(&mut self) + fn query_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, code_repo: &CodeRepo) { loop { - self.execute_instr(); + self.execute_instr(indices, policies, code_repo); - if self.failed() { + if self.fail { 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, + 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) + 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 e = self.e; let r = var_data.as_reg_type().reg_num(); - let addr = self.ms.and_stack[e][r].clone(); + let addr = self.and_stack[e][r].clone(); heap_locs.insert(var.clone(), addr); }, @@ -452,7 +557,7 @@ impl Machine { let r = var_data.as_reg_type(); if r.reg_num() != 0 { - let addr = self.ms[r].clone(); + let addr = self[r].clone(); heap_locs.insert(var.clone(), addr); } }, @@ -461,13 +566,16 @@ impl Machine { } } - fn run_query(&mut self, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict) + 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, self.cached_query_size()); + let end_ptr = top_level_code_ptr!(0, code_repo.size_of_cached_query()); - while self.ms.p < end_ptr { - if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.ms.p { - match &self[LocalCodePtr::TopLevel(cn, p)] { + 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; @@ -475,12 +583,12 @@ impl Machine { _ => {} } - self.ms.p = top_level_code_ptr!(cn, p); + self.p = top_level_code_ptr!(cn, p); } - self.query_stepper(); + self.query_stepper(indices, policies, code_repo); - match self.ms.p { + match self.p { CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {}, _ => { if heap_locs.is_empty() { @@ -491,87 +599,6 @@ impl Machine { } }; } - } - - 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(); - - let error_str = self.ms.print_exception(Addr::HeapCell(h), - &heap_locs, - TermFormatter {}, - PrinterOutputter::new()) - .result(); - - EvalSession::from(SessionError::QueryFailureWithException(error_str)) - } else { - EvalSession::from(SessionError::QueryFailure) - } - } - - pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession - { - let mut heap_locs = HashMap::new(); - - self.code_repo.cached_query = Some(code); - self.run_query(&alloc_locs, &mut heap_locs); - - if self.failed() { - self.fail(&heap_locs) - } else { - EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) - } - } - - 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(); - - if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.ms.p { - return EvalSession::from(SessionError::QueryFailure); - } - - self.run_query(alloc_l, heap_l); - - if self.failed() { - self.fail(&heap_l) - } else { - EvalSession::SubsequentQuerySuccess - } - } else { - EvalSession::from(SessionError::QueryFailure) - } - } - - pub fn heap_view(&self, var_dir: &HeapVarDict, mut output: Outputter) -> Outputter - where Outputter: HCValueOutputter - { - let mut sorted_vars: Vec<(&Rc, &Addr)> = var_dir.iter().collect(); - sorted_vars.sort_by_key(|ref v| v.0); - - for (var, addr) in sorted_vars { - let fmt = TermFormatter {}; - output = self.ms.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output); - } - - output - } - - pub fn or_stack_is_empty(&self) -> bool { - self.ms.b == 0 - } - - pub fn clear(&mut self) { - let mut machine = Machine::new(); - mem::swap(self, &mut machine); - } - - pub fn reset(&mut self) { - self.cut_policy = Box::new(DefaultCutPolicy {}); - self.ms.reset(); - } + } } + diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index e4ee2056..97a148ba 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -9,16 +9,26 @@ use prolog::read::*; use std::cell::Cell; use std::io::Read; -pub struct TermStream { +pub struct TermStream<'a, R: Read> { stack: Vec, + pub(crate) indices: &'a mut IndexStore, + policies: &'a mut MachinePolicies, + code_repo: &'a mut CodeRepo, parser: Parser, in_module: bool } -impl TermStream { - pub fn new(src: R, atom_tbl: TabledData, flags: MachineFlags) -> Self { +impl<'a, R: Read> TermStream<'a, R> { + pub fn new(src: R, atom_tbl: TabledData, 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 TermStream { } } - pub fn read_term(&mut self, wam: &mut Machine, op_dir: &OpDir) -> Result + pub fn read_term(&mut self, machine_st: &mut MachineState, op_dir: &OpDir) + -> Result { 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, 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, 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)) } diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 1b87b6f6..8ea8c414 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -46,10 +46,11 @@ pub fn read_toplevel(wam: &mut Machine) -> Result { }, _ => { 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())?)) } } } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index f5b15c0e..8ea97ec0 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -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(wam: &Machine, buf: R) -> Result } pub -fn consume_term(static_code_dir: &mut CodeDir, term: Term, indices: &mut IndexStore) - -> Result +fn consume_term(term: Term, indices: &mut IndexStore) -> Result { 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 { - pub(crate) term_stream: TermStream, +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)>, pub(crate) in_module: bool } -impl TopLevelBatchWorker { - pub fn new(inner: R, atom_tbl: TabledData, flags: MachineFlags, static_code_dir: CodeDir) +impl<'a, R: Read> TopLevelBatchWorker<'a, R> { + pub fn new(inner: R, + atom_tbl: TabledData, + 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, 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 TopLevelBatchWorker { } 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));