Data-Bind
view release on metacpan or search on metacpan
lib/Data/Bind.pm view on Meta::CPAN
my $inv = ref($arg->[0]) && ref($arg->[0]) eq 'ARRAY' ? undef : shift @$arg;
last unless defined $inv || @$arg;
my $pos = shift @$arg;
my $named = shift @$arg;
if ($multidim) {
push @x, \Data::Capture::Overload->new( { invocant => $inv, positional => $pos, named => $named });
}
else {
die 'wrong dimension' unless $self->[$i];
push @install_local,
@{ $self->[$i++]->bind({ invocant => $inv, positional => $pos, named => $named }, $lv) };
}
}
if ($multidim) {
$self->[0]->bind( { positional => \@x }, $lv );
}
return \@install_local;
}
sub is_compatible {
my $self = shift;
no warnings 'redefine';
local *Data::Bind::Param::slurpy_bind = sub {};
local *Data::Bind::Param::bind = sub {};
local *Data::Bind::Array::bind = sub {};
local $@;
eval { $self->bind_all(\@_) };
return $@ ? 0 : 1;
}
sub bind {
# XXX: old api
my $self = shift;
die 'old api used with multidimension sig' if $#{$self};
$self->[0]->bind($_[0], $_[1] || 2);
}
sub prepare_binding {
shift->[0]->prepare_binding(@_);
}
sub finalize_binding {
my ( $self, $binding, $lv ) = @_;
$lv ||= 1;
$self->[0]->finalize_binding($binding, $lv + 1);
}
sub all_variable_names {
my %seen; grep { !$seen{$_}++ or die "duplicate variable $_ in signature" } $_[0][0]->all_variable_names;
}
package Data::Bind::Sig;
use base 'Class::Accessor::Fast';
__PACKAGE__->mk_accessors(qw(positional invocant named named_slurpy is_multidimension));
use Carp qw(croak);
use Scalar::Util qw(blessed);
use PadWalker qw(peek_my);
use Data::Capture;
sub bind {
my ( $self, $args, $lv ) = @_;
$lv ||= 1;
$self->finalize_binding( $self->prepare_binding(Data::Capture->new($args)), $lv + 1 );
}
sub prepare_binding {
my ($self, $capture, %opts) = @_;
local $Carp::CarpLevel = 2;
my %bound;
my $named_arg = $capture->named;
my $bindings;
# FIXME invocant should be ref, it's writable in perl5
if ($self->invocant) {
croak 'invocant missing'
if !defined $capture->invocant;
$bindings->{$self->invocant->container_var} = [ $self->invocant, \$capture->invocant ];
}
else {
croak 'unexpected invocant'
if defined $capture->invocant;
}
for my $param_name (keys %{$self->named || {}}) {
my $param = $self->named->{$param_name};
if (my $current = delete $named_arg->{$param_name}) {
# XXX: handle array concating
$bindings->{ $param->container_var } = [ $param, $current ];
$bound{$param_name}++;
}
elsif ($param->default) {
$bindings->{ $param->container_var } = [ $param, $opts{no_defaults} ? undef : \$param->default->(), 'default' ];
}
elsif ($param->named_only) {
croak "named argument ".$param->name." is required"
unless $param->is_optional;
}
}
if ($self->named_slurpy) {
$bindings->{ $self->named_slurpy->container_var } =
[ $self->named_slurpy, $named_arg, 'slurpy' ];
}
else {
# XXX: report extra incoming named args
}
my $pos_arg = $capture->positional;
for my $param (@{$self->positional || []}) {
if ($param->is_slurpy && $param->p5type ne '$') {
$bindings->{ $param->container_var } = [ $param, $pos_arg, 'slurpy' ];
$pos_arg = [];
( run in 1.860 second using v1.01-cache-2.11-cpan-39bf76dae61 )