(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