From: Jeff Dalton
Subject: Re: KCL Report wanted for debugging
Date: 
Message-ID: <6164@skye.ed.ac.uk>
In article <······················@menudo.uh.edu> ·····@cs.uh.edu (Man Lung Li) writes:
>
>Does anybody know whether the "Kyoto Common Lisp Report" by Taiichi Yuasa &
>Masami Hagiya, as referred to in the KCL licence agreement, is in electronic
>form and where to get hold of it?

Ftp from rascal.ics.utexas.edu, the same place where you can get AKCL.
There's a TeX version, at least.

>Specifically, I like to know how to step a function called inside a large
>program.  In SUN Common Lisp, you can do this by setting up the function in
>trace mode using
>
>(trace (foo) :step t)
>
>You will be in step mode when the function 'foo is called.  I wonder whether
>there is similar feature in KCL.  To step from the top is out of question.
>
>I would appreciate if anyone has an idea.

--------------------
One solution: Call STEP at the top but use the "f" command to have it
skip until a specified function is called.  For instance:

   > (defun broken (x) x)
   broken

   > (step (+ 10 (* 30 40) (broken 50)))
   Type ? and a newline for help.
     (+ 10 (* 30 40) (broken 50)) f broken
       (broken 50) n
	 50 n
	 x n
	 = 50
       = 50
     = 1260
   1260

The help message from the stepper will tell you about this command.

--------------------
Another solution: Redefine the function you want stepped so that
it uses the stepper.  Here's one way to do it:

   >   (defun make-stepped (f)
	 (let ((real-definition (symbol-function f)))
	   (setf (get f 'real-definition) real-definition)
	   (setf (symbol-function f)
		 #'(lambda (&rest args)
		     (step (apply real-definition args))))))
   make-stepped

   >   (make-stepped 'broken)
   (lambda-closure
       ((real-definition (lambda-block broken (x) x)) (f broken)) ()
       ((make-stepped block #<@0019BDE8>)) (&rest args)
     (step (apply real-definition args)))

   >   (+ 10 (* 30 40) (broken 50))
   Type ? and a newline for help.
     (apply real-definition args) n
       real-definition n
       = (lambda-block broken (x) x)
       args n
       = (50)
       x n
       = 50
     = 50
   1260

I think this looks more cryptic for a simple example that it
would if BROKEN did something more complex.

In any case, there's a problem.  The usual KCL and AKCL stepper
can be used only at the top level, as far as lexical env is 
concerned, because (step (f x)) expands to something like

  ... (system::stepper '(f x) nil) ...

Note that (f x) is quoted; so it can refer only to global f or x.

To fix this, redefine STEP as follows:

----------------------------------------------------------------------
;;; New step macro

(in-package :system)

(defvar *step-print-level* 4
  "The stepper binds *print-level* to this value.")

(defvar *step-print-length* 5
  "The stepper binds *print-length* to this value.")

(defmacro step (form)
  `(let* ((*old-print-level* *print-level*)
	  (*old-print-length* *print-length*)
	  (*print-level* *step-print-level*)
	  (*print-length* *step-print-length*))
     (read-line)				;s.b. clear-input?
     (format *debug-io* "Type ? and a newline for help.~%")
     (setq *step-quit* nil)
     (let ((*evalhook* #'stepper))
       ,form)))
----------------------------------------------------------------------

Jeff Dalton,                      JANET: ········@uk.ac.ed             
AI Applications Institute,        ARPA:  ········@ed.ac.uk
Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!J.Dalton