
STEPPER					Peter Baumgartner
=======					AI resarch group
					University of Koblenz
A single step package			Germany
for SCHEME				mail: peter@uni-koblenz.de
					www:  http://www.uni-koblenz.de/~peter


Contents
========
1) Do I need _this_ package?
2) User commands/how to use it
	2.1. General
	2.2. Preparing the procedure definitions for stepping
	2.3. loads
	2.4. STEPPER interaction.
	2.5. Breakpoints
	2.6. Other functions/macros
	2.7. Customisation

3) System requirements/Porting
4) Bugs and Todo-list
5) How it works
6) Commented Sample Session


1) Do I need _this_ package?
----------------------------

Being used to usual prolog debuggers with their single-step facility I
wished to have a similar thing for scheme.  Such debuggers seem to be
rare. I only know of two of them: C Scheme comes with one (I
think). For reasons irrelevant here I do not want to use C scheme; if
you use C scheme then this package probably is nothing for you.

The other thing is PSD (portable system debugger). PSD is really nice
and runs on top of emacs (only). Unfortunately PSD does not run with
bigloo as underlying interpreter. I couldn't repair it with moderate
effort. Hence (and because it was fun) I wrote my own STEPPER package. 

With this STEPPER package one can single-step through scheme
expressions or trace through their evaluation (entry/exit of function
calls) without interaction. Breakpoints are supported.

STEPPER is in a pre-pre-alpha phase, or so. It just turned out to have
enough features and is stable enough to be useful.  So be mercyful
with me. I will be happy to hear about any suggestions or improvements
from you. I also welcome bug reports and doing todos.


2) User commands/how to use it
------------------------------

2.1. General

The stepper package is in one file named "stepper.scm". Obviously, it
must be loaded to become effective. See also the example file "fib.scm"

STEPPER has 3 modes of operation:

- creep mode: single step through a form
- leap mode:  quietly run until a breakpoint is reached; when a
  breakpoint is reached go into creep mode.
- trace mode: run, but show entry/exit of procedure calls. breakpoints 
  are in effect.

I will refer to all each of these three as 'stepping mode'

Initially, after loading, STEPPER is in creep mode. 
In order to explicitly switch to one of the stepping modes for an
expression, use one of

(step <expression>)
(leap <expression>)
(trace <expression>)

<expression> is not quoted, i.e. invoke (step (fib 4))

2.2. Preparing the procedure definitions for stepping

The following functions and macros can be used to prepare a
procedure for stepping mode (loads - see below - can also bee used). 

(define-step (<variable> <formals>) <body>)
(define-step (<variable> . <formal>) <body>)
(define-step <variable> <expression>)

define-step behaves like R4RS define, except that if a function is
defined, calls to this function will be executed in a stepping mode. 
(define-step a 5) will be the same as (define a 5).

Locally definied functions inside such a definition will also be
prepared for stepping mode.

NOTE: (step (fib (* n n))) will step through evaluation of the
argument (* n n) . Stepping through the execution of the body of fib
can take place only if fib is prepared for stepping  (either
explicitly using define-step or implicitly by loads). 
If (fib (* n n)) is evaluated then the evaluation of the body of
fib will take place according to the current stepping mode in effect.

2.3. loads

As an alternative to define-step, use (loads <file>) instead. It
behaves like (load <file>) except that all top-level 
(define ...) expressions in <file> are treated as (define-step ...) 
instead. 
Note: If <file> is FILE.scm then loads writes a file FILE-stepper.scm
and loads it with load. FILE-stepper.scm is not deleted, as we might
want to manually turn some define-step's into define's and explicity load 
FILE-stepper.scm instead.


2.4. STEPPER interaction.

Once the stepper interaction loop is invoked (either by explicit
stepping into creep mode or when a breakpoint is reached), you can
issue commands.  
A ? at the Now? prompt gives you this help text:

	Stepper commands:
	-----------------
	?       - this text.
	a       - abort - return to read-eval-print loop
	b       - break - enter a read-eval-print loop
	h       - history of pending forms in evaluation
	v       - current local bindings
	c       - creep - step into current form
	s       - skip - eval current form without stepping
	st      - skip trace, like skip but trace evaluation of form
	l       - leap - continue until next break point is reached
	g       - go - resume execution without stepping
	gt      - go trace - like go but trace evaluation
	e FORM  - eval FORM and print result
	pp FORM - eval FORM and pretty print result


NOTE: there is an alternate command set available, resembling the 
gdb commands. The "c" and "s" are interchanged, and "st" is replaced by "ct". 
See Section 2.7 below for customising.

NOTE: during interaction the variables !0, !1, ... are bound to the respective 
forms in the evaluation stack (cf. the "h" command). Use e.g.
	pp !0 
to see the current form, and
	pp !1
to see the form invoking it.


The other commands should be rather self-documenting; see also the
commented sample session below. Warning: g and gt will put STEPPER
into skip mode after when returning to the toplevel read-eval-print
loop. Same for l if no breakpoint is encountered.


2.5. Breakpoints

(breakf <name>)		add a breakpoint on procedure entry of <name>
(unbreakf <name>)	remove a breakpoint from procedure <name>

e.g. (breakf fib)

Note: 

(break <expression1> ... <expressionn>)

explicitly switch to creep mode, evaluate and display the
<expression>s, enter STEPPER interaction loop.


2.6. Other functions/macros:

(stepper-reset)		resets the internal state of STEPPER
			creep mode is set.

(define-step-test (<var> <formals>) <body>)
(step-test <form>)	

			to see how decoration is done. See section
			5 below ('How it works') for an example.

(lambda-step <formals> <body>)

			like R4RS lambda, but <body> will be evaluated 
			in stepping mode.


2.7. Customisation:

the following is pasted from stepper.scm, modify the source to your needs. 

;; in interaction, the most recent *stepper-offered-dynamic-history-length*
;; entries in the stepper dynamic history shall be bound to variables
;; !0, !1, ...
;; these are the relevant variables:
(define *stepper-offered-dynamic-history-length* 8)
(define *stepper-dynamic-history-names* '(!0 !1 !2 !3 !4 !5 !6 !7))
;; this list should be in accordance with 
;; *stepper-offered-dynamic-history-length*

(define *return-to-continue* "[RETURN to continue] ")
;; the string to be display during interaction after some value
;; has been computed, as initiated by the creep or skip command
;; legal values: 
;;    if *return-to-continue* is #f the nothing is diplayed
;;    otherwise the string bound to *return-to-continue* is displayed 
;;    and thee user is queried for some trivial input
;; 

(define *stepper-macros-as-functions* '(and or)) 
;; these macros are treated as functions, i.e. they are not 
;; subject to expand before decoration
;; 'and' and 'or' are treated as way, because otherwise
;; the user will see unexpected things


(define *stepper-interaction-command-style* 'prolog-like)
;; affects in interaction how to name commands. Legal values are
;;
;; prolog-like:
;; c  - creep          means single step through next form
;; s  - skip           means skip stepping the evaluation of next form
;; st - skip trace     like skip, but show trace
;; 
;; gdb-like:
;; s  - step           means single step through next form
;; c  - continue       means skip stepping the evaluation of next form
;; ct - skip trace     like continue, but show trace



3) System requirements/Porting
------------------------------

Currently runs with the bigloo scheme interpreter by 
Manuel Serrano (version 1.9b). 
Check out the scheme internet repository or contact 
Manuel.Serrano@cui.unige.ch for more information on bigloo.

In order to port STEPPER to other platforms (maybe slib??), some few
bigloo specific procedures have to be replaced:

	display, error, define-macro, #unspecified, try, prefix, suffix,
	expand-once 

most of them are uncritical and can be circumvented easily.
Hope I forgot none...



4) Bugs and Todo-list
---------------------

4.1. Bugs.

- New identifiers introduced in the decoration like  STEPPER-BINDINGS
  (cf. section 5) are not fancy enough and could conflict with user
  defined identifiers. 

- (step (lambda ...)) results in a procedure which steps its body.
  is this desired? or should use explicit lambda-step instead??

4.2. ToDo.

- inspector is missing
- portable implementation
- output format during STEPPER interaction should be improved. 
- Not the whole language is supported yet, still missing are (at least)
	- match-case, labels, 
	- keywords #!optional, blabla:  etc. still missing

5) How it works
---------------

