Version 0.006001
[p5sagit/Devel-Declare.git] / lib / Devel / Declare / MethodInstaller / Simple.pm
1 package Devel::Declare::MethodInstaller::Simple;
2
3 use base 'Devel::Declare::Context::Simple';
4
5 use Devel::Declare ();
6 use Sub::Name;
7 use strict;
8 use warnings;
9
10 our $VERSION = '0.006001';
11
12 sub install_methodhandler {
13   my $class = shift;
14   my %args  = @_;
15   {
16     no strict 'refs';
17     *{$args{into}.'::'.$args{name}}   = sub (&) {};
18   }
19
20   my $ctx = $class->new(%args);
21   Devel::Declare->setup_for(
22     $args{into},
23     { $args{name} => { const => sub { $ctx->parser(@_) } } }
24   );
25 }
26
27 sub code_for {
28   my ($self, $name) = @_;
29
30   if (defined $name) {
31     my $pkg = $self->get_curstash_name;
32     $name = join( '::', $pkg, $name )
33       unless( $name =~ /::/ );
34     return sub (&) {
35       my $code = shift;
36       # So caller() gets the subroutine name
37       no strict 'refs';
38       *{$name} = subname $name => $code;
39       return;
40     };
41   } else {
42     return sub (&) { shift };
43   }
44 }
45
46 sub install {
47   my ($self, $name ) = @_;
48
49   $self->shadow( $self->code_for($name) );
50 }
51
52 sub parser {
53   my $self = shift;
54   $self->init(@_);
55
56   $self->skip_declarator;
57   my $name   = $self->strip_name;
58   my $proto  = $self->strip_proto;
59   my $attrs  = $self->strip_attrs;
60   my @decl   = $self->parse_proto($proto);
61   my $inject = $self->inject_parsed_proto(@decl);
62   if (defined $name) {
63     $inject = $self->scope_injector_call() . $inject;
64   }
65   $self->inject_if_block($inject, $attrs ? "sub ${attrs} " : '');
66
67   $self->install( $name );
68
69   return;
70 }
71
72 sub parse_proto { '' }
73
74 sub inject_parsed_proto {
75   return $_[1];
76 }
77
78 1;
79