[Openmcl-devel] Delay / force doesn't work
Gary Byers
gb at clozure.com
Thu Nov 30 16:48:10 PST 2006
There's a mechanism that tries to catch cases where the act of
signaling an error signals an error. (One way of triggering this
is to write a buggy PRINT-OBJECT method and then signal an error
whose :REPORT method causes the buggy PRINT-OBJECT to be invoked.)
The mechanism (in which CCL::FUNCALL-WITH-ERROR-REENTRY-DETECTION
is involved) tries to catch this and reports a simple error
("I tried to report an error, but an error occurred while doing so")
if it detects that things might not be making progress. That might
prevent cases where :REPORT methods intentionally signal errors for
some reason, but it also prevents stack overflows in cases where the
recursive errors are just due to a bug. The error-reentry-detection
mechanism is mostly used around code that runs in response to some
sort of machine exeption or trap; a lot of simple type-errors and
things like wrong-number-of-args generate traps and some trap-handling
code is then responsible for figuring out what happened and (usually)
signalling a lisp error.
If a slot in a standard instance is unbound when referenced, that also
generates a trap; whether it involves signalling an error or not
depends on what the applicable SLOT-UNBOUND method decides. The
SLOT-UNBOUND method in your example recurses (references an unbound
slot a few more times until a terminating condition is reached), and
the trap handler interprets this as if a buggy error-reporting method
was wedged. Moving the trap-handling code for the SLOT-UNBOUND case
outside of the error-reentry-detection code would fix this; I'll try
to do that for the next snapshots.
I have mixed feelings about the whole notion of trying to catch
recursive errors like this. In some cases, it makes debugging
a little easier (because you don't have to look through thousands
of stack frames to figure out where you were when the -real- problem
occurred), but on general principles You Should Have Enough Rope.
(The cases where the error-reentry-detection is often most useful
to me are cases that're fatal anyhow, like *ERROR-OUTPUT* not being
a stream during the early stages of initialization; I'm not sure
if user-level cases are common enough that anything should try to
avoid just letting the stack overflow.)
Regardless of whether this should happen in the ERROR case or not,
it's pretty clear that it shouldn't get in the way of doing recursive
SLOT-UNBOUNDs.
On Thu, 30 Nov 2006, Pascal Costanza wrote:
> Hi,
>
> Here is an implementation of Scheme's delay/force in Common Lisp
> together with a test case, modeled after the example implementations
> in R5RS - see http://www.schemers.org/Documents/Standards/R5RS/HTML/
> r5rs-Z-H-9.html#%_idx_562
>
> When I run this code in OpenMCL 1.0 (on Mac OS X), I get the
> following error:
>
> > Error in process listener(1): Error reporting error
> > While executing: CCL::FUNCALL-WITH-ERROR-REENTRY-DETECTION
> > Type :POP to abort.
>
> IMHO, this shouldn't happen. The code below works correctly in
> Allegro, clisp, cmu, ecl and LispWorks, but not on OpenMCL, MCL and
> SBCL.
>
> (defclass promise ()
> ((value :accessor promise-value)
> (thunk :initarg :thunk)))
>
> (defmethod slot-unbound (class (instance promise) (slot (eql 'value)))
> (declare (ignore class))
> (let ((x (funcall (slot-value instance 'thunk))))
> (if (slot-boundp instance 'value)
> (promise-value instance)
> (setf (promise-value instance) x))))
>
> (defmacro delay (&body body)
> `(make-instance 'promise :thunk (lambda () , at body)))
>
> (defgeneric force (value)
> (:method (value) value)
> (:method ((value promise))
> (promise-value value)))
>
> (defvar *count* 0)
>
> (defvar *x* 5)
>
> (defvar *p*
> (delay (incf *count*)
> (if (> *count* *x*)
> *count*
> (force *p*))))
>
> (assert (typep *p* 'promise))
> (assert (= (force *p*) 6))
> (assert (typep *p* 'promise))
> (setf *x* 10)
> (assert (= (force *p*) 6))
> (print :done)
>
> --
> Pascal Costanza, mailto:pc at p-cos.net, http://p-cos.net
> Vrije Universiteit Brussel, Programming Technology Lab
> Pleinlaan 2, B-1050 Brussel, Belgium
>
>
>
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>
More information about the Openmcl-devel
mailing list