.NH 1 The State Indicator .PP \*a is a recursive language which supports local variables. Therefore, it is essential that it maintain some sort of information concerning its current state of execution, local variables, and status of functions. Part of this information \(em the current status of active functions, is called the ``state indicator''.* .FS *Users of other \*a systems should note that the state indicator as implemented on \*u \*a is similar in concept to the standard \*a state indicator, but does not function entirely the same way. In particular, the system command ``)siv'' is not supported, and the state indicator is cleared in a different manner. Read on. .FE Each time a function begins execution, \*a keeps track of the current line number in that function. When the current function calls another function, the line number where the request was made is recorded in the state indicator. .PP When a function terminates abnormally, it is said to be ``suspended''. This means that \*a stops execution of the function, but retains all information about its current state of execution. In some cases, the problem can be corrected and the function restarted where it left off. This discussion will not include that technique. In any event, when the function is suspended, \*a will print a traceback automatically, perhaps such as: .sp .DS L varx: used before set at fn3[5] from fn2[12] from main[4] .DE .sp In this case, the error (undefined variable) occurred in the function ``fn3'' at line 5. ``fn3'' was called by the function ``fn2'' at line 12, which in turn was called by the function ``main'' at line 14. .PP The ``)si'' command produces a similar traceback. For the above example, the traceback could be: .sp .DS L fn3[5] * fn2[12] main[4] .DE .sp This shows that the function ``fn3'' was suspended due to error, and that ``fn2'' and ``main'' are waiting for ``fn3'' and ``fn2'', respectively. .PP When an error occurs and a function is suspended, all of that function's variables are accessible from the keyboard. Thus, you can examine the current variables to help determine the problem. As stated above, in some cases it may be possible to change some variables and resume execution of the suspended function. However, in general, after you examine the variables you will probably want to restart from the beginning. In order to do this, type the ``)reset'' command. This causes \*a to clear the state indicator, resetting suspended functions and releasing local variables. .PP If you do not use ``)reset'', you will find two things. First, if you get another error, the state indicator may look like: .sp .DS L fn3[3] * fn2[12] main[4] fn3[5] * fn2[12] main[4] .DE .sp This shows that ``fn3'' was suspended due to an error at line 3, and it traces execution back to the start of ``main''. Then, it shows that in a previous run, ``fn3'' was suspended due to an error at line 5, and it traces execution back to the start of ``main''. You can still use the ``)reset'' command to get back to a clear state indicator. .PP The other effect which you will notice if you do not ``)reset'' the state indicator is that you will be unable to edit some functions. If a function is suspended (it appears in the state indicator), it cannot be changed, because it is possible that the error condition may be corrected and execution resumed. Therefore, if you try to edit a function which appears in the state indicator, you will get the error message: .sp si damage -- type \')reset\' .sp To edit the function, clear the state indicator with ``)reset'' first, and then you may proceeed with an ``)edit'' or ``)editf'' command. .PP A useful technique for finding errors is to look at the function which ``blew up'' and try retyping the line which failed, a little bit at a time. This often helps isolate the problem. Generally, you want to do this before the state indicator is ``)reset'' so that the state of \*a is exactly the same as it was when the error was detected. Since you cannot run the editor to list the function without typing ``)reset'', you will probably want to use the ``)list'' command to look at the bad function. .PP As an example, suppose your ``friend'' Chris (male or female, take your pick) gave you the following program to compute the reciprocal of the numbers from 1 to x: .DS L r { recip x [1] r { % Ix .DE You are using origin 0, and your attempt to run the function yields the following: .DS L recip 10 recip domain at recip[1] .DE It looks like Chris gave you a bum steer. You decide to try to debug the function. You can't use the editor to look at it with ``)editf'' unless you type ``)reset'' first. You don't want to ``)reset'', because that would take you back to the beginning and you would lose any temporary variables (in this case, just ``x''). Thus, you can use the ``)list'' command: .DS L )list recip y { recip x [1] y { %Ix .DE Now, you can experiment with the function by typing the commands yourself: .DS L x 10 Ix 0 1 2 3 4 5 6 7 8 9 .DE At this point, you immediately spot the trouble \(em \*a was trying to take the reciprocal of 0. The function ``recip'' was written assuming that the origin was 1, but Chris did not tell you and you were using 0 instead. Thus, you merely say: .DS L )reset .DE (now that you've found the problem, you want to reset \*a to clear the state indicator), and .DS L )origin 1 was 0 recip 1.00000000e+00 5.00000000e\(mi01 3.33333333e\(mi01 2.50000000e\(mi01 2.00000000e\(mi01 1.66666667e\(mi01 1.42857143e\(mi01 1.25000000e\(mi01 1.11111111e\(mi01 1.00000000e\(mi01 .DE