From: Mark Thom Date: Mon, 15 Jan 2018 03:46:03 +0000 (-0700) Subject: print ops properly. X-Git-Tag: v0.8.110~630 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=b2b4ce68775be333397bc142263d67958045773c;p=scryer-prolog.git print ops properly. --- diff --git a/src/main.rs b/src/main.rs index 70d257ef..0b52d046 100644 --- a/src/main.rs +++ b/src/main.rs @@ -145,15 +145,15 @@ mod tests { 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). diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index a385843a..cdb5afd3 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -1,7 +1,6 @@ use prolog::num::bigint::BigInt; use prolog::num::{Float, ToPrimitive, Zero}; use prolog::num::rational::Ratio; - use prolog::ordered_float::*; use std::cell::Cell; diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index ddfdc17e..af9c91ca 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -1,4 +1,5 @@ use prolog::ast::*; +use prolog::builtins::*; use prolog::heap_iter::*; use std::cell::Cell; @@ -13,12 +14,14 @@ pub enum TokenOrRedirect { Comma, OpenList(Rc>), CloseList(Rc>), - HeadTailSeparator + HeadTailSeparator, + Space } pub trait HeapCellValueFormatter { - // this function belongs to the display predicate formatter. - fn format_clause(&self, arity: usize, name: Rc, state_stack: &mut Vec) + // this function belongs to the display predicate formatter, which it uses + // to format all clauses. + fn format_struct(&self, arity: usize, name: Rc, state_stack: &mut Vec) { state_stack.push(TokenOrRedirect::Close); @@ -32,12 +35,66 @@ pub trait HeapCellValueFormatter { 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, state_stack: &mut Vec); } // 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, state_stack: &mut Vec) + { + 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, state_stack: &mut Vec) { + 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, @@ -98,6 +155,8 @@ impl<'a, Formatter: HeapCellValueFormatter> HeapCellPrinter<'a, 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 => { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 52a53f67..367fd859 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -347,7 +347,7 @@ impl Machine { 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); diff --git a/src/prolog/parser b/src/prolog/parser index 96f4b3e3..171e1f6d 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 96f4b3e33cc0cfabfbb9cb31fcb22012182653d2 +Subproject commit 171e1f6d6ff8ef5b916cc57062958295a1203895 diff --git a/src/prolog/rc_atom.rs b/src/prolog/rc_atom.rs new file mode 100644 index 00000000..646a6871 --- /dev/null +++ b/src/prolog/rc_atom.rs @@ -0,0 +1,11 @@ +use prolog::ast::*; + +use std::cell::RefCell; +use std::rc::Rc; + +pub type TabledData = HashSet> + +pub struct TabledRc { + atom: Rc, + table: Rc>> +} diff --git a/src/prolog/tabled_rc.rs b/src/prolog/tabled_rc.rs new file mode 100644 index 00000000..7e34883c --- /dev/null +++ b/src/prolog/tabled_rc.rs @@ -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 = HashSet>; + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct TabledRc { + atom: Rc, + table: Rc>> +} + +impl TabledRc { + pub fn new(atom: T, table: Rc>>) -> Self { + TabledRc { atom: Rc::new(atom), table } + } +} + +impl Drop for TabledRc { + fn drop(&mut self) { + if Rc::strong_count(&self.atom) == 2 { + let table = *self.table.borrow_mut(); + table.remove(&self.atom); + } + } +} + +impl Deref for TabledRc { + type Target = T; + + fn deref(&self) -> &Self::Target { + &*self.atom + } +}