print ops properly.
This commit is contained in:
10
src/main.rs
10
src/main.rs
@@ -145,15 +145,15 @@ mod tests {
|
|||||||
|
|
||||||
submit(&mut wam, "p(X, a). p(X, Y) :- q(Y), p(X, X).");
|
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, Y)."), true); // infinite.
|
||||||
assert_eq!(submit(&mut wam, "?- p(X, b)."), false);
|
assert_eq!(submit(&mut wam, "?- p(X, b)."), false); // infinite.
|
||||||
|
|
||||||
submit(&mut wam, "p(a, z). p(X, Y) :- q(Y), p(X, Y).");
|
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, Y)."), true); // infinite.
|
||||||
assert_eq!(submit(&mut wam, "?- p(X, z)."), true);
|
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, 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);
|
assert_eq!(submit(&mut wam, "?- p(b, a)."), false);
|
||||||
|
|
||||||
submit(&mut wam, "p(X, Y, Z) :- q(X), r(Y), s(Z).
|
submit(&mut wam, "p(X, Y, Z) :- q(X), r(Y), s(Z).
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use prolog::num::bigint::BigInt;
|
use prolog::num::bigint::BigInt;
|
||||||
use prolog::num::{Float, ToPrimitive, Zero};
|
use prolog::num::{Float, ToPrimitive, Zero};
|
||||||
use prolog::num::rational::Ratio;
|
use prolog::num::rational::Ratio;
|
||||||
|
|
||||||
use prolog::ordered_float::*;
|
use prolog::ordered_float::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use prolog::ast::*;
|
use prolog::ast::*;
|
||||||
|
use prolog::builtins::*;
|
||||||
use prolog::heap_iter::*;
|
use prolog::heap_iter::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
@@ -13,12 +14,14 @@ pub enum TokenOrRedirect {
|
|||||||
Comma,
|
Comma,
|
||||||
OpenList(Rc<Cell<bool>>),
|
OpenList(Rc<Cell<bool>>),
|
||||||
CloseList(Rc<Cell<bool>>),
|
CloseList(Rc<Cell<bool>>),
|
||||||
HeadTailSeparator
|
HeadTailSeparator,
|
||||||
|
Space
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HeapCellValueFormatter {
|
pub trait HeapCellValueFormatter {
|
||||||
// this function belongs to the display predicate formatter.
|
// this function belongs to the display predicate formatter, which it uses
|
||||||
fn format_clause(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
|
// 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::Close);
|
||||||
|
|
||||||
@@ -32,12 +35,66 @@ pub trait HeapCellValueFormatter {
|
|||||||
|
|
||||||
state_stack.push(TokenOrRedirect::Atom(name));
|
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.
|
// the 'classic' display corresponding to the display predicate.
|
||||||
pub struct DisplayFormatter {}
|
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> {
|
pub struct HeapCellPrinter<'a, Formatter> {
|
||||||
formatter: Formatter,
|
formatter: Formatter,
|
||||||
@@ -98,6 +155,8 @@ impl<'a, Formatter: HeapCellValueFormatter> HeapCellPrinter<'a, Formatter>
|
|||||||
loop {
|
loop {
|
||||||
if let Some(loc_data) = self.state_stack.pop() {
|
if let Some(loc_data) = self.state_stack.pop() {
|
||||||
match loc_data {
|
match loc_data {
|
||||||
|
TokenOrRedirect::Space =>
|
||||||
|
result += " ",
|
||||||
TokenOrRedirect::Atom(atom) =>
|
TokenOrRedirect::Atom(atom) =>
|
||||||
result += atom.as_str(),
|
result += atom.as_str(),
|
||||||
TokenOrRedirect::Redirect => {
|
TokenOrRedirect::Redirect => {
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ impl Machine {
|
|||||||
|
|
||||||
fn print_var(&self, r: Ref) -> String
|
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 iter = HeapCellIterator::new(&self.ms, r);
|
||||||
|
|
||||||
let mut printer = HeapCellPrinter::new(iter, disp);
|
let mut printer = HeapCellPrinter::new(iter, disp);
|
||||||
|
|||||||
Submodule src/prolog/parser updated: 96f4b3e33c...171e1f6d6f
11
src/prolog/rc_atom.rs
Normal file
11
src/prolog/rc_atom.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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>>>
|
||||||
|
}
|
||||||
36
src/prolog/tabled_rc.rs
Normal file
36
src/prolog/tabled_rc.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user