comparison src/clojure/core_print.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
comparison
equal deleted inserted replaced
9:35cf337adfcf 10:ef7dbbd6452c
1 ; Copyright (c) Rich Hickey. All rights reserved.
2 ; The use and distribution terms for this software are covered by the
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
9 (in-ns 'clojure.core)
10
11 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
13 (import '(java.io Writer))
14
15 (def
16 ^{:doc "*print-length* controls how many items of each collection the
17 printer will print. If it is bound to logical false, there is no
18 limit. Otherwise, it must be bound to an integer indicating the maximum
19 number of items of each collection to print. If a collection contains
20 more items, the printer will print items up to the limit followed by
21 '...' to represent the remaining items. The root binding is nil
22 indicating no limit."
23 :added "1.0"}
24 *print-length* nil)
25
26 (def
27 ^{:doc "*print-level* controls how many levels deep the printer will
28 print nested objects. If it is bound to logical false, there is no
29 limit. Otherwise, it must be bound to an integer indicating the maximum
30 level to print. Each argument to print is at level 0; if an argument is a
31 collection, its items are at level 1; and so on. If an object is a
32 collection and is at a level greater than or equal to the value bound to
33 *print-level*, the printer prints '#' to represent it. The root binding
34 is nil indicating no limit."
35 :added "1.0"}
36 *print-level* nil)
37
38 (defn- print-sequential [^String begin, print-one, ^String sep, ^String end, sequence, ^Writer w]
39 (binding [*print-level* (and (not *print-dup*) *print-level* (dec *print-level*))]
40 (if (and *print-level* (neg? *print-level*))
41 (.write w "#")
42 (do
43 (.write w begin)
44 (when-let [xs (seq sequence)]
45 (if (and (not *print-dup*) *print-length*)
46 (loop [[x & xs] xs
47 print-length *print-length*]
48 (if (zero? print-length)
49 (.write w "...")
50 (do
51 (print-one x w)
52 (when xs
53 (.write w sep)
54 (recur xs (dec print-length))))))
55 (loop [[x & xs] xs]
56 (print-one x w)
57 (when xs
58 (.write w sep)
59 (recur xs)))))
60 (.write w end)))))
61
62 (defn- print-meta [o, ^Writer w]
63 (when-let [m (meta o)]
64 (when (and (pos? (count m))
65 (or *print-dup*
66 (and *print-meta* *print-readably*)))
67 (.write w "^")
68 (if (and (= (count m) 1) (:tag m))
69 (pr-on (:tag m) w)
70 (pr-on m w))
71 (.write w " "))))
72
73 (defmethod print-method :default [o, ^Writer w]
74 (print-method (vary-meta o #(dissoc % :type)) w))
75
76 (defmethod print-method nil [o, ^Writer w]
77 (.write w "nil"))
78
79 (defmethod print-dup nil [o w] (print-method o w))
80
81 (defn print-ctor [o print-args ^Writer w]
82 (.write w "#=(")
83 (.write w (.getName ^Class (class o)))
84 (.write w ". ")
85 (print-args o w)
86 (.write w ")"))
87
88 (defmethod print-method Object [o, ^Writer w]
89 (.write w "#<")
90 (.write w (.getSimpleName (class o)))
91 (.write w " ")
92 (.write w (str o))
93 (.write w ">"))
94
95 (defmethod print-method clojure.lang.Keyword [o, ^Writer w]
96 (.write w (str o)))
97
98 (defmethod print-dup clojure.lang.Keyword [o w] (print-method o w))
99
100 (defmethod print-method Number [o, ^Writer w]
101 (.write w (str o)))
102
103 (defmethod print-dup Number [o, ^Writer w]
104 (print-ctor o
105 (fn [o w]
106 (print-dup (str o) w))
107 w))
108
109 (defmethod print-dup clojure.lang.Fn [o, ^Writer w]
110 (print-ctor o (fn [o w]) w))
111
112 (prefer-method print-dup clojure.lang.IPersistentCollection clojure.lang.Fn)
113 (prefer-method print-dup java.util.Map clojure.lang.Fn)
114 (prefer-method print-dup java.util.Collection clojure.lang.Fn)
115
116 (defmethod print-method Boolean [o, ^Writer w]
117 (.write w (str o)))
118
119 (defmethod print-dup Boolean [o w] (print-method o w))
120
121 (defn print-simple [o, ^Writer w]
122 (print-meta o w)
123 (.write w (str o)))
124
125 (defmethod print-method clojure.lang.Symbol [o, ^Writer w]
126 (print-simple o w))
127
128 (defmethod print-dup clojure.lang.Symbol [o w] (print-method o w))
129
130 (defmethod print-method clojure.lang.Var [o, ^Writer w]
131 (print-simple o w))
132
133 (defmethod print-dup clojure.lang.Var [^clojure.lang.Var o, ^Writer w]
134 (.write w (str "#=(var " (.name (.ns o)) "/" (.sym o) ")")))
135
136 (defmethod print-method clojure.lang.ISeq [o, ^Writer w]
137 (print-meta o w)
138 (print-sequential "(" pr-on " " ")" o w))
139
140 (defmethod print-dup clojure.lang.ISeq [o w] (print-method o w))
141 (defmethod print-dup clojure.lang.IPersistentList [o w] (print-method o w))
142 (prefer-method print-method clojure.lang.ISeq clojure.lang.IPersistentCollection)
143 (prefer-method print-dup clojure.lang.ISeq clojure.lang.IPersistentCollection)
144 (prefer-method print-method clojure.lang.ISeq java.util.Collection)
145 (prefer-method print-dup clojure.lang.ISeq java.util.Collection)
146
147
148
149 (defmethod print-dup java.util.Collection [o, ^Writer w]
150 (print-ctor o #(print-sequential "[" print-dup " " "]" %1 %2) w))
151
152 (defmethod print-dup clojure.lang.IPersistentCollection [o, ^Writer w]
153 (print-meta o w)
154 (.write w "#=(")
155 (.write w (.getName ^Class (class o)))
156 (.write w "/create ")
157 (print-sequential "[" print-dup " " "]" o w)
158 (.write w ")"))
159
160 (prefer-method print-dup clojure.lang.IPersistentCollection java.util.Collection)
161
162 (def ^{:tag String
163 :doc "Returns escape string for char or nil if none"
164 :added "1.0"}
165 char-escape-string
166 {\newline "\\n"
167 \tab "\\t"
168 \return "\\r"
169 \" "\\\""
170 \\ "\\\\"
171 \formfeed "\\f"
172 \backspace "\\b"})
173
174 (defmethod print-method String [^String s, ^Writer w]
175 (if (or *print-dup* *print-readably*)
176 (do (.append w \")
177 (dotimes [n (count s)]
178 (let [c (.charAt s n)
179 e (char-escape-string c)]
180 (if e (.write w e) (.append w c))))
181 (.append w \"))
182 (.write w s))
183 nil)
184
185 (defmethod print-dup String [s w] (print-method s w))
186
187 (defmethod print-method clojure.lang.IPersistentVector [v, ^Writer w]
188 (print-meta v w)
189 (print-sequential "[" pr-on " " "]" v w))
190
191 (defn- print-map [m print-one w]
192 (print-sequential
193 "{"
194 (fn [e ^Writer w]
195 (do (print-one (key e) w) (.append w \space) (print-one (val e) w)))
196 ", "
197 "}"
198 (seq m) w))
199
200 (defmethod print-method clojure.lang.IPersistentMap [m, ^Writer w]
201 (print-meta m w)
202 (print-map m pr-on w))
203
204 (defmethod print-dup java.util.Map [m, ^Writer w]
205 (print-ctor m #(print-map (seq %1) print-dup %2) w))
206
207 (defmethod print-dup clojure.lang.IPersistentMap [m, ^Writer w]
208 (print-meta m w)
209 (.write w "#=(")
210 (.write w (.getName (class m)))
211 (.write w "/create ")
212 (print-map m print-dup w)
213 (.write w ")"))
214
215 (prefer-method print-dup clojure.lang.IPersistentCollection java.util.Map)
216
217 (defmethod print-method clojure.lang.IPersistentSet [s, ^Writer w]
218 (print-meta s w)
219 (print-sequential "#{" pr-on " " "}" (seq s) w))
220
221 (def ^{:tag String
222 :doc "Returns name string for char or nil if none"
223 :added "1.0"}
224 char-name-string
225 {\newline "newline"
226 \tab "tab"
227 \space "space"
228 \backspace "backspace"
229 \formfeed "formfeed"
230 \return "return"})
231
232 (defmethod print-method java.lang.Character [^Character c, ^Writer w]
233 (if (or *print-dup* *print-readably*)
234 (do (.append w \\)
235 (let [n (char-name-string c)]
236 (if n (.write w n) (.append w c))))
237 (.append w c))
238 nil)
239
240 (defmethod print-dup java.lang.Character [c w] (print-method c w))
241 (defmethod print-dup java.lang.Integer [o w] (print-method o w))
242 (defmethod print-dup java.lang.Double [o w] (print-method o w))
243 (defmethod print-dup clojure.lang.Ratio [o w] (print-method o w))
244 (defmethod print-dup java.math.BigDecimal [o w] (print-method o w))
245 (defmethod print-dup clojure.lang.PersistentHashMap [o w] (print-method o w))
246 (defmethod print-dup clojure.lang.PersistentHashSet [o w] (print-method o w))
247 (defmethod print-dup clojure.lang.PersistentVector [o w] (print-method o w))
248 (defmethod print-dup clojure.lang.LazilyPersistentVector [o w] (print-method o w))
249
250 (def primitives-classnames
251 {Float/TYPE "Float/TYPE"
252 Integer/TYPE "Integer/TYPE"
253 Long/TYPE "Long/TYPE"
254 Boolean/TYPE "Boolean/TYPE"
255 Character/TYPE "Character/TYPE"
256 Double/TYPE "Double/TYPE"
257 Byte/TYPE "Byte/TYPE"
258 Short/TYPE "Short/TYPE"})
259
260 (defmethod print-method Class [^Class c, ^Writer w]
261 (.write w (.getName c)))
262
263 (defmethod print-dup Class [^Class c, ^Writer w]
264 (cond
265 (.isPrimitive c) (do
266 (.write w "#=(identity ")
267 (.write w ^String (primitives-classnames c))
268 (.write w ")"))
269 (.isArray c) (do
270 (.write w "#=(java.lang.Class/forName \"")
271 (.write w (.getName c))
272 (.write w "\")"))
273 :else (do
274 (.write w "#=")
275 (.write w (.getName c)))))
276
277 (defmethod print-method java.math.BigDecimal [b, ^Writer w]
278 (.write w (str b))
279 (.write w "M"))
280
281 (defmethod print-method java.util.regex.Pattern [p ^Writer w]
282 (.write w "#\"")
283 (loop [[^Character c & r :as s] (seq (.pattern ^java.util.regex.Pattern p))
284 qmode false]
285 (when s
286 (cond
287 (= c \\) (let [[^Character c2 & r2] r]
288 (.append w \\)
289 (.append w c2)
290 (if qmode
291 (recur r2 (not= c2 \E))
292 (recur r2 (= c2 \Q))))
293 (= c \") (do
294 (if qmode
295 (.write w "\\E\\\"\\Q")
296 (.write w "\\\""))
297 (recur r qmode))
298 :else (do
299 (.append w c)
300 (recur r qmode)))))
301 (.append w \"))
302
303 (defmethod print-dup java.util.regex.Pattern [p ^Writer w] (print-method p w))
304
305 (defmethod print-dup clojure.lang.Namespace [^clojure.lang.Namespace n ^Writer w]
306 (.write w "#=(find-ns ")
307 (print-dup (.name n) w)
308 (.write w ")"))
309
310 (defmethod print-method clojure.lang.IDeref [o ^Writer w]
311 (print-sequential (format "#<%s@%x%s: "
312 (.getSimpleName (class o))
313 (System/identityHashCode o)
314 (if (and (instance? clojure.lang.Agent o)
315 (agent-error o))
316 " FAILED"
317 ""))
318 pr-on, "", ">", (list (if (and (future? o) (not (future-done? o))) :pending @o)), w))
319
320 (def ^{:private true} print-initialized true)