Created
August 1, 2012 12:28
-
-
Save tobyink/3226417 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package returning; | |
use 5.008001; | |
use strict; | |
BEGIN { | |
$returning::AUTHORITY = 'cpan:TOBYINK'; | |
$returning::VERSION = '0.001'; | |
} | |
use Carp 0 qw( croak ); | |
use Scope::Upper 0 qw( :all ); | |
use Sub::Install 0.900 qw( install_sub reinstall_sub ); | |
use Scalar::Util 0.02 qw( set_prototype ); | |
sub import | |
{ | |
my $class = shift; | |
my $default_target = caller; | |
foreach my $arg (@_) | |
{ | |
if (ref $arg eq 'HASH') | |
{ | |
my $target = $arg->{-into} || $default_target; | |
foreach my $f (keys %$arg) | |
{ | |
next unless $f =~ /^[^\W\d]\w*$/; | |
my $v = $arg->{$f}; | |
my $code = ('CODE' eq ref $v) ? $v : sub(){$v if $]}; | |
install_sub { | |
code => $code, | |
into => $target, | |
as => $f, | |
}; | |
$class->setup_for($target, $f); | |
} | |
} | |
elsif ($arg =~ /^[^\W\d]\w*$/) | |
{ | |
$class->setup_for($default_target, $arg); | |
} | |
else | |
{ | |
croak "unrecognised import argument to returning: $arg"; | |
} | |
} | |
} | |
sub setup_for | |
{ | |
my ($class, $target, $func) = @_; | |
my $orig_code = do | |
{ | |
no strict 'refs'; | |
\&{"$target\::$func"}; | |
}; | |
my $new_code = sub | |
{ | |
my $cx = SUB UP; | |
my $want = want_at $cx; | |
my @result; | |
if ($want) | |
{ @result = $orig_code->(@_) } | |
elsif (defined $want) | |
{ @result = scalar $orig_code->(@_) } | |
else | |
{ $orig_code->(@_); @result = undef } | |
unwind @result => $cx; | |
}; | |
&set_prototype( | |
$new_code, | |
prototype($orig_code), | |
) | |
if defined prototype($orig_code); | |
reinstall_sub { | |
code => $new_code, | |
into => $target, | |
as => $func, | |
}; | |
} | |
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Test::More tests => 4; | |
use returning { | |
Affirmative => !0, | |
Negitive => !1, | |
ReturnNumber => sub { 0+$_[0] }, | |
Ctx => sub () { wantarray ? 'list' : 'scalar' }, | |
}; | |
sub test1 | |
{ | |
Affirmative; | |
Negitive; | |
} | |
sub test2 | |
{ | |
ReturnNumber("2bad"); | |
die "failed!"; | |
} | |
sub test3 | |
{ | |
Ctx; | |
die "failed!"; | |
} | |
ok( | |
test1(), | |
); | |
cmp_ok( | |
test2(), | |
'eq', | |
'2' | |
); | |
is( | |
[test3()]->[0], | |
'list', | |
); | |
is( | |
scalar test3(), | |
'scalar', | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment