guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: debugger restarts


From: Federico Beffa
Subject: Re: debugger restarts
Date: Fri, 5 Feb 2016 14:10:41 +0100

Hi,

I've prepared a start of a prototype restart library based on Taylor Campbell's
proposal [1] which is itself based on the exception handling system of
Common Lisp and MIT Scheme.

A trivial example to show the functionality is the following
definition of a toy replacement for '/' where the
'error:divide-by-zero' is a custom condition making use of restarts:

(define (/:fbe num . dens)
  (if (any zero? dens)
      (apply error:divide-by-zero '/:fbe (cons num dens))
      (apply / num dens)))

Now when you divide by zero you end up in the debugger where you have
a new meta command called 'restart' which allows you to list the
available restarts and to call one:

scheme@(guile-user)> (1+ (/:fbe 1 0))
<unnamed port>:51:4: In procedure #<procedure 3158700 at <current
input>:51:0 ()>:
<unnamed port>:51:4: ERROR: R6RS exception:
  1. &restartable: (#<r6rs:record:<resterter>>
#<r6rs:record:<resterter>> #<r6rs:record:<resterter>>)
  2. &divide-by-zero
  3. &message: "Division by zero."
  4. &who: /:fbe
  5. &irritants: (1 0)

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,restart
The following restarts are available:
  1: (use-value)         Specify a value to use instead of (/:fbe 1 0).
  2: (abort)             Abort computation.
  3: (greatest-fixnum)   Use greatest-fixnum instead of (/:fbe 1 0).
scheme@(guile-user) [1]> ,restart 1
Enter a value: 100
$2 = 101
scheme@(guile-user)>

Of course you can also use the restarts programmatically:

(define (1+reciprocal-of value)
  (1+ (/:fbe 1 value)))

(with-exception-handler
    (lambda (c)
      (if (divide-by-zero? c)
          (use-value 20 c)))
  (lambda () (1+reciprocal-of 0)))
=> 21

The reason for writing to this list is that, to be useful, restarts
should be included at a fairly low level.  This means that they would
be best included in the native Guile exception handling system.  This
would allow amazing things like extensions of the Scheme interpreter
as exemplified by the MIT Scheme Scmutils library [2] where you can,
e.g., apply a vector of functions to a symbol ('up' denotes
contravariant vectors and are just Scheme vectors):

((up sin cos) 't)
#|
(up (sin t) (cos t))
|#

Without restarts in Guile I need to use (the custom, generic
combinators based) 'apply' explicitly.  Even then, nested applications
do not work.

scheme@(guile-user)> (apply (up sin cos) '(t))
$3 = (up (sin t) (cos t))
scheme@(guile-user}#)> ((up sin cos) 't)
ERROR: In procedure #(#<procedure 16fd090 at
scmutils/kernel/ghelper.scm:78:9 (arg)> #<procedure 16fd000 at
scmutils/kernel/ghelper.scm:78:9 (arg)>):
ERROR: Wrong type to apply: #(#<procedure 16fd090 at
scmutils/kernel/ghelper.scm:78:9 (arg)> #<procedure 16fd000 at
scmutils/kernel/ghelper.scm:78:9 (arg)>)

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>

So the questions are:

* Would such functionality be welcome?

* What would this imply in practical terms?  I've barely started
  looking into Guile source and don't yet understand what is
  implemented in C and what in Scheme.  It would be of great help if
  someone could give an overview explanation of the current exception
  handling design.

Thanks,
Federico

[1] mumble.net/~campbell/proposals/restart.scm
[2] http://groups.csail.mit.edu/mac/users/gjs/6946/linux-install.htm

Attachment: restart.tar.gz
Description: GNU Zip compressed data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]