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