At 09:12 PM 8/16/00 -0600, Tony Olekshy wrote:
>Executive summary: I no longer want catch blocks to "daisy chain"
>after a exception is thrown in a catch block. Thanks to everyone
>who has helped me see the light on this.

I'm not sure what you mean by "daisy chain".  I have been taking it to mean 
that there are multiple blocks bound together syntactically in an order, 
like elsif blocks.

>Yes, that's much better.  Thanks Peter.  Here is a slightly
>different version which is still slightly more complex, but
>which allows me to more clearly illustrate the change I am
>proposing.
>
>   1. Whenever an exception is thrown it becomes the current
>      exception (with a link to the previous one if there was one)
>      and Perl looks for an enclosing try/catch/finally block.

If you're trying to encompass the behavior of exceptions thrown in catch 
and finally blocks here, I think it makes it harder to 
understand.  Granted, my rule 1 was incomplete in that it didn't address 
those, but I think the way it was addressed in rules 2 and 3 was a more 
natural order.

>This probably means that it should be a syntax error to have any
>catch clause follow a non-conditional catch, because such a clause
>could never be executed.

That's reasonable; that could be codified.

> > throws() outside a try block are caught by the catch
> > blocks of the next enclosing try block.  See above.
>
>Not quite. Throws in a catch block (not a try block per se) still
>have to be trapped in order to get to the finally block, if any.
>I think you probably meant that, I'm just making it explicit.

Right.  The 'current exception' language is more precise.

>The change I described above would get the effect we want, that is,
>that throws in a catch block prevent subsequent catch blocks (up to
>the next finally, if any) from being attempted, and after the finally
>the throw from the catch is propagated.
>
>To put it another way, catches don't "daisy chain" any more.  Once
>a catch is triggered, subsequent catches (up to the next finally
>block, if any) are ignored, even if the triggered catch threw.  I
>think that gets rid of much of the complexity we have been trying
>to avoid, and we can always use nested trys if we really need to.

Actually, this is the way I've always thought about it, and that's why I 
worded my explanation the way I did.  But I see where it wasn't as clear as 
it could have been.

I still think the explanation can be made simpler with fewer forward 
references.  I'll have another try:

The following rules form a sequence to be read in order.

1. When an exception (which we will call the 'current' exception) is thrown 
(other than in catch or finally blocks, described below), perl looks for 
the enclosing try block (which may be in a higher call frame); if there is 
none then the program dies with the stringified exception.  If 
$SIG{__DIE__} is still in the language this is where it would be called 
instead of program death.

2. Finding the enclosing try block, perl looks at the attached catch blocks 
in order (if there are none, skip to step 3).  If the catch criteria 
succeed (the exception class matches one in a list, or a catch expression 
evaluates to tue, or the catch block catches everything), the catch block 
is executed.  If no catch block is executed skip to step 4.

3. Once a catch block begins executing no other catch block will be 
executed, even if its criteria would succeed.  If the catch block throws an 
exception it becomes the current exception (with a link to the previous 
one) and the catch block stops executing (go to step 4).  If no exception 
is thrown in the catch block then at the end of the catch block there is no 
longer a current exception (it is cleared).

4. If a finally block is present it is now executed.  If there is none, 
skip to step 5.  If the finally block throws an exception, it becomes the 
current exception (with a link to the previous one if there is one) and the 
finally block stops executing (go to step 5).  Unlike catch blocks, 
however, the current exception is not cleared at the end of the  block.

5.  If a current exception still exists, go to step 1 (start looking for 
the next enclosing try block).  This will happen if an exception was not 
caught, or if a catch or finally block threw an exception.


I note that under these rules it would be possible to have "try { ... } 
finally { }"  with no catch blocks.  I guess that's okay.
--
Peter Scott
Pacific Systems Design Technologies

Reply via email to