return $r;
}
+sub _clean_msg {
+ my ($msg) = @_;
+ $msg =~ s/(?:\s+called)?\s+at\s+.*$//s;
+ return $msg;
+}
+
=head2 C<flatten $proto, @args>
Flattens the array C<@args> according to the prototype C<$proto>. When C<@args> is what C<@_> is after calling a subroutine with prototype C<$proto>, C<flatten> returns the list of what C<@_> would have been if there were no prototype.
if ($1) {
my $a = shift;
my $r = _check_ref $a, $p;
- my %deref = (
- SCALAR => sub { push @args, $$a },
- ARRAY => sub { push @args, @$a },
- HASH => sub { push @args, %$a },
- GLOB => sub { push @args, *$a },
- CODE => sub { push @args, &$a }
- );
- $deref{$r}->();
+ push @args, $r eq 'SCALAR'
+ ? $$a
+ : ($r eq 'ARRAY'
+ ? @$a
+ : ($r eq 'HASH'
+ ? %$a
+ : ($r eq 'GLOB'
+ ? *$a
+ : &$a # _check_ref ensures this must be a code ref
+ )
+ )
+ );
} elsif ($p =~ /[\@\%]/) {
push @args, @_;
last;
- } elsif ($p eq '_' && @_ == 0) {
- push @args, $_;
} else {
+ croak 'Not enough arguments to match this prototype' unless @_;
push @args, shift;
}
}
sub _wrap {
my ($name, $proto, $i, $args, $cr, $opts) = @_;
- if ($proto =~ /(\\?)(\[[^\]]+\]|[^\];])(.*)/g) {
+ while ($proto =~ s/(\\?)(\[[^\]]+\]|[^\];])//) {
my ($ref, $p) = ($1, $2);
- $proto = $3;
$p = $1 if $p =~ /^\[([^\]]+)\]/;
my $cur = '$_[' . $i . ']';
if ($ref) {
} else {
$args .= $cur . ', ';
}
- return _wrap($name, $proto, ($i + 1), $args, $cr, $opts);
- } else {
- $args =~ s/,\s*$//;
- return $name . '(' . $args . ')';
+ ++$i;
}
+ $args =~ s/,\s*$//;
+ return $name . '(' . $args . ')';
}
sub _check_name {
$call = 'sub ' . $call if $opts{sub};
if ($opts{compile}) {
$call = eval $call;
- croak $@ if $@;
+ croak _clean_msg $@ if $@;
}
return $call;
}
sub recall {
my $wrap = eval { wrap shift };
- croak $@ if $@;
+ croak _clean_msg $@ if $@;
return $wrap->(@_);
}