Aion
view release on metacpan or search on metacpan
lib/Aion/Meta/Subroutine.pm view on Meta::CPAN
package Aion::Meta::Subroutine;
# ÐпиÑÑÐ²Ð°ÐµÑ ÑÑнкÑÐ¸Ñ Ñ ÑигнаÑÑÑой
use common::sense;
use Aion::Meta::Util qw//;
use Aion::Types qw/Tuple/;
use Scalar::Util qw//;
use Sub::Util qw//;
Aion::Meta::Util::create_getters(qw/pkg subname signature referent wrapsub/);
sub new {
my $cls = shift;
bless {@_}, ref $cls || $cls;
}
sub wrap_sub {
my ($self) = @_;
my ($pkg, $subname, $signature, $referent) = @$self{qw/pkg subname signature referent/};
my $args_of_meth = "Arguments of method `$subname`";
my $returns_of_meth = "Returns of method `$subname`";
my $return_of_meth = "Return of method `$subname`";
my @signature = @$signature;
my $ret = pop @signature;
my ($ret_array, $ret_scalar) = exists $ret->{is_wantarray}? @{$ret->{args}}: (Tuple([$ret]), $ret);
my $args = Tuple(\@signature);
my $sub = sub {
$args->validate(\@_, $args_of_meth);
wantarray? do {
my @returns = $referent->(@_);
$ret_array->validate(\@returns, $returns_of_meth);
@returns
}: do {
my $return = $referent->(@_);
$ret_scalar->validate($return, $return_of_meth);
$return
}
};
Sub::Util::set_prototype Sub::Util::prototype($referent), $sub;
Sub::Util::set_subname Sub::Util::subname($referent), $sub;
*{"$pkg\::$subname"} = $sub if $subname ne '__ANON__';
$self->{wrapsub} = $sub;
$Aion::META{$pkg}{subroutine}{$subname} = $self;
my $key = pack 'J', Scalar::Util::refaddr $sub;
$Aion::Isa{$key} = $self;
Scalar::Util::weaken $Aion::Isa{$key};
$self
}
sub compare {
my ($self, $subroutine) = @_;
die "Requires subroutine ${\$self->name}" unless $subroutine->isa('Aion::Meta::Subroutine');
my $i = 0;
my $signature = $subroutine->signature;
my $fail = 0;
if(@$signature == @{$self->signature}) {
for my $type (@{$self->{signature}}) {
my $other_type = $signature->[$i++];
$fail = 1, last unless $type eq $other_type;
}
( run in 0.587 second using v1.01-cache-2.11-cpan-39bf76dae61 )