annotate src/clojure/contrib/trace.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 ;;; trace.clj -- simple call-tracing macros for Clojure
rlm@10 2
rlm@10 3 ;; by Stuart Sierra, http://stuartsierra.com/
rlm@10 4 ;; December 3, 2008
rlm@10 5
rlm@10 6 ;; Copyright (c) Stuart Sierra, 2008. All rights reserved. The use
rlm@10 7 ;; and distribution terms for this software are covered by the Eclipse
rlm@10 8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
rlm@10 9 ;; which can be found in the file epl-v10.html at the root of this
rlm@10 10 ;; distribution. By using this software in any fashion, you are
rlm@10 11 ;; agreeing to be bound by the terms of this license. You must not
rlm@10 12 ;; remove this notice, or any other, from this software.
rlm@10 13
rlm@10 14
rlm@10 15 ;; This file defines simple "tracing" macros to help you see what your
rlm@10 16 ;; code is doing.
rlm@10 17
rlm@10 18
rlm@10 19 ;; CHANGE LOG
rlm@10 20 ;;
rlm@10 21 ;; December 3, 2008:
rlm@10 22 ;;
rlm@10 23 ;; * replaced *trace-out* with tracer
rlm@10 24 ;;
rlm@10 25 ;; * made trace a function instead of a macro
rlm@10 26 ;; (suggestion from Stuart Halloway)
rlm@10 27 ;;
rlm@10 28 ;; * added trace-fn-call
rlm@10 29 ;;
rlm@10 30 ;; June 9, 2008: first version
rlm@10 31
rlm@10 32
rlm@10 33
rlm@10 34 (ns
rlm@10 35 ^{:author "Stuart Sierra, Michel Salim",
rlm@10 36 :doc "This file defines simple \"tracing\" macros to help you see what your
rlm@10 37 code is doing."}
rlm@10 38 clojure.contrib.trace)
rlm@10 39
rlm@10 40 (def
rlm@10 41 ^{:doc "Current stack depth of traced function calls."}
rlm@10 42 *trace-depth* 0)
rlm@10 43
rlm@10 44 (defn tracer
rlm@10 45 "This function is called by trace. Prints to standard output, but
rlm@10 46 may be rebound to do anything you like. 'name' is optional."
rlm@10 47 [name value]
rlm@10 48 (println (str "TRACE" (when name (str " " name)) ": " value)))
rlm@10 49
rlm@10 50 (defn trace
rlm@10 51 "Sends name (optional) and value to the tracer function, then
rlm@10 52 returns value. May be wrapped around any expression without
rlm@10 53 affecting the result."
rlm@10 54 ([value] (trace nil value))
rlm@10 55 ([name value]
rlm@10 56 (tracer name (pr-str value))
rlm@10 57 value))
rlm@10 58
rlm@10 59 (defn trace-indent
rlm@10 60 "Returns an indentation string based on *trace-depth*"
rlm@10 61 []
rlm@10 62 (apply str (take *trace-depth* (repeat "| "))))
rlm@10 63
rlm@10 64 (defn trace-fn-call
rlm@10 65 "Traces a single call to a function f with args. 'name' is the
rlm@10 66 symbol name of the function."
rlm@10 67 [name f args]
rlm@10 68 (let [id (gensym "t")]
rlm@10 69 (tracer id (str (trace-indent) (pr-str (cons name args))))
rlm@10 70 (let [value (binding [*trace-depth* (inc *trace-depth*)]
rlm@10 71 (apply f args))]
rlm@10 72 (tracer id (str (trace-indent) "=> " (pr-str value)))
rlm@10 73 value)))
rlm@10 74
rlm@10 75 (defmacro deftrace
rlm@10 76 "Use in place of defn; traces each call/return of this fn, including
rlm@10 77 arguments. Nested calls to deftrace'd functions will print a
rlm@10 78 tree-like structure."
rlm@10 79 [name & definition]
rlm@10 80 `(do
rlm@10 81 (def ~name)
rlm@10 82 (let [f# (fn ~@definition)]
rlm@10 83 (defn ~name [& args#]
rlm@10 84 (trace-fn-call '~name f# args#)))))
rlm@10 85
rlm@10 86 (defmacro dotrace
rlm@10 87 "Given a sequence of function identifiers, evaluate the body
rlm@10 88 expressions in an environment in which the identifiers are bound to
rlm@10 89 the traced functions. Does not work on inlined functions,
rlm@10 90 such as clojure.core/+"
rlm@10 91 [fnames & exprs]
rlm@10 92 `(binding [~@(interleave fnames
rlm@10 93 (for [fname fnames]
rlm@10 94 `(let [f# @(var ~fname)]
rlm@10 95 (fn [& args#]
rlm@10 96 (trace-fn-call '~fname f# args#)))))]
rlm@10 97 ~@exprs))