view 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
line wrap: on
line source
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.
9 (in-ns 'clojure.core)
11 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (import '(java.io Writer))
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)
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)
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)))))
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 " "))))
73 (defmethod print-method :default [o, ^Writer w]
74 (print-method (vary-meta o #(dissoc % :type)) w))
76 (defmethod print-method nil [o, ^Writer w]
77 (.write w "nil"))
79 (defmethod print-dup nil [o w] (print-method o w))
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 ")"))
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 ">"))
95 (defmethod print-method clojure.lang.Keyword [o, ^Writer w]
96 (.write w (str o)))
98 (defmethod print-dup clojure.lang.Keyword [o w] (print-method o w))
100 (defmethod print-method Number [o, ^Writer w]
101 (.write w (str o)))
103 (defmethod print-dup Number [o, ^Writer w]
104 (print-ctor o
105 (fn [o w]
106 (print-dup (str o) w))
107 w))
109 (defmethod print-dup clojure.lang.Fn [o, ^Writer w]
110 (print-ctor o (fn [o w]) w))
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)
116 (defmethod print-method Boolean [o, ^Writer w]
117 (.write w (str o)))
119 (defmethod print-dup Boolean [o w] (print-method o w))
121 (defn print-simple [o, ^Writer w]
122 (print-meta o w)
123 (.write w (str o)))
125 (defmethod print-method clojure.lang.Symbol [o, ^Writer w]
126 (print-simple o w))
128 (defmethod print-dup clojure.lang.Symbol [o w] (print-method o w))
130 (defmethod print-method clojure.lang.Var [o, ^Writer w]
131 (print-simple o w))
133 (defmethod print-dup clojure.lang.Var [^clojure.lang.Var o, ^Writer w]
134 (.write w (str "#=(var " (.name (.ns o)) "/" (.sym o) ")")))
136 (defmethod print-method clojure.lang.ISeq [o, ^Writer w]
137 (print-meta o w)
138 (print-sequential "(" pr-on " " ")" o w))
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)
149 (defmethod print-dup java.util.Collection [o, ^Writer w]
150 (print-ctor o #(print-sequential "[" print-dup " " "]" %1 %2) w))
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 ")"))
160 (prefer-method print-dup clojure.lang.IPersistentCollection java.util.Collection)
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"})
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)
185 (defmethod print-dup String [s w] (print-method s w))
187 (defmethod print-method clojure.lang.IPersistentVector [v, ^Writer w]
188 (print-meta v w)
189 (print-sequential "[" pr-on " " "]" v w))
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))
200 (defmethod print-method clojure.lang.IPersistentMap [m, ^Writer w]
201 (print-meta m w)
202 (print-map m pr-on w))
204 (defmethod print-dup java.util.Map [m, ^Writer w]
205 (print-ctor m #(print-map (seq %1) print-dup %2) w))
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 ")"))
215 (prefer-method print-dup clojure.lang.IPersistentCollection java.util.Map)
217 (defmethod print-method clojure.lang.IPersistentSet [s, ^Writer w]
218 (print-meta s w)
219 (print-sequential "#{" pr-on " " "}" (seq s) w))
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"})
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)
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))
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"})
260 (defmethod print-method Class [^Class c, ^Writer w]
261 (.write w (.getName c)))
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)))))
277 (defmethod print-method java.math.BigDecimal [b, ^Writer w]
278 (.write w (str b))
279 (.write w "M"))
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 \"))
303 (defmethod print-dup java.util.regex.Pattern [p ^Writer w] (print-method p w))
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 ")"))
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))
320 (def ^{:private true} print-initialized true)