streamline inputs.

This commit is contained in:
Mark Thom
2018-09-13 19:44:50 -06:00
parent d09e9fd8d8
commit 1e2047e72c
10 changed files with 119 additions and 98 deletions

View File

@@ -9,7 +9,6 @@ use prolog::toplevel::*;
use std::collections::{HashMap, HashSet, VecDeque};
use std::io::Read;
use std::mem;
use std::ops::DerefMut;
#[allow(dead_code)]
fn print_code(code: &Code) {
@@ -98,10 +97,10 @@ fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>, flags: MachineFlag
}
fn package_term(wam: &mut Machine, term: Term) -> Result<TopLevelPacket, ParserError> {
let mut code_dir = wam.code_dir.borrow_mut();
let indices = machine_code_indices!(code_dir.deref_mut(), &mut wam.op_dir, &mut wam.modules);
parse_term(term, indices)
let code_dir = wam.code_dir.clone();
let indices = machine_code_indices!(&mut CodeDir::new(), &mut wam.op_dir, &mut wam.modules);
consume_term(code_dir, term, indices)
}
pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
@@ -262,10 +261,10 @@ impl ListingCompiler {
}
}
pub fn compile_listing<'a, R>(wam: &mut Machine, src: R, mut indices: MachineCodeIndices<'a>,
mut toplevel_indices: MachineCodeIndices<'a>)
-> EvalSession
where R: Read
pub
fn compile_listing<'a, R: Read>(wam: &mut Machine, src: R, mut indices: MachineCodeIndices<'a>,
mut toplevel_indices: MachineCodeIndices<'a>)
-> EvalSession
{
let mut worker = TopLevelBatchWorker::new(src, wam.atom_tbl(), wam.machine_flags(),
wam.code_dir.clone());

View File

@@ -770,7 +770,7 @@ impl HeapCellValue {
}
}
#[derive(Clone, Copy,PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub enum IndexPtr {
Undefined, Index(usize),
Module // This is a resolved module call. The module
@@ -794,7 +794,7 @@ impl CodeIndex {
#[inline]
pub fn module_name(&self) -> ClauseName {
self.0.borrow().1.clone()
self.0.borrow().1.clone()
}
}

View File

