Arc Forumnew | comments | leaders | submitlogin
Trace à la Common Lisp
14 points by fallintothis 3049 days ago | discuss
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.