From: Michel T. <ta...@lp...> - 2022-02-16 21:06:15
|
Hello, having been in close contact with the debugger yesterday, i would like to share some remarks, which may be useful for newcomers. First on Maxima 5.43.2 using Lisp SBCL 2.0.1.debian, the command to set breakpoints doesn't work. Using the file "example.mac" which contains kill(all)$ i:3$ j:-2$ bug(i,j):=float(i)/float(j)$ for k from 1 thru 4 do ( i:i+1, j:j+1, bug(i,j)); (%i27) :br bug No line info for $BUG I had this problem repeatedly with colnew.mac. The only way to set a breakpoint on a function is to use trace(bug) with a trace_option. I then devised a method which is not documented as far as i have seen, which is to introduce a "function break" in the source code, like this: bug(i,j):= ( break(), float(i)/float(j))$ ................. (%i4) for k from 1 thru 4 do ( i:i+1, j:j+1, bug(i,j)); Entering a Maxima break point. Type 'exit;' to resume. Here one can examine all the variables and see the cause of the bug. _i; 4 _j; - 1 _exit; Here the for loop runs once Entering a Maxima break point. Type 'exit;' to resume. _i; 5 _j; 0 _exit; Here float(i)/float(j) runs and bugs Maxima encountered a Lisp error: arithmetic error DIVISION-BY-ZERO signalled ..... Since we are in a lisp error one can enter the lisp debugger: (%i5) :lisp(setq *debugger-hook* nil) .... debugger invoked on a DIVISION-BY-ZERO in thread #<THREAD "main thread" RUNNING {1000560083}>: arithmetic error DIVISION-BY-ZERO signalled Operation was (/ 5.0d0 0.0d0). restarts (invokable by number or by possibly-abbreviated name): 0: [MACSYMA-QUIT] Maxima top-level 1: [ABORT ] Exit debugger, returning to top level. (SB-KERNEL:TWO-ARG-/ 5.0d0 0.0d0) 0] ba 5 Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {1000560083}> 0: (SB-KERNEL:TWO-ARG-/ 5.0d0 0.0d0) 1: (MLAMBDA ((LAMBDA) ((MLIST) $I $J) ((MQUOTIENT) (($FLOAT) $I) (($FLOAT) $J))) (5 0) $BUG NIL (($BUG) $I $J)) 2: (MEVAL1 (($BUG) $I $J)) 3: (MEVAL (($BUG) $I $J)) 4: (MEVALN ((#1=(MSETQ) $I (#2=(MPLUS) $I 1)) (#1# $J (#2# $J 1)) (($BUG) $I $J))) The problematic instruction is obvious in frame 1. One should now hit 0 to return to maxima, but suppose i made an error and hit 1. All is not lost: 0] 1 * (run) Maxima restarted. (%i5) Now let us modify the program to produce maxima error and not a lisp error in order to look at the maxima debugger. So let us modify bug(i,j) to bug(i,j):= i/j$ and set debugmode(true). (%i4) for k from 1 thru 4 do ( i:i+1, j:j+1, bug(i,j)); expt: undefined: 0 to a negative exponent. -- an error. Entering the Maxima debugger. Enter ':h' for help. bug(i=5,j=0) (dbm:1) The first thing to note is that :br still doesn't work. (%i6) :br bug Turning on debugging debugmode(true)No line info for $BUG Consequently :step :next etc. don't work either. What works is: (dbm:1) :bt #0: bug(i=5,j=0) (dbm:1) i; 5 (dbm:1) j; 0 (dbm:1) bug(i,j); expt: undefined: 0 to a negative exponent. -- an error. Entering the Maxima debugger. Enter ':h' for help. bug(i=5,j=0) (dbm:2) Second level in the debugger, etc. So one can examine the variables and run the program by hand in the context in which the debugger was called, which is sufficient to do the job. One can even enter the lisp debugger by issuing: (dbm:2) :lisp(break) debugger invoked on a SIMPLE-CONDITION in thread #<THREAD "main thread" RUNNING {1000560083}>: break ................ I have tried the same wih clisp, apparently :br runs somewhat better. In conclusion i think it would be nice to update the manual (section debugging) with what really works, at present, notably with sbcl which is the dominant lisp underlying maxima, and it would also be useful to indicate there is a function break() in maxima, which allows to do almost everything useful for debugging, similar to the function (break) in lisp. -- Michel Talon |