1 package Devel::Declare;
7 our $VERSION = 0.001000;
9 # mirrored in Declare.xs as DD_HANDLE_*
11 use constant DECLARE_NAME => 1;
12 use constant DECLARE_PROTO => 2;
13 use constant DECLARE_NONE => 4;
14 use constant DECLARE_PACKAGE => 8+1; # name implicit
16 use vars qw(%declarators %declarator_handlers);
17 use base qw(DynaLoader);
18 use Scalar::Util 'set_prototype';
20 bootstrap Devel::Declare;
23 my ($class, %args) = @_;
25 if (@_ == 1) { # "use Devel::Declare;"
27 foreach my $name (qw(NAME PROTO NONE PACKAGE)) {
28 *{"${target}::DECLARE_${name}"} = *{"DECLARE_${name}"};
31 $class->setup_for($target => \%args);
38 $class->teardown_for($target);
42 my ($class, $target, $args) = @_;
44 foreach my $key (keys %$args) {
45 my $info = $args->{$key};
47 if (ref($info) eq 'ARRAY') {
48 ($flags, $sub) = @$info;
49 } elsif (ref($info) eq 'CODE') {
50 $flags = DECLARE_NAME;
53 die "Info for sub ${key} must be [ \$flags, \$sub ] or \$sub";
55 $declarators{$target}{$key} = $flags;
56 $declarator_handlers{$target}{$key} = $sub;
61 my ($class, $target) = @_;
62 delete $declarators{$target};
63 delete $declarator_handlers{$target};
71 my ($usepack, $use, $inpack, $name, $proto) = @_;
72 my ($name_h, $XX_h, $extra_code)
73 = $declarator_handlers{$usepack}{$use}->(
74 $usepack, $use, $inpack, $name, $proto, defined(wantarray)
76 ($temp_name, $temp_save) = ([], []);
78 $name = "${inpack}::${name}" unless $name =~ /::/;
79 push(@$temp_name, $name);
81 push(@$temp_save, \&{$name});
82 no warnings 'redefine';
83 no warnings 'prototype';
87 push(@$temp_name, "${inpack}::X");
89 push(@$temp_save, \&{"${inpack}::X"});
90 no warnings 'redefine';
91 no warnings 'prototype';
92 *{"${inpack}::X"} = $XX_h;
94 if (defined wantarray) {
95 return $extra_code || '0;';
103 my $name = pop(@{$temp_name||[]});
104 die "done_declare called with no temp_name stack" unless defined($name);
105 my $saved = pop(@$temp_save);
108 delete ${"${temp_pack}::"}{$name};
110 no warnings 'prototype';
111 *{"${temp_pack}::${name}"} = $saved;
115 sub build_sub_installer {
116 my ($class, $pack, $name, $proto) = @_;
120 sub ${name} (${proto}) :lvalue {\n"
123 sub { ($body) = @_; };';
126 sub setup_declarators {
127 my ($class, $pack, $to_setup) = @_;
128 die "${class}->setup_declarator(\$pack, \\\%to_setup)"
129 unless defined($pack) && ref($to_setup eq 'HASH');
130 foreach my $name (keys %$to_setup) {
131 my $info = $to_setup->{$name};
132 my $flags = $info->{flags} || DECLARE_NAME;
133 my $run = $info->{run};
134 my $compile = $info->{compile};
135 my $proto = $info->{proto} || '&';
136 my $sub_proto = $proto;
137 # make all args optional to enable lvalue for DECLARE_NONE
138 $sub_proto =~ s/;//; $sub_proto = ';'.$sub_proto;
139 my $installer = $class->build_sub_installer($pack, $name, $proto);
154 use Devel::Declare qw(list of subs);
156 Calls Devel::Declare->setup_for(__PACKAGE__ => \@list_of_subs);
162 Calls Devel::Declare->teardown_for(__PACKAGE__);
166 Devel::Declare->setup_for($package => \@subnames);
168 Installs declarator magic (unless already installed) and registers
169 "${package}::$name" for each member of @subnames
173 Devel::Declare->teardown_for($package);
175 Deregisters all subs currently registered for $package and uninstalls
176 declarator magic if number of teardown_for calls matches number of setup_for
181 Matt S Trout - <mst@shadowcatsystems.co.uk>
183 Company: http://www.shadowcatsystems.co.uk/
184 Blog: http://chainsawblues.vox.com/
188 This library is free software under the same terms as perl itself