Kavorka
view release on metacpan or search on metacpan
lib/Kavorka.pm view on Meta::CPAN
use PadWalker ();
use Parse::Keyword ();
use Module::Runtime ();
use Scalar::Util ();
use Sub::Util ();
package Kavorka;
our $AUTHORITY = 'cpan:TOBYINK';
our $VERSION = '0.039';
our @ISA = qw( Exporter::Tiny );
our @EXPORT = qw( fun method );
our @EXPORT_OK = qw( fun method after around before override augment classmethod objectmethod multi );
our %EXPORT_TAGS = (
modifiers => [qw( after around before )],
allmodifiers => [qw( after around before override augment )],
);
our %IMPLEMENTATION = (
after => 'Kavorka::Sub::After',
around => 'Kavorka::Sub::Around',
augment => 'Kavorka::Sub::Augment',
before => 'Kavorka::Sub::Before',
classmethod => 'Kavorka::Sub::ClassMethod',
f => 'Kavorka::Sub::Fun',
fun => 'Kavorka::Sub::Fun',
func => 'Kavorka::Sub::Fun',
function => 'Kavorka::Sub::Fun',
method => 'Kavorka::Sub::Method',
multi => 'Kavorka::Multi',
objectmethod => 'Kavorka::Sub::ObjectMethod',
override => 'Kavorka::Sub::Override',
);
our %INFO;
sub info
{
my $me = shift;
my $code = $_[0];
$INFO{$code};
}
sub guess_implementation
{
my $me = shift;
$IMPLEMENTATION{$_[0]};
}
sub compose_implementation
{
shift;
require Moo::Role;
Moo::Role->create_class_with_roles(@_);
}
sub _exporter_validate_opts
{
my $class = shift;
$^H{'Kavorka/package'} = $_[0]{into};
$_[0]{replace} = 1 unless exists $_[0]{replace};
}
sub _fqname ($;$)
{
my $name = shift;
my ($package, $subname);
$name =~ s{'}{::}g;
if ($name =~ /::/)
{
($package, $subname) = $name =~ m{^(.+)::(\w+)$};
}
else
{
my $caller = @_ ? shift : $^H{'Kavorka/package'};
($package, $subname) = ($caller, $name);
}
return wantarray ? ($package, $subname) : "$package\::$subname";
}
sub _exporter_fail
{
my $me = shift;
my ($name, $args, $globals) = @_;
my $implementation =
$args->{'implementation'}
// $me->guess_implementation($name)
// $me;
my $into = $globals->{into};
Module::Runtime::use_package_optimistically($implementation);
{
my $traits = $globals->{traits} // $args->{traits};
$implementation = $me->compose_implementation($implementation, @$traits)
if $traits;
}
$implementation->can('parse')
or Carp::croak("No suitable implementation for keyword '$name'");
# Workaround for RT#95786 which might be caused by a bug in the Perl
# interpreter.
# Also RT#98666 is why we can't just call undefer_all.
require Sub::Defer;
for (keys %Sub::Defer::DEFERRED) {
no warnings;
Sub::Defer::undefer_sub($_)
if $Sub::Defer::DEFERRED{$_} && $Sub::Defer::DEFERRED{$_}[0] =~ /\AKavorkaX?\b/;
}
# Kavorka::Multi (for example) needs to know what Kavorka keywords are
# currently in scope.
$^H{'Kavorka'} .= "$name=$implementation ";
( run in 1.979 second using v1.01-cache-2.11-cpan-364913b4093 )