Hi --
I'd like to customize how SBCL's TRACE prints a function call and
return values. To illustrate what I have in mind, here are small but
illustrative examples using GCL and Allegro CL (much simpler than what
I actually do).
GCL:
>(defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
FACT
>(trace (fact :entry (list 'fact-argument '= (car si::arglist))
:exit (list 'fact-value '= (car values))))
(FACT)
>(fact 4)
1> (FACT-ARGUMENT = 4)
2> (FACT-ARGUMENT = 3)
3> (FACT-ARGUMENT = 2)
4> (FACT-ARGUMENT = 1)
5> (FACT-ARGUMENT = 0)
<5 (FACT-VALUE = 1)
<4 (FACT-VALUE = 1)
<3 (FACT-VALUE = 2)
<2 (FACT-VALUE = 6)
<1 (FACT-VALUE = 24)
24
>
Allegro CL:
CL-USER(1): (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
FACT
CL-USER(2): (progn (excl:advise fact :before nil nil
(print (list 'fact-argument '= (car excl:arglist))))
(excl:advise fact :after nil nil
(print (list 'fact-value '= (car values)))))
FACT
CL-USER(3): (fact 4)
(FACT-ARGUMENT = 4)
(FACT-ARGUMENT = 3)
(FACT-ARGUMENT = 2)
(FACT-ARGUMENT = 1)
(FACT-ARGUMENT = 0)
(FACT-VALUE = 1)
(FACT-VALUE = 1)
(FACT-VALUE = 2)
(FACT-VALUE = 6)
(FACT-VALUE = 24)
24
CL-USER(4):
Can I similarly get control over the arglist and values in SBCL?
Here's the best I could do, where I'm just guessing about this use of
SB-INT:ARG-LIST (not documented though as far as I can tell). Notice
that :report isn't implemented (this from Version 1.0.13.31, obtained
today by CVS), and notice that even if it were, I would still get
noise added to the output I want (as shown above).
* (trace fact
:print (list 'fact-argument '= (car sb-int:arg-list))
:print-after (list 'fact-value '= (car sb-debug:*trace-values*)))
; in: LAMBDA NIL
; (CAR SB-INT:ARG-LIST)
;
; caught WARNING:
; undefined variable: SB-INT:ARG-LIST
;
; caught WARNING:
; This variable is undefined:
; SB-INT:ARG-LIST
;
; compilation unit finished
; caught 2 WARNING conditions
(FACT)
* (fact 4)
0: (FACT 4)
0: (LIST 'FACT-ARGUMENT '= (CAR SB-INT:ARG-LIST)) = (FACT-ARGUMENT = 4)
1: (FACT 3)
1: (LIST 'FACT-ARGUMENT '= (CAR SB-INT:ARG-LIST)) = (FACT-ARGUMENT = 3)
2: (FACT 2)
2: (LIST 'FACT-ARGUMENT '= (CAR SB-INT:ARG-LIST)) = (FACT-ARGUMENT = 2)
3: (FACT 1)
3: (LIST 'FACT-ARGUMENT '= (CAR SB-INT:ARG-LIST)) = (FACT-ARGUMENT = 1)
4: (FACT 0)
4: (LIST 'FACT-ARGUMENT '= (CAR SB-INT:ARG-LIST))
= (FACT-ARGUMENT = 0)
4: FACT returned 1
4: (LIST 'FACT-VALUE '= (CAR *TRACE-VALUES*)) = (FACT-VALUE = 1)
3: FACT returned 1
3: (LIST 'FACT-VALUE '= (CAR *TRACE-VALUES*)) = (FACT-VALUE = 1)
2: FACT returned 2
2: (LIST 'FACT-VALUE '= (CAR *TRACE-VALUES*)) = (FACT-VALUE = 2)
1: FACT returned 6
1: (LIST 'FACT-VALUE '= (CAR *TRACE-VALUES*)) = (FACT-VALUE = 6)
0: FACT returned 24
0: (LIST 'FACT-VALUE '= (CAR *TRACE-VALUES*)) = (FACT-VALUE = 24)
24
* (trace fact
:print (list 'fact-argument '= (car sb-int:arg-list))
:print-after (list 'fact-value '= (car sb-debug:*trace-values*))
:report nil)
debugger invoked on a SIMPLE-ERROR:
stub: The :REPORT option is not yet implemented.
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-DEBUG::PARSE-TRACE-OPTIONS
(:PRINT (LIST 'FACT-ARGUMENT '= (CAR SB-INT:ARG-LIST)) :PRINT-AFTER
(LIST 'FACT-VALUE '= (CAR *TRACE-VALUES*)) :REPORT NIL)
#<SB-DEBUG::TRACE-INFO NIL>)
0]
A google search seems to suggest that SBCL has some sort of FWRAP
support that might help, but I don't know anything about FWRAP and I
don't see user-level documentation for it.
Any suggestions?
Thanks --
-- Matt
|