From: Wei Jen Yeh
Subject: ``unwind-protect'' eval
Date: 
Message-ID: <18342@ector.cs.purdue.edu>
Hello,
  Is it possible to recover after you're thrown out to the top-level?
I need to implement something like
  (let ((cmd NIL))
       (loop (setq cmd (getline))
             (if (registered_service cmd)
                 (myapply (symbol-function (1st cmd)) (rest cmd))
                 (eval cmd))))

How does one recover from the eval call when error occurs?  The
book says that no standard way of error handling is defined, since they
have not found a satisfactory one.  Hm...

I guess I can use the brute-force way of intercepting the "Error:" keyword
and re-invoking the main loop.  What are the error-handling mechanisms of
current CL dialects?  BTW, the particular code is to run under akcl/TopCL.

Thanks.

Wei Jen Yeh                      ···@cs.purdue.edu
                                 Department of Computer Science
                                 Purdue University
                                 West Lafayette, Indiana
From: Barry Margolin
Subject: Re: ``unwind-protect'' eval
Date: 
Message-ID: <ku0uakINNcfk@early-bird.think.com>
In article <·····@ector.cs.purdue.edu> ···@cs.purdue.EDU (Wei Jen Yeh) writes:
>  Is it possible to recover after you're thrown out to the top-level?

Not *after*, but you can provide a way to intercept and/or allow the user
to throw to your own routine instead of the Lisp top-level.

>I need to implement something like

[his own read-eval-print loop]

>How does one recover from the eval call when error occurs?  The
>book says that no standard way of error handling is defined, since they
>have not found a satisfactory one.  Hm...

That book (CLtL, I presume you're referring to) is out of date.

>What are the error-handling mechanisms of
>current CL dialects?  BTW, the particular code is to run under akcl/TopCL.

Most current dialects implement the condition system described in Chapter
29 of CLtL, 2nd Edition.  I'm not directly familiar with TopCL, but I'll
bet it does.  However, I'm not so sure about AKCL; if (macro-function
'handler-bind) returns NIL then it doesn't implement it.

If you want to provide your own restart option in the debugger, so that the
user can go back to your loop, use RESTART-BIND or one of its derivatives,
RESTART-CASE or WITH-SIMPLE-RESTART.  For instance, your r-e-p loop might
look like this:

(let ((cmd NIL))
  (loop (restart-case
	    (progn
	      (setq cmd (getline))
	      (if (registered_service cmd)
		  (myapply (symbol-function (1st cmd)) (rest cmd))
		  (eval cmd)))
	  (abort () :report "Return to registered-service top-level."))))

This won't *prevent* someone from choosing the restart that exits your
program and goes out to the normal Lisp top-level, but it will force him to
do so consciously.  Most systems provide a shortcut for choosing the most
recent ABORT restart, so the above code will cause your restart to be
chosen when that's done.

If the above doesn't meet your needs, other things you may find relevant
may be *DEBUGGER-HOOK* and HANDLER-CASE or HANDLER-BIND.
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar