結構かんたんにtraceって書けるものなんだなー

(use gauche.parameter)
(define *depth* (make-parameter 0))
(define *origin-fun* (make-parameter #f))

(define-macro (trace f)
  `(begin
     (*origin-fun* ,f)
     (set! ,f (lambda args 
		(let* ((d (*depth*))
		       (padding (make-string d #\space)))
		  (print padding "call:" args)
		  (*depth* (+ 1 d))
		  (receive rvs (apply (*origin-fun*) args)
		    (unless (zero? d)
		      (print padding "retv:" rvs))
		    (apply values rvs)))))))

(define-macro (untrace f) `(set! ,f (*origin-fun*)))

;;
(define (gcd x y) (if (zero? y) x (gcd y (modulo x y))))
(trace gcd)
(gcd 124 14)
(untrace gcd)
(gcd 124 14)
gosh> *depth*
gosh> *origin-fun*
gosh> #<undef>
gosh> #<undef>
gosh> gcd
gosh> #<closure #f>
gosh> call:(124 14)
 call:(14 12)
  call:(12 2)
   call:(2 0)
   retv:(2)
  retv:(2)
 retv:(2)
2
gosh> #<closure gcd>
gosh> 2