Stepping through a form is realized by decorating the form with scheme 
code which monitors the flow of execution. This means to query the
user before evaluating (the function STEPPER-INTERACTION does this) 
and display the result (the function STEPPER-CONTINUE does
this). Additionally, all variable bindings have to be monitored (cf. 
the   (LET ((STEPPER-BINDINGS ....))) construction below, because
local variable bindings are not known to eval, but we would like to
inspect them during user interaction.

Here is an example. Suppose that you want to 

	(define (foo x) (* x x))

I use define-step-test instead to see the effect of the decoration
(define-step-test only prints the decoration):


1:=> (define-step-test (foo x) (* x x))

(BEGIN
  (DEFINE FOO
    (LAMBDA (X)
      (LET ((STEPPER-BINDINGS
              (STEPPER-MAKE-BINDINGS
                '(X)
                (LIST X)
                STEPPER-BINDINGS))
            (FORM-TEXT
              (LIST 'BODY-OF
                    'FOO
                    'FORMAL-PARAMETERS
                    '(X)
                    'EVALED-ARGUMENTS
                    (LIST X))))
        (STEPPER-INTERACTION FORM-TEXT STEPPER-BINDINGS)
        (DECVAL! *STEPPER-LEVEL*)
        (LET ((FORM-TEXT '(* X X)))
          (STEPPER-INTERACTION FORM-TEXT STEPPER-BINDINGS)
          (STEPPER-CONTINUE
            FORM-TEXT
            (* (LET ((FORM-TEXT 'X))
                 (STEPPER-INTERACTION FORM-TEXT STEPPER-BINDINGS)
                 (STEPPER-CONTINUE FORM-TEXT X))
               (LET ((FORM-TEXT 'X))
                 (STEPPER-INTERACTION FORM-TEXT STEPPER-BINDINGS)
                 (STEPPER-CONTINUE FORM-TEXT X))))))))
 (SET! STEPPER-BINDINGS
    (STEPPER-DEFINE-BINDING
      'FOO
      '(LAMBDA (X) (* X X))
      STEPPER-BINDINGS))
  'FOO)


There is another macro step-test which prints the decoration produced
by the step macro:

1:=> (step-test (foo 8))

(LET ((FORM-TEXT '(FOO 8)))
  (STEPPER-INTERACTION FORM-TEXT STEPPER-BINDINGS)
  (STEPPER-CONTINUE
    FORM-TEXT
    (FOO (LET ((FORM-TEXT '8))
           (STEPPER-INTERACTION FORM-TEXT STEPPER-BINDINGS)
           (STEPPER-CONTINUE FORM-TEXT 8)))))


6) Commented Sample Session
---------------------------
Sample session through single stepping a call to (fib 4)
see fib.scm for source

[peter]% bigloo
------------------------------------------------------------------------------
Bigloo (1.9) (level b)                                                   ,--^,
`a practical Scheme compiler'                                      _ ___/ /|/
Tue Jun 24 23:57:03 MET DST 1997                               ,;'( )__, ) '
Manuel Serrano                                                ;;  //   L__.
email:                                                        '   \    /  '
Manuel.Serrano@cui.unige.ch                                        ^   ^
------------------------------------------------------------------------------

Welcome to the interpreter

1:=> (load "stepper.scm")		;; load the stepper package
;; some meassages deleted
1:=> (loads "fib.scm")			;; load a file for stepping
#unspecified
MINUS
FIB
FIB
INC
FAC-ITER
FAC-ITER

1:=> (step (fib 4))			;; want to step through (fib 4)
[STEPPER set to CREEP mode]

FORM: (FIB 4)
Now? u
Unknown command for stepper
Stepper commands:
-----------------
?       - this text.
a       - abort - return to read-eval-print loop
b       - break - enter a read-eval-print loop
h       - history of pending forms in evaluation
v       - current local bindings
c       - creep - step into current form
s       - skip - eval current form without stepping
st      - skip trace, like skip but trace evaluation of form
l       - leap - continue until next break point is reached
g       - go - resume execution without stepping
gt      - go trace - like go but trace evaluation
e FORM  - eval FORM and print result
pp FORM - eval FORM and pretty print result

FORM: (FIB 4)
Now? pp fib				;; pretty print def of fib
File "fib.scm", character 439: 
(DEFINE-STEP
  (FIB N)
  (BREAK #"break - Enter fib of " N)
  (IF (< N 2)
    1
    (PLUS (FIB (MINUS N 1)) (FIB (MINUS N 2)))))

FORM: (FIB 4)
Now? c					;; creep into eval of (fib 4)

 FORM: 4
 Now? s
 EXIT: 4 => 4
 [RETURN to continue] 

 FORM: (BODY-OF FIB FORMAL-PARAMETERS (N) ...)
 Now? c

  FORM: (BREAK break - Enter fib of  4)
  Now? c

  FORM: (IF (< N 2) 1 (PLUS (FIB (...)) (FIB (...))))
  Now? c

   FORM: (< N 2)
   Now? h
Evaluation stack:
-----------------
!0   (< N 2)
!1   (IF (< N 2) 1 (PLUS (FIB (...)) (FIB (...))))
!2   (BODY-OF FIB FORMAL-PARAMETERS (N) ...)
!3   (FIB 4)

   FORM: (< N 2)
   Now? pp !2
(BODY-OF
  FIB
  FORMAL-PARAMETERS
  (N)
  EVALED-ARGUMENTS
  (4))

   FORM: (< N 2)
   Now? s				;; boring, skip this
   EXIT: (< N 2) => #f
   [RETURN to continue] 

   FORM: (+ (FIB (MINUS N 1)) (FIB (MINUS N 2)))
   Now? c

    FORM: (FIB (MINUS N 1))
    Now? e n				;; eval n
    => 4

    FORM: (FIB (MINUS N 1))
    Now? st				;; skip this form, but trace

     FORM: (MINUS N 1)
      FORM: N      EXIT: N => 4

      FORM: 1      EXIT: 1 => 1

      FORM: (BODY-OF MINUS FORMAL-PARAMETERS (X Y) ...)
       FORM: (- X Y)
        FORM: X        EXIT: X => 4

        FORM: Y        EXIT: Y => 1
       EXIT: (- X Y) => 3
      EXIT: (BODY-OF MINUS FORMAL-PARAMETERS (X Y) ...) => 3
     EXIT: (MINUS N 1) => 3

    ;; quite soem lines deleted here


           FORM: 1           EXIT: 1 => 1
          EXIT: (IF (< N 2) 1 (PLUS (FIB (...)) (FIB (...)))) => 1
         EXIT: (BODY-OF FIB FORMAL-PARAMETERS (N) ...) => 1
        EXIT: (FIB (MINUS N 2)) => 1
       EXIT: (+ (FIB (MINUS N 1)) (FIB (MINUS N 2))) => 3
      EXIT: (IF (< N 2) 1 (PLUS (FIB (...)) (FIB (...)))) => 3
     EXIT: (BODY-OF FIB FORMAL-PARAMETERS (N) ...) => 3
    EXIT: (FIB (MINUS N 1)) => 3
    [RETURN to continue] 

    FORM: (FIB (MINUS N 2))
    Now? v
Local bindings:
---------------
N   4

    FORM: (FIB (MINUS N 2))
    Now? g				;; seen enough
5

1:=> 


That's all

Have Fun!

	Peter
