[Perl5-syntax] Syntax/implementation for try/catch

Florian Ragwitz rafl at debian.org
Sun Jan 18 00:15:26 GMT 2009


On Tue, Jan 13, 2009 at 07:26:49PM +0000, Ash Berlin wrote:
> Thanks to Vincent Pit's Scope::Upper I can now make return from a
> block/anon sub return to from the enclosing sub. Wonderful. However
> consider the two cases below:
>
> sub simple_return {
>   try {
>     return "simple_return";
>   }
>   return "bar";
> }
> sub simple_no_return {
>   try {
>     "simple_return"; # Not a return op
>   }
>   return "bar";
> }
>
> is(simple_return(), "simple_return");
> is(simple_no_return(), "bar");

To make the above work I'd suggest to do something like this:

 1. when Devel::Declare calls your parser method after it hits the try
    keyword, store information about the try block you just entered in
    the hints hash

 2. use B::Hooks::OP::Check to get a callback for every OP_RETURN that's
    being compiled. in that callback, do nothing unless the hint you
    previously set in 1 is set.

 3. if it is set, use B::Hooks::OP::PPAddr to to change the c function
    that will be executed when the return op you're currently compiling is
    executed. change it to a function that'll do your uplevel return
    using Scope::Upper.

 4. after you're finished handling the try block, unset the hint from 1.

that way all return ops compiled within a try block would return to the
upper scope.

You'd also need to specially handle coderefs created in try blocks so

sub foo {
  try {
    return sub { return 42 }
  }
}

sub bar {
  my $fourty_two = foo()->();
  return 23;
}

will work and not return 42 from bar.

> The issue here is detecting an explicit return versus returning value
> of last statement. The way I managed it currently is by a custom
> PL_runops. However rafl pointed out that this would likely mess up
> debugging. He also suggested that it should be possible using
> B::Hooks::{Check,OP::PPAddr}, and for the simple cases above that
> would work. However I *think* it wouldn't work for the cases below.
> Please tell me I'm wrong :)
>
> sub bar {
>   # ...
>   return "bar";
> }
>
> # I'm not sure I can even make devel::declare parse this one properly
> # since there is no scope to post hook.

> sub foo {
>   try \&bar
> }

I'd simply not allow this specific syntax.

> sub foo_2 {
>   try {
>     goto \&bar
>   }
> }

You're right. The return in bar wouldn't be compiled while your
try/catch hint is set and therefor not return to the scope above.

One might consider that a feature as i think doing that would be quite
confusing, however, if you really want to get it working, you could also
replace the ppaddrs of all return ops at compile time and store the hint
somewhere at runtime for the return op to check. Doing that might be
even more confusing, given that it would only work for return ops
compiled after your module was loaded.

Maybe others have better ideas on how to solve this, however I suggest
to not do anything special to work around goto \&sub and document that
corner case properly.


-- 
BOFH excuse #52:
Smell from unhygienic janitorial staff wrecked the tape heads
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://lists.scsys.co.uk/pipermail/perl5-syntax/attachments/20090118/e6e4cb8e/attachment.pgp


More information about the Perl5-syntax mailing list