package handling
[p5sagit/Devel-Declare.git] / lib / Devel / Declare.pm
CommitLineData
94caac6e 1package Devel::Declare;
2
3use strict;
4use warnings;
5use 5.008001;
6
7our $VERSION = 0.001000;
8
0ba8c7aa 9# mirrored in Declare.xs as DD_HANDLE_*
10
11use constant DECLARE_NAME => 1;
12use constant DECLARE_PROTO => 2;
53e3ab32 13use constant DECLARE_NONE => 4;
15d0d014 14use constant DECLARE_PACKAGE => 8+1; # name implicit
0ba8c7aa 15
15d0d014 16use vars qw(%declarators %declarator_handlers);
94caac6e 17use base qw(DynaLoader);
18
19bootstrap Devel::Declare;
20
21sub import {
0ba8c7aa 22 my ($class, %args) = @_;
94caac6e 23 my $target = caller;
0ba8c7aa 24 if (@_ == 1) { # "use Devel::Declare;"
25 no strict 'refs';
15d0d014 26 foreach my $name (qw(NAME PROTO NONE PACKAGE)) {
53e3ab32 27 *{"${target}::DECLARE_${name}"} = *{"DECLARE_${name}"};
0ba8c7aa 28 }
29 } else {
30 $class->setup_for($target => \%args);
31 }
94caac6e 32}
33
34sub unimport {
35 my ($class) = @_;
36 my $target = caller;
37 $class->teardown_for($target);
38}
39
40sub setup_for {
41 my ($class, $target, $args) = @_;
42 setup();
0ba8c7aa 43 foreach my $key (keys %$args) {
44 my $info = $args->{$key};
45 my ($flags, $sub);
46 if (ref($info) eq 'ARRAY') {
47 ($flags, $sub) = @$info;
48 } elsif (ref($info) eq 'CODE') {
49 $flags = DECLARE_NAME;
50 $sub = $info;
51 } else {
52 die "Info for sub ${key} must be [ \$flags, \$sub ] or \$sub";
53 }
54 $declarators{$target}{$key} = $flags;
55 $declarator_handlers{$target}{$key} = $sub;
56 }
94caac6e 57}
58
59sub teardown_for {
60 my ($class, $target) = @_;
61 delete $declarators{$target};
0ba8c7aa 62 delete $declarator_handlers{$target};
94caac6e 63 teardown();
64}
65
94caac6e 66my $temp_name;
0ba8c7aa 67my $temp_save;
94caac6e 68
69sub init_declare {
0ba8c7aa 70 my ($pack, $use, $name, $proto) = @_;
53e3ab32 71 my ($name_h, $XX_h, $extra_code)
72 = $declarator_handlers{$pack}{$use}->(
73 $pack, $use, $name, $proto, defined(wantarray)
74 );
15d0d014 75 ($temp_name, $temp_save) = ([], []);
0ba8c7aa 76 if ($name) {
15d0d014 77 $name = "${pack}::${name}" unless $name =~ /::/;
0ba8c7aa 78 push(@$temp_name, $name);
79 no strict 'refs';
15d0d014 80 push(@$temp_save, \&{$name});
0ba8c7aa 81 no warnings 'redefine';
82 no warnings 'prototype';
15d0d014 83 *{$name} = $name_h;
0ba8c7aa 84 }
85 if ($XX_h) {
15d0d014 86 push(@$temp_name, "${pack}::X");
0ba8c7aa 87 no strict 'refs';
88 push(@$temp_save, \&{"${pack}::X"});
89 no warnings 'redefine';
90 no warnings 'prototype';
91 *{"${pack}::X"} = $XX_h;
92 }
53e3ab32 93 if (defined wantarray) {
94 return $extra_code || '0;';
95 } else {
96 return;
97 }
94caac6e 98}
99
100sub done_declare {
101 no strict 'refs';
0ba8c7aa 102 my $name = pop(@{$temp_name||[]});
103 die "done_declare called with no temp_name stack" unless defined($name);
104 my $saved = pop(@$temp_save);
15d0d014 105 $name =~ s/(.*):://;
106 my $temp_pack = $1;
0ba8c7aa 107 delete ${"${temp_pack}::"}{$name};
108 if ($saved) {
109 no warnings 'prototype';
110 *{"${temp_pack}::${name}"} = $saved;
111 }
94caac6e 112}
113
114=head1 NAME
115
116Devel::Declare -
117
118=head1 SYNOPSIS
119
120=head1 DESCRIPTION
121
122=head2 import
123
124 use Devel::Declare qw(list of subs);
125
126Calls Devel::Declare->setup_for(__PACKAGE__ => \@list_of_subs);
127
128=head2 unimport
129
130 no Devel::Declare;
131
132Calls Devel::Declare->teardown_for(__PACKAGE__);
133
134=head2 setup_for
135
136 Devel::Declare->setup_for($package => \@subnames);
137
138Installs declarator magic (unless already installed) and registers
139"${package}::$name" for each member of @subnames
140
141=head2 teardown_for
142
143 Devel::Declare->teardown_for($package);
144
145Deregisters all subs currently registered for $package and uninstalls
146declarator magic if number of teardown_for calls matches number of setup_for
147calls.
148
149=head1 AUTHOR
150
151Matt S Trout - <mst@shadowcatsystems.co.uk>
152
153Company: http://www.shadowcatsystems.co.uk/
154Blog: http://chainsawblues.vox.com/
155
156=head1 LICENSE
157
158This library is free software under the same terms as perl itself
159
160=cut
161
1621;