submit(&mut wam, "p(X, a). p(X, Y) :- q(Y), p(X, X).");
- assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
- assert_eq!(submit(&mut wam, "?- p(X, b)."), false);
+ assert_eq!(submit(&mut wam, "?- p(X, Y)."), true); // infinite.
+ assert_eq!(submit(&mut wam, "?- p(X, b)."), false); // infinite.
submit(&mut wam, "p(a, z). p(X, Y) :- q(Y), p(X, Y).");
- assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
- assert_eq!(submit(&mut wam, "?- p(X, z)."), true);
+ assert_eq!(submit(&mut wam, "?- p(X, Y)."), true); // infinite.
+ assert_eq!(submit(&mut wam, "?- p(X, z)."), true); // infinite.
assert_eq!(submit(&mut wam, "?- p(a, z)."), true);
- assert_eq!(submit(&mut wam, "?- p(a, X)."), true);
+ assert_eq!(submit(&mut wam, "?- p(a, X)."), true); // infinite.
assert_eq!(submit(&mut wam, "?- p(b, a)."), false);
submit(&mut wam, "p(X, Y, Z) :- q(X), r(Y), s(Z).
use prolog::num::bigint::BigInt;
use prolog::num::{Float, ToPrimitive, Zero};
use prolog::num::rational::Ratio;
-
use prolog::ordered_float::*;
use std::cell::Cell;
use prolog::ast::*;
+use prolog::builtins::*;
use prolog::heap_iter::*;
use std::cell::Cell;
Comma,
OpenList(Rc<Cell<bool>>),
CloseList(Rc<Cell<bool>>),
- HeadTailSeparator
+ HeadTailSeparator,
+ Space
}
pub trait HeapCellValueFormatter {
- // this function belongs to the display predicate formatter.
- fn format_clause(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
+ // this function belongs to the display predicate formatter, which it uses
+ // to format all clauses.
+ fn format_struct(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
{
state_stack.push(TokenOrRedirect::Close);
state_stack.push(TokenOrRedirect::Atom(name));
}
+
+ // this can be overloaded to handle special cases, falling back on the default of
+ // format_struct when convenient.
+ fn format_clause(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>);
}
// the 'classic' display corresponding to the display predicate.
pub struct DisplayFormatter {}
-impl HeapCellValueFormatter for DisplayFormatter {}
+impl HeapCellValueFormatter for DisplayFormatter {
+ fn format_clause(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
+ {
+ self.format_struct(arity, name, state_stack);
+ }
+}
+
+pub struct TermFormatter<'a> {
+ op_dir: &'a OpDir
+}
+
+impl<'a> TermFormatter<'a> {
+ pub fn new(op_dir: &'a OpDir) -> Self {
+ TermFormatter { op_dir }
+ }
+}
+
+impl<'a> HeapCellValueFormatter for TermFormatter<'a> {
+ fn format_clause(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>) {
+ if arity == 1 {
+ match self.op_dir.get(&(name.clone(), Fixity::Post)) {
+ Some(_) => {
+ state_stack.push(TokenOrRedirect::Atom(name));
+ state_stack.push(TokenOrRedirect::Space);
+ state_stack.push(TokenOrRedirect::Redirect);
+ },
+ None => match self.op_dir.get(&(name.clone(), Fixity::Pre)) {
+ Some(_) => {
+ state_stack.push(TokenOrRedirect::Redirect);
+ state_stack.push(TokenOrRedirect::Space);
+ state_stack.push(TokenOrRedirect::Atom(name));
+ },
+ None => self.format_struct(arity, name, state_stack)
+ }
+ }
+ } else if arity == 2 {
+ match self.op_dir.get(&(name.clone(), Fixity::In)) {
+ Some(_) => {
+ state_stack.push(TokenOrRedirect::Redirect);
+ state_stack.push(TokenOrRedirect::Space);
+ state_stack.push(TokenOrRedirect::Atom(name));
+ state_stack.push(TokenOrRedirect::Space);
+ state_stack.push(TokenOrRedirect::Redirect);
+ },
+ None => self.format_struct(arity, name, state_stack)
+ };
+ } else {
+ self.format_struct(arity, name, state_stack);
+ }
+ }
+}
pub struct HeapCellPrinter<'a, Formatter> {
formatter: Formatter,
loop {
if let Some(loc_data) = self.state_stack.pop() {
match loc_data {
+ TokenOrRedirect::Space =>
+ result += " ",
TokenOrRedirect::Atom(atom) =>
result += atom.as_str(),
TokenOrRedirect::Redirect => {
fn print_var(&self, r: Ref) -> String
{
- let disp = DisplayFormatter {};
+ let disp = TermFormatter::new(&self.op_dir);
let iter = HeapCellIterator::new(&self.ms, r);
let mut printer = HeapCellPrinter::new(iter, disp);
-Subproject commit 96f4b3e33cc0cfabfbb9cb31fcb22012182653d2
+Subproject commit 171e1f6d6ff8ef5b916cc57062958295a1203895
--- /dev/null
+use prolog::ast::*;
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+pub type TabledData<T> = HashSet<Rc<T>>
+
+pub struct TabledRc<T> {
+ atom: Rc<T>,
+ table: Rc<RefCell<TabledData<T>>>
+}
--- /dev/null
+use std::cell::RefCell;
+use std::collections::HashSet;
+use std::hash::Hash;
+use std::ops::Deref;
+use std::rc::Rc;
+
+pub type TabledData<T> = HashSet<Rc<T>>;
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct TabledRc<T: Hash + Eq> {
+ atom: Rc<T>,
+ table: Rc<RefCell<TabledData<T>>>
+}
+
+impl<T: Hash + Eq> TabledRc<T> {
+ pub fn new(atom: T, table: Rc<RefCell<TabledData<T>>>) -> Self {
+ TabledRc { atom: Rc::new(atom), table }
+ }
+}
+
+impl<T: Hash + Eq> Drop for TabledRc<T> {
+ fn drop(&mut self) {
+ if Rc::strong_count(&self.atom) == 2 {
+ let table = *self.table.borrow_mut();
+ table.remove(&self.atom);
+ }
+ }
+}
+
+impl<T: Hash + Eq> Deref for TabledRc<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.atom
+ }
+}