expand goals in queries and queues
This commit is contained in:
12
src/main.rs
12
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) => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
16
src/tests.rs
16
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<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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user