X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=lib%2FSub%2FPrototype%2FUtil.pm;h=73a1a60115f6d384ace73083584543d99bf60cc0;hb=29d3a214c70390edd665985eddfb42ff7e29a02a;hp=2e2a5045a6f9fafadfb35492e42bfba9f7c0984c;hpb=60e38805350346d06fe27a7dee61932e0da22413;p=perl%2Fmodules%2FSub-Prototype-Util.git diff --git a/lib/Sub/Prototype/Util.pm b/lib/Sub/Prototype/Util.pm index 2e2a504..73a1a60 100644 --- a/lib/Sub/Prototype/Util.pm +++ b/lib/Sub/Prototype/Util.pm @@ -12,13 +12,13 @@ Sub::Prototype::Util - Prototype-related utility routines. =head1 VERSION -Version 0.03 +Version 0.05 =cut use vars qw/$VERSION/; -$VERSION = '0.03'; +$VERSION = '0.05'; =head1 SYNOPSIS @@ -98,38 +98,58 @@ Calls the function C<$name> with the prototyped argument list C<@args>. That is, will call C and so fill the arrayref C<$a> with C<1, 2, 3>. This is especially needed for core functions because you can't C into them. +You can also force the use of a specific prototype. In this case, C<$name> must be a hash reference that holds exactly one key/value pair, the key being the function name and the value the prototpye that should be used to call it. + + recall { 'CORE::push' => '\@$' }, $a, 1, 2, 3; # will only push 1 + +This allows you to recall into C and C by using the C<\&@> prototype : + + sub mygrep (&@) { recall { 'CORE::grep' => '\&@' }, @_ } # the prototypes are intentionally different + =cut sub recall { - my ($name, @a) = @_; - croak 'Wrong subroutine name' unless $name; + my $name = shift; + croak 'No subroutine specified' unless $name; + my $proto; + my $r = ref $name; + if ($r eq 'HASH') { + croak 'Forced prototype hash reference must contain exactly one key/value pair' unless keys %$name == 1; + ($name, $proto) = %$name; + } elsif (length $r) { + croak 'Unhandled ' . $r . ' reference as first argument'; + } $name =~ s/^\s+//; $name =~ s/[\s\$\@\%\*\&;].*//; - my $proto = prototype $name; - my @args; + $proto = prototype $name unless $proto; + my $call = $name . '('; + my @cr; if (defined $proto) { my $i = 0; while ($proto =~ /(\\?)(\[[^\]]+\]|[^\];])/g) { my $p = $2; if ($1) { - my $r = _check_ref $a[$i], $p; - push @args, join '', $sigils{$r}, '{$a[', $i, ']}'; + my $r = _check_ref $_[$i], $p; + $call .= $sigils{$r} . '{$_[' . $i . ']},'; } elsif ($p =~ /[\@\%]/) { - push @args, join '', '@a[', $i, '..', (@a - 1), ']'; + $call .= '@_[' . $i . '..' . (@_ - 1) . ']'; last; } elsif ($p =~ /\&/) { - push @args, 'sub{&{$a[' . $i . ']}}'; - } elsif ($p eq '_' && $i >= @a) { - push @args, '$_'; + push @cr, $_[$i]; + $call .= 'sub{&{$cr[' . $#cr . ']}},'; + } elsif ($p eq '_' && $i >= @_) { + $call .= '$_,'; } else { - push @args, '$a[' . $i . ']'; + $call .= '$_[' . $i . '],'; } ++$i; } + $call =~ s/,$//; } else { - @args = map '$a[' . $_ . ']', 0 .. @a - 1; + $call .= join ',', map '$_[' . $_ . ']', 0 .. @_ - 1; } - my @ret = eval $name . '(' . join(',', @args) . ');'; + $call .= ');'; + my @ret = eval $call; croak $@ if $@; return @ret; } @@ -142,11 +162,13 @@ The functions L and L are only exported on request, either by use base qw/Exporter/; -our @EXPORT = (); -our %EXPORT_TAGS = ( +use vars qw/@EXPORT @EXPORT_OK %EXPORT_TAGS/; + +@EXPORT = (); +%EXPORT_TAGS = ( 'funcs' => [ qw/flatten recall/ ] ); -our @EXPORT_OK = map { @$_ } values %EXPORT_TAGS; +@EXPORT_OK = map { @$_ } values %EXPORT_TAGS; $EXPORT_TAGS{'all'} = [ @EXPORT_OK ]; =head1 DEPENDENCIES