use prolog::compile::*;
use prolog::machine::*;
use prolog::read::*;
+use prolog::toplevel::string_to_toplevel;
use prolog::write::*;
use std::io::{Write, stdin, stdout};
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) => {
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()) {
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());
-> 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 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);
(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).
}
impl MachineState {
- pub(super) fn new() -> Self {
+ pub(crate) fn new() -> Self {
MachineState {
s: 0,
p: CodePtr::default(),
}
}
- 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,
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);
}
};
}
}
+ pub(crate)
fn run_goal_expanders(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, term: Term)
-> Result<Term, ParserError>
{
}
}
- 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![];
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)
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};
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();
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))
}
}
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)
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)?;
+
+ 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> {
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);
}
}
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)
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;
}
use prolog::toplevel::*;
use std::collections::HashSet;
+use std::io::empty;
use std::mem::swap;
use std::ops::{Range, RangeFrom};
{
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) =>
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")
}
}
{
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) =>
EvalSession::EntrySuccess => true,
_ => false
},
- Err(e) => panic!("syntax_error({})", e.as_str())
+ Err(_) => panic!("syntax_error")
}
}