From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Neil Jerram Newsgroups: gmane.lisp.guile.devel Subject: Re: Backtrace and enhanced catch Date: Wed, 01 Feb 2006 23:04:36 +0000 Message-ID: <874q3i65q3.fsf@ossau.uklinux.net> References: <200511301616.22258.bkorb@gnu.org> <87wthpkyan.fsf@ossau.uklinux.net> <43B69F41.6030509@xs4all.nl> <87hd8pb8o7.fsf@ossau.uklinux.net> <87lkxy3abo.fsf@ossau.uklinux.net> <877j9i31gc.fsf@ossau.uklinux.net> <87acebhf1o.fsf@ossau.uklinux.net> <871wyu8t5e.fsf@zip.com.au> <87k6cl8o5c.fsf@ossau.uklinux.net> <87k6cgi2jo.fsf@zip.com.au> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1138842351 4850 80.91.229.2 (2 Feb 2006 01:05:51 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Thu, 2 Feb 2006 01:05:51 +0000 (UTC) Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Feb 02 02:05:44 2006 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1F4Suo-0002h2-Hb for guile-devel@m.gmane.org; Thu, 02 Feb 2006 02:05:38 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1F4Sxt-0000bS-Fh for guile-devel@m.gmane.org; Wed, 01 Feb 2006 20:08:49 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1F4R7b-0006DM-37 for guile-devel@gnu.org; Wed, 01 Feb 2006 18:10:43 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1F4R7a-0006C9-9h for guile-devel@gnu.org; Wed, 01 Feb 2006 18:10:42 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1F4R7a-0006Bi-3n for guile-devel@gnu.org; Wed, 01 Feb 2006 18:10:42 -0500 Original-Received: from [80.84.72.33] (helo=mail3.uklinux.net) by monty-python.gnu.org with esmtp (Exim 4.52) id 1F4R6J-0005ei-E0 for guile-devel@gnu.org; Wed, 01 Feb 2006 18:09:23 -0500 Original-Received: from laruns (host86-129-143-105.range86-129.btcentralplus.com [86.129.143.105]) by mail3.uklinux.net (Postfix) with ESMTP id E824A40A020 for ; Wed, 1 Feb 2006 23:07:25 +0000 (UTC) Original-Received: from laruns (laruns [127.0.0.1]) by laruns (Postfix) with ESMTP id 5EA139F92B for ; Wed, 1 Feb 2006 23:04:36 +0000 (GMT) Original-To: guile-devel@gnu.org In-Reply-To: <87k6cgi2jo.fsf@zip.com.au> (Kevin Ryde's message of "Wed, 01 Feb 2006 07:07:55 +1100") User-Agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:5644 Archived-At: Kevin Ryde writes: > ;; lazy-catch, but with HANDLER allowed to return > (define-public (c-lazy-catch key thunk handler) > (catch 'c-lazy-catch > (lambda () > (lazy-catch key thunk > (lambda args > (throw 'c-lazy-catch (apply handler args))))) > (lambda (key val) > val))) Thanks. It took me a while to get my head round this, but in the end it has helped me see how we can put some finishing touches to catch and lazy-catch so that they are really nice, clear, consistent and useful. With these finishing touches, I think you would be able to write c-lazy-catch as: (define (c-lazy-catch key thunk handler) (catch key thunk noop handler)) The spec for catch's pre-unwind-handler would be that it can exit either normally or non-locally. If it exits normally, Guile unwinds (dynamic context + stack) and then calls the normal (post-unwind) handler. If it exits non-locally, that exit determines the continuation. The spec for a lazy-catch handler would be nicely consistent with this. Again, we say that the lazy-catch handler can exit either normally or non-locally. It if exits normally, Guile itself throws the same key and args again. If it exits non-locally, that exit determines the continuation. For both cases, we need to make sure that a pre-unwind or lazy-catch handler that rethrows (or, more generally, throws something whose key matches its own catch/lazy-catch) does not call the same pre-unwind or lazy-catch handler again recursively. (For two reasons: first, to avoid a possible infinite recursion; second, to allow an interesting new behaviour, chained calling of lazy-catch/pre-unwind handlers up the dynamic context.) Guile currently does this by unwinding the dynamic context before calling the handler, but this has the problem that the handler does not truly run in the context where the throw occurred. Instead of that, we can avoid the recursion quite easily by adding a "running" field to the lazy_catch/pre_unwind structure, and using the scm_frame_ API to ensure that this is set when the handler is running and reset when it is exited (either normally or non-locally). Existing lazy-catch handlers usually end with `(apply throw key args)' to do a rethrow. A nice consequence of the spec and implementation just proposed is that such a handler (if it exits by this throw) will behave exactly the same as if this final expression was not there. If we implement this under the existing lazy-catch interface, there would be 3 kinds of incompatible behaviour change. 1. A lazy-catch handler that returns normally would be equivalent to ending with a rethrow, whereas currently Guile does a scm_misc_error ("throw", "lazy-catch handler did return.", SCM_EOL); 2. Lazy-catch handlers would execute in the full dynamic context where the throw occurred, including in particular fluid values; whereas currently they don't. (The only bit of dynamic context that the current implementation preserves is the stack.) 3. If a lazy-catch handler throws to a key that does not match its own lazy-catch, the proposed new implementation could match that key to a catch/lazy-catch that is _closer_ to the throw than the first lazy-catch; whereas existing Guile would always look for a catch/lazy-catch higher up the dynamic context. For example: (catch 'a (lambda () (lazy-catch 'b (lambda () (catch 'a (lambda () (throw 'b)) inner-handler)) (lambda (key . args) (throw 'a)))) outer-handler) Current Guile would handle the (throw 'a) by calling outer-handler, and continuing with the continuation of the outer catch. The proposed implementation would call inner-handler and continue with the continuation of the inner catch. This seems surprising at first, but I reckon it's inevitable if you are serious about executing lazy handlers truly lazily - i.e. in the full context of the original throw. I think all these changes are sufficiently obscure that we could get away with implementing them under lazy-catch. But if we want to be ultra-cautious we could keep lazy-catch as it is and introduce `with-pre-unwind-handler' (or something) with the proposed semantics. Anyone still reading? What do you think? Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel