Inserting breaks
The break function interrupts your program and jumps to a prompt where you can examine the state of your program. For example, you can:
- Examine the values of the local variables, or even change them.
- See a backtrace of up to seven previously called functions.
- Abort from your program and return to the uLisp prompt.
- Continue execution, executing the rest of your program from where it was interrupted.
Example
For example, here's a program intended to set the brightness of an LED for values of x from 1 to 16 by calculating y = x2 - 1 and setting the analogue output to y:
(defun set (x) (let ((x (* x x)) (y (- x 1))) (analogwrite 9 y)))
Unfortunately the LED is always dim, even when we execute (set 16). What's going on? The solution is to insert a call to break:
(defun set (x) (let ((x (* x x)) (y (- x 1))) (break) (analogwrite 9 y)))
Now when we run it we can examine the variables when the program is interrupted with the break:
9444> (set 16) Break! 9444 : 1>
Within the break the prompt : 1> indicates the depth of the break. After the prompt you can find the values of variables, and evaluate functions, just like at the main uLisp prompt.
For example, we can find the values of the local variables x and y by typing:
9444 : 1> x 256 9444 : 1> y 15
In addition, at the break prompt there are the special options nil, :a, :b, and :c; see below.
The problem is revealed: y is taking the value of x from the parameter, not the previous let assignment. What we need is let*:
(defun set (x) (let* ((x (* x x)) (y (- x 1))) (analogwrite 9 y)))
Break options
The following options are available within a break:
Option | Description |
nil or :c | Continue execution |
:b | Display backtrace |
:a | Abort |
Abort
Typing :a aborts execution and returns to the main prompt. It's equivalent to typing :c repeatedly.
Backtrace
Typing :b will display a backtrace in the same format as in the error messages.
First the backtrace feature needs to be enabled if necessary, by typing:
(backtrace t)
For example, suppose you are debugging the following functions:
(defun myprog () (dotimes (x 2) (print (eqn (+ 3 x))))) (defun eqn (x) (* x (/ (- 4 x))))
Insert a call to break within the eqn function by redefining it as:
(defun eqn (x) (break) (* x (/ (- 4 x))))
Running myprog will execute the break and put you in the REPL:
> (myprog) Break! 9366 : 1>
The :b option will display a backtrace in the same format as in the error messages:
9366 : 1> :b [eqn <- myprog]
This shows that eqn was called by myprog when the break occurred.
Continue
Typing :c (or nil) continues execution of the program until it either encounters the (break) again, or it terminates.