X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDevel%2FDeclare.pm;h=de3c3f5b4367541afd9e70fbe35a738c61e3001d;hb=c5912dc7bcfef549b39316544d7532ccf9d8f5b3;hp=db54af1111ecfe01628430602999d25b460b5dcd;hpb=323ae557f7cdab8861315cd7fc67dd31b26dbfcf;p=p5sagit%2FDevel-Declare.git diff --git a/lib/Devel/Declare.pm b/lib/Devel/Declare.pm index db54af1..de3c3f5 100644 --- a/lib/Devel/Declare.pm +++ b/lib/Devel/Declare.pm @@ -4,7 +4,7 @@ use strict; use warnings; use 5.008001; -our $VERSION = 0.001000; +our $VERSION = '0.001005'; # mirrored in Declare.xs as DD_HANDLE_* @@ -13,12 +13,14 @@ use constant DECLARE_PROTO => 2; use constant DECLARE_NONE => 4; use constant DECLARE_PACKAGE => 8+1; # name implicit -use vars qw(%declarators %declarator_handlers); +use vars qw(%declarators %declarator_handlers @ISA); use base qw(DynaLoader); use Scalar::Util 'set_prototype'; bootstrap Devel::Declare; +@ISA = (); + sub import { my ($class, %args) = @_; my $target = caller; @@ -100,9 +102,9 @@ sub init_declare { sub done_declare { no strict 'refs'; - my $name = pop(@{$temp_name||[]}); + my $name = shift(@{$temp_name||[]}); die "done_declare called with no temp_name stack" unless defined($name); - my $saved = pop(@$temp_save); + my $saved = shift(@$temp_save); $name =~ s/(.*):://; my $temp_pack = $1; delete ${"${temp_pack}::"}{$name}; @@ -118,15 +120,20 @@ sub build_sub_installer { package ${pack}; my \$body; sub ${name} (${proto}) :lvalue {\n" - .'$body->(@_); + .' if (wantarray) { + goto &$body; + } + my $ret = $body->(@_); + return $ret; }; sub { ($body) = @_; };'; } sub setup_declarators { my ($class, $pack, $to_setup) = @_; - die "${class}->setup_declarator(\$pack, \\\%to_setup)" - unless defined($pack) && ref($to_setup eq 'HASH'); + die "${class}->setup_declarators(\$pack, \\\%to_setup)" + unless defined($pack) && ref($to_setup) eq 'HASH'; + my %setup_for_args; foreach my $name (keys %$to_setup) { my $info = $to_setup->{$name}; my $flags = $info->{flags} || DECLARE_NAME; @@ -136,9 +143,58 @@ sub setup_declarators { my $sub_proto = $proto; # make all args optional to enable lvalue for DECLARE_NONE $sub_proto =~ s/;//; $sub_proto = ';'.$sub_proto; - my $installer = $class->build_sub_installer($pack, $name, $proto); - # XXX UNCLEAN + #my $installer = $class->build_sub_installer($pack, $name, $proto); + my $installer = $class->build_sub_installer($pack, $name, '@'); + $installer->(sub :lvalue { +#{ no warnings 'uninitialized'; warn 'INST: '.join(', ', @_)."\n"; } + if (@_) { + if (ref $_[0] eq 'HASH') { + shift; + if (wantarray) { + my @ret = $run->(undef, undef, @_); + return @ret; + } + my $r = $run->(undef, undef, @_); + return $r; + } else { + return @_[1..$#_]; + } + } + return my $sv; + }); + $setup_for_args{$name} = [ + $flags, + sub { + my ($usepack, $use, $inpack, $name, $proto, $shift_hashref) = @_; + my $extra_code = $compile->($name, $proto); + my $main_handler = sub { shift if $shift_hashref; + ("DONE", $run->($name, $proto, @_)); + }; + my ($name_h, $XX); + if (defined $proto) { + $name_h = sub :lvalue { return my $sv; }; + $XX = $main_handler; + } elsif (defined $name && length $name) { + $name_h = $main_handler; + } + $extra_code ||= ''; + $extra_code = '}, sub {'.$extra_code; + return ($name_h, $XX, $extra_code); + } + ]; } + $class->setup_for($pack, \%setup_for_args); +} + +sub install_declarator { + my ($class, $target_pack, $target_name, $flags, $filter, $handler) = @_; + $class->setup_declarators($target_pack, { + $target_name => { + flags => $flags, + compile => $filter, + run => $handler, + } + }); } =head1 NAME @@ -147,6 +203,10 @@ Devel::Declare - =head1 SYNOPSIS +Look at the tests. This module is currently on CPAN to ease smoke testing +and allow early adopters who've been involved in the design to experiment +with it. + =head1 DESCRIPTION =head2 import @@ -178,9 +238,9 @@ calls. =head1 AUTHOR -Matt S Trout - +Matt S Trout - -Company: http://www.shadowcatsystems.co.uk/ +Company: http://www.shadowcat.co.uk/ Blog: http://chainsawblues.vox.com/ =head1 LICENSE