diff 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 diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojure/core_print.clj	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,320 @@
     1.4 +;   Copyright (c) Rich Hickey. All rights reserved.
     1.5 +;   The use and distribution terms for this software are covered by the
     1.6 +;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
     1.7 +;   which can be found in the file epl-v10.html at the root of this distribution.
     1.8 +;   By using this software in any fashion, you are agreeing to be bound by
     1.9 +;   the terms of this license.
    1.10 +;   You must not remove this notice, or any other, from this software.
    1.11 +
    1.12 +(in-ns 'clojure.core)
    1.13 +
    1.14 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.15 +
    1.16 +(import '(java.io Writer))
    1.17 +
    1.18 +(def
    1.19 + ^{:doc "*print-length* controls how many items of each collection the
    1.20 +  printer will print. If it is bound to logical false, there is no
    1.21 +  limit. Otherwise, it must be bound to an integer indicating the maximum
    1.22 +  number of items of each collection to print. If a collection contains
    1.23 +  more items, the printer will print items up to the limit followed by
    1.24 +  '...' to represent the remaining items. The root binding is nil
    1.25 +  indicating no limit."
    1.26 +   :added "1.0"}
    1.27 + *print-length* nil)
    1.28 +
    1.29 +(def
    1.30 + ^{:doc "*print-level* controls how many levels deep the printer will
    1.31 +  print nested objects. If it is bound to logical false, there is no
    1.32 +  limit. Otherwise, it must be bound to an integer indicating the maximum
    1.33 +  level to print. Each argument to print is at level 0; if an argument is a
    1.34 +  collection, its items are at level 1; and so on. If an object is a
    1.35 +  collection and is at a level greater than or equal to the value bound to
    1.36 +  *print-level*, the printer prints '#' to represent it. The root binding
    1.37 +  is nil indicating no limit."
    1.38 +   :added "1.0"}
    1.39 +*print-level* nil)
    1.40 +
    1.41 +(defn- print-sequential [^String begin, print-one, ^String sep, ^String end, sequence, ^Writer w]
    1.42 +  (binding [*print-level* (and (not *print-dup*) *print-level* (dec *print-level*))]
    1.43 +    (if (and *print-level* (neg? *print-level*))
    1.44 +      (.write w "#")
    1.45 +      (do
    1.46 +        (.write w begin)
    1.47 +        (when-let [xs (seq sequence)]
    1.48 +          (if (and (not *print-dup*) *print-length*)
    1.49 +            (loop [[x & xs] xs
    1.50 +                   print-length *print-length*]
    1.51 +              (if (zero? print-length)
    1.52 +                (.write w "...")
    1.53 +                (do
    1.54 +                  (print-one x w)
    1.55 +                  (when xs
    1.56 +                    (.write w sep)
    1.57 +                    (recur xs (dec print-length))))))
    1.58 +            (loop [[x & xs] xs]
    1.59 +              (print-one x w)
    1.60 +              (when xs
    1.61 +                (.write w sep)
    1.62 +                (recur xs)))))
    1.63 +        (.write w end)))))
    1.64 +
    1.65 +(defn- print-meta [o, ^Writer w]
    1.66 +  (when-let [m (meta o)]
    1.67 +    (when (and (pos? (count m))
    1.68 +               (or *print-dup*
    1.69 +                   (and *print-meta* *print-readably*)))
    1.70 +      (.write w "^")
    1.71 +      (if (and (= (count m) 1) (:tag m))
    1.72 +          (pr-on (:tag m) w)
    1.73 +          (pr-on m w))
    1.74 +      (.write w " "))))
    1.75 +
    1.76 +(defmethod print-method :default [o, ^Writer w]
    1.77 +  (print-method (vary-meta o #(dissoc % :type)) w))
    1.78 +
    1.79 +(defmethod print-method nil [o, ^Writer w]
    1.80 +  (.write w "nil"))
    1.81 +
    1.82 +(defmethod print-dup nil [o w] (print-method o w))
    1.83 +
    1.84 +(defn print-ctor [o print-args ^Writer w]
    1.85 +  (.write w "#=(")
    1.86 +  (.write w (.getName ^Class (class o)))
    1.87 +  (.write w ". ")
    1.88 +  (print-args o w)
    1.89 +  (.write w ")"))
    1.90 +
    1.91 +(defmethod print-method Object [o, ^Writer w]
    1.92 +  (.write w "#<")
    1.93 +  (.write w (.getSimpleName (class o)))
    1.94 +  (.write w " ")
    1.95 +  (.write w (str o))
    1.96 +  (.write w ">"))
    1.97 +
    1.98 +(defmethod print-method clojure.lang.Keyword [o, ^Writer w]
    1.99 +  (.write w (str o)))
   1.100 +
   1.101 +(defmethod print-dup clojure.lang.Keyword [o w] (print-method o w))
   1.102 +
   1.103 +(defmethod print-method Number [o, ^Writer w]
   1.104 +  (.write w (str o)))
   1.105 +
   1.106 +(defmethod print-dup Number [o, ^Writer w]
   1.107 +  (print-ctor o
   1.108 +              (fn [o w]
   1.109 +                  (print-dup (str o) w))
   1.110 +              w))
   1.111 +
   1.112 +(defmethod print-dup clojure.lang.Fn [o, ^Writer w]
   1.113 +  (print-ctor o (fn [o w]) w))
   1.114 +
   1.115 +(prefer-method print-dup clojure.lang.IPersistentCollection clojure.lang.Fn)
   1.116 +(prefer-method print-dup java.util.Map clojure.lang.Fn)
   1.117 +(prefer-method print-dup java.util.Collection clojure.lang.Fn)
   1.118 +
   1.119 +(defmethod print-method Boolean [o, ^Writer w]
   1.120 +  (.write w (str o)))
   1.121 +
   1.122 +(defmethod print-dup Boolean [o w] (print-method o w))
   1.123 +
   1.124 +(defn print-simple [o, ^Writer w]
   1.125 +  (print-meta o w)
   1.126 +  (.write w (str o)))
   1.127 +
   1.128 +(defmethod print-method clojure.lang.Symbol [o, ^Writer w]
   1.129 +  (print-simple o w))
   1.130 +
   1.131 +(defmethod print-dup clojure.lang.Symbol [o w] (print-method o w))
   1.132 +
   1.133 +(defmethod print-method clojure.lang.Var [o, ^Writer w]
   1.134 +  (print-simple o w))
   1.135 +
   1.136 +(defmethod print-dup clojure.lang.Var [^clojure.lang.Var o, ^Writer w]
   1.137 +  (.write w (str "#=(var " (.name (.ns o)) "/" (.sym o) ")")))
   1.138 +
   1.139 +(defmethod print-method clojure.lang.ISeq [o, ^Writer w]
   1.140 +  (print-meta o w)
   1.141 +  (print-sequential "(" pr-on " " ")" o w))
   1.142 +
   1.143 +(defmethod print-dup clojure.lang.ISeq [o w] (print-method o w))
   1.144 +(defmethod print-dup clojure.lang.IPersistentList [o w] (print-method o w))
   1.145 +(prefer-method print-method clojure.lang.ISeq clojure.lang.IPersistentCollection)
   1.146 +(prefer-method print-dup clojure.lang.ISeq clojure.lang.IPersistentCollection)
   1.147 +(prefer-method print-method clojure.lang.ISeq java.util.Collection)
   1.148 +(prefer-method print-dup clojure.lang.ISeq java.util.Collection)
   1.149 +
   1.150 +
   1.151 +
   1.152 +(defmethod print-dup java.util.Collection [o, ^Writer w]
   1.153 + (print-ctor o #(print-sequential "[" print-dup " " "]" %1 %2) w))
   1.154 +
   1.155 +(defmethod print-dup clojure.lang.IPersistentCollection [o, ^Writer w]
   1.156 +  (print-meta o w)
   1.157 +  (.write w "#=(")
   1.158 +  (.write w (.getName ^Class (class o)))
   1.159 +  (.write w "/create ")
   1.160 +  (print-sequential "[" print-dup " " "]" o w)
   1.161 +  (.write w ")"))
   1.162 +
   1.163 +(prefer-method print-dup clojure.lang.IPersistentCollection java.util.Collection)
   1.164 +
   1.165 +(def ^{:tag String 
   1.166 +       :doc "Returns escape string for char or nil if none"
   1.167 +       :added "1.0"}
   1.168 +  char-escape-string
   1.169 +    {\newline "\\n"
   1.170 +     \tab  "\\t"
   1.171 +     \return "\\r"
   1.172 +     \" "\\\""
   1.173 +     \\  "\\\\"
   1.174 +     \formfeed "\\f"
   1.175 +     \backspace "\\b"})
   1.176 +
   1.177 +(defmethod print-method String [^String s, ^Writer w]
   1.178 +  (if (or *print-dup* *print-readably*)
   1.179 +    (do (.append w \")
   1.180 +      (dotimes [n (count s)]
   1.181 +        (let [c (.charAt s n)
   1.182 +              e (char-escape-string c)]
   1.183 +          (if e (.write w e) (.append w c))))
   1.184 +      (.append w \"))
   1.185 +    (.write w s))
   1.186 +  nil)
   1.187 +
   1.188 +(defmethod print-dup String [s w] (print-method s w))
   1.189 +
   1.190 +(defmethod print-method clojure.lang.IPersistentVector [v, ^Writer w]
   1.191 +  (print-meta v w)
   1.192 +  (print-sequential "[" pr-on " " "]" v w))
   1.193 +
   1.194 +(defn- print-map [m print-one w]
   1.195 +  (print-sequential 
   1.196 +   "{"
   1.197 +   (fn [e  ^Writer w] 
   1.198 +     (do (print-one (key e) w) (.append w \space) (print-one (val e) w)))
   1.199 +   ", "
   1.200 +   "}"
   1.201 +   (seq m) w))
   1.202 +
   1.203 +(defmethod print-method clojure.lang.IPersistentMap [m, ^Writer w]
   1.204 +  (print-meta m w)
   1.205 +  (print-map m pr-on w))
   1.206 +
   1.207 +(defmethod print-dup java.util.Map [m, ^Writer w]
   1.208 +  (print-ctor m #(print-map (seq %1) print-dup %2) w))
   1.209 +
   1.210 +(defmethod print-dup clojure.lang.IPersistentMap [m, ^Writer w]
   1.211 +  (print-meta m w)
   1.212 +  (.write w "#=(")
   1.213 +  (.write w (.getName (class m)))
   1.214 +  (.write w "/create ")
   1.215 +  (print-map m print-dup w)
   1.216 +  (.write w ")"))
   1.217 +
   1.218 +(prefer-method print-dup clojure.lang.IPersistentCollection java.util.Map)
   1.219 +
   1.220 +(defmethod print-method clojure.lang.IPersistentSet [s, ^Writer w]
   1.221 +  (print-meta s w)
   1.222 +  (print-sequential "#{" pr-on " " "}" (seq s) w))
   1.223 +
   1.224 +(def ^{:tag String 
   1.225 +       :doc "Returns name string for char or nil if none"
   1.226 +       :added "1.0"} 
   1.227 + char-name-string
   1.228 +   {\newline "newline"
   1.229 +    \tab "tab"
   1.230 +    \space "space"
   1.231 +    \backspace "backspace"
   1.232 +    \formfeed "formfeed"
   1.233 +    \return "return"})
   1.234 +
   1.235 +(defmethod print-method java.lang.Character [^Character c, ^Writer w]
   1.236 +  (if (or *print-dup* *print-readably*)
   1.237 +    (do (.append w \\)
   1.238 +        (let [n (char-name-string c)]
   1.239 +          (if n (.write w n) (.append w c))))
   1.240 +    (.append w c))
   1.241 +  nil)
   1.242 +
   1.243 +(defmethod print-dup java.lang.Character [c w] (print-method c w))
   1.244 +(defmethod print-dup java.lang.Integer [o w] (print-method o w))
   1.245 +(defmethod print-dup java.lang.Double [o w] (print-method o w))
   1.246 +(defmethod print-dup clojure.lang.Ratio [o w] (print-method o w))
   1.247 +(defmethod print-dup java.math.BigDecimal [o w] (print-method o w))
   1.248 +(defmethod print-dup clojure.lang.PersistentHashMap [o w] (print-method o w))
   1.249 +(defmethod print-dup clojure.lang.PersistentHashSet [o w] (print-method o w))
   1.250 +(defmethod print-dup clojure.lang.PersistentVector [o w] (print-method o w))
   1.251 +(defmethod print-dup clojure.lang.LazilyPersistentVector [o w] (print-method o w))
   1.252 +
   1.253 +(def primitives-classnames
   1.254 +  {Float/TYPE "Float/TYPE"
   1.255 +   Integer/TYPE "Integer/TYPE"
   1.256 +   Long/TYPE "Long/TYPE"
   1.257 +   Boolean/TYPE "Boolean/TYPE"
   1.258 +   Character/TYPE "Character/TYPE"
   1.259 +   Double/TYPE "Double/TYPE"
   1.260 +   Byte/TYPE "Byte/TYPE"
   1.261 +   Short/TYPE "Short/TYPE"})
   1.262 +
   1.263 +(defmethod print-method Class [^Class c, ^Writer w]
   1.264 +  (.write w (.getName c)))
   1.265 +
   1.266 +(defmethod print-dup Class [^Class c, ^Writer w]
   1.267 +  (cond
   1.268 +    (.isPrimitive c) (do
   1.269 +                       (.write w "#=(identity ")
   1.270 +                       (.write w ^String (primitives-classnames c))
   1.271 +                       (.write w ")"))
   1.272 +    (.isArray c) (do
   1.273 +                   (.write w "#=(java.lang.Class/forName \"")
   1.274 +                   (.write w (.getName c))
   1.275 +                   (.write w "\")"))
   1.276 +    :else (do
   1.277 +            (.write w "#=")
   1.278 +            (.write w (.getName c)))))
   1.279 +
   1.280 +(defmethod print-method java.math.BigDecimal [b, ^Writer w]
   1.281 +  (.write w (str b))
   1.282 +  (.write w "M"))
   1.283 +
   1.284 +(defmethod print-method java.util.regex.Pattern [p ^Writer w]
   1.285 +  (.write w "#\"")
   1.286 +  (loop [[^Character c & r :as s] (seq (.pattern ^java.util.regex.Pattern p))
   1.287 +         qmode false]
   1.288 +    (when s
   1.289 +      (cond
   1.290 +        (= c \\) (let [[^Character c2 & r2] r]
   1.291 +                   (.append w \\)
   1.292 +                   (.append w c2)
   1.293 +                   (if qmode
   1.294 +                      (recur r2 (not= c2 \E))
   1.295 +                      (recur r2 (= c2 \Q))))
   1.296 +        (= c \") (do
   1.297 +                   (if qmode
   1.298 +                     (.write w "\\E\\\"\\Q")
   1.299 +                     (.write w "\\\""))
   1.300 +                   (recur r qmode))
   1.301 +        :else    (do
   1.302 +                   (.append w c)
   1.303 +                   (recur r qmode)))))
   1.304 +  (.append w \"))
   1.305 +
   1.306 +(defmethod print-dup java.util.regex.Pattern [p ^Writer w] (print-method p w))
   1.307 +
   1.308 +(defmethod print-dup clojure.lang.Namespace [^clojure.lang.Namespace n ^Writer w]
   1.309 +  (.write w "#=(find-ns ")
   1.310 +  (print-dup (.name n) w)
   1.311 +  (.write w ")"))
   1.312 +
   1.313 +(defmethod print-method clojure.lang.IDeref [o ^Writer w]
   1.314 +  (print-sequential (format "#<%s@%x%s: "
   1.315 +                            (.getSimpleName (class o))
   1.316 +                            (System/identityHashCode o)
   1.317 +                            (if (and (instance? clojure.lang.Agent o)
   1.318 +                                     (agent-error o))
   1.319 +                              " FAILED"
   1.320 +                              ""))
   1.321 +                    pr-on, "", ">", (list (if (and (future? o) (not (future-done? o))) :pending @o)), w))
   1.322 +
   1.323 +(def ^{:private true} print-initialized true)