Switcheroo
view release on metacpan or search on metacpan
lib/Switcheroo.pm view on Meta::CPAN
use 5.014;
use strict;
use warnings;
package Switcheroo;
our $AUTHORITY = 'cpan:TOBYINK';
our $VERSION = '0.008';
our @EXPORT = qw( switch );
our @EXPORT_OK = qw( match );
our @ISA = qw( Exporter::Tiny );
use Exporter::Tiny qw( );
use match::simple qw( match );
use PadWalker qw( peek_my set_closed_over );
use Parse::Keyword { switch => \&_parse_switch };
sub import
{
my $pkg = caller;
eval qq[ package $pkg; our \$a; our \$b; ];
goto \&Exporter::Tiny::import;
}
sub switch
{
my ($pkg, $expr, $comparator, $cases, $default) = @_;
my @args = @_ = do {
package # replaces Devel::Caller::caller_args(1)
DB; my @x = caller(1); our @args;
};
my $pad = peek_my(1);
my $var = defined($expr)
? do {
set_closed_over($expr, $pad);
$expr->(@args);
}
: $_;
Internals::SvREADONLY($var, 1);
local *_ = \$var;
my $match = \&match::simple::match;
if ($comparator)
{
$match = sub {
no strict 'refs';
local *{"$pkg\::a"} = \ $_[0];
local *{"$pkg\::b"} = \ $_[1];
$comparator->(@args);
};
}
CASE: for my $case ( @$cases )
{
my ($type, $condition, $block) = @$case;
my $matched = 0;
if ($type eq 'block')
{
set_closed_over($condition, $pad);
$matched = !!$condition->(@args);
}
else
{
TERM: for my $termexpr (@$condition)
{
set_closed_over($termexpr, $pad);
my $term = $termexpr->(@args);
$match->($var, $term) ? (++$matched && last TERM) : next TERM;
}
}
set_closed_over($block, $pad);
( run in 0.837 second using v1.01-cache-2.11-cpan-39bf76dae61 )