@@ -105,7 +105,6 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> {
}
set_code_index!(code_idx, idx.0, idx.1);
return;
}
@@ -169,14 +168,15 @@ impl Machine {
}
};
if idx.module_name().as_str() == "builtins" {
continue;
}
if let Some(ref existing_idx) = self.code_dir.borrow().get(&key) {
// ensure we don't try to overwrite an existing predicate from a different module.
if !existing_idx.is_undefined() {
if existing_idx.module_name() != idx.module_name() {
if !existing_idx.is_undefined() && !idx.is_undefined() {
// allow the overwriting of user-level predicates by all other predicates.
if existing_idx.module_name().as_str() == "user" {
continue;
}
if existing_idx.module_name().as_str() != idx.module_name().as_str() {
let err_str = format!("{}/{} from module {}", key.0, key.1,
existing_idx.module_name().as_str());
return Err(SessionError::CannotOverwriteImport(err_str));
@@ -185,8 +185,23 @@ impl Machine {
}
}
// error detection has finished, so update the master index of keys.
for (key, idx) in code_dir {
if let Some(ref mut master_idx) = self.code_dir.borrow_mut().get_mut(&key) {
// ensure we don't double borrow if master_idx == idx.
// we don't need to modify anything in that case.
if !Rc::ptr_eq(&master_idx.0, &idx.0) {
set_code_index!(master_idx, idx.0.borrow().0, idx.module_name());
}
continue;
}
self.code_dir.borrow_mut().insert(key.clone(), idx.clone());
}
self.code.extend(code.into_iter());
Ok(self.code_dir.borrow_mut().extend(code_dir.into_iter()))
Ok(())
}
#[inline]

View File

@@ -6,7 +6,7 @@ extern crate prolog_parser;
mod and_stack;
#[macro_use] mod macros;
#[macro_use] mod allocator;
mod toplevel;
pub mod toplevel;
pub mod machine;
pub mod compile;
mod arithmetic;

View File

@@ -5,6 +5,7 @@ use prolog::instructions::*;
use prolog::iterators::*;
use prolog::machine::*;
use prolog::machine::machine_state::MachineState;
use prolog::toplevel::*;
use std::collections::VecDeque;
use std::io::{Read, stdin};
@@ -38,13 +39,11 @@ pub fn read_toplevel(wam: &Machine) -> Result<Input, ParserError> {
match &*buffer.trim() {
"quit" => Ok(Input::Quit),
"clear" => Ok(Input::Clear),
"[user]" => Ok(Input::Batch),
_ => {
let mut parser = Parser::new(stdin.lock(), wam.atom_tbl(), wam.machine_flags());
parser.add_to_top(buffer.as_str());
Ok(Input::Term(parser.read_term(composite_op!(&wam.op_dir))?))
}
"[user]" => {
println!("(type Enter + Ctrl-D to terminate the stream when finished)");
Ok(Input::Batch)
},
_ => Ok(Input::Term(parse_term(wam, buffer.as_bytes())?))
}
}

View File

@@ -36,12 +36,15 @@ impl<'a, 'b : 'a> CompositeIndices<'a, 'b>
{
fn get_code_index(&mut self, name: ClauseName, arity: usize) -> CodeIndex {
let idx_opt = self.local.code_dir.get(&(name.clone(), arity)).cloned()
.or_else(|| self.static_code_dir.clone().and_then(|code_dir| {
code_dir.borrow().get(&(name.clone(), arity)).cloned()
}));
.or_else(|| {
self.static_code_dir.clone().and_then(|code_dir| {
code_dir.borrow().get(&(name.clone(), arity)).cloned()
})
});
if let Some(idx) = idx_opt {
idx.clone()
self.local.code_dir.insert((name, arity), idx.clone());
idx
} else {
let idx = CodeIndex::default();
self.local.code_dir.insert((name, arity), idx.clone());
@@ -666,10 +669,20 @@ impl RelationWorker {
}
}
pub fn parse_term<'a>(term: Term, mut indices: MachineCodeIndices<'a>) -> Result<TopLevelPacket, ParserError>
// used to parse queries. mostly.
pub fn parse_term<R: Read>(wam: &Machine, buf: R) -> Result<Term, ParserError>
{
let mut parser = Parser::new(buf, wam.atom_tbl(), wam.machine_flags());
parser.read_term(composite_op!(&wam.op_dir))
}
pub
fn consume_term<'a>(static_code_dir: Rc<RefCell<CodeDir>>, term: Term,
mut indices: MachineCodeIndices<'a>)
-> Result<TopLevelPacket, ParserError>
{
let mut rel_worker = RelationWorker::new();
let mut indices = composite_indices!(&mut indices);
let mut indices = composite_indices!(false, &mut indices, static_code_dir);
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
let results = rel_worker.parse_queue(&mut indices)?;

View File

@@ -1,9 +1,8 @@
use prolog_parser::ast::*;
use prolog::heap_print::*;
use prolog::instructions::*;
use prolog::compile::*;
use prolog::machine::*;
use prolog::toplevel::*;
use std::collections::HashSet;
use std::mem::swap;
@@ -120,16 +119,12 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool
{
wam.reset();
match parse_code(wam, buffer) {
Ok(tl) =>
match compile_packet(wam, tl) {
EvalSession::InitialQuerySuccess(_, _) |
EvalSession::EntrySuccess |
EvalSession::SubsequentQuerySuccess =>
true,
_ => false
},
Err(e) => panic!("syntax_error({})", e.as_str())
match compile_user_module(wam, buffer.as_bytes()) {
EvalSession::InitialQuerySuccess(_, _) |
EvalSession::EntrySuccess |
EvalSession::SubsequentQuerySuccess =>
true,
_ => false
}
}
@@ -138,9 +133,9 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>
{
wam.reset();
match parse_code(wam, buffer) {
Ok(tl) =>
match compile_packet(wam, tl) {
match parse_term(&wam, buffer.as_bytes()) {
Ok(term) =>
match compile_term(wam, term) {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
result == collect_test_output(wam, alloc_locs, heap_locs),
EvalSession::EntrySuccess => true,
@@ -150,6 +145,21 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>
}
}
#[allow(dead_code)]
pub fn submit_query_without_results(wam: &mut Machine, buffer: &str) -> bool {
wam.reset();
match parse_term(&wam, buffer.as_bytes()) {
Ok(term) =>
match compile_term(wam, term) {
EvalSession::InitialQuerySuccess(..)
| EvalSession::EntrySuccess => true,
_ => false
},
Err(e) => panic!("syntax_error({})", e.as_str())
}
}
#[allow(dead_code)]
pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
result: Vec<HashSet<String>>, limit: usize)
@@ -157,9 +167,9 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
{
wam.reset();
match parse_code(wam, buffer) {
Ok(tl) =>
match compile_packet(wam, tl) {
match parse_term(&wam, buffer.as_bytes()) {
Ok(term) =>
match compile_term(wam, term) {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
result == collect_test_output_with_limit(wam, alloc_locs,
heap_locs, limit),
@@ -187,7 +197,7 @@ macro_rules! assert_prolog_success_with_limit {
#[allow(unused_macros)]
macro_rules! assert_prolog_failure {
($wam: expr, $buf: expr) => (
assert_eq!(submit($wam, $buf), false)
assert_eq!(submit_query_without_results($wam, $buf), false)
)
}
@@ -197,7 +207,7 @@ macro_rules! assert_prolog_success {
assert!(submit_query($wam, $query, vec![$(expand_strs!($res)),*]))
);
($wam:expr, $buf:expr) => (
assert_eq!(submit($wam, $buf), true)
assert_eq!(submit_query_without_results($wam, $buf), true)
)
}
@@ -1342,7 +1352,7 @@ fn test_queries_on_modules()
{
let mut wam = Machine::new();
wam.use_module_in_toplevel(clause_name!("lists"));
submit(&mut wam, ":- use_module(library(lists)).");
compile_user_module(&mut wam, "
:- module(my_lists, [local_member/2, reverse/2]).
@@ -1357,8 +1367,8 @@ reverse(Xs, Ys) :- lists:reverse(Xs, Ys).
assert_prolog_success!(&mut wam, "?- my_lists:reverse([a,b,c], [c,b,a]).");
compile_user_module(&mut wam, "
:- use_module(library(my_lists), [local_member/2]).
:- module(my_lists_2, [local_member/2]).
:- use_module(library(my_lists), [local_member/2]).
".as_bytes());
assert_prolog_success!(&mut wam, "?- my_lists_2:local_member(1, [1,2,3]).");
@@ -1371,8 +1381,8 @@ fn test_queries_on_builtins()
{
let mut wam = Machine::new();
wam.use_module_in_toplevel(clause_name!("lists"));
wam.use_module_in_toplevel(clause_name!("control"));
submit(&mut wam, ":- use_module(library(lists)).");
submit(&mut wam, ":- use_module(library(control)).");
assert_prolog_failure!(&mut wam, "?- atom(X).");
assert_prolog_success!(&mut wam, "?- atom(a).");
@@ -1876,19 +1886,19 @@ fn test_queries_on_string_lists()
assert_prolog_success!(&mut wam, "?- X = [a,b,c|\"abc\"].",
[["X = [a, b, c, a, b, c]"]]);
submit(&mut wam, "?- set_prolog_flag(double_quotes, atom).");
assert_prolog_success!(&mut wam, "?- set_prolog_flag(double_quotes, atom).");
assert_prolog_success!(&mut wam, "?- matcher(X, Y).",
[["X = [a, b, c | _1]", "Y = _1"]]);
assert_prolog_failure!(&mut wam, "?- matcher(\"abcdef\", Y).");
submit(&mut wam, "?- set_prolog_flag(double_quotes, chars).");
assert_prolog_success!(&mut wam, "?- set_prolog_flag(double_quotes, chars).");
assert_prolog_success!(&mut wam, "?- X = \"abc\", X = ['a' | Y], set_prolog_flag(double_quotes, atom).",
[["X = \"abc\"", "Y = \"bc\""]]);
// partial strings.
submit(&mut wam, "?- set_prolog_flag(double_quotes, chars).");
assert_prolog_success!(&mut wam, "?- set_prolog_flag(double_quotes, chars).");
assert_prolog_failure!(&mut wam, "?- Y = 5, partial_string(\"abc\", Y).");
assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X).",