streamline inputs.
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -87,6 +87,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "prolog_parser"
|
name = "prolog_parser"
|
||||||
version = "0.7.12"
|
version = "0.7.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -107,12 +108,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusty-wam"
|
name = "rusty-wam"
|
||||||
version = "0.7.10"
|
version = "0.7.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"prolog_parser 0.7.12",
|
"prolog_parser 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -151,6 +152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
|
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
|
||||||
"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
|
"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
|
||||||
"checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f"
|
"checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f"
|
||||||
|
"checksum prolog_parser 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bbf4229f9ff4f5826367591b0c76de86093c9ea8a8c4a8f2ac7cc66668788ce9"
|
||||||
"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
|
"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
|
||||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rusty-wam"
|
name = "rusty-wam"
|
||||||
version = "0.7.10"
|
version = "0.7.11"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
repository = "https://github.com/mthom/rusty-wam"
|
repository = "https://github.com/mthom/rusty-wam"
|
||||||
description = "The Warren Abstract Machine in Rust."
|
description = "The Warren Abstract Machine in Rust."
|
||||||
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
|
|||||||
downcast = "0.9.1"
|
downcast = "0.9.1"
|
||||||
num = "0.2"
|
num = "0.2"
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = { path = "../prolog_parser", version = "0.7.12" }
|
prolog_parser = "0.7.12"
|
||||||
|
|
||||||
[dependencies.termion]
|
[dependencies.termion]
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
51
README.md
51
README.md
@@ -169,53 +169,36 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `writeq/1`
|
* `writeq/1`
|
||||||
|
|
||||||
## Tutorial
|
## Tutorial
|
||||||
To enter a multi-clause predicate, the brackets ":{" and "}:" are used
|
To enter a multi-clause predicate, the directive "[user]" is used.
|
||||||
as delimiters. They must be contained entirely within their own lines.
|
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
```
|
```
|
||||||
prolog> :{
|
prolog> [user]
|
||||||
|
(type Enter + Ctrl-D to terminate the stream when finished)
|
||||||
p(f(f(X)), h(W), Y) :- g(W), h(W), f(X).
|
p(f(f(X)), h(W), Y) :- g(W), h(W), f(X).
|
||||||
p(X, Y, Z) :- h(Y), z(Z).
|
p(X, Y, Z) :- h(Y), z(Z).
|
||||||
}:
|
prolog> [user]
|
||||||
prolog> :{
|
(type Enter + Ctrl-D to terminate the stream when finished)
|
||||||
h(x).
|
h(x). h(y).
|
||||||
h(y).
|
|
||||||
h(z).
|
h(z).
|
||||||
}:
|
|
||||||
```
|
|
||||||
|
|
||||||
Single clause predicates can be entered without brackets, as in
|
|
||||||
```
|
|
||||||
prolog> p(X) :- q(X).
|
|
||||||
prolog> f(s).
|
|
||||||
prolog> z(Z).
|
|
||||||
```
|
```
|
||||||
|
In the example, `Enter + Ctrl-D` is used to terminate the standard
|
||||||
|
input stream. The instructive message is always printed.
|
||||||
|
|
||||||
Queries are issued as
|
Queries are issued as
|
||||||
```
|
```
|
||||||
prolog> ?- p(X, Y, Z).
|
prolog> ?- p(X, Y, Z).
|
||||||
```
|
```
|
||||||
|
|
||||||
Given the above work, the result of the query will be
|
|
||||||
```
|
|
||||||
prolog> ?- p(X, Y, Z).
|
|
||||||
true
|
|
||||||
Y = x
|
|
||||||
X = _0
|
|
||||||
Z = _2
|
|
||||||
```
|
|
||||||
|
|
||||||
Pressing `SPACE` will backtrack through other possible answers, if any exist.
|
Pressing `SPACE` will backtrack through other possible answers, if any exist.
|
||||||
Pressing `.` will abort the search and return to the prompt.
|
Pressing `.` will abort the search and return to the prompt.
|
||||||
|
|
||||||
Wildcards work as well:
|
Wildcards work as well:
|
||||||
|
|
||||||
```
|
```
|
||||||
prolog> :{
|
prolog> [user]
|
||||||
member(X, [X|_]).
|
member(X, [X|_]).
|
||||||
member(X, [_|Xs]) :- member(X, Xs).
|
member(X, [_|Xs]) :- member(X, Xs).
|
||||||
}:
|
|
||||||
prolog> ?- member(X, [a, b, c]).
|
prolog> ?- member(X, [a, b, c]).
|
||||||
true .
|
true .
|
||||||
X = a ;
|
X = a ;
|
||||||
@@ -225,11 +208,12 @@ false.
|
|||||||
```
|
```
|
||||||
and so do conjunctive queries:
|
and so do conjunctive queries:
|
||||||
```
|
```
|
||||||
prolog> f(X) :- g(X).
|
prolog> [user]
|
||||||
prolog> :{
|
f(X) :- g(X).
|
||||||
|
prolog> [user]
|
||||||
g(x). g(y). g(z).
|
g(x). g(y). g(z).
|
||||||
}:
|
prolog> [user]
|
||||||
prolog> h(call(f, X)).
|
h(call(f, X)).
|
||||||
prolog> ?- h(X), X.
|
prolog> ?- h(X), X.
|
||||||
true .
|
true .
|
||||||
X = call(f, x) ;
|
X = call(f, x) ;
|
||||||
@@ -289,16 +273,15 @@ prolog> :- use_module(library(lists)).
|
|||||||
prolog> :- use_module(library(control)).
|
prolog> :- use_module(library(control)).
|
||||||
```
|
```
|
||||||
|
|
||||||
To define modules inline at the REPL, use the ":{{" and "}}:"
|
The [user] prompt can also be used to define modules inline at the
|
||||||
delimiters:
|
REPL:
|
||||||
|
|
||||||
```
|
```
|
||||||
prolog> :{{
|
prolog> [user]
|
||||||
:- module(test, [local_member/2]).
|
:- module(test, [local_member/2]).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
local_member(X, Xs) :- member(X, Xs).
|
local_member(X, Xs) :- member(X, Xs).
|
||||||
}}:
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`use_module` directives can be qualified by adding a list of imports:
|
`use_module` directives can be qualified by adding a list of imports:
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use prolog::toplevel::*;
|
|||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::DerefMut;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn print_code(code: &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> {
|
fn package_term(wam: &mut Machine, term: Term) -> Result<TopLevelPacket, ParserError> {
|
||||||
let mut code_dir = wam.code_dir.borrow_mut();
|
let code_dir = wam.code_dir.clone();
|
||||||
let indices = machine_code_indices!(code_dir.deref_mut(), &mut wam.op_dir, &mut wam.modules);
|
let indices = machine_code_indices!(&mut CodeDir::new(), &mut wam.op_dir, &mut wam.modules);
|
||||||
|
|
||||||
parse_term(term, indices)
|
consume_term(code_dir, term, indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
|
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>,
|
pub
|
||||||
mut toplevel_indices: MachineCodeIndices<'a>)
|
fn compile_listing<'a, R: Read>(wam: &mut Machine, src: R, mut indices: MachineCodeIndices<'a>,
|
||||||
-> EvalSession
|
mut toplevel_indices: MachineCodeIndices<'a>)
|
||||||
where R: Read
|
-> EvalSession
|
||||||
{
|
{
|
||||||
let mut worker = TopLevelBatchWorker::new(src, wam.atom_tbl(), wam.machine_flags(),
|
let mut worker = TopLevelBatchWorker::new(src, wam.atom_tbl(), wam.machine_flags(),
|
||||||
wam.code_dir.clone());
|
wam.code_dir.clone());
|
||||||
|
|||||||
@@ -770,7 +770,7 @@ impl HeapCellValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy,PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum IndexPtr {
|
pub enum IndexPtr {
|
||||||
Undefined, Index(usize),
|
Undefined, Index(usize),
|
||||||
Module // This is a resolved module call. The module
|
Module // This is a resolved module call. The module
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_code_index!(code_idx, idx.0, idx.1);
|
set_code_index!(code_idx, idx.0, idx.1);
|
||||||
|
|
||||||
return;
|
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) {
|
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.
|
// ensure we don't try to overwrite an existing predicate from a different module.
|
||||||
if !existing_idx.is_undefined() {
|
if !existing_idx.is_undefined() && !idx.is_undefined() {
|
||||||
if existing_idx.module_name() != idx.module_name() {
|
// 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,
|
let err_str = format!("{}/{} from module {}", key.0, key.1,
|
||||||
existing_idx.module_name().as_str());
|
existing_idx.module_name().as_str());
|
||||||
return Err(SessionError::CannotOverwriteImport(err_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());
|
self.code.extend(code.into_iter());
|
||||||
Ok(self.code_dir.borrow_mut().extend(code_dir.into_iter()))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ extern crate prolog_parser;
|
|||||||
mod and_stack;
|
mod and_stack;
|
||||||
#[macro_use] mod macros;
|
#[macro_use] mod macros;
|
||||||
#[macro_use] mod allocator;
|
#[macro_use] mod allocator;
|
||||||
mod toplevel;
|
pub mod toplevel;
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
pub mod compile;
|
pub mod compile;
|
||||||
mod arithmetic;
|
mod arithmetic;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use prolog::instructions::*;
|
|||||||
use prolog::iterators::*;
|
use prolog::iterators::*;
|
||||||
use prolog::machine::*;
|
use prolog::machine::*;
|
||||||
use prolog::machine::machine_state::MachineState;
|
use prolog::machine::machine_state::MachineState;
|
||||||
|
use prolog::toplevel::*;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::{Read, stdin};
|
use std::io::{Read, stdin};
|
||||||
@@ -38,13 +39,11 @@ pub fn read_toplevel(wam: &Machine) -> Result<Input, ParserError> {
|
|||||||
match &*buffer.trim() {
|
match &*buffer.trim() {
|
||||||
"quit" => Ok(Input::Quit),
|
"quit" => Ok(Input::Quit),
|
||||||
"clear" => Ok(Input::Clear),
|
"clear" => Ok(Input::Clear),
|
||||||
"[user]" => Ok(Input::Batch),
|
"[user]" => {
|
||||||
_ => {
|
println!("(type Enter + Ctrl-D to terminate the stream when finished)");
|
||||||
let mut parser = Parser::new(stdin.lock(), wam.atom_tbl(), wam.machine_flags());
|
Ok(Input::Batch)
|
||||||
|
},
|
||||||
parser.add_to_top(buffer.as_str());
|
_ => Ok(Input::Term(parse_term(wam, buffer.as_bytes())?))
|
||||||
Ok(Input::Term(parser.read_term(composite_op!(&wam.op_dir))?))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,12 +36,15 @@ impl<'a, 'b : 'a> CompositeIndices<'a, 'b>
|
|||||||
{
|
{
|
||||||
fn get_code_index(&mut self, name: ClauseName, arity: usize) -> CodeIndex {
|
fn get_code_index(&mut self, name: ClauseName, arity: usize) -> CodeIndex {
|
||||||
let idx_opt = self.local.code_dir.get(&(name.clone(), arity)).cloned()
|
let idx_opt = self.local.code_dir.get(&(name.clone(), arity)).cloned()
|
||||||
.or_else(|| self.static_code_dir.clone().and_then(|code_dir| {
|
.or_else(|| {
|
||||||
code_dir.borrow().get(&(name.clone(), arity)).cloned()
|
self.static_code_dir.clone().and_then(|code_dir| {
|
||||||
}));
|
code_dir.borrow().get(&(name.clone(), arity)).cloned()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(idx) = idx_opt {
|
if let Some(idx) = idx_opt {
|
||||||
idx.clone()
|
self.local.code_dir.insert((name, arity), idx.clone());
|
||||||
|
idx
|
||||||
} else {
|
} else {
|
||||||
let idx = CodeIndex::default();
|
let idx = CodeIndex::default();
|
||||||
self.local.code_dir.insert((name, arity), idx.clone());
|
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 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 tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
||||||
let results = rel_worker.parse_queue(&mut indices)?;
|
let results = rel_worker.parse_queue(&mut indices)?;
|
||||||
|
|||||||
64
src/tests.rs
64
src/tests.rs
@@ -1,9 +1,8 @@
|
|||||||
use prolog_parser::ast::*;
|
|
||||||
|
|
||||||
use prolog::heap_print::*;
|
use prolog::heap_print::*;
|
||||||
use prolog::instructions::*;
|
use prolog::instructions::*;
|
||||||
use prolog::compile::*;
|
use prolog::compile::*;
|
||||||
use prolog::machine::*;
|
use prolog::machine::*;
|
||||||
|
use prolog::toplevel::*;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
@@ -120,16 +119,12 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool
|
|||||||
{
|
{
|
||||||
wam.reset();
|
wam.reset();
|
||||||
|
|
||||||
match parse_code(wam, buffer) {
|
match compile_user_module(wam, buffer.as_bytes()) {
|
||||||
Ok(tl) =>
|
EvalSession::InitialQuerySuccess(_, _) |
|
||||||
match compile_packet(wam, tl) {
|
EvalSession::EntrySuccess |
|
||||||
EvalSession::InitialQuerySuccess(_, _) |
|
EvalSession::SubsequentQuerySuccess =>
|
||||||
EvalSession::EntrySuccess |
|
true,
|
||||||
EvalSession::SubsequentQuerySuccess =>
|
_ => false
|
||||||
true,
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
Err(e) => panic!("syntax_error({})", e.as_str())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +133,9 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>
|
|||||||
{
|
{
|
||||||
wam.reset();
|
wam.reset();
|
||||||
|
|
||||||
match parse_code(wam, buffer) {
|
match parse_term(&wam, buffer.as_bytes()) {
|
||||||
Ok(tl) =>
|
Ok(term) =>
|
||||||
match compile_packet(wam, tl) {
|
match compile_term(wam, term) {
|
||||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
||||||
result == collect_test_output(wam, alloc_locs, heap_locs),
|
result == collect_test_output(wam, alloc_locs, heap_locs),
|
||||||
EvalSession::EntrySuccess => true,
|
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)]
|
#[allow(dead_code)]
|
||||||
pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
||||||
result: Vec<HashSet<String>>, limit: usize)
|
result: Vec<HashSet<String>>, limit: usize)
|
||||||
@@ -157,9 +167,9 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
|||||||
{
|
{
|
||||||
wam.reset();
|
wam.reset();
|
||||||
|
|
||||||
match parse_code(wam, buffer) {
|
match parse_term(&wam, buffer.as_bytes()) {
|
||||||
Ok(tl) =>
|
Ok(term) =>
|
||||||
match compile_packet(wam, tl) {
|
match compile_term(wam, term) {
|
||||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
||||||
result == collect_test_output_with_limit(wam, alloc_locs,
|
result == collect_test_output_with_limit(wam, alloc_locs,
|
||||||
heap_locs, limit),
|
heap_locs, limit),
|
||||||
@@ -187,7 +197,7 @@ macro_rules! assert_prolog_success_with_limit {
|
|||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
macro_rules! assert_prolog_failure {
|
macro_rules! assert_prolog_failure {
|
||||||
($wam: expr, $buf: expr) => (
|
($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)),*]))
|
assert!(submit_query($wam, $query, vec![$(expand_strs!($res)),*]))
|
||||||
);
|
);
|
||||||
($wam:expr, $buf:expr) => (
|
($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();
|
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, "
|
compile_user_module(&mut wam, "
|
||||||
:- module(my_lists, [local_member/2, reverse/2]).
|
:- 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]).");
|
assert_prolog_success!(&mut wam, "?- my_lists:reverse([a,b,c], [c,b,a]).");
|
||||||
|
|
||||||
compile_user_module(&mut wam, "
|
compile_user_module(&mut wam, "
|
||||||
:- use_module(library(my_lists), [local_member/2]).
|
|
||||||
:- module(my_lists_2, [local_member/2]).
|
:- module(my_lists_2, [local_member/2]).
|
||||||
|
:- use_module(library(my_lists), [local_member/2]).
|
||||||
".as_bytes());
|
".as_bytes());
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- my_lists_2:local_member(1, [1,2,3]).");
|
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();
|
let mut wam = Machine::new();
|
||||||
|
|
||||||
wam.use_module_in_toplevel(clause_name!("lists"));
|
submit(&mut wam, ":- use_module(library(lists)).");
|
||||||
wam.use_module_in_toplevel(clause_name!("control"));
|
submit(&mut wam, ":- use_module(library(control)).");
|
||||||
|
|
||||||
assert_prolog_failure!(&mut wam, "?- atom(X).");
|
assert_prolog_failure!(&mut wam, "?- atom(X).");
|
||||||
assert_prolog_success!(&mut wam, "?- atom(a).");
|
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\"].",
|
assert_prolog_success!(&mut wam, "?- X = [a,b,c|\"abc\"].",
|
||||||
[["X = [a, b, c, a, b, c]"]]);
|
[["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).",
|
assert_prolog_success!(&mut wam, "?- matcher(X, Y).",
|
||||||
[["X = [a, b, c | _1]", "Y = _1"]]);
|
[["X = [a, b, c | _1]", "Y = _1"]]);
|
||||||
assert_prolog_failure!(&mut wam, "?- matcher(\"abcdef\", Y).");
|
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).",
|
assert_prolog_success!(&mut wam, "?- X = \"abc\", X = ['a' | Y], set_prolog_flag(double_quotes, atom).",
|
||||||
[["X = \"abc\"", "Y = \"bc\""]]);
|
[["X = \"abc\"", "Y = \"bc\""]]);
|
||||||
|
|
||||||
// partial strings.
|
// 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_failure!(&mut wam, "?- Y = 5, partial_string(\"abc\", Y).");
|
||||||
assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X).",
|
assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X).",
|
||||||
|
|||||||
Reference in New Issue
Block a user