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