add atom predicate.
This commit is contained in:
@@ -123,6 +123,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `(;)/2`
|
* `(;)/2`
|
||||||
* `append/3`
|
* `append/3`
|
||||||
* `arg/3`
|
* `arg/3`
|
||||||
|
* `atom/1`
|
||||||
* `atomic/1`
|
* `atomic/1`
|
||||||
* `between/3`
|
* `between/3`
|
||||||
* `call/1..63`
|
* `call/1..63`
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
extern crate termion;
|
extern crate termion;
|
||||||
|
|
||||||
mod prolog;
|
mod prolog;
|
||||||
#[macro_use] mod test_utils;
|
|
||||||
|
|
||||||
use prolog::ast::*;
|
use prolog::ast::*;
|
||||||
use prolog::io::*;
|
use prolog::io::*;
|
||||||
|
|||||||
@@ -551,6 +551,7 @@ pub enum Term {
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum InlinedClauseType {
|
pub enum InlinedClauseType {
|
||||||
CompareNumber(CompareNumberQT),
|
CompareNumber(CompareNumberQT),
|
||||||
|
IsAtom,
|
||||||
IsAtomic,
|
IsAtomic,
|
||||||
IsCompound,
|
IsCompound,
|
||||||
IsInteger,
|
IsInteger,
|
||||||
@@ -565,6 +566,7 @@ impl InlinedClauseType {
|
|||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
&InlinedClauseType::CompareNumber(qt) => qt.name(),
|
&InlinedClauseType::CompareNumber(qt) => qt.name(),
|
||||||
|
&InlinedClauseType::IsAtom => "atom",
|
||||||
&InlinedClauseType::IsAtomic => "atomic",
|
&InlinedClauseType::IsAtomic => "atomic",
|
||||||
&InlinedClauseType::IsCompound => "compound",
|
&InlinedClauseType::IsCompound => "compound",
|
||||||
&InlinedClauseType::IsInteger => "integer",
|
&InlinedClauseType::IsInteger => "integer",
|
||||||
@@ -584,6 +586,7 @@ impl InlinedClauseType {
|
|||||||
("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
|
("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
|
||||||
("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
|
("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
|
||||||
("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
|
("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
|
||||||
|
("atom", 1) => Some(InlinedClauseType::IsAtom),
|
||||||
("atomic", 1) => Some(InlinedClauseType::IsAtomic),
|
("atomic", 1) => Some(InlinedClauseType::IsAtomic),
|
||||||
("compound", 1) => Some(InlinedClauseType::IsCompound),
|
("compound", 1) => Some(InlinedClauseType::IsCompound),
|
||||||
("integer", 1) => Some(InlinedClauseType::IsInteger),
|
("integer", 1) => Some(InlinedClauseType::IsInteger),
|
||||||
@@ -1203,6 +1206,7 @@ pub enum BuiltInInstruction {
|
|||||||
InstallInferenceCounter(RegType, RegType, RegType),
|
InstallInferenceCounter(RegType, RegType, RegType),
|
||||||
InstallNewBlock,
|
InstallNewBlock,
|
||||||
InternalCallN,
|
InternalCallN,
|
||||||
|
IsAtom(RegType),
|
||||||
IsAtomic(RegType),
|
IsAtomic(RegType),
|
||||||
IsCompound(RegType),
|
IsCompound(RegType),
|
||||||
IsFloat(RegType),
|
IsFloat(RegType),
|
||||||
|
|||||||
@@ -620,7 +620,9 @@ fn get_builtins() -> Code {
|
|||||||
query![put_value!(temp_v!(5), 1)],
|
query![put_value!(temp_v!(5), 1)],
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
fail!(),
|
fail!(),
|
||||||
compare_execute!() // compare/3, 464.
|
compare_execute!(), // compare/3, 464.
|
||||||
|
is_atom!(temp_v!(1)), // atom/1, 465.
|
||||||
|
proceed!()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,7 +735,8 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
|||||||
code_dir.insert((clause_name!("=@="), 2), (391, builtin.clone()));
|
code_dir.insert((clause_name!("=@="), 2), (391, builtin.clone()));
|
||||||
code_dir.insert((clause_name!("\\=@="), 2), (392, builtin.clone()));
|
code_dir.insert((clause_name!("\\=@="), 2), (392, builtin.clone()));
|
||||||
code_dir.insert((clause_name!("compare"), 3), (464, builtin.clone()));
|
code_dir.insert((clause_name!("compare"), 3), (464, builtin.clone()));
|
||||||
|
code_dir.insert((clause_name!("atom"), 1), (465, builtin.clone()));
|
||||||
|
|
||||||
(code_dir, op_dir)
|
(code_dir, op_dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -320,6 +320,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
|||||||
at_1.unwrap_or(interm!(1)),
|
at_1.unwrap_or(interm!(1)),
|
||||||
at_2.unwrap_or(interm!(2))));
|
at_2.unwrap_or(interm!(2))));
|
||||||
},
|
},
|
||||||
|
InlinedClauseType::IsAtom =>
|
||||||
|
match terms[0].as_ref() {
|
||||||
|
&Term::Constant(_, Constant::Atom(_)) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
},
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_atom!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
InlinedClauseType::IsAtomic =>
|
InlinedClauseType::IsAtomic =>
|
||||||
match terms[0].as_ref() {
|
match terms[0].as_ref() {
|
||||||
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
|
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
|
||||||
@@ -608,12 +621,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
|||||||
|
|
||||||
vs.populate_restricting_sets();
|
vs.populate_restricting_sets();
|
||||||
self.marker.drain_var_data(vs);
|
self.marker.drain_var_data(vs);
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
if let &Term::Clause(_, _, ref args, _) = term {
|
if let &Term::Clause(_, _, ref args, _) = term {
|
||||||
self.marker.reset_at_head(args);
|
self.marker.reset_at_head(args);
|
||||||
|
|
||||||
let iter = FactInstruction::iter(term);
|
let iter = FactInstruction::iter(term);
|
||||||
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
|
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
|
||||||
|
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ impl fmt::Display for BuiltInInstruction {
|
|||||||
write!(f, "unwind_stack"),
|
write!(f, "unwind_stack"),
|
||||||
&BuiltInInstruction::Unify =>
|
&BuiltInInstruction::Unify =>
|
||||||
write!(f, "unify"),
|
write!(f, "unify"),
|
||||||
|
&BuiltInInstruction::IsAtom(r) =>
|
||||||
|
write!(f, "is_atom {}", r),
|
||||||
&BuiltInInstruction::IsAtomic(r) =>
|
&BuiltInInstruction::IsAtomic(r) =>
|
||||||
write!(f, "is_atomic {}", r),
|
write!(f, "is_atomic {}", r),
|
||||||
&BuiltInInstruction::IsCompound(r) =>
|
&BuiltInInstruction::IsCompound(r) =>
|
||||||
|
|||||||
@@ -1350,6 +1350,14 @@ impl MachineState {
|
|||||||
_ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
|
_ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
&BuiltInInstruction::IsAtom(r) => {
|
||||||
|
let d = self.store(self.deref(self[r].clone()));
|
||||||
|
|
||||||
|
match d {
|
||||||
|
Addr::Con(Constant::Atom(_)) => self.p += 1,
|
||||||
|
_ => self.fail = true
|
||||||
|
};
|
||||||
|
},
|
||||||
&BuiltInInstruction::IsAtomic(r) => {
|
&BuiltInInstruction::IsAtomic(r) => {
|
||||||
let d = self.store(self.deref(self[r].clone()));
|
let d = self.store(self.deref(self[r].clone()));
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,12 @@ macro_rules! retry_me_else {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! is_atom {
|
||||||
|
($reg:expr) => (
|
||||||
|
Line::BuiltIn(BuiltInInstruction::IsAtom($reg))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! is_atomic {
|
macro_rules! is_atomic {
|
||||||
($reg:expr) => (
|
($reg:expr) => (
|
||||||
Line::BuiltIn(BuiltInInstruction::IsAtomic($reg))
|
Line::BuiltIn(BuiltInInstruction::IsAtomic($reg))
|
||||||
|
|||||||
@@ -1,196 +0,0 @@
|
|||||||
use prolog::ast::*;
|
|
||||||
use prolog::heap_print::*;
|
|
||||||
use prolog::io::*;
|
|
||||||
use prolog::machine::*;
|
|
||||||
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::mem::swap;
|
|
||||||
|
|
||||||
pub struct TestOutputter {
|
|
||||||
results: Vec<HashSet<String>>,
|
|
||||||
contents: HashSet<String>,
|
|
||||||
focus: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TestOutputter {
|
|
||||||
fn cache(&mut self) {
|
|
||||||
self.begin_new_var();
|
|
||||||
|
|
||||||
let mut contents = HashSet::new();
|
|
||||||
swap(&mut contents, &mut self.contents);
|
|
||||||
|
|
||||||
self.results.push(contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HeapCellValueOutputter for TestOutputter {
|
|
||||||
type Output = Vec<HashSet<String>>;
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
TestOutputter { results: vec![],
|
|
||||||
contents: HashSet::new(),
|
|
||||||
focus: String::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append(&mut self, focus: &str) {
|
|
||||||
self.focus += focus;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn begin_new_var(&mut self) {
|
|
||||||
if !self.focus.is_empty() {
|
|
||||||
let mut focus = String::new();
|
|
||||||
swap(&mut focus, &mut self.focus);
|
|
||||||
|
|
||||||
self.contents.insert(focus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn result(self) -> Self::Output {
|
|
||||||
self.results
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ends_with(&self, s: &str) -> bool {
|
|
||||||
self.focus.ends_with(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.focus.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn truncate(&mut self, len: usize) {
|
|
||||||
self.focus.truncate(len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict, mut heap_locs: HeapVarDict)
|
|
||||||
-> Vec<HashSet<String>>
|
|
||||||
{
|
|
||||||
let mut output = TestOutputter::new();
|
|
||||||
|
|
||||||
output = wam.heap_view(&heap_locs, output);
|
|
||||||
output.cache();
|
|
||||||
|
|
||||||
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs)
|
|
||||||
{
|
|
||||||
output = wam.heap_view(&heap_locs, output);
|
|
||||||
output.cache();
|
|
||||||
}
|
|
||||||
|
|
||||||
output.result()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDict,
|
|
||||||
mut heap_locs: HeapVarDict, limit: usize)
|
|
||||||
-> Vec<HashSet<String>>
|
|
||||||
{
|
|
||||||
let mut output = TestOutputter::new();
|
|
||||||
|
|
||||||
output = wam.heap_view(&heap_locs, output);
|
|
||||||
output.cache();
|
|
||||||
|
|
||||||
let mut count = 1;
|
|
||||||
|
|
||||||
if count == limit {
|
|
||||||
return output.result();
|
|
||||||
}
|
|
||||||
|
|
||||||
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs)
|
|
||||||
{
|
|
||||||
output = wam.heap_view(&heap_locs, output);
|
|
||||||
output.cache();
|
|
||||||
|
|
||||||
count += 1;
|
|
||||||
|
|
||||||
if count == limit {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.result()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
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!("parse error: {:?}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>>) -> bool
|
|
||||||
{
|
|
||||||
wam.reset();
|
|
||||||
|
|
||||||
match parse_code(wam, buffer) {
|
|
||||||
Ok(tl) =>
|
|
||||||
match compile_packet(wam, tl) {
|
|
||||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
|
||||||
result == collect_test_output(wam, alloc_locs, heap_locs),
|
|
||||||
EvalSession::EntrySuccess => true,
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
Err(e) => panic!("parse error: {:?}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
|
||||||
result: Vec<HashSet<String>>, limit: usize)
|
|
||||||
-> bool
|
|
||||||
{
|
|
||||||
wam.reset();
|
|
||||||
|
|
||||||
match parse_code(wam, buffer) {
|
|
||||||
Ok(tl) =>
|
|
||||||
match compile_packet(wam, tl) {
|
|
||||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
|
||||||
result == collect_test_output_with_limit(wam, alloc_locs,
|
|
||||||
heap_locs, limit),
|
|
||||||
EvalSession::EntrySuccess => true,
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
Err(e) => panic!("parse error: {:?}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! expand_strs {
|
|
||||||
($arr:expr) => (
|
|
||||||
$arr.into_iter().map(|s| String::from(*s)).collect()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! assert_prolog_success_with_limit {
|
|
||||||
($wam:expr, $buf:expr, [$($res:expr),*], $limit:expr) => (
|
|
||||||
assert!(submit_query_with_limit($wam, $buf, vec![$(expand_strs!($res)),*], $limit))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! assert_prolog_failure {
|
|
||||||
($wam: expr, $buf: expr) => (
|
|
||||||
assert_eq!(submit($wam, $buf), false)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! assert_prolog_success {
|
|
||||||
($wam:expr, $query:expr, [$($res:expr),*]) => (
|
|
||||||
assert!(submit_query($wam, $query, vec![$(expand_strs!($res)),*]))
|
|
||||||
);
|
|
||||||
($wam:expr, $buf:expr) => (
|
|
||||||
assert_eq!(submit($wam, $buf), true)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
211
src/tests.rs
211
src/tests.rs
@@ -1,5 +1,199 @@
|
|||||||
use super::*;
|
use prolog::ast::*;
|
||||||
use test_utils::*;
|
use prolog::heap_print::*;
|
||||||
|
use prolog::io::*;
|
||||||
|
use prolog::machine::*;
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::mem::swap;
|
||||||
|
|
||||||
|
pub struct TestOutputter {
|
||||||
|
results: Vec<HashSet<String>>,
|
||||||
|
contents: HashSet<String>,
|
||||||
|
focus: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestOutputter {
|
||||||
|
fn cache(&mut self) {
|
||||||
|
self.begin_new_var();
|
||||||
|
|
||||||
|
let mut contents = HashSet::new();
|
||||||
|
swap(&mut contents, &mut self.contents);
|
||||||
|
|
||||||
|
self.results.push(contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeapCellValueOutputter for TestOutputter {
|
||||||
|
type Output = Vec<HashSet<String>>;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
TestOutputter { results: vec![],
|
||||||
|
contents: HashSet::new(),
|
||||||
|
focus: String::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append(&mut self, focus: &str) {
|
||||||
|
self.focus += focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn begin_new_var(&mut self) {
|
||||||
|
if !self.focus.is_empty() {
|
||||||
|
let mut focus = String::new();
|
||||||
|
swap(&mut focus, &mut self.focus);
|
||||||
|
|
||||||
|
self.contents.insert(focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn result(self) -> Self::Output {
|
||||||
|
self.results
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ends_with(&self, s: &str) -> bool {
|
||||||
|
self.focus.ends_with(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.focus.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn truncate(&mut self, len: usize) {
|
||||||
|
self.focus.truncate(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict, mut heap_locs: HeapVarDict)
|
||||||
|
-> Vec<HashSet<String>>
|
||||||
|
{
|
||||||
|
let mut output = TestOutputter::new();
|
||||||
|
|
||||||
|
output = wam.heap_view(&heap_locs, output);
|
||||||
|
output.cache();
|
||||||
|
|
||||||
|
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs)
|
||||||
|
{
|
||||||
|
output = wam.heap_view(&heap_locs, output);
|
||||||
|
output.cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
output.result()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDict,
|
||||||
|
mut heap_locs: HeapVarDict, limit: usize)
|
||||||
|
-> Vec<HashSet<String>>
|
||||||
|
{
|
||||||
|
let mut output = TestOutputter::new();
|
||||||
|
|
||||||
|
output = wam.heap_view(&heap_locs, output);
|
||||||
|
output.cache();
|
||||||
|
|
||||||
|
let mut count = 1;
|
||||||
|
|
||||||
|
if count == limit {
|
||||||
|
return output.result();
|
||||||
|
}
|
||||||
|
|
||||||
|
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs)
|
||||||
|
{
|
||||||
|
output = wam.heap_view(&heap_locs, output);
|
||||||
|
output.cache();
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
if count == limit {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.result()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
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!("parse error: {:?}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>>) -> bool
|
||||||
|
{
|
||||||
|
wam.reset();
|
||||||
|
|
||||||
|
match parse_code(wam, buffer) {
|
||||||
|
Ok(tl) =>
|
||||||
|
match compile_packet(wam, tl) {
|
||||||
|
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
||||||
|
result == collect_test_output(wam, alloc_locs, heap_locs),
|
||||||
|
EvalSession::EntrySuccess => true,
|
||||||
|
_ => false
|
||||||
|
},
|
||||||
|
Err(e) => panic!("parse error: {:?}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
||||||
|
result: Vec<HashSet<String>>, limit: usize)
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
wam.reset();
|
||||||
|
|
||||||
|
match parse_code(wam, buffer) {
|
||||||
|
Ok(tl) =>
|
||||||
|
match compile_packet(wam, tl) {
|
||||||
|
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
||||||
|
result == collect_test_output_with_limit(wam, alloc_locs,
|
||||||
|
heap_locs, limit),
|
||||||
|
EvalSession::EntrySuccess => true,
|
||||||
|
_ => false
|
||||||
|
},
|
||||||
|
Err(e) => panic!("parse error: {:?}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! expand_strs {
|
||||||
|
($arr:expr) => (
|
||||||
|
$arr.into_iter().map(|s| String::from(*s)).collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! assert_prolog_success_with_limit {
|
||||||
|
($wam:expr, $buf:expr, [$($res:expr),*], $limit:expr) => (
|
||||||
|
assert!(submit_query_with_limit($wam, $buf, vec![$(expand_strs!($res)),*], $limit))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! assert_prolog_failure {
|
||||||
|
($wam: expr, $buf: expr) => (
|
||||||
|
assert_eq!(submit($wam, $buf), false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! assert_prolog_success {
|
||||||
|
($wam:expr, $query:expr, [$($res:expr),*]) => (
|
||||||
|
assert!(submit_query($wam, $query, vec![$(expand_strs!($res)),*]))
|
||||||
|
);
|
||||||
|
($wam:expr, $buf:expr) => (
|
||||||
|
assert_eq!(submit($wam, $buf), true)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_queries_on_facts()
|
fn test_queries_on_facts()
|
||||||
@@ -1172,7 +1366,6 @@ fn test_queries_on_conditionals()
|
|||||||
assert_prolog_success!(&mut wam, "?- catch(test(a, [a]), type_error(E), true).",
|
assert_prolog_success!(&mut wam, "?- catch(test(a, [a]), type_error(E), true).",
|
||||||
[["E = _6"], ["E = _6"]]);
|
[["E = _6"], ["E = _6"]]);
|
||||||
|
|
||||||
//TODO: write tests for calling ;, ->, to confirm behavior is correct.
|
|
||||||
assert_prolog_success!(&mut wam, "?- f(X), call(->, atomic(X), true).",
|
assert_prolog_success!(&mut wam, "?- f(X), call(->, atomic(X), true).",
|
||||||
[["X = a"], ["X = b"]]);
|
[["X = a"], ["X = b"]]);
|
||||||
}
|
}
|
||||||
@@ -1182,6 +1375,16 @@ fn test_queries_on_builtins()
|
|||||||
{
|
{
|
||||||
let mut wam = Machine::new();
|
let mut wam = Machine::new();
|
||||||
|
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom(X).");
|
||||||
|
assert_prolog_success!(&mut wam, "?- atom(a).");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom(\"string\").");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom([]).");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom(1).");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom(0).");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom(0.0).");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom([a,b,c]).");
|
||||||
|
assert_prolog_failure!(&mut wam, "?- atom(atop(the_trees)).");
|
||||||
|
|
||||||
assert_prolog_failure!(&mut wam, "?- atomic(X).");
|
assert_prolog_failure!(&mut wam, "?- atomic(X).");
|
||||||
assert_prolog_success!(&mut wam, "?- atomic(a).");
|
assert_prolog_success!(&mut wam, "?- atomic(a).");
|
||||||
assert_prolog_success!(&mut wam, "?- atomic(\"string\").");
|
assert_prolog_success!(&mut wam, "?- atomic(\"string\").");
|
||||||
@@ -1570,5 +1773,5 @@ fn test_queries_on_call_with_inference_limit()
|
|||||||
[["R = !", "X = 6"]]);
|
[["R = !", "X = 6"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 1, R), call_with_inference_limit(g(X), 1, R).",
|
assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 1, R), call_with_inference_limit(g(X), 1, R).",
|
||||||
[["R = inference_limit_exceeded", "X = _1"]]);
|
[["R = inference_limit_exceeded", "X = _1"]]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user