For Development HEAD DRAFTSearch (procedure/syntax/module):

3.4 Debugging

Gauche doesn’t have much support for debugging yet. The idea of good debugging interfaces are welcome.

For now, the author uses the classic ’debug print stub’ technique when necessary. Gauche’s reader supports special syntaxes beginning with #?, to print the intermediate value.

The syntax #?=expr shows expr itself before evaluating it, and prints its result(s) after evaluation.

gosh> #?=(+ 2 3)
#?="(stdin)":1:(+ 2 3)
#?-    5
5
gosh> #?=(begin (print "foo") (values 'a 'b 'c))
#?="(stdin)":2:(begin (print "foo") (values 'a 'b 'c))
foo
#?-    a
#?+    b
#?+    c
a
b
c

Note: If the debug stub is evaluated in a thread other than the primordial thread (see gauche.threads - Threads), the output includes a number to distinguish which thread it is generated. In the following example, #<thread ...> and the prompt is the output of REPL in the primordial thread, but following #?=[1]... and #?-[1]... are the debug output from the thread created by make-thread. The number is for debugging only— they differ for each thread, but other than that there’s no meaning.

gosh> (use gauche.threads)
gosh> (thread-start! (make-thread (^[] #?=(+ 2 3))))
#<thread #f (1) runnable 0xf51400>
gosh> #?=[1]"(standard input)":1:(+ 2 3)
#?-[1]    5

The syntax #?,(proc arg …) is specifically for procedure call; it prints the value of arguments right before calling proc, and prints the result(s) of call afterwards.

gosh> (define (fact n)
        (if (zero? n)
            1
            (* n #?,(fact (- n 1)))))
fact
#?,"(standard input)":4:calling `fact' with args:
#?,> 4
#?,"(standard input)":4:calling `fact' with args:
#?,> 3
#?,"(standard input)":4:calling `fact' with args:
#?,> 2
#?,"(standard input)":4:calling `fact' with args:
#?,> 1
#?,"(standard input)":4:calling `fact' with args:
#?,> 0
#?-    1
#?-    1
#?-    2
#?-    6
#?-    24
120

Internally, the syntax #?=x and #?,x are read as (debug-print x) and (debuf-funcall x), respectively, and the macros debug-print and debug-funcall handles the actual printing. See Debugging aid, for more details.

The reasons of special syntax are: (1) It’s easy to insert the debug stub, for you don’t need to enclose the target expression by extra parenthesis, and (2) It’s easy to find and remove those stabs within the editor.

Simple debug stubs may produce too many output, and you may want to limit them when certain conditions are met. A reader syntax #??=test expr and #??,test procedure-call works much like #??=expr and #?,procedure-call, but only when test yields true:

(define (fib n)
  (if (< n 2)
    1
    #??,(= n 5) (+ (fib (- n 1)) (fib (- n 2)))))

gosh> (fib 7)
#?,calling `+' with args:
#?,> 5
#?,> 3
#?-    8
#?,calling `+' with args:
#?,> 5
#?,> 3
#?-    8
21

Internally, #??=test expr and #??,test procedure-call are expanded to macro calls (debug-print-conditionally test expr) and (debug-funcallt-conditionally test procedure-call).



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT