| http://bitbucket.org/fallintothis/trace I was missing this feature from Common Lisp, so I whipped up an analog for Arc. It has a couple of hacks, but on the whole is simple, weighing in at 65 lines (according to codelines). In action: Use (quit) to quit, (tl) to return here after an interrupt.
arc> (load "trace.arc")
nil
arc> (trace def mac)
*** tracing def
*** tracing mac
nil
arc> (def map- (f xs) (when xs (cons (f (car xs)) (map- f (cdr xs)))))
1. Trace:
(def map- (f xs)
(when xs
(cons (f (car xs))
(map- f (cdr xs)))))
1. Trace: def ==>
(do (sref sig
'(f xs)
'map-)
(safeset map-
(fn (f xs)
(when xs
(cons (f (car xs))
(map- f (cdr xs)))))))
#<procedure: map->
arc> (map- [+ _ 1] '(1 2 3))
(2 3 4)
arc> (map- (traced [+ _ 1]) '(1 2 3)) ; traced tries to figure out function name
1. Trace: (#<procedure> 1)
1. Trace: #<procedure> ==> 2
1. Trace: (#<procedure> 2)
1. Trace: #<procedure> ==> 3
1. Trace: (#<procedure> 3)
1. Trace: #<procedure> ==> 4
(2 3 4)
arc> (map- (traced [+ _ 1] 'traced-f) '(1 2 3)) ; but you can supply your own
1. Trace: (traced-f 1)
1. Trace: traced-f ==> 2
1. Trace: (traced-f 2)
1. Trace: traced-f ==> 3
1. Trace: (traced-f 3)
1. Trace: traced-f ==> 4
(2 3 4)
arc> ((traced map-) [+ _ 1] '(1 2 3)) ; only top-level map- is traced!
1. Trace: (map- #<procedure> (1 2 3))
1. Trace: map- ==> (2 3 4)
(2 3 4)
arc> (trace map-) ; since this is destructive, all calls to map- are traced
*** tracing map-
nil
arc> (map- [+ _ 1] '(1 2 3))
1. Trace: (map- #<procedure> (1 2 3))
2. Trace: (map- #<procedure> (2 3))
3. Trace: (map- #<procedure> (3))
4. Trace: (map- #<procedure> nil)
4. Trace: map- ==> nil
3. Trace: map- ==> (4)
2. Trace: map- ==> (3 4)
1. Trace: map- ==> (2 3 4)
(2 3 4)
arc> (= trace-indent* 2)
2
arc> (map- [+ _ 1] '(1 2 3))
1. Trace: (map- #<procedure> (1 2 3))
2. Trace: (map- #<procedure> (2 3))
3. Trace: (map- #<procedure> (3))
4. Trace: (map- #<procedure> nil)
4. Trace: map- ==> nil
3. Trace: map- ==> (4)
2. Trace: map- ==> (3 4)
1. Trace: map- ==> (2 3 4)
(2 3 4)
arc> (untrace map-)
*** untracing map-
nil
arc> (map- [+ _ 1] '(1 2 3))
(2 3 4)
arc> (mac m (x) `(list ',x))
1. Trace:
(mac m
(x)
(quasiquote (list (quote (unquote x)))))
1. Trace: mac ==>
(do (sref sig (quote (x)) (quote m))
(safeset m
(annotate 'mac
(fn (x)
(quasiquote (list (quote (unquote x))))))))
#(tagged mac #<procedure: m>)
arc> ((traced m) 1) ; note: no first-class macros
Error: "Function call on inappropriate object #(tagged mac #<procedure: traced>) (1)"
arc> (= tm (traced m)) ; could do this, but why? prefer (trace m)
#(tagged mac #<procedure: traced>)
arc> (tm 1)
1. Trace: (m 1)
1. Trace: m ==> (list (quote 1))
(1)
arc> (trace m)
*** tracing m
nil
arc> (m 1)
1. Trace: (m 1)
1. Trace: m ==> (list (quote 1))
(1)
arc> (untrace) ; everything
*** untracing def
*** untracing mac
*** untracing m
nil
arc> (trace trace)
*** tracing trace
nil
arc> (trace trace)
1. Trace: (trace trace)
1. Trace: trace ==>
(do1 nil
(if (no (traced* (quote trace)))
(do (prn "*** tracing " (quote trace))
(make-traced trace))
(prn "*** already traced " (quote trace))))
*** already traced trace
nil
arc> (untrace)
*** untracing trace
nil
Be careful tracing predefined Arc functions/macros. Because this (and so much of Arc) is written in Arc, tracing things that trace.arc uses (even if indirectly) can lead to infinite loops. arc> (trace +)
*** tracing +
nil
arc> (+ 1 2) ; hangs
user break
Rather than restrict what you can and cannot trace (no really clean, disciplined way of doing so), I figured I'd warn you. Doesn't seem like much of a show-stopper; and if it is, well, a) patches are welcome and b) I told you so. |