From: Mark Thom Date: Sat, 2 Feb 2019 06:36:51 +0000 (-0700) Subject: expand goals in queries and queues X-Git-Tag: v0.8.110~282 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=c5fbff505b3103cdbf3e55bb272182994e11ae58;p=scryer-prolog.git expand goals in queries and queues --- diff --git a/src/main.rs b/src/main.rs index 3f0076e9..48dc33d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod prolog; use prolog::compile::*; use prolog::machine::*; use prolog::read::*; +use prolog::toplevel::string_to_toplevel; use prolog::write::*; use std::io::{Write, stdin, stdout}; @@ -23,9 +24,14 @@ fn prolog_repl() { print!("prolog> "); stdout().flush().unwrap(); - match read_toplevel(&mut wam) { - Ok(Input::Term(term)) => { - let result = compile_term(&mut wam, term); + match toplevel_read_line() { + Ok(Input::TermString(buffer)) => { + let stdin = stdin(); + let result = match string_to_toplevel(stdin.lock(), buffer, &mut wam) { + Ok(packet) => compile_term(&mut wam, packet), + Err(e) => EvalSession::from(e) + }; + print(&mut wam, result) }, Ok(Input::Batch) => { diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index 2f746e79..49c1f491 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -138,10 +138,8 @@ fn compile_decl(wam: &mut Machine, compiler: &mut ListingCompiler, decl: Declara Ok(indices) } -pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession +pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession { - let packet = try_eval_session!(consume_term(term, &mut wam.indices)); - match packet { TopLevelPacket::Query(terms, queue) => match compile_query(terms, queue, wam.machine_flags()) { @@ -260,7 +258,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()); @@ -384,7 +382,6 @@ impl ListingCompiler { -> Result { 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(); @@ -395,7 +392,7 @@ impl ListingCompiler { let mut toplevel_results = vec![]; let mut toplevel_indices = default_index_store!(atom_tbl.clone()); - while let Some(decl) = worker.consume(machine_st, indices)? { + while let Some(decl) = worker.consume(indices)? { if decl.is_module_decl() { toplevel_indices.copy_and_swap(indices); mem::swap(&mut worker.results, &mut toplevel_results); diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl index a202e2de..76c600c9 100644 --- a/src/prolog/lib/atts.pl +++ b/src/prolog/lib/atts.pl @@ -111,9 +111,9 @@ get_attr(Name, Arity) --> (get_atts(V, Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)), (get_atts(V, -Attr) :- !, functor(Attr, _, _), absent_attr(V, Attr))]. -user:goal_expansion(Term, [M:put_atts(Var, Attr)]) :- +user:goal_expansion(Term, M:put_atts(Var, Attr)) :- nonvar(Term), Term = put_atts(Var, M, Attr). -user:goal_expansion(Term, [M:get_atts(Var, Attr)]) :- +user:goal_expansion(Term, M:get_atts(Var, Attr)) :- nonvar(Term), Term = get_atts(Var, M, Attr). diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index efe72501..11a41941 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -31,7 +31,7 @@ macro_rules! try_or_fail { } impl MachineState { - pub(super) fn new() -> Self { + pub(crate) fn new() -> Self { MachineState { s: 0, p: CodePtr::default(), diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 2106895a..2b336973 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -193,17 +193,17 @@ impl<'a, R: Read> TermStream<'a, R> { } } - fn parse_expansion_output(&mut self, term_string: &str, op_dir: &OpDir) - -> Result + fn parse_expansion_output(&self, term_string: &str, op_dir: &OpDir) -> Result { let mut parser = Parser::new(term_string.trim().as_bytes(), self.parser.get_atom_tbl(), self.flags); parser.read_term(composite_op!(self.in_module, &self.indices.op_dir, op_dir)) } - pub fn read_term(&mut self, machine_st: &mut MachineState, op_dir: &OpDir) - -> Result + pub fn read_term(&mut self, op_dir: &OpDir) -> Result { + let mut machine_st = MachineState::new(); + loop { while let Some(term) = self.stack.pop() { match machine_st.try_expand_term(self.indices, self.policies, self.code_repo, @@ -214,7 +214,7 @@ impl<'a, R: Read> TermStream<'a, R> { self.enqueue_term(term)? }, None => { - let term = self.run_goal_expanders(machine_st, op_dir, term)?; + let term = self.run_goal_expanders(&mut machine_st, op_dir, term)?; return Ok(term); } }; @@ -227,6 +227,7 @@ impl<'a, R: Read> TermStream<'a, R> { } } + pub(crate) fn run_goal_expanders(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, term: Term) -> Result { @@ -257,8 +258,7 @@ impl<'a, R: Read> TermStream<'a, R> { } } - fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, - mut terms: VecDeque) + fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, mut terms: VecDeque) -> Result, ParserError> { let mut results = vec![]; @@ -275,8 +275,7 @@ impl<'a, R: Read> TermStream<'a, R> { for term in extract_from_list(head, tail)? { terms.push_front(term); }, - term => - terms.push_front(term) + term => terms.push_front(term) }; }, None => results.push(term) diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 891280ad..6dc39e3e 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -4,9 +4,7 @@ use prolog_parser::tabled_rc::TabledData; use prolog::instructions::*; use prolog::iterators::*; -use prolog::machine::*; use prolog::machine::machine_state::MachineState; -use prolog::machine::term_expansion::*; use std::collections::VecDeque; use std::io::{Read, stdin}; @@ -28,10 +26,10 @@ pub enum Input { Quit, Clear, Batch, - Term(Term) + TermString(String) } -pub fn read_toplevel(wam: &mut Machine) -> Result { +pub fn toplevel_read_line() -> Result { let mut buffer = String::new(); let stdin = stdin(); @@ -44,14 +42,7 @@ pub fn read_toplevel(wam: &mut Machine) -> Result { println!("(type Enter + Ctrl-D to terminate the stream when finished)"); Ok(Input::Batch) }, - _ => { - let mut term_stream = TermStream::new(stdin.lock(), wam.indices.atom_tbl.clone(), - 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(&mut wam.machine_st, &OpDir::new())?)) - } + _ => Ok(Input::TermString(buffer)) } } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index cc8be68e..edafbe2d 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -700,7 +700,6 @@ impl RelationWorker { while let Some(terms) = self.queue.pop_front() { let clauses = merge_clauses(&mut self.try_terms_to_tls(indices, terms, false)?)?; queue.push_back(clauses); - } Ok(queue) @@ -709,29 +708,59 @@ impl RelationWorker { fn absorb(&mut self, other: RelationWorker) { self.queue.extend(other.queue.into_iter()); } + + fn expand_queue_contents<'a, R>(&mut self, term_stream: &mut TermStream<'a, R>, op_dir: &OpDir) + -> Result<(), SessionError> + where R: Read + { + let mut machine_st = MachineState::new(); + let mut new_queue = VecDeque::new(); + + while let Some(terms) = self.queue.pop_front() { + let mut new_terms = VecDeque::new(); + + for term in terms { + new_terms.push_back(term_stream.run_goal_expanders(&mut machine_st, &op_dir, term)?); + } + + new_queue.push_back(new_terms); + } + + Ok(self.queue = new_queue) + } } -// used to parse queries in test. -#[cfg(test)] -pub fn parse_term(wam: &Machine, buf: R) -> Result +fn term_to_toplevel<'a, R>(term_stream: &mut TermStream<'a, R>, code_dir: &mut CodeDir, term: Term) + -> Result<(TopLevel, RelationWorker), ParserError> + where R: Read { - use prolog_parser::parser::*; + let mut rel_worker = RelationWorker::new(); + let mut indices = composite_indices!(false, term_stream.indices, code_dir); - let mut parser = Parser::new(buf, wam.indices.atom_tbl.clone(), wam.machine_flags()); - parser.read_term(composite_op!(&wam.indices.op_dir)) + Ok((rel_worker.try_term_to_tl(&mut indices, term, true)?, rel_worker)) } pub -fn consume_term(term: Term, indices: &mut IndexStore) -> Result +fn string_to_toplevel(src: R, buffer: String, wam: &mut Machine) + -> Result { - let mut rel_worker = RelationWorker::new(); + let mut term_stream = TermStream::new(src, wam.indices.atom_tbl.clone(), + wam.machine_flags(), &mut wam.indices, + &mut wam.policies, &mut wam.code_repo); + + term_stream.add_to_top(buffer.as_str()); + + let term = term_stream.read_term(&OpDir::new())?; 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)?; + let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term)?; + + rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?; + + let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir); + let queue = rel_worker.parse_queue(&mut indices)?; - Ok(deque_to_packet(tl, results)) + Ok(deque_to_packet(tl, queue)) } pub struct TopLevelBatchWorker<'a, R: Read> { @@ -756,31 +785,47 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> { in_module: false } } + fn try_term_to_tl(&self, indices: &mut IndexStore, term: Term) + -> Result<(TopLevel, RelationWorker), SessionError> + { + let mut new_rel_worker = RelationWorker::new(); + let mut indices = composite_indices!(self.in_module, indices, + &self.term_stream.indices.code_dir); + + Ok((new_rel_worker.try_term_to_tl(&mut indices, term, true)?, new_rel_worker)) + } + + fn process_result(&mut self, indices: &mut IndexStore, preds: &mut Vec) + -> Result<(Predicate, VecDeque), SessionError> + { + self.rel_worker.expand_queue_contents(&mut self.term_stream, &indices.op_dir)?; + + let mut indices = composite_indices!(self.in_module, indices, + &mut self.term_stream.indices.code_dir); + + let queue = self.rel_worker.parse_queue(&mut indices)?; + let result = (append_preds(preds), queue); + + let in_situ_code_dir = &mut self.term_stream.indices.in_situ_code_dir; + + self.term_stream.code_repo.add_in_situ_result(&result, in_situ_code_dir, + self.term_stream.flags)?; + + Ok(result) + } + pub - fn consume(&mut self, machine_st: &mut MachineState, indices: &mut IndexStore) - -> Result, SessionError> + fn consume(&mut self, indices: &mut IndexStore) -> Result, SessionError> { let mut preds = vec![]; while !self.term_stream.eof()? { - let mut new_rel_worker = RelationWorker::new(); - let term = self.term_stream.read_term(machine_st, &indices.op_dir)?; + let term = self.term_stream.read_term(&indices.op_dir)?; + let (tl, new_rel_worker) = self.try_term_to_tl(indices, term)?; - 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 returns false, preds is non-empty. + // if is_consistent is false, preds is non-empty. if !is_consistent(&tl, &preds) { - let result_queue = self.rel_worker.parse_queue(&mut indices)?; - let result = (append_preds(&mut preds), result_queue); - let in_situ_code_dir = &mut self.term_stream.indices.in_situ_code_dir; - - self.term_stream.code_repo.add_in_situ_result(&result, - in_situ_code_dir, - self.term_stream.flags)?; + let result = self.process_result(indices, &mut preds)?; self.results.push(result); } @@ -796,12 +841,8 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> { } if !preds.is_empty() { - 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)); + let result = self.process_result(indices, &mut preds)?; + self.results.push(result); } Ok(None) diff --git a/src/prolog/write.rs b/src/prolog/write.rs index 1b6bf0c1..e54d8527 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -320,7 +320,7 @@ impl fmt::Display for Level { pub fn print(wam: &mut Machine, result: EvalSession) { match result { EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => { - if heap_locs.is_empty() { + if wam.or_stack_is_empty() && heap_locs.is_empty() { println!("true."); return; } diff --git a/src/tests.rs b/src/tests.rs index 4e5ab35e..df2904a3 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -5,6 +5,7 @@ use prolog::machine::*; use prolog::toplevel::*; use std::collections::HashSet; +use std::io::empty; use std::mem::swap; use std::ops::{Range, RangeFrom}; @@ -146,7 +147,7 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec { wam.reset(); - match parse_term(&wam, buffer.as_bytes()) { + match string_to_toplevel(empty(), String::from(buffer), wam) { Ok(term) => match compile_term(wam, term) { EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) => @@ -154,22 +155,23 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec EvalSession::EntrySuccess => true, _ => false }, - Err(e) => panic!("syntax_error({})", e.as_str()) + Err(_) => panic!("syntax error") } } #[allow(dead_code)] -pub fn submit_query_without_results(wam: &mut Machine, buffer: &str) -> bool { +pub fn submit_query_without_results(wam: &mut Machine, buffer: &str) -> bool +{ wam.reset(); - match parse_term(&wam, buffer.as_bytes()) { + match string_to_toplevel(empty(), String::from(buffer), wam) { Ok(term) => match compile_term(wam, term) { EvalSession::InitialQuerySuccess(..) | EvalSession::EntrySuccess => true, _ => false }, - Err(e) => panic!("syntax_error({})", e.as_str()) + Err(_) => panic!("syntax error") } } @@ -180,7 +182,7 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str, { wam.reset(); - match parse_term(&wam, buffer.as_bytes()) { + match string_to_toplevel(empty(), String::from(buffer), wam) { Ok(term) => match compile_term(wam, term) { EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) => @@ -189,7 +191,7 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str, EvalSession::EntrySuccess => true, _ => false }, - Err(e) => panic!("syntax_error({})", e.as_str()) + Err(_) => panic!("syntax_error") } }