Re: try: execpt:/ try: finally: behavior

Mark S. Riggle (sasmsr@zinfande.unx.sas.com)
Tue, 28 Jun 1994 15:17:25 GMT

Sorry it has taken awhile to follow up on this topic, but it is
not to bed yet. From the prior followups, I think perhaps that
I have not communicated the true nature of the problem.

The following example hopefully will show the difficulty.
It needs 3 nested try/except forms to illustrate the stack states.

my_exec= 'my_exec'
my_exec2= 'my_exec2'
my_exec3='my_exec3'

def foo(x):
try:
try:
try:
bar(x)
print "after bar"
except my_exec, val:
print "handling inner my_exec exception"
print "after inner try"
except my_exec2, val:
print "handling my_exec2 exception"
print "after 2nd try"
except (my_exec, my_exec3), val:
print "handling outer", val, "exception"

def bar(x):
try:
print "raising my_exec2"
raise my_exec2, "my_exec2"
finally:
if (x ==0) :
print "raising my_exec"
raise my_exec, "my_exec"
else:
print "raising my_exec3"
raise my_exec3, "my_exec3"

>>> foo(0)
raising my_exec2
raising my_exec
handling inner my_exec exception
after inner try
after 2nd try

>>> foo(1)
raising my_exec2
raising my_exec3
handling outer my_exec3 exception
>>>
-----------------------------------------

So foo(0) will raise my_exec in the finally part of a try clause
that has raised my_exec2.
The stack in the call to bar on try statement at point of raising my_exec2
will look something like:

@finally - contains raising my_exec <- current stack position
entering bar
@my_exec - inner one
@my_exec2
@my_exec - outer one
entering foo
#bottom - top level

and we raise the my_exec2 exception in the 'try' part in bar.
Scan back and find the @my_exec2 marker in the stack. Now
either intervening exception markers are allowed to stay active or
they are not; in this case the inner @my_exec is at issue.
Now we need to do any finally clauses (top down) on the stack
that lie between the top (current position) and the called exception
marker, @my_exec2. The @finally clause raises the my_exec exception.
What exception marker do you use now. If
the intervening exception markers were allowed to stay active, the
inner @my_exec is selected, otherwise the outer @my_exec is selected.
If the inner one is selected (current implementation) control returns
to the exception part of the inner my_exec try clause even though an
exception occured that indicated it should get out past that context.

I would consider the inner @my_exec exception handler to be invalid as
an exception handler when processing an exception that will unwind the
stack past that handler. That is, foo(0) should behave the same way
as foo(1).

I think that is a better semantics of exceptions than the current
implementation, however, it should be documented which ever is decided
upon.

There is no way to simulate the semantics of one given the other.

BTW, the nested tuples for exception handling is a nice touch so that
hierarchies of exceptions can be created easily.

-- 
=========================================================
Mark Riggle                         | "Give me LAMBDA or
sasmsr@unx.sas.com                  |  give me death"
SAS Institute Inc.,                 |
SAS Campus Drive, Cary, NC, 27513   |  
(919) 677-8000                      |