Philosophy of Algorithmic Composition
Chapter 3 Introduction to SAL
3.10 Stack Traces
SAL> print transpose-midi-note(60) error: too few arguments
Call traceback:
SAL top-level command interpreter
3.10 Stack Traces
When expressions are nested and when user-defined functions are evaluated, the SAL evaluation process can be nested hundreds of levels deep. The top-level command can call a function, which calls another function, which calls another, and so on. Often, an error message has no immediate connection to the top-level expression you typed. The traceback facility lets you see exactly what the SAL evaluator was doing leading up to the error condition. Stack traces require careful study, but this can pay off handsomely when you need to know how an error occurred.
There are actually two traceback facilities offering different levels of detail. The first is the “SAL traceback” that we have already seen hints of. To illustrate the SAL traceback, consider the user-defined transpose-midi-note function and an expression that calls it with an incorrect input:
Example 3.10.1: Define and call transpose-midi-note SAL> define function transpose-midi-note(
key-number, interval) begin
return key-number + interval end
SAL> print transpose-midi-note(quote(c4), 4) error: bad argument type - C4
Call traceback:
TRANSPOSE-MIDI-NOTE(
KEY-NUMBER = C4,
INTERVAL = 4) at line 4
SAL top-level command interpreter
At this point, it is pretty clear that C4 is a bad input (the values of input expressions are called arguments; notice the output text:
“error: bad argument type – C4”), but what function generated the error message? Reading further, the Call traceback shows that the er-ror occurred in transpose-midi-note, with inputs key-number = C4, and interval = 4. Furthermore, the error occurred at line 4 of the function (at the return statement). Why was transpose-midi-note
3.10 Stack Traces 41
called? The next line of the traceback says transpose-midi-note was called from the SAL top-level command interpreter. In other words, the user typed in a command.
The Call traceback tells you about SAL program evaluation, but sometimes more detail is useful. Recall that SAL works by translat-ing programs into Lisp, so errors are actually detected in the process of Lisp evaluation. The Lisp evaluation system has its own stack trace mechanism. To enable this, set the “Print Stack Trace on Error”
option in the Preferences dialog box (opened using the Preferences menu item). With this option, try the same call to transpose-midi-note:
Example 3.10.2: XLISP traceback
SAL> print transpose-midi-note(quote(c4), 4) error: bad argument type - C4
Function: #<Subr-SND-OFFSET: #71c788>
Arguments:
C4 4
Function: #<FSubr-COND: #71fc50>
Arguments:
((NUMBERP S1) (COND ((NUMBERP S2) (+ S1 S2 … ((NUMBERP S2) (SND-OFFSET S1 S2))
(T (LET ((S1SR (SND-SRATE S1)) …
Function: #<Closure-NYQ:ADD-2-SOUNDS: #736a50>
Arguments:
C4 4
Function: #<FSubr-COND: #71fc50>
Arguments:
… …many more function/argument pairs elided…
Function: #<Closure-SAL-COMPILE: #790864>
Arguments:
"print transpose-midi-note(quote(c4), 4)"
T NIL
"<console>"
…more function/argument pairs elided…
1>
The full stack trace is over 100 lines long. It shows in detail how the program arrived at the error. A full understanding of the stack trace requires a good knowledge of Lisp, but a look at the stack trace can
be helpful even without a complete understanding. The general for-mat of the XLISP stack trace is just like the SAL stack trace: both give a list of functions and arguments (input values). Here, we see that the error occurred in SND-OFFSET, a Lisp primitive. (Lisp primitives are indicated by the “Subr-” prefix.) Looking down a bit further, we see that SND-OFFSET was called indirectly from NYQ:ADD-2-SOUNDS, which has inputs C4 and 4. This may seem a bit unrelated to the SAL program, but it should be clear that C4 and 4 come from the SAL command, and at least the word “ADD”
should indicate that execution is related to the “+” in transpose-midi-note. Looking further down the stack trace, you can find a call to SAL-COMPILE, and one of the inputs is the SAL command repre-sented as a string. This gives a bit of insight into how SAL programs are converted to Lisp and evaluated.
After the stack trace is printed, the prompt “1>” appears. The user can enter additional commands in Lisp, or return to SAL input mode.
To resume working in SAL, click on the Top button of the IDE, then click on the SAL button. The output will look like this:
1> (top)
[ back to top level ]
> (sal)
Entering SAL mode ...
SAL>
To conclude, SAL automatically prints a stack trace that tells you where an error occurred, including the chain of calls from the com-mand line to the function raising the error. If the nature of the error is still unclear, it can be helpful to take out the “magnifying glass” by enabling the “Print Stack Trace on Error” option and running the program again. The resulting stack trace has more detail, but the de-tail is expressed in terms of the underlying Lisp system, which may be less familiar. To resume work in SAL, push the Top and SAL buttons in the IDE.
3.11 Printing
The print command is also very useful for understanding and de-bugging programs. When functions and expressions are deeply nested, the print function allows you to insert check points and con-firm that evaluation is proceeding as planned. In fact, print’ing is such a useful aid to debugging that SAL has a special command, display, that is especially designed for debugging. We will return to this topic after a discussion of programming concepts in the next chapter.
43