|
|
BSD 4.3
CHAPTER 14
The LISP Stepper
14.1. Simple Use Of Stepping
(step s_arg1...)
NOTE: The LISP "stepping" package is intended to give
the LISP programmer a facility analogous to the
Instruction Step mode of running a machine
language program. The user interface is through
the function (fexpr) step, which sets switches to
put the LISP interpreter in and out of "stepping"
mode. The most common _s_t_e_p invocations follow.
These invocations are usually typed at the top-
level, and will take effect immediately (i.e. the
next S-expression typed in will be evaluated in
stepping mode).
____________________________________________________
(_s_t_e_p _t) ; Turn on stepping mode.
(_s_t_e_p _n_i_l) ; Turn off stepping mode.
____________________________________________________
SIDE EFFECT: In stepping mode, the LISP evaluator will
print out each S-exp to be evaluated
before evaluation, and the returned value
after evaluation, calling itself recur-
sively to display the stepped evaluation
of each argument, if the S-exp is a func-
tion call. In stepping mode, the evalua-
tor will wait after displaying each S-exp
before evaluation for a command character
from the console.
9
9The LISP Stepper 14-1
The LISP Stepper 14-2
____________________________________________________
_S_T_E_P _C_O_M_M_A_N_D _S_U_M_M_A_R_Y
<return> Continue stepping recursively.
c Show returned value from this level
only, and continue stepping upward.
e Only step interpreted code.
g Turn off stepping mode. (but continue
evaluation without stepping).
n <number> Step through <number> evaluations without
stopping
p Redisplay current form in full
(i.e. rebind prinlevel and prinlength to nil)
b Get breakpoint
q Quit
d Call debug
____________________________________________________
14.2. Advanced Features
14.2.1. Selectively Turning On Stepping.
If
(_s_t_e_p _f_o_o_1 _f_o_o_2 ...)
is typed at top level, stepping will not commence
immediately, but rather when the evaluator first
encounters an S-expression whose car is one of
_f_o_o_1, _f_o_o_2, etc. This form will then display at
the console, and the evaluator will be in stepping
mode waiting for a command character.
Normally the stepper intercepts calls to _f_u_n_-
_c_a_l_l and _e_v_a_l. When _f_u_n_c_a_l_l is intercepted, the
arguments to the function have already been
evaluated but when _e_v_a_l is intercepted, the
Printed: July 21, 1983
The LISP Stepper 14-3
arguments have not been evaluated. To differen-
tiate the two cases, when printing the form in
evaluation, the stepper preceded intercepted calls
to _f_u_n_c_a_l_l with "f:". Calls to _f_u_n_c_a_l_l are nor-
mally caused by compiled lisp code calling other
functions, whereas calls to _e_v_a_l usually occur when
lisp code is interpreted. To step only calls to
eval use: (_s_t_e_p _e)
14.2.2. Stepping With Breakpoints.
For the moment, step is turned off inside of
error breaks, but not by the break function. Upon
exiting the error, step is reenabled. However,
executing (_s_t_e_p _n_i_l) inside a error loop will turn
off stepping globally, i.e. within the error loop,
and after return has be made from the loop.
14.3. Overhead of Stepping.
If stepping mode has been turned off by (_s_t_e_p
_n_i_l), the execution overhead of having the stepping
packing in your LISP is identically nil. If one stops
stepping by typing "g", every call to eval incurs a
small overhead--several machine instructions,
corresponding to the compiled code for a simple cond
and one function pushdown. Running with (_s_t_e_p _f_o_o_1
_f_o_o_2 ...) can be more expensive, since a member of the
car of the current form into the list (_f_o_o_1 _f_o_o_2 ...)
is required at each call to eval.
14.4. Evalhook and Funcallhook
There are hooks in the FRANZ LISP interpreter to
permit a user written function to gain control of the
evaluation process. These hooks are used by the Step
package just described. There are two hooks and they
have been strategically placed in the two key func-
tions in the interpreter: _e_v_a_l (which all interpreted
code goes through) and _f_u_n_c_a_l_l (which all compiled
code goes through if (_s_s_t_a_t_u_s _t_r_a_n_s_l_i_n_k _n_i_l) has been
done). The hook in _e_v_a_l is compatible with Maclisp,
but there is no Maclisp equivalent of the hook in _f_u_n_-
_c_a_l_l.
9
9 Printed: July 21, 1983
The LISP Stepper 14-4
To arm the hooks two forms must be evaluated:
(*_r_s_e_t _t) and (_s_s_t_a_t_u_s _e_v_a_l_h_o_o_k _t). Once that is
done, _e_v_a_l and _f_u_n_c_a_l_l do a special check when they
enter.
If _e_v_a_l is given a form to evaluate, say
(_f_o_o _b_a_r), and the symbol `evalhook' is non nil, say
its value is `ehook', then _e_v_a_l will lambda bind the
symbols `evalhook' and `funcallhook' to nil and will
call ehook passing (_f_o_o _b_a_r) as the argument. It is
ehook's responsibility to evaluate (_f_o_o _b_a_r) and
return its value. Typically ehook will call the func-
tion `evalhook' to evaluate (_f_o_o _b_a_r). Note that
`evalhook' is a symbol whose function binding is a
system function described in Chapter 4, and whose
value binding, if non nil, is the name of a user writ-
ten function (or a lambda expression, or a binary
object) which will gain control whenever eval is
called. `evalhook' is also the name of the _s_t_a_t_u_s tag
which must be set for all of this to work.
If _f_u_n_c_a_l_l is given a function, say foo, and a
set of already evaluated arguments, say barv and bazv,
and if the symbol `funcallhook' has a non nil value,
say `fhook', then _f_u_n_c_a_l_l will lambda bind `evalhook'
and `funcallhook' to nil and will call fhook with
arguments barv, bazv and foo. Thus fhook must be a
lexpr since it may be given any number of arguments.
The function to call, foo in this case, will be the
_l_a_s_t of the arguments given to fhook. It is fhooks
responsibility to do the function call and return the
value. Typically fhook will call the function _f_u_n_-
_c_a_l_l_h_o_o_k to do the funcall. This is an example of a
funcallhook function which just prints the arguments
on each entry to funcall and the return value.
9
9 Printed: July 21, 1983
The LISP Stepper 14-5
____________________________________________________
-> (_d_e_f_u_n _f_h_o_o_k _n (_l_e_t ((_f_o_r_m (_c_o_n_s (_a_r_g _n) (_l_i_s_t_i_f_y (_1- _n))))
(_r_e_t_v_a_l))
(_p_a_t_o_m "_c_a_l_l_i_n_g ")(_p_r_i_n_t _f_o_r_m)(_t_e_r_p_r)
(_s_e_t_q _r_e_t_v_a_l (_f_u_n_c_a_l_l_h_o_o_k _f_o_r_m '_f_h_o_o_k))
(_p_a_t_o_m "_r_e_t_u_r_n_s ")(_p_r_i_n_t _r_e_t_v_a_l)(_t_e_r_p_r)
_r_e_t_v_a_l))
fhook
-> (*_r_s_e_t _t) (_s_s_t_a_t_u_s _e_v_a_l_h_o_o_k _t) (_s_s_t_a_t_u_s _t_r_a_n_s_l_i_n_k _n_i_l)
-> (_s_e_t_q _f_u_n_c_a_l_l_h_o_o_k '_f_h_o_o_k)
calling (print fhook) ;; now all compiled code is traced
fhookreturns nil
calling (terpr)
returns nil
calling (patom "-> ")
-> returns "-> "
calling (read nil Q00000)
(_a_r_r_a_y _f_o_o _t _1_0) ;; to test it, we see what happens when
returns (array foo t 10) ;; we make an array
calling (eval (array foo t 10))
calling (append (10) nil)
returns (10)
calling (lessp 1 1)
returns nil
calling (apply times (10))
returns 10
calling (small-segment value 10)
calling (boole 4 137 127)
returns 128
... there is plenty more ...
____________________________________________________
9
9 Printed: July 21, 1983
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.