]> Repositorios git - scryer-prolog.git/commitdiff
print ops properly.
authorMark Thom <[email protected]>
Mon, 15 Jan 2018 03:46:03 +0000 (20:46 -0700)
committerMark Thom <[email protected]>
Mon, 15 Jan 2018 03:46:03 +0000 (20:46 -0700)
src/main.rs
src/prolog/ast.rs
src/prolog/heap_print.rs
src/prolog/machine/mod.rs
src/prolog/parser
src/prolog/rc_atom.rs [new file with mode: 0644]
src/prolog/tabled_rc.rs [new file with mode: 0644]

index 70d257ef5954f6d0f65a6794693e63e58f0bca5a..0b52d046c08c1c3a9e9ec21bbdc1f0da20e7379b 100644 (file)
@@ -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).
index a385843a0f3e659e7e437c80f23da1b6638807e3..cdb5afd335461bcd5a2c964c3d9b9090ae836932 100644 (file)
@@ -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;
index ddfdc17ebc12fe037b5d871a3555466573aac7d6..af9c91ca2ae9cd282e8e581ba18be8c8eefc9a28 100644 (file)
@@ -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<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);
 
@@ -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<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,
@@ -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 => {
index 52a53f6786cd33896a739d09842522ca65b5e6d1..367fd859efda00ffadca6bf653ddf6ca578ff227 100644 (file)
@@ -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);
index 96f4b3e33cc0cfabfbb9cb31fcb22012182653d2..171e1f6d6ff8ef5b916cc57062958295a1203895 160000 (submodule)
@@ -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 (file)
index 0000000..646a687
--- /dev/null
@@ -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>>>
+}
diff --git a/src/prolog/tabled_rc.rs b/src/prolog/tabled_rc.rs
new file mode 100644 (file)
index 0000000..7e34883
--- /dev/null
@@ -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
+    }
+}