High-level question

4 views
Skip to first unread message

Joe Gibbs Politz

unread,
Mar 27, 2013, 8:25:28 PM3/27/13
to lamb...@googlegroups.com
We implement re-raise with a special kind of exception.

It seems like it should be possible to handle re-raise as just another type of Result, which is handled specially in catch and finally blocks, and passes through everywhere else.  Agree?

Joe Gibbs Politz

unread,
Mar 27, 2013, 8:27:46 PM3/27/13
to lamb...@googlegroups.com
($10 says Alejandro did it this way in his implementation)

Sumner Warren

unread,
Mar 27, 2013, 11:11:50 PM3/27/13
to lamb...@googlegroups.com
Yes, definitely. I just wasn't sure if it was worth creating a new Result type for a single use case.


--
You received this message because you are subscribed to the Google Groups "lambda-py" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lambda-py+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Joe Gibbs Politz

unread,
Mar 27, 2013, 11:15:46 PM3/27/13
to lamb...@googlegroups.com
OK, just validating my intuition.

This and the True/False/None forms are on my short list of things I would like to clean up first in the long term.  I have a feeling reraise can be desugared to nested try/catch blocks, but it's subtle and I know Daniel tried and ran into issues.

Matthew Milano

unread,
Mar 27, 2013, 11:57:58 PM3/27/13
to lamb...@googlegroups.com
It's basically the same problem as the locals problem. The same
strategy should solve it. Or we could just do it in the core - either
way it's likely not happening before the submission deadline.

~matthew

Joe Gibbs Politz

unread,
Mar 28, 2013, 12:02:22 AM3/28/13
to lamb...@googlegroups.com
I think they're actually a little different.  Locals interacts with scope in ways that reraise doesn't... reraise is just a control operator that needs the last exception to be floating around somewhere above it.  We happen to hold onto it in the interpreter while we interpret the catch block, and we use a special value check rather than a distinguished return value to detect it.

Locals is a more general trickyness about Python and how it handles scope in function-chunks.

I know we're not going to change any implementation, but it is relevant to know what these things are for how we present the semantics.

Daniel Patterson

unread,
Mar 28, 2013, 12:17:21 AM3/28/13
to lamb...@googlegroups.com
I think it is somewhere in between the two. There is dynamic-ness, so
to desugar it to "raise %lastexception" is going to require some
global set!ing and non-trivial (but not particularly hard) desugaring
for exit points.

For example, in this first example, break should be desugared to
un-set the %lastexception, but in the second, it shouldn't.

while True:
try:
raise Exception
except:
# blah
break
raise # should error

==== desugars to =====>
try:
raise Exception
except:
%lastexception = $exn-id # or whatever we do in core
# blah
%lastexception = undefined
break
raise %lastexception # throws error, as %lastexception isn't defined

And:

try:
raise Exception
except:
while True:
break
raise

=== desugars to ===>

try:
raise Exception
except:
%lastexception = $exn-id
while True:
break
raise %lastexception
%lastexception = undefined

But none of this isn't stuff we can't do with a reasonably
straightforward desugaring-pass - we just need to figure out all the
exit points of except blocks (essentially break, continue, return, and
maybe yield?) and unset the global, and then we can just turn `raise`
into `raise %lastexception`. I originally thought it was more
complicated because I thought that the exceptions behaved more like a
stack, but they don't, (I did a bunch of testing and read some of the
specs).

Joe Gibbs Politz

unread,
Mar 28, 2013, 12:21:16 AM3/28/13
to lamb...@googlegroups.com
What about desugaring to:

let %reraise-exn = some-special-value

around everything, desugaring

desugaring raise() to (raise %reraise-exn),

and then desugaring from:

try:
  tbody
catch e:
  tcatch

try:
  tbody
catch e1:
  try:
    tcatch
  catch e2:
    if e2 is %reraise-exn:
      raise e1
    else
      raise e2

Then try/finally would need to be extended to be handed the current exception (as a %-var not exposed to Python code), and use the same pattern.




Joe Gibbs Politz

unread,
Mar 28, 2013, 12:24:08 AM3/28/13
to lamb...@googlegroups.com
Actually you don't need to extend try/finally, you just desugar every try/finally into a try/catch nested inside a try/finally with the same pattern.

Daniel Patterson

unread,
Mar 28, 2013, 12:44:08 AM3/28/13
to lamb...@googlegroups.com
I believe this breaks it - the point is that `raise` needs to raise
the right exception, it can't raise anything else.

try:
raise SpecialException
except:
try:
raise
except SpecialException:
pass

Joe Gibbs Politz

unread,
Mar 28, 2013, 12:57:15 AM3/28/13
to lamb...@googlegroups.com
I see.  Does our current solution get this right?

Joe Gibbs Politz

unread,
Mar 28, 2013, 1:02:24 AM3/28/13
to lamb...@googlegroups.com
Nope.

try:
  raise Exception('foo')
except:
  try:  
    raise
  except Exception as e:
    print('made it to second catch')

print('made it to end')

made it to end

Joe Gibbs Politz

unread,
Mar 28, 2013, 1:03:01 AM3/28/13
to lamb...@googlegroups.com
Sorry, that's output of running on \py.  Python gives:  

>>> try:
...   raise Exception('foo')
... except:
...   try:  
...     raise
...   except Exception as e:
...     print('made it to second catch')
... 
made it to second catch

Joe Gibbs Politz

unread,
Mar 28, 2013, 1:04:08 AM3/28/13
to lamb...@googlegroups.com
Subtle.  So it isn't enough to store the exception to rethrow back in the catcher of the original exception.  It needs to be passed down.

Joe Gibbs Politz

unread,
Mar 28, 2013, 1:16:35 AM3/28/13
to lamb...@googlegroups.com
Where the heck does it go in our implementation?

try:
  raise Exception('foo')
except:
  try:  
    print('pre-raise')
    raise
    print('post raise?!')
  except Exception as e:
    print('made it to second catch')
  else:
    print('else')
else:
  print('else2')

print('done')

pre-raise
done

Alejandro Martinez

unread,
Mar 28, 2013, 1:18:08 AM3/28/13
to lamb...@googlegroups.com

Nope :)
I played safe and ued an stack of exceptions under treatment (push on entry to except blocks, pop on exit), reraise  the last one or SyntaxError.

Joe Gibbs Politz

unread,
Mar 28, 2013, 1:19:05 AM3/28/13
to lamb...@googlegroups.com
Darn.  Do you take PayPal?

Joe Gibbs Politz

unread,
Mar 28, 2013, 1:21:35 AM3/28/13
to lamb...@googlegroups.com
I wonder if this is why Python doesn't allow break and continue in except blocks.  Too much state to keep track of in the interpreter.

Alejandro Martinez

unread,
Mar 28, 2013, 1:42:46 AM3/28/13
to lamb...@googlegroups.com

No, only beer :)

Reply all
Reply to author
Forward
0 new messages