38. Error Recovery 

In an interpreted language, it is often possible to recover from errors. When an error occurs Basis does its best to help the user understand the nature of the problem. A user variable debug governs the error message that goes to the terminal and logfile. The variable debug can be assigned the values yes or no. The default value is no, and error messages will be brief. If debug = yes, a much more thorough error message goes to the terminal and logfile. If Basis was executing, information is given about the location where the error occurred; a complete  trace of all the local variables and arguments to any functions is given, and some symbolic information about the error is given. Whether debug = yes or no, a file is produced that contains the debug information.  The filename is first the contents of the variable  probname, then a numerical extenstion, then the file type appended.

Here is an example. The call to function boom fails when it attempts to add two arrays that are not the same length. The error message, ``Operands not compatible in size for +'' is followed by a more detailed error analysis because debug = yes.

Basis> function boom(a,b) 
Basis> chameleon temp 
Basis> temp= (a+b)/2 
Basis> return [temp,temp**2] 
Basis> endf 
Basis> debug=yes;boom([2,2],[2,3,4]) 
parcnfm: Operands not compatible in size for + 
Writing traceback info to file problem.001 
Returned to user input level.

The relevant contents of the file problem.001 are:

Here is the information I have on where you were: 
   A call to boom containing 
   the problem. 
The error occurred in the assignment or append statement: 
               temp = expression 
The following lines contain clues(not facts) about the r. h. s. 
b 
+ 
a+b 
temp 
Parser's action number = 115(ADD), program counter = 45. 
Group: Locals_boom  Num Vars: 3 
a(2) 
 1:     -  2 2 
b(3) 
 1:     -  2 3 4 
temp     =  0

If the parser function errortrp("off") has been called, no error recovery is attempted.

 

A compiled routine kaboom(iflag) can be called from the parser to force a return to the parser. If iflag is greater or equal to 0 Basis acts as if an error has taken place, and produces a trace file. If iflag is set negative, Basis returns to the parser without any error messages.

function subt(a,b) 
if( a < b) then 
     remark "Error: subt called with a < b" 
     call kaboom(-1) 
endif 
return a-b 
endf

In interpreting the information printed out when debug = yes, you should begin with the error message itself, examine the description of the nesting levels to find out where you were generally, and examine the symbols listed for some hints about the parts of the expressions involved in the error. As a last resort, the pc counter can be used in conjunction with the list command. The value of the pc counter is given in the trace file. Do a list on the function in which the error occurred, and when asked answer `y' to the question about viewing the intermediate code. The listing which results shows the operations being performed and using the pc you should be able to pinpoint which instructions caused the error. For example, in the example above, boom reported that the error occurred at pc = 45.

Basis> list boom 
boom(a,b) 
    user-defined function 
Minimum number of arguments:     2 
Maximum number of arguments:     2 
User-defined function, begins at absolute address      3967064 
Function consists of    104 words of intermediate code. 
 NAME                    TYPE 
 boom                      varies 
 a                         varies 
 b                         varies 
Dump intermediate code? (y|n) 
y
   pc   opcode  stack     operation 
    1:     16          Enter function, set up actual parameters. 
    3:    421      7   REGULAR_SCOPE 
    5:    404      9   CHAMELEON 
    7:   -100     10   TOKEN = 'temp' (name). 
   12:    412     10   SCALAR DECLARE 
   14:    415     10   NO INITIAL VALUE 
   16:    410     11   CREATE VARIABLE 
   18:   -100      8   TOKEN = 'temp' (name). 
   23:      1      8   ID->LHS 
   25:     10      9   BEGIN RHS 
   27:   -100     11   TOKEN = 'a' (name). 
   32:      1     11   ID->LHS 
   34:    136     11   <LHS>-><FACTOR> 
   36:   -100     13   TOKEN = 'b' (name). 
   41:      1     13   ID->LHS 
   43:    136     13   <LHS>-><FACTOR> 
   45:    115     13   ADD 
   47:    130     12   MOVE-1 
   49:    136     10   <LHS>-><FACTOR> 
   51:   -101     12   TOKEN = '2' (integer constant). value = 2. 
   56:     11     12   PUSH VALUE
   58:    121     12   DIVIDE 
   60:      3     10   ASSIGN 
   62:   -100     10   TOKEN = 'temp' (name). 
   67:      1     10   ID->LHS 
   69:    136     10   <LHS>-><FACTOR> 
   71:      8     10   FETCH VARIABLE 
   73:   -100     12   TOKEN = 'temp' (name). 
   78:      1     12   ID->LHS 
   80:    136     12   <LHS>-><FACTOR> 
   82:   -101     14   TOKEN = '2' (integer constant). value = 2. 
   87:     11     14   PUSH VALUE 
   89:    126     14   POWER 
   91:    101     12   EXPLIST 
   93:    129     11   [EXPLIST] 
   95:    136      9   <LHS>-><FACTOR> 
   97:     19      9   FETCH COPY 
   99:     17      9   RET 
  101:     18      8   NULLRET 
  103:     17      9   RET 
***************************