|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Devel::Declare;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ABSTRACT: (DEPRECATED) Adding keywords to perl, in perl  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
1267542
 | 
 use strict;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
285
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
914
 | 
    | 
| 
5
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
149
 | 
 use warnings;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
762
 | 
    | 
| 
6
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
676
 | 
 use 5.008001;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
157
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.006_020';  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION =~ tr/_//d;  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
204
 | 
 use constant DECLARE_NAME => 1;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3142
 | 
    | 
| 
12
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
190
 | 
 use constant DECLARE_PROTO => 2;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1681
 | 
    | 
| 
13
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
181
 | 
 use constant DECLARE_NONE => 4;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1859
 | 
    | 
| 
14
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
176
 | 
 use constant DECLARE_PACKAGE => 8+1; # name implicit  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1637
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
16
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
310
 | 
 use vars qw(%declarators %declarator_handlers @ISA);  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2494
 | 
    | 
| 
17
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
210
 | 
 use base qw(DynaLoader);  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
87
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4710
 | 
    | 
| 
18
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
209
 | 
 use Scalar::Util 'set_prototype';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3000
 | 
    | 
| 
19
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
14200
 | 
 use B::Hooks::OP::Check 0.19;  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38169
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2262
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 bootstrap Devel::Declare;  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 @ISA = ();  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 initialize();  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub import {  | 
| 
28
 | 
18
 | 
 
 | 
 
 | 
  
18
  
 | 
 
 | 
154
 | 
   my ($class, %args) = @_;  | 
| 
29
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
   my $target = caller;  | 
| 
30
 | 
18
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
70
 | 
   if (@_ == 1) { # "use Devel::Declare;"  | 
| 
31
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
209
 | 
     no strict 'refs';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
53
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15571
 | 
    | 
| 
32
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     foreach my $name (qw(NAME PROTO NONE PACKAGE)) {  | 
| 
33
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51
 | 
       *{"${target}::DECLARE_${name}"} = *{"DECLARE_${name}"};  | 
| 
 
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2037
 | 
    | 
| 
 
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
151
 | 
    | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
36
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
     $class->setup_for($target => \%args);  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub unimport {  | 
| 
41
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($class) = @_;  | 
| 
42
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $target = caller;  | 
| 
43
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $class->teardown_for($target);  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub setup_for {  | 
| 
47
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
  
1
  
 | 
292737
 | 
   my ($class, $target, $args) = @_;  | 
| 
48
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
212
 | 
   setup();  | 
| 
49
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
117
 | 
   foreach my $key (keys %$args) {  | 
| 
50
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
     my $info = $args->{$key};  | 
| 
51
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
     my ($flags, $sub);  | 
| 
52
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
224
 | 
     if (ref($info) eq 'ARRAY') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
53
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
       ($flags, $sub) = @$info;  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (ref($info) eq 'CODE') {  | 
| 
55
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
       $flags = DECLARE_NAME;  | 
| 
56
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
       $sub = $info;  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (ref($info) eq 'HASH') {  | 
| 
58
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
       $flags = 1;  | 
| 
59
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
300
 | 
       $sub = $info;  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
61
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       die "Info for sub ${key} must be [ \$flags, \$sub ] or \$sub or handler hashref";  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
63
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
202
 | 
     $declarators{$target}{$key} = $flags;  | 
| 
64
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7008
 | 
     $declarator_handlers{$target}{$key} = $sub;  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub teardown_for {  | 
| 
69
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my ($class, $target) = @_;  | 
| 
70
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   delete $declarators{$target};  | 
| 
71
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   delete $declarator_handlers{$target};  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $temp_name;  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $temp_save;  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub init_declare {  | 
| 
78
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
  
0
  
 | 
48
 | 
   my ($usepack, $use, $inpack, $name, $proto, $traits) = @_;  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my ($name_h, $XX_h, $extra_code)  | 
| 
80
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
        = $declarator_handlers{$usepack}{$use}->(  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
            $usepack, $use, $inpack, $name, $proto, defined(wantarray), $traits  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          );  | 
| 
83
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
147
 | 
   ($temp_name, $temp_save) = ([], []);  | 
| 
84
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
41
 | 
   if ($name) {  | 
| 
85
 | 
11
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
     $name = "${inpack}::${name}" unless $name =~ /::/;  | 
| 
86
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     shadow_sub($name, $name_h);  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
88
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
40
 | 
   if ($XX_h) {  | 
| 
89
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
     shadow_sub("${inpack}::X", $XX_h);  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
91
 | 
17
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
69
 | 
   if (defined wantarray) {  | 
| 
92
 | 
17
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
123
 | 
     return $extra_code || '0;';  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
94
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return;  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub shadow_sub {  | 
| 
99
 | 
79
 | 
 
 | 
 
 | 
  
79
  
 | 
  
1
  
 | 
1624
 | 
   my ($name, $cr) = @_;  | 
| 
100
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
206
 | 
   push(@$temp_name, $name);  | 
| 
101
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
232
 | 
   no strict 'refs';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3235
 | 
    | 
| 
102
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
620
 | 
   my ($pack, $pname) = ($name =~ m/(.+)::([^:]+)/);  | 
| 
103
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
593
 | 
   push(@$temp_save, $pack->can($pname));  | 
| 
104
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
215
 | 
   no warnings 'redefine';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
78
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1656
 | 
    | 
| 
105
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
187
 | 
   no warnings 'prototype';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3158
 | 
    | 
| 
106
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
144
 | 
   *{$name} = $cr;  | 
| 
 
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
283
 | 
    | 
| 
107
 | 
79
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
132
 | 
   set_in_declare(~~@{$temp_name||[]});  | 
| 
 
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
579
 | 
    | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub done_declare {  | 
| 
111
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
194
 | 
   no strict 'refs';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3775
 | 
    | 
| 
112
 | 
79
 | 
  
 50
  
 | 
 
 | 
  
79
  
 | 
  
0
  
 | 
139
 | 
   my $name = shift(@{$temp_name||[]});  | 
| 
 
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
314
 | 
    | 
| 
113
 | 
79
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
214
 | 
   die "done_declare called with no temp_name stack" unless defined($name);  | 
| 
114
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
136
 | 
   my $saved = shift(@$temp_save);  | 
| 
115
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
371
 | 
   $name =~ s/(.*):://;  | 
| 
116
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
236
 | 
   my $temp_pack = $1;  | 
| 
117
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
109
 | 
   delete ${"${temp_pack}::"}{$name};  | 
| 
 
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
261
 | 
    | 
| 
118
 | 
79
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
223
 | 
   if ($saved) {  | 
| 
119
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
 
 | 
202
 | 
     no warnings 'prototype';  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
62
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40755
 | 
    | 
| 
120
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
82
 | 
     *{"${temp_pack}::${name}"} = $saved;  | 
| 
 
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
301
 | 
    | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
122
 | 
79
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
143
 | 
   set_in_declare(~~@{$temp_name||[]});  | 
| 
 
 | 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11881
 | 
    | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub build_sub_installer {  | 
| 
126
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
100
 | 
   my ($class, $pack, $name, $proto) = @_;  | 
| 
127
 | 
2
 | 
  
 50
  
 | 
 
 | 
  
8
  
 | 
 
 | 
306
 | 
   return eval "  | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
214
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
89
 | 
    | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     package ${pack};  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my \$body;  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub ${name} (${proto}) :lvalue {\n"  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     .'  if (wantarray) {  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         goto &$body;  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $ret = $body->(@_);  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return $ret;  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub { ($body) = @_; };';  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub setup_declarators {  | 
| 
141
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
2
 | 
   my ($class, $pack, $to_setup) = @_;  | 
| 
142
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
13
 | 
   die "${class}->setup_declarators(\$pack, \\\%to_setup)"  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unless defined($pack) && ref($to_setup) eq 'HASH';  | 
| 
144
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
   my %setup_for_args;  | 
| 
145
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
   foreach my $name (keys %$to_setup) {  | 
| 
146
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
     my $info = $to_setup->{$name};  | 
| 
147
 | 
1
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
3
 | 
     my $flags = $info->{flags} || DECLARE_NAME;  | 
| 
148
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my $run = $info->{run};  | 
| 
149
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
     my $compile = $info->{compile};  | 
| 
150
 | 
1
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
4
 | 
     my $proto = $info->{proto} || '&';  | 
| 
151
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
     my $sub_proto = $proto;  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # make all args optional to enable lvalue for DECLARE_NONE  | 
| 
153
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $sub_proto =~ s/;//; $sub_proto = ';'.$sub_proto;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #my $installer = $class->build_sub_installer($pack, $name, $proto);  | 
| 
155
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my $installer = $class->build_sub_installer($pack, $name, '@');  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $installer->(sub :lvalue {  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #{ no warnings 'uninitialized'; warn 'INST: '.join(', ', @_)."\n"; }  | 
| 
158
 | 
7
 | 
  
100
  
 | 
 
 | 
  
7
  
 | 
 
 | 
14
 | 
       if (@_) {  | 
| 
159
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
         if (ref $_[0] eq 'HASH') {  | 
| 
160
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
           shift;  | 
| 
161
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
           if (wantarray) {  | 
| 
162
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my @ret = $run->(undef, undef, @_);  | 
| 
163
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return @ret;  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           }  | 
| 
165
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
           my $r = $run->(undef, undef, @_);  | 
| 
166
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
           return $r;  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
168
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
95
 | 
           return @_[1..$#_];  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
171
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
       return my $sv;  | 
| 
172
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     });  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $setup_for_args{$name} = [  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $flags,  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       sub {  | 
| 
176
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
16
 | 
         my ($usepack, $use, $inpack, $name, $proto, $shift_hashref, $traits) = @_;  | 
| 
177
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
         my $extra_code = $compile->($name, $proto, $traits);  | 
| 
178
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
137
 | 
         my $main_handler = sub { shift if $shift_hashref;  | 
| 
179
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
           ("DONE", $run->($name, $proto, @_));  | 
| 
180
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
         };  | 
| 
181
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
         my ($name_h, $XX);  | 
| 
182
 | 
7
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
22
 | 
         if (defined $proto) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
183
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
           $name_h = sub :lvalue { return my $sv; };  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
117
 | 
    | 
| 
184
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1604
 | 
           $XX = $main_handler;  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif (defined $name && length $name) {  | 
| 
186
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
           $name_h = $main_handler;  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
188
 | 
7
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
21
 | 
         $extra_code ||= '';  | 
| 
189
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
         $extra_code = '}, sub {'.$extra_code;  | 
| 
190
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
         return ($name_h, $XX, $extra_code);  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
192
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     ];  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
194
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
   $class->setup_for($pack, \%setup_for_args);  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub install_declarator {  | 
| 
198
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
83
 | 
   my ($class, $target_pack, $target_name, $flags, $filter, $handler) = @_;  | 
| 
199
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   $class->setup_declarators($target_pack, {  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $target_name => {  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       flags => $flags,  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       compile => $filter,  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       run => $handler,  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    }  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   });  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub linestr_callback_rv2cv {  | 
| 
209
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
  
0
  
 | 
35
 | 
   my ($name, $offset) = @_;  | 
| 
210
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
   $offset += toke_move_past_token($offset);  | 
| 
211
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
   my $pack = get_curstash_name();  | 
| 
212
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
   my $flags = $declarators{$pack}{$name};  | 
| 
213
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
   my ($found_name, $found_proto);  | 
| 
214
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
55
 | 
   if ($flags & DECLARE_NAME) {  | 
| 
215
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     $offset += toke_skipspace($offset);  | 
| 
216
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     my $linestr = get_linestr();  | 
| 
217
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
42
 | 
     if (substr($linestr, $offset, 2) eq '::') {  | 
| 
218
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
       substr($linestr, $offset, 2) = '';  | 
| 
219
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
       set_linestr($linestr);  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
221
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
49
 | 
     if (my $len = toke_scan_word($offset, $flags & DECLARE_PACKAGE)) {  | 
| 
222
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
       $found_name = substr($linestr, $offset, $len);  | 
| 
223
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
       $offset += $len;  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
226
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
45
 | 
   if ($flags & DECLARE_PROTO) {  | 
| 
227
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     $offset += toke_skipspace($offset);  | 
| 
228
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     my $linestr = get_linestr();  | 
| 
229
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     if (substr($linestr, $offset, 1) eq '(') {  | 
| 
230
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
       my $length = toke_scan_str($offset);  | 
| 
231
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
       $found_proto = get_lex_stuff();  | 
| 
232
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
       clear_lex_stuff();  | 
| 
233
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
       my $replace =  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ($found_name ? ' ' : '=')  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         .'X'.(' ' x length($found_proto));  | 
| 
236
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
       $linestr = get_linestr();  | 
| 
237
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
       substr($linestr, $offset, $length) = $replace;  | 
| 
238
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
       set_linestr($linestr);  | 
| 
239
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
       $offset += $length;  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
242
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
   my @args = ($pack, $name, $pack, $found_name, $found_proto);  | 
| 
243
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
   $offset += toke_skipspace($offset);  | 
| 
244
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
   my $linestr = get_linestr();  | 
| 
245
 | 
17
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
66
 | 
   if (substr($linestr, $offset, 1) eq '{') {  | 
| 
246
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
     my $ret = init_declare(@args);  | 
| 
247
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     $offset++;  | 
| 
248
 | 
17
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
78
 | 
     if (defined $ret && length $ret) {  | 
| 
249
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
       substr($linestr, $offset, 0) = $ret;  | 
| 
250
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1569
 | 
       set_linestr($linestr);  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
253
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     init_declare(@args);  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #warn "linestr now ${linestr}";  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub linestr_callback_const {  | 
| 
259
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
  
0
  
 | 
40
 | 
   my ($name, $offset) = @_;  | 
| 
260
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
   my $pack = get_curstash_name();  | 
| 
261
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
   my $flags = $declarators{$pack}{$name};  | 
| 
262
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
70
 | 
   if ($flags & DECLARE_NAME) {  | 
| 
263
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
     $offset += toke_move_past_token($offset);  | 
| 
264
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     $offset += toke_skipspace($offset);  | 
| 
265
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
65
 | 
     if (toke_scan_word($offset, $flags & DECLARE_PACKAGE)) {  | 
| 
266
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
       my $linestr = get_linestr();  | 
| 
267
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
       substr($linestr, $offset, 0) = '::';  | 
| 
268
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
65
 | 
       set_linestr($linestr);  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub linestr_callback {  | 
| 
274
 | 
126
 | 
 
 | 
 
 | 
  
126
  
 | 
  
0
  
 | 
11077
 | 
   my $type = shift;  | 
| 
275
 | 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
201
 | 
   my $name = $_[0];  | 
| 
276
 | 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
337
 | 
   my $pack = get_curstash_name();  | 
| 
277
 | 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
246
 | 
   my $handlers = $declarator_handlers{$pack}{$name};  | 
| 
278
 | 
126
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
417
 | 
   if (ref $handlers eq 'CODE') {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
279
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
70
 | 
     my $meth = "linestr_callback_${type}";  | 
| 
280
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
200
 | 
     __PACKAGE__->can($meth)->(@_);  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (ref $handlers eq 'HASH') {  | 
| 
282
 | 
92
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
6718
 | 
     if ($handlers->{$type}) {  | 
| 
283
 | 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
289
 | 
       $handlers->{$type}->(@_);  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
286
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     die "PANIC: unknown thing in handlers for $pack $name: $handlers";  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Devel::Declare - Adding keywords to perl, in perl  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Method::Signatures;  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # or ...  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use MooseX::Declare;  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # etc.  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Use some new and exciting syntax like:  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   method hello (Str :$who, Int :$age where { $_ > 0 }) {  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->say("Hello ${who}, I am ${age} years old!");  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L can install subroutines called declarators which locally take  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 over Perl's parser, allowing the creation of new syntax.  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This document describes how to create a simple declarator.  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 WARNING  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =for comment mst wrote this warning for MooseX::Declare, and ether adapted it for here:  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B Devel::Declare is a giant bag of crack  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 originally implemented by mst with the goal of upsetting the perl core  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 developers so much by its very existence that they implemented proper  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 keyword handling in the core.  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 As of perl5 version 14, this goal has been achieved, and modules such  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 as L, L, and L provide  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 mechanisms to mangle perl syntax that don't require hallucinogenic  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 drugs to interpret the error messages they produce.  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If you are using something that uses Devel::Declare, please for the love  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 of kittens use something else:  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 4  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item *  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Instead of L, use L  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item *  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Instead of L, use  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L (requires perl 5.22) or L  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 USAGE  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We'll demonstrate the usage of C with a motivating example: a new  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C keyword, which acts like the builtin C, but automatically unpacks  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C<$self> and the other arguments.  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   package My::Methods;  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Devel::Declare;  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Creating a declarator with C  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You will typically create  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub import {  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $class = shift;  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $caller = caller;  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Devel::Declare->setup_for(  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $caller,  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         { method => { const => \&parser } }  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     no strict 'refs';  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     *{$caller.'::method'} = sub (&) {};  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Starting from the end of this import routine, you'll see that we're creating a  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subroutine called C in the caller's namespace.  Yes, that's just a normal  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subroutine, and it does nothing at all (yet!)  Note the prototype C<(&)> which means  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 that the caller would call it like so:  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method {  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my ($self, $arg1, $arg2) = @_;  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ...  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 However we want to be able to call it like this  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method foo ($arg1, $arg2) {  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ...  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 That's why we call C above, to register the declarator 'method' with a custom  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 parser, as per the next section.  It acts on an optype, usually C<'const'> as above.  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 (Other valid values are C<'check'> and C<'rv2cv'>).  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For a simpler way to install new methods, see also L  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Writing a parser subroutine  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This subroutine is called at I time, and allows you to read the custom  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 syntaxes that we want (in a syntax that may or may not be valid core Perl 5) and  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 munge it so that the result will be parsed by the C compiler.  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For this example, we're defining some globals for convenience:  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     our ($Declarator, $Offset);  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Then we define a parser subroutine to handle our declarator.  We'll look at this in  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 a few chunks.  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub parser {  | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       local ($Declarator, $Offset) = @_;  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C provides some very low level utility methods to parse character  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 strings.  We'll define some useful higher level routines below for convenience,  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 and we can use these to parse the various elements in our new syntax.  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Notice how our parser subroutine is invoked at compile time,  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 when the C parser is pointed just I the declarator name.  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       skip_declarator;          # step past 'method'  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $name = strip_name;    # strip out the name 'foo', if present  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $proto = strip_proto;  # strip out the prototype '($arg1, $arg2)', if present  | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Now we can prepare some code to 'inject' into the new subroutine.  For example we  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 might want the method as above to have C injected at  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the beginning of it.  We also do some clever stuff with scopes that we'll look  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 at shortly.  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $inject = make_proto_unwrap($proto);  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (defined $name) {  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $inject = scope_injector_call().$inject;  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       inject_if_block($inject);  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We've now managed to change C into C
 | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 injected_code; ... }>.  This will compile...  but we've lost the name of the  | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 method!  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 In a cute (or horrifying, depending on your perspective) trick, we temporarily  | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 change the definition of the subroutine C itself, to specialise it with  | 
| 
434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the C<$name> we stripped, so that it assigns the code block to that name.  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Even though the I time C is compiled, it will be  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 redefined again, C caches these definitions in its parse  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 tree, so we'll always get the right one!  | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Note that we also handle the case where there was no name, allowing  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 an anonymous method analogous to an anonymous subroutine.  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (defined $name) {  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $name = join('::', Devel::Declare::get_curstash_name(), $name)  | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           unless ($name =~ /::/);  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shadow(sub (&) { no strict 'refs'; *{$name} = shift; });  | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shadow(sub (&) { shift });  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
451
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Parser utilities in detail  | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For simplicity, we're using global variables like C<$Offset> in these examples.  | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You may prefer to look at L, which  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 encapsulates the context much more cleanly.  | 
| 
458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This simple parser just moves across a 'token'.  The common case is  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 to skip the declarator, i.e.  to move to the end of the string  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 'method' and before the prototype and code block.  | 
| 
464
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub skip_declarator {  | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $Offset += Devel::Declare::toke_move_past_token($Offset);  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin parser simply moves past a 'token' (matching C[a-zA-Z_]\w*/>)  | 
| 
472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 It takes an offset into the source document, and skips past the token.  | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 It returns the number of characters skipped.  | 
| 
474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This parser skips any whitespace, then scans the next word (again matching a  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 'token').  We can then analyse the current line, and manipulate it (using pure  | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Perl).  In this case we take the name of the method out, and return it.  | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub strip_name {  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       skipspace;  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (my $len = Devel::Declare::toke_scan_word($Offset, 1)) {  | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $linestr = Devel::Declare::get_linestr();  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $name = substr($linestr, $Offset, $len);  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         substr($linestr, $Offset, $len) = '';  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Devel::Declare::set_linestr($linestr);  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return $name;  | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return;  | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin parser, given an offset into the source document,  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 matches a 'token' as above but does not skip.  It returns the  | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 length of the token matched, if any.  | 
| 
498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin returns the full text of the current line of the source document.  | 
| 
502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
503
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin sets the full text of the current line of the source document.  | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Beware that injecting a newline into the middle of the line is likely  | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 to fail in surprising ways.  Generally, Perl's parser can rely on the  | 
| 
508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 `current line' actually being only a single line.  Use other kinds of  | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 whitespace instead, in the code that you inject.  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This parser skips whitsepace.  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub skipspace {  | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $Offset += Devel::Declare::toke_skipspace($Offset);  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
518
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin parser, given an offset into the source document,  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 skips over any whitespace, and returns the number of characters  | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 skipped.  | 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
526
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This is a more complex parser that checks if it's found something that  | 
| 
528
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 starts with C<'('> and returns everything till the matching C<')'>.  | 
| 
529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
530
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub strip_proto {  | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       skipspace;  | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
533
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $linestr = Devel::Declare::get_linestr();  | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (substr($linestr, $Offset, 1) eq '(') {  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $length = Devel::Declare::toke_scan_str($Offset);  | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $proto = Devel::Declare::get_lex_stuff();  | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Devel::Declare::clear_lex_stuff();  | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $linestr = Devel::Declare::get_linestr();  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         substr($linestr, $Offset, $length) = '';  | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Devel::Declare::set_linestr($linestr);  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return $proto;  | 
| 
542
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return;  | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin parser uses Perl's own parsing routines to match a "stringlike"  | 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 expression.  Handily, this includes bracketed expressions (just think about  | 
| 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 things like C).   | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Also it Does The Right Thing with nested delimiters (like C).   | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 It returns the effective length of the expression matched.  Really, what  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 it returns is the difference in position between where the string started,  | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 within the buffer, and where it finished.  If the string extended across  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 multiple lines then the contents of the buffer may have been completely  | 
| 
558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 replaced by the new lines, so this position difference is not the same  | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 thing as the actual length of the expression matched.  However, because  | 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 moving backward in the buffer causes problems, the function arranges  | 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 for the effective length to always be positive, padding the start of  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the buffer if necessary.  | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Use C to get the actual matched text, the content of  | 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the string.  Because of the behaviour around multiline strings, you  | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 can't reliably get this from the buffer.  In fact, after the function  | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 returns, you can't rely on any content of the buffer preceding the end  | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 of the string.  | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If the string being scanned is not well formed (has no closing delimiter),  | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C returns C.  In this case you cannot rely on the  | 
| 
572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 contents of the buffer.  | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This builtin returns what was matched by C.  To avoid segfaults,  | 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 you should call C immediately afterwards.  | 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
579
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Munging the subroutine  | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
581
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Let's look at what we need to do in detail.  | 
| 
582
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
584
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
585
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We may have defined our method in different ways, which will result  | 
| 
586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 in a different value for our prototype, as parsed above.  For example:  | 
| 
587
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
588
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method foo         {  # undefined  | 
| 
589
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method foo ()      {  # ''  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method foo ($arg1) {  # '$arg1'  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
592
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We deal with them as follows, and return the appropriate C  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 string.  | 
| 
594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
595
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub make_proto_unwrap {  | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my ($proto) = @_;  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $inject = 'my ($self';  | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (defined $proto) {  | 
| 
599
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $inject .= ", $proto" if length($proto);  | 
| 
600
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $inject .= ') = @_; ';  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $inject .= ') = shift;';  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       return $inject;  | 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
606
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Now we need to inject it after the opening C<'{'> of the method body.  | 
| 
610
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We can do this with the building blocks we defined above like C  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 and C.  | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub inject_if_block {  | 
| 
614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $inject = shift;  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       skipspace;  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $linestr = Devel::Declare::get_linestr;  | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if (substr($linestr, $Offset, 1) eq '{') {  | 
| 
618
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         substr($linestr, $Offset+1, 0) = $inject;  | 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Devel::Declare::set_linestr($linestr);  | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
624
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We want to be able to handle both named and anonymous methods.  i.e.  | 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method foo () { ... }  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $meth = method () { ... };  | 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
630
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 These will then get rewritten as  | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     method { ... }  | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $meth = method { ... };  | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
635
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 where 'method' is a subroutine that takes a code block.  Spot the problem?  | 
| 
636
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The first one doesn't have a semicolon at the end of it!  Unlike 'sub' which  | 
| 
637
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is a builtin, this is just a normal statement, so we need to terminate it.  | 
| 
638
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Luckily, using C, we can do this!  | 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use B::Hooks::EndOfScope;  | 
| 
641
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
642
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We'll add this to what gets 'injected' at the beginning of the method source.  | 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub scope_injector_call {  | 
| 
645
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return ' BEGIN { MethodHandlers::inject_scope }; ';  | 
| 
646
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 So at the beginning of every method, we are passing a callback that will get invoked  | 
| 
649
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 at the I of the method's compilation... i.e. exactly then the closing C<'}'>  | 
| 
650
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is compiled.  | 
| 
651
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub inject_scope {  | 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     on_scope_end {  | 
| 
654
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $linestr = Devel::Declare::get_linestr;  | 
| 
655
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $offset = Devel::Declare::get_linestr_offset;  | 
| 
656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       substr($linestr, $offset, 0) = ';';  | 
| 
657
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       Devel::Declare::set_linestr($linestr);  | 
| 
658
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Shadowing each method.  | 
| 
662
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
663
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head3 C  | 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 We override the current definition of 'method' using C.  | 
| 
666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub shadow {  | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       my $pack = Devel::Declare::get_curstash_name;  | 
| 
669
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       Devel::Declare::shadow_sub("${pack}::${Declarator}", $_[0]);  | 
| 
670
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
671
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
672
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For a named method we invoked like this:  | 
| 
673
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
674
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     shadow(sub (&) { no strict 'refs'; *{$name} = shift; });  | 
| 
675
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 So in the case of a C, this call would redefine C  | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 to be a subroutine that exports 'sub foo' as the (munged) contents of C<{...}>.  | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The case of an anonymous method is also cute:  | 
| 
680
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
681
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     shadow(sub (&) { shift });  | 
| 
682
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
683
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This means that  | 
| 
684
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
685
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $meth = method () { ... };  | 
| 
686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is rewritten with C taking the codeblock, and returning it as is to become  | 
| 
688
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the value of C<$meth>.  | 
| 
689
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
690
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
691
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
692
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This returns the package name I.  | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
694
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head4 C  | 
| 
695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
696
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Handles the details of redefining the subroutine.  | 
| 
697
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SEE ALSO  | 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 One of the best ways to learn C is still to look at  | 
| 
701
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 modules that use it:  | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L.  | 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 AUTHORS  | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Matt S Trout - Emst@shadowcat.co.ukE - original author  | 
| 
708
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Company: http://www.shadowcat.co.uk/  | 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Blog: http://chainsawblues.vox.com/  | 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
712
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Florian Ragwitz Erafl@debian.orgE - maintainer  | 
| 
713
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 osfameron Eosfameron@cpan.orgE - first draft of documentation  | 
| 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 COPYRIGHT AND LICENSE  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This library is free software under the same terms as perl itself  | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Copyright (c) 2007, 2008, 2009  Matt S Trout  | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Copyright (c) 2008, 2009  Florian Ragwitz  | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 stolen_chunk_of_toke.c based on toke.c from the perl core, which is  | 
| 
725
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,  | 
| 
727
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others  | 
| 
728
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
729
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
730
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
731
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  |