expand goals in queries and queues

This commit is contained in:
Mark Thom
2019-02-01 23:36:51 -07:00
parent b6922e2a0d
commit c5fbff505b
9 changed files with 114 additions and 78 deletions

View File

@@ -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) => {

View File

@@ -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<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();
@@ -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);

View File

@@ -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).

View File

@@ -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(),

View File

@@ -193,17 +193,17 @@ impl<'a, R: Read> TermStream<'a, R> {
}
}
fn parse_expansion_output(&mut self, term_string: &str, op_dir: &OpDir)
-> Result<Term, ParserError>
fn parse_expansion_output(&self, term_string: &str, op_dir: &OpDir) -> Result<Term, ParserError>
{
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<Term, ParserError>
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError>
{
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<Term, ParserError>
{
@@ -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<Term>)
fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, mut terms: VecDeque<Term>)
-> Result<Vec<Term>, 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)

View File

@@ -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<Input, ParserError> {
pub fn toplevel_read_line() -> Result<Input, ParserError> {
let mut buffer = String::new();
let stdin = stdin();
@@ -44,14 +42,7 @@ pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {
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))
}
}

View File

@@ -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<R: Read>(wam: &Machine, buf: R) -> Result<Term, ParserError>
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<TopLevelPacket, ParserError>
fn string_to_toplevel<R: Read>(src: R, buffer: String, wam: &mut Machine)
-> Result<TopLevelPacket, SessionError>
{
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)?;
Ok(deque_to_packet(tl, results))
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, 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<PredicateClause>)
-> Result<(Predicate, VecDeque<TopLevel>), 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<Option<Declaration>, SessionError>
fn consume(&mut self, indices: &mut IndexStore) -> Result<Option<Declaration>, 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)

View File

@@ -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;
}

View File

@@ -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<HashSet<String>
{
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<HashSet<String>
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")
}
}