summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-09-22 13:49:13 +0000
committerRich Hickey <richhickey@gmail.com>2008-09-22 13:49:13 +0000
commitca5ba2de079ba6d18781c14c49136d5682934514 (patch)
tree817ce639d1483ed815f5330cfc935bb3f17b5921 /src
parent454da80b478c4901c1d99cf56cb957b2aee7caac (diff)
added print-method multimethod and switched printing to use it
built on contribution from Erik Soehnel
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/boot.clj117
-rw-r--r--src/jvm/clojure/lang/Compiler.java3
-rw-r--r--src/jvm/clojure/lang/RT.java7
3 files changed, 119 insertions, 8 deletions
diff --git a/src/clj/clojure/boot.clj b/src/clj/clojure/boot.clj
index 4645abf3..ee2b651c 100644
--- a/src/clj/clojure/boot.clj
+++ b/src/clj/clojure/boot.clj
@@ -1506,6 +1506,12 @@
array [& items]
(into-array items))
+(defn class
+ "Returns the Class of x"
+ [#^Object x] (if (nil? x) x (. x (getClass))))
+
+(defmulti print-method (fn [x writer] (class x)))
+
(defn pr
"Prints the object(s) to the output stream that is the current value
of *out*. Prints the object(s), separated by spaces if there is
@@ -1513,7 +1519,7 @@
can be read by the reader"
([] nil)
([x]
- (. clojure.lang.RT (print x *out*))
+ (print-method x *out*)
nil)
([x & more]
(pr x)
@@ -2483,10 +2489,6 @@
"Returns true if v is of type clojure.lang.Var"
[v] (instance? clojure.lang.Var v))
-(defn class
- "Returns the Class of x"
- [#^Object x] (if (nil? x) x (. x (getClass))))
-
(defn slurp
"Reads the file named by f into a string and returns it."
[#^String f]
@@ -3362,3 +3364,108 @@
(def
#^{:doc "bound in a repl thread to the most recent exception caught by the repl"}
*e)
+
+(import '(java.io Writer))
+
+(defn- print-sequential [#^String begin, print-one, #^String sep, #^String end, sequence, #^Writer w]
+ (.write w begin)
+ (loop [[f & r :as s] (seq sequence)]
+ (if r
+ (do (print-one f w) (.write w sep) (recur r))
+ (when s (print-one f w))))
+ (.write w end))
+
+(defn- print-meta [o, #^Writer w]
+ (when-let m (meta o)
+ (when (and *print-meta* *print-readably* (pos? (count m)))
+ (.write w "#^")
+ (if (and (= (count m) 1) (:tag m))
+ (print-method (:tag m) w)
+ (print-method m w))
+ (.write w " "))))
+
+(defmethod print-method nil [o, #^Writer w]
+ (.write w "nil"))
+
+(defmethod print-method :default [o, #^Writer w]
+ (print-meta o w)
+ (.write w (str o)))
+
+(defmethod print-method clojure.lang.ISeq [o, #^Writer w]
+ (print-meta o w)
+ (print-sequential "(" print-method " " ")" o w))
+
+(defmethod print-method clojure.lang.IPersistentList [o, #^Writer w]
+ (print-meta o w)
+ (print-sequential "(" print-method " " ")" o w))
+
+(def #^{:tag String
+ :doc "Returns escape string for char or nil if none"}
+ char-escape-string
+ {\newline "\\n"
+ \tab "\\t"
+ \return "\\r"
+ \" "\\\""
+ \\ "\\\\"
+ \formfeed "\\f"
+ \backspace "\\b"})
+
+(defmethod print-method String [#^String s, #^Writer w]
+ (if *print-readably*
+ (do (.append w \")
+ (dotimes n (count s)
+ (let [c (.charAt s n)
+ e (char-escape-string c)]
+ (if e (.write w e) (.append w c))))
+ (.append w \"))
+ (.write w s))
+ nil)
+
+(defmethod print-method clojure.lang.IPersistentVector [v, #^Writer w]
+ (print-meta v w)
+ (.append w \[)
+ (dotimes n (dec (count v))
+ (print-method (nth v n) w)
+ (.append w \ ))
+ (print-method (nth v (dec (count v))) w)
+ (.append w \])
+ nil)
+
+(defmethod print-method clojure.lang.IPersistentMap [m, #^Writer w]
+ (print-meta m w)
+ (print-sequential
+ "{"
+ (fn [e #^Writer w]
+ (do (print-method (key e) w) (.append w \ ) (print-method (val e) w)))
+ ", "
+ "}"
+ (seq m) w))
+
+(defmethod print-method clojure.lang.IPersistentSet [s, #^Writer w]
+ (print-meta s w)
+ (print-sequential "#{" print-method " " "}" (seq s) w))
+
+(def #^{:tag String
+ :doc "Returns name string for char or nil if none"}
+ char-name-string
+ {\newline "newline"
+ \tab "tab"
+ \space "space"
+ \backspace "backspace"
+ \formfeed "formfeed"
+ \return "return"})
+
+(defmethod print-method java.lang.Character [#^Character c, #^Writer w]
+ (if *print-readably*
+ (do (.append w \\)
+ (let [n (char-name-string c)]
+ (if n (.write w n) (.append w c))))
+ (.append w c))
+ nil)
+
+(defmethod print-method Class [#^Class c, #^Writer w]
+ (.write w (.getName c)))
+
+(defmethod print-method java.math.BigDecimal [b, #^Writer w]
+ (.write w (str b))
+ (.write w "M"))
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index aae4cc9b..6f1351cd 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -4324,7 +4324,7 @@ public static Object load(Reader rdr, String sourcePath, String sourceName) thro
}
return ret;
}
-
+/*
public static void main(String[] args) throws Exception{
RT.init();
for(String file : args)
@@ -4389,4 +4389,5 @@ SOURCE, "REPL"
Var.popThreadBindings();
}
}
+*/
}
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java
index 06379eb3..2a01ab36 100644
--- a/src/jvm/clojure/lang/RT.java
+++ b/src/jvm/clojure/lang/RT.java
@@ -202,7 +202,7 @@ final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.create("*
final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("in-ns"), F);
final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("ns"), F);
-
+static final Var PRINT_METHOD = Var.intern(CLOJURE_NS, Symbol.create("print-method"));
//final static Var IMPORTS = Var.intern(CLOJURE_NS, Symbol.create("*imports*"), DEFAULT_IMPORTS);
final static IFn inNamespace = new AFn(){
public Object invoke(Object arg1) throws Exception{
@@ -1156,7 +1156,9 @@ static public boolean suppressRead(){
static public void print(Object x, Writer w) throws Exception{
- //todo - make extensible
+ //call multimethod
+ PRINT_METHOD.invoke(x, w);
+/*
boolean readably = booleanCast(PRINT_READABLY.get());
if(x instanceof Obj)
{
@@ -1318,6 +1320,7 @@ static public void print(Object x, Writer w) throws Exception{
w.write('M');
}
else w.write(x.toString());
+ */
}
private static void printInnerSeq(ISeq x, Writer w) throws Exception{