






                        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



