/lib/trace.arc

http://github.com/alimoeeny/arc · Unknown · 85 lines · 69 code · 16 blank · 0 comment · 0 complexity · e4dc95ce5ecd00a9f6d5498d5627223e MD5 · raw file

  1. ; written by fallintothis
  2. ; stolen from from http://bitbucket.org/fallintothis/trace/src/tip/trace.arc
  3. ; function & macro tracing
  4. (= trace-level* 0)
  5. (= trace-indent* nil)
  6. (= traced* (table))
  7. (def traced (f (o name (fn-name f)))
  8. (check-traceable f)
  9. (let orig f
  10. (annotate (type orig)
  11. (fn args
  12. (++ trace-level*)
  13. (trace-enter name args)
  14. (after (trace-exit name (apply (rep orig) args))
  15. (-- trace-level*))))))
  16. (mac trace fs
  17. `(do1 nil ,@(map (fn (f)
  18. `(if (no (traced* ',f))
  19. (do (prn "*** tracing " ',f)
  20. (make-traced ,f))
  21. (prn "*** already traced " ',f)))
  22. fs)))
  23. (mac make-traced (name)
  24. (check-traceable-name name)
  25. (w/uniq f
  26. `(let ,f (traced ,name ',name)
  27. (= (traced* ',name) ,name
  28. ,name ,f))))
  29. (mac untrace fs
  30. `(do1 nil ,@(map (fn (f)
  31. `(if (traced* ',f)
  32. (do (prn "*** untracing " ',f)
  33. (make-untraced ,f))
  34. (prn "*** already untraced " ',f)))
  35. (or fs (keys traced*)))))
  36. (mac make-untraced (name)
  37. `(= ,name (traced* ',name)
  38. (traced* ',name) nil))
  39. (def indent () (sp (indent-amount)))
  40. (def indent-amount ()
  41. (* (or trace-indent* 0) (- trace-level* 1)))
  42. (def trace-enter (name args)
  43. (indent)
  44. (pr trace-level* ". Trace: ")
  45. (pprn-elastic (cons name args)))
  46. (def trace-exit (name result)
  47. (indent)
  48. (pr trace-level* ". Trace: " name " ==> ")
  49. (pprn-elastic result)
  50. result)
  51. (def pprn-elastic (expr)
  52. (let broke (w/stdout (outstring) (ppr expr))
  53. (if broke (prn))
  54. (ppr expr (if broke (indent-amount) 0)) ; xxx gross to redo ppr
  55. (prn)))
  56. (def check-traceable-name (name)
  57. (if (~isa name 'sym)
  58. (err "Not a function or macro name:" name)
  59. (~bound name)
  60. (err "Can't trace unbound symbol:" name)))
  61. (def check-traceable (f)
  62. (unless (in (type f) 'fn 'mac)
  63. (err "Can only trace functions and macros:" f)))
  64. ; gross, but more-or-less effective
  65. (def fn-name (f)
  66. (let repr (tostring:disp (case (type f) fn f mac (rep f)))
  67. (if (headmatch "#<procedure:" repr)
  68. (sym:trim (cut repr 12 -1))
  69. f))) ; ppr uses write, not disp, so (sym:tostring:disp f) has bars