4.3BSD/usr/contrib/apl/doc/man.5

Compare this file to the similar file:
Show the results in this format:

.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