From: Didier Verna
Subject: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <muxy71sus2w.fsf@uzeb.lrde.epita.fr>
       Hello,

Assume some code like this:

(restart-case (do-something)
  (register (error)
    :report "Save the error somewhere."
    ;; ...))


Somewhere else I have this:

(handler-bind ((my-error-type
               (lambda (error)
                 (invoke-restart 'register error))))
  ;; do something that calls the code above.
  )


So far so good. Now, there are times when I don't want/have a handler
for this error, because I actually want to be dropped in the debugger.
How do I make the restart available in the debugger, *with* the proper
argument (the error) passed to it?

And the more general question (I think), how can we tell the debugger to
pass specific arguments to specific restarts, other than with the
:interactive option?


Thanks !

-- 
Resistance is futile. You will be jazzimilated.

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com

EPITA/LRDE, 14-16 rue Voltaire, 94276 Le Kremlin-Bic�tre, France
Tel. +33 (0)1 44 08 01 85       Fax. +33 (0)1 53 14 59 22

From: Madhu
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <m3r67kc8oc.fsf@moon.robolove.meer.net>
* Didier Verna <···············@uzeb.lrde.epita.fr> :
Wrote on Tue, 16 Sep 2008 15:40:39 +0200:
| Assume some code like this:
|
| (restart-case (do-something)
|   (register (error)
|     :report "Save the error somewhere."
|     ;; ...))
|
|
| (handler-bind ((my-error-type
|                (lambda (error)
|                  (invoke-restart 'register error))))
|   ;; do something that calls the code above.
|   )
|
| So far so good. Now, there are times when I don't want/have a handler
| for this error, because I actually want to be dropped in the debugger.
| How do I make the restart available in the debugger, *with* the proper
| argument (the error) passed to it?

You could replace the handler body with 
  (when (find-restart 'register condition)
      (invoke-restart 'register))

and then use the :test expression in the clasuse for the register
restart in the restart-case. See clhs for details

That way you can arrange via the test-expression the situations when the
restart will visible; and when it is invisible, you hit the debugger

| And the more general question (I think), how can we tell the debugger to
| pass specific arguments to specific restarts, other than with the
| :interactive option?

invoke-restart takes arguments that are passed to the function
associated by the restart-case: check clhs

invoke-restart restart &rest arguments

--
Madhu
From: Rainer Joswig
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <joswig-5C8677.19264416092008@news-europe.giganews.com>
In article <··············@moon.robolove.meer.net>,
 Madhu <·······@meer.net> wrote:

> * Didier Verna <···············@uzeb.lrde.epita.fr> :
> Wrote on Tue, 16 Sep 2008 15:40:39 +0200:
> | Assume some code like this:
> |
> | (restart-case (do-something)
> |   (register (error)
> |     :report "Save the error somewhere."
> |     ;; ...))
> |
> |
> | (handler-bind ((my-error-type
> |                (lambda (error)
> |                  (invoke-restart 'register error))))
> |   ;; do something that calls the code above.
> |   )
> |
> | So far so good. Now, there are times when I don't want/have a handler
> | for this error, because I actually want to be dropped in the debugger.
> | How do I make the restart available in the debugger, *with* the proper
> | argument (the error) passed to it?
> 
> You could replace the handler body with 
>   (when (find-restart 'register condition)
>       (invoke-restart 'register))
> 
> and then use the :test expression in the clasuse for the register
> restart in the restart-case. See clhs for details
> 
> That way you can arrange via the test-expression the situations when the
> restart will visible; and when it is invisible, you hit the debugger
> 
> | And the more general question (I think), how can we tell the debugger to
> | pass specific arguments to specific restarts, other than with the
> | :interactive option?
> 
> invoke-restart takes arguments that are passed to the function
> associated by the restart-case: check clhs
> 
> invoke-restart restart &rest arguments
> 
> --
> Madhu


As I understand it, he wants to have the restart
when in the debugger and when one selects the restart
(say from a list of restarts) he wants it called
with the condition object.

So the restart is always there. But sometimes there might be no
handler to handle the error. Then one drops into
the debugger (unless some other handler is used) and
the list of restarts will be provided.

I can't also answer the question - don't know how to have
the provided restart calls get the condition. I'm not sure
that it actually would work - maybe Kent knows.
I would hack it by providing some special variable
that knows the error condition.

-- 
http://lispm.dyndns.org/
From: Madhu
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <m3iqswc5q7.fsf@moon.robolove.meer.net>
* Rainer Joswig <····························@news-europe.giganews.com> :
Wrote on Tue, 16 Sep 2008 19:26:44 +0200:

| As I understand it, he wants to have the restart when in the debugger
| and when one selects the restart (say from a list of restarts) he
| wants it called with the condition object.

Yes I'm afraid misunderstood the question.  Which is embarrassing
because I misunderstood it twice, *and* its the same question I've often
asked.

<http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2007-01/msg01099.html>


| So the restart is always there. But sometimes there might be no
| handler to handle the error. Then one drops into the debugger (unless
| some other handler is used) and the list of restarts will be provided.
|
| I can't also answer the question - don't know how to have the provided
| restart calls get the condition. I'm not sure that it actually would
| work - maybe Kent knows.  I would hack it by providing some special
| variable that knows the error condition.

You have to stash the error in a special.  As atonement I present this hack.

(defvar *last-condition* nil)

(setq *debugger-hook* 
       (let ((orig-debugger-hook *debugger-hook*))
          (lambda (condition debugger-hook)
              (declare (ignore debugger-hook))
              (setq *last-condition* condition)
              (when orig-debugger-hook
                 (funcall orig-debugger-hook condition orig-debugger-hook)))))

Then at the debugger you have *last-condition* to refer to the latest
condition that called INVOKE-DEBUGGER

(Thanks Kaz)

--
Madhu
From: Rainer Joswig
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <joswig-0E5122.20511016092008@news-europe.giganews.com>
In article <··············@moon.robolove.meer.net>,
 Madhu <·······@meer.net> wrote:

> * Rainer Joswig <····························@news-europe.giganews.com> :
> Wrote on Tue, 16 Sep 2008 19:26:44 +0200:
> 
> | As I understand it, he wants to have the restart when in the debugger
> | and when one selects the restart (say from a list of restarts) he
> | wants it called with the condition object.
> 
> Yes I'm afraid misunderstood the question.  Which is embarrassing
> because I misunderstood it twice, *and* its the same question I've often
> asked.
> 
> <http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2007-01/msg01099.html>
> 
> 
> | So the restart is always there. But sometimes there might be no
> | handler to handle the error. Then one drops into the debugger (unless
> | some other handler is used) and the list of restarts will be provided.
> |
> | I can't also answer the question - don't know how to have the provided
> | restart calls get the condition. I'm not sure that it actually would
> | work - maybe Kent knows.  I would hack it by providing some special
> | variable that knows the error condition.
> 
> You have to stash the error in a special.  As atonement I present this hack.
> 
> (defvar *last-condition* nil)
> 
> (setq *debugger-hook* 
>        (let ((orig-debugger-hook *debugger-hook*))
>           (lambda (condition debugger-hook)
>               (declare (ignore debugger-hook))
>               (setq *last-condition* condition)
>               (when orig-debugger-hook
>                  (funcall orig-debugger-hook condition orig-debugger-hook)))))
> 
> Then at the debugger you have *last-condition* to refer to the latest
> condition that called INVOKE-DEBUGGER

I was thinking of that, too.

Though I expect most debuggers to have a non-portable way to
get the current condition.  dbg:*error* on the Lisp Machine
for example.

> 
> (Thanks Kaz)
> 
> --
> Madhu

-- 
http://lispm.dyndns.org/
From: Madhu
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <m3bpyndgu8.fsf@moon.robolove.meer.net>
* Rainer Joswig <····························@news-europe.giganews.com> :
Wrote on Tue, 16 Sep 2008 20:51:10 +0200:

[...]
|> Then at the debugger you have *last-condition* to refer to the latest
|> condition that called INVOKE-DEBUGGER
|
| I was thinking of that, too.

[There are problems with this approach, say if you are looking at
 returning from some other stackframe.]

| Though I expect most debuggers to have a non-portable way to
| get the current condition.  dbg:*error* on the Lisp Machine
| for example.

Yes, As you pointed out in another post, lispworks has what I wanted,
and also keeps the call to invoke-debugger on the stack.

If you are using slime, there is a chance that the condition is
available in swank::*swank-debugger-condition*.  With CMUCL'S
invoke-debugger you get the condition in debug::*debug-condition*.

--
Madhu
From: Didier Verna
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <muxiqsvush3.fsf@uzeb.lrde.epita.fr>
Rainer Joswig <······@lisp.de> wrote:

> In article <··············@moon.robolove.meer.net>,
>  Madhu <·······@meer.net> wrote:
>
>> Then at the debugger you have *last-condition* to refer to the latest
>> condition that called INVOKE-DEBUGGER
>
> I was thinking of that, too.
>
> Though I expect most debuggers to have a non-portable way to get the
> current condition. dbg:*error* on the Lisp Machine for example.

  Madhu, Rainer, thanks for your feedback.

I was afraid I had to go non-standard, but anyway. It seems that the
following does the trick for SBCL (and that there's probably the
equivalent for other implementations):

(restart-case (error "foo")
  (print (error)
    :report "Print the error."
    :interactive (lambda () (list sb-debug:*debug-condition*))
    (print-object error t)))

This way, I can either restart from a handler (which is then in charge
of providing the ERROR argument), or from the debugger by just typing
the restart number /without/ having to provide the error manually.

Good enough for me.

-- 
Resistance is futile. You will be jazzimilated.

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com

EPITA/LRDE, 14-16 rue Voltaire, 94276 Le Kremlin-Bic�tre, France
Tel. +33 (0)1 44 08 01 85       Fax. +33 (0)1 53 14 59 22
From: Madhu
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <m3myi8c84z.fsf@moon.robolove.meer.net>
[Sorry I misunderstood]

* Madhu <··············@moon.robolove.meer.net> :
Wrote on Tue, 16 Sep 2008 22:47:07 +0530:
| * Didier Verna <···············@uzeb.lrde.epita.fr> :
| Wrote on Tue, 16 Sep 2008 15:40:39 +0200:
| | (restart-case (do-something)
| |   (register (error)
| |     :report "Save the error somewhere."
| |     ;; ...))
| |
| |
| | (handler-bind ((my-error-type
| |                (lambda (error)
| |                  (invoke-restart 'register error))))
| |   ;; do something that calls the code above.
| |   )
| |
| | So far so good. Now, there are times when I don't want/have a handler
| | for this error, because I actually want to be dropped in the debugger.
| | How do I make the restart available in the debugger, *with* the proper
| | argument (the error) passed to it?

If you dont handle the error, it propagates till you hit the debugger.
So what I should have suggested is:

  (handler-bind ((my-error-type (lambda (c)
                                  (when (and
                                         (complicated-test-to-see-if-we-should-handle c)
                                         (find-restart 'regsister))
                           |       (invoke-restart 'register)))))
               ... )

I don't understand what you mean by `` *with* the proper argument (the
error) passed to it?''

There is no notion of "current-condition being handled" in the cl
debugger.  [I've asked that here before]

--
Madhu
From: Rainer Joswig
Subject: Re: [Q] passing non-interactive arguments to a restart from the debugger
Date: 
Message-ID: <joswig-8030CF.20083116092008@news-europe.giganews.com>
In article <··············@moon.robolove.meer.net>,
 Madhu <·······@meer.net> wrote:

> [Sorry I misunderstood]
> 
> * Madhu <··············@moon.robolove.meer.net> :
> Wrote on Tue, 16 Sep 2008 22:47:07 +0530:
> | * Didier Verna <···············@uzeb.lrde.epita.fr> :
> | Wrote on Tue, 16 Sep 2008 15:40:39 +0200:
> | | (restart-case (do-something)
> | |   (register (error)
> | |     :report "Save the error somewhere."
> | |     ;; ...))
> | |
> | |
> | | (handler-bind ((my-error-type
> | |                (lambda (error)
> | |                  (invoke-restart 'register error))))
> | |   ;; do something that calls the code above.
> | |   )
> | |
> | | So far so good. Now, there are times when I don't want/have a handler
> | | for this error, because I actually want to be dropped in the debugger.
> | | How do I make the restart available in the debugger, *with* the proper
> | | argument (the error) passed to it?
> 
> If you dont handle the error, it propagates till you hit the debugger.
> So what I should have suggested is:
> 
>   (handler-bind ((my-error-type (lambda (c)
>                                   (when (and
>                                          (complicated-test-to-see-if-we-should-handle c)
>                                          (find-restart 'regsister))
>                            |       (invoke-restart 'register)))))
>                ... )
> 
> I don't understand what you mean by `` *with* the proper argument (the
> error) passed to it?''
> 
> There is no notion of "current-condition being handled" in the cl
> debugger.  [I've asked that here before]
> 
> --
> Madhu


Well, the debugger may know a current condition. INVOKE-DEBUGGER takes a condition
argument.

With LispWorks you can also interactively call the restart with arguments:

CL-USER 42 > (restart-case (error "foo") 
                (foo-restart (condition) 
                   (format t "the condition ~s" condition)))

Error: foo
  1 (continue) FOO-RESTART
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other options

CL-USER 43 : 1 > :cc
#<SIMPLE-ERROR 4020099243>

CL-USER 44 : 1 > :c 1 *
the condition #<SIMPLE-ERROR 4020099243>
NIL


Above I called the FOO-RESTART from the debugger and gave it the current
condition as an argument.

-- 
http://lispm.dyndns.org/