* `(;)/2`
* `append/3`
* `arg/3`
+* `atom/1`
* `atomic/1`
* `between/3`
* `call/1..63`
extern crate termion;
mod prolog;
-#[macro_use] mod test_utils;
use prolog::ast::*;
use prolog::io::*;
#[derive(Clone, Copy)]
pub enum InlinedClauseType {
CompareNumber(CompareNumberQT),
+ IsAtom,
IsAtomic,
IsCompound,
IsInteger,
pub fn name(&self) -> &'static str {
match self {
&InlinedClauseType::CompareNumber(qt) => qt.name(),
+ &InlinedClauseType::IsAtom => "atom",
&InlinedClauseType::IsAtomic => "atomic",
&InlinedClauseType::IsCompound => "compound",
&InlinedClauseType::IsInteger => "integer",
("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
+ ("atom", 1) => Some(InlinedClauseType::IsAtom),
("atomic", 1) => Some(InlinedClauseType::IsAtomic),
("compound", 1) => Some(InlinedClauseType::IsCompound),
("integer", 1) => Some(InlinedClauseType::IsInteger),
InstallInferenceCounter(RegType, RegType, RegType),
InstallNewBlock,
InternalCallN,
+ IsAtom(RegType),
IsAtomic(RegType),
IsCompound(RegType),
IsFloat(RegType),
query![put_value!(temp_v!(5), 1)],
reset_block!(),
fail!(),
- compare_execute!() // compare/3, 464.
+ compare_execute!(), // compare/3, 464.
+ is_atom!(temp_v!(1)), // atom/1, 465.
+ proceed!()
]
}
code_dir.insert((clause_name!("=@="), 2), (391, 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!("atom"), 1), (465, builtin.clone()));
+
(code_dir, op_dir)
}
at_1.unwrap_or(interm!(1)),
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 =>
match terms[0].as_ref() {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
vs.populate_restricting_sets();
self.marker.drain_var_data(vs);
-
+
let mut code = Vec::new();
if let &Term::Clause(_, _, ref args, _) = term {
self.marker.reset_at_head(args);
-
+
let iter = FactInstruction::iter(term);
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
write!(f, "unwind_stack"),
&BuiltInInstruction::Unify =>
write!(f, "unify"),
+ &BuiltInInstruction::IsAtom(r) =>
+ write!(f, "is_atom {}", r),
&BuiltInInstruction::IsAtomic(r) =>
write!(f, "is_atomic {}", r),
&BuiltInInstruction::IsCompound(r) =>
_ => 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) => {
let d = self.store(self.deref(self[r].clone()));
)
}
+macro_rules! is_atom {
+ ($reg:expr) => (
+ Line::BuiltIn(BuiltInInstruction::IsAtom($reg))
+ )
+}
+
macro_rules! is_atomic {
($reg:expr) => (
Line::BuiltIn(BuiltInInstruction::IsAtomic($reg))
+++ /dev/null
-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)
- )
-}
-use super::*;
-use test_utils::*;
+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)
+ )
+}
#[test]
fn test_queries_on_facts()
assert_prolog_success!(&mut wam, "?- catch(test(a, [a]), type_error(E), true).",
[["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).",
[["X = a"], ["X = b"]]);
}
{
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_success!(&mut wam, "?- atomic(a).");
assert_prolog_success!(&mut wam, "?- atomic(\"string\").");
[["R = !", "X = 6"]]);
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"]]);
-
+
}