1Devel::Declare(3)     User Contributed Perl Documentation    Devel::Declare(3)
2
3
4

NAME

6       Devel::Declare - Adding keywords to perl, in perl
7

SYNOPSIS

9         use Method::Signatures;
10         # or ...
11         use MooseX::Declare;
12         # etc.
13
14         # Use some new and exciting syntax like:
15         method hello (Str :$who, Int :$age where { $_ > 0 }) {
16           $self->say("Hello ${who}, I am ${age} years old!");
17         }
18

DESCRIPTION

20       Devel::Declare can install subroutines called declarators which locally
21       take over Perl's parser, allowing the creation of new syntax.
22
23       This document describes how to create a simple declarator.
24

USAGE

26       We'll demonstrate the usage of "Devel::Declare" with a motivating
27       example: a new "method" keyword, which acts like the builtin "sub", but
28       automatically unpacks $self and the other arguments.
29
30         package My::Methods;
31         use Devel::Declare;
32
33   Creating a declarator with "setup_for"
34       You will typically create
35
36         sub import {
37           my $class = shift;
38           my $caller = caller;
39
40           Devel::Declare->setup_for(
41               $caller,
42               { method => { const => \&parser } }
43           );
44           no strict 'refs';
45           *{$caller.'::method'} = sub (&) {};
46         }
47
48       Starting from the end of this import routine, you'll see that we're
49       creating a subroutine called "method" in the caller's namespace.  Yes,
50       that's just a normal subroutine, and it does nothing at all (yet!)
51       Note the prototype "(&)" which means that the caller would call it like
52       so:
53
54           method {
55               my ($self, $arg1, $arg2) = @_;
56               ...
57           }
58
59       However we want to be able to call it like this
60
61           method foo ($arg1, $arg2) {
62               ...
63           }
64
65       That's why we call "setup_for" above, to register the declarator
66       'method' with a custom parser, as per the next section.  It acts on an
67       optype, usually 'const' as above.  (Other valid values are 'check' and
68       'rv2cv').
69
70       For a simpler way to install new methods, see also
71       Devel::Declare::MethodInstaller::Simple
72
73   Writing a parser subroutine
74       This subroutine is called at compilation time, and allows you to read
75       the custom syntaxes that we want (in a syntax that may or may not be
76       valid core Perl 5) and munge it so that the result will be parsed by
77       the "perl" compiler.
78
79       For this example, we're defining some globals for convenience:
80
81           our ($Declarator, $Offset);
82
83       Then we define a parser subroutine to handle our declarator.  We'll
84       look at this in a few chunks.
85
86           sub parser {
87             local ($Declarator, $Offset) = @_;
88
89       "Devel::Declare" provides some very low level utility methods to parse
90       character strings.  We'll define some useful higher level routines
91       below for convenience, and we can use these to parse the various
92       elements in our new syntax.
93
94       Notice how our parser subroutine is invoked at compile time, when the
95       "perl" parser is pointed just before the declarator name.
96
97             skip_declarator;          # step past 'method'
98             my $name = strip_name;    # strip out the name 'foo', if present
99             my $proto = strip_proto;  # strip out the prototype '($arg1, $arg2)', if present
100
101       Now we can prepare some code to 'inject' into the new subroutine.  For
102       example we might want the method as above to have "my ($self, $arg1,
103       $arg2) = @_" injected at the beginning of it.  We also do some clever
104       stuff with scopes that we'll look at shortly.
105
106             my $inject = make_proto_unwrap($proto);
107             if (defined $name) {
108               $inject = scope_injector_call().$inject;
109             }
110             inject_if_block($inject);
111
112       We've now managed to change "method ($arg1, $arg2) { ... }" into
113       "method { injected_code; ... }".  This will compile...  but we've lost
114       the name of the method!
115
116       In a cute (or horrifying, depending on your perspective) trick, we
117       temporarily change the definition of the subroutine "method" itself, to
118       specialise it with the $name we stripped, so that it assigns the code
119       block to that name.
120
121       Even though the next time "method" is compiled, it will be redefined
122       again, "perl" caches these definitions in its parse tree, so we'll
123       always get the right one!
124
125       Note that we also handle the case where there was no name, allowing an
126       anonymous method analogous to an anonymous subroutine.
127
128             if (defined $name) {
129               $name = join('::', Devel::Declare::get_curstash_name(), $name)
130                 unless ($name =~ /::/);
131               shadow(sub (&) { no strict 'refs'; *{$name} = shift; });
132             } else {
133               shadow(sub (&) { shift });
134             }
135           }
136
137   Parser utilities in detail
138       For simplicity, we're using global variables like $Offset in these
139       examples.  You may prefer to look at Devel::Declare::Context::Simple,
140       which encapsulates the context much more cleanly.
141
142       "skip_declarator"
143
144       This simple parser just moves across a 'token'.  The common case is to
145       skip the declarator, i.e.  to move to the end of the string 'method'
146       and before the prototype and code block.
147
148           sub skip_declarator {
149             $Offset += Devel::Declare::toke_move_past_token($Offset);
150           }
151
152       "toke_move_past_token"
153
154       This builtin parser simply moves past a 'token' (matching
155       "/[a-zA-Z_]\w*/") It takes an offset into the source document, and
156       skips past the token.  It returns the number of characters skipped.
157
158       "strip_name"
159
160       This parser skips any whitespace, then scans the next word (again
161       matching a 'token').  We can then analyse the current line, and
162       manipulate it (using pure Perl).  In this case we take the name of the
163       method out, and return it.
164
165           sub strip_name {
166             skipspace;
167             if (my $len = Devel::Declare::toke_scan_word($Offset, 1)) {
168               my $linestr = Devel::Declare::get_linestr();
169               my $name = substr($linestr, $Offset, $len);
170               substr($linestr, $Offset, $len) = '';
171               Devel::Declare::set_linestr($linestr);
172               return $name;
173             }
174             return;
175           }
176
177       "toke_scan_word"
178
179       This builtin parser, given an offset into the source document, matches
180       a 'token' as above but does not skip.  It returns the length of the
181       token matched, if any.
182
183       "get_linestr"
184
185       This builtin returns the full text of the current line of the source
186       document.
187
188       "set_linestr"
189
190       This builtin sets the full text of the current line of the source
191       document.
192
193       "skipspace"
194
195       This parser skips whitsepace.
196
197           sub skipspace {
198             $Offset += Devel::Declare::toke_skipspace($Offset);
199           }
200
201       "toke_skipspace"
202
203       This builtin parser, given an offset into the source document, skips
204       over any whitespace, and returns the number of characters skipped.
205
206       "strip_proto"
207
208       This is a more complex parser that checks if it's found something that
209       starts with '(' and returns everything till the matching ')'.
210
211           sub strip_proto {
212             skipspace;
213
214             my $linestr = Devel::Declare::get_linestr();
215             if (substr($linestr, $Offset, 1) eq '(') {
216               my $length = Devel::Declare::toke_scan_str($Offset);
217               my $proto = Devel::Declare::get_lex_stuff();
218               Devel::Declare::clear_lex_stuff();
219               $linestr = Devel::Declare::get_linestr();
220               substr($linestr, $Offset, $length) = '';
221               Devel::Declare::set_linestr($linestr);
222               return $proto;
223             }
224             return;
225           }
226
227       "toke_scan_str"
228
229       This builtin parser uses Perl's own parsing routines to match a
230       "stringlike" expression.  Handily, this includes bracketed expressions
231       (just think about things like "q(this is a quote)").
232
233       Also it Does The Right Thing with nested delimiters (like "q(this (is
234       (a) quote))").
235
236       It returns the effective length of the expression matched.  Really,
237       what it returns is the difference in position between where the string
238       started, within the buffer, and where it finished.  If the string
239       extended across multiple lines then the contents of the buffer may have
240       been completely replaced by the new lines, so this position difference
241       is not the same thing as the actual length of the expression matched.
242       However, because moving backward in the buffer causes problems, the
243       function arranges for the effective length to always be positive,
244       padding the start of the buffer if necessary.
245
246       Use "get_lex_stuff" to get the actual matched text, the content of the
247       string.  Because of the behaviour around multiline strings, you can't
248       reliably get this from the buffer.  In fact, after the function
249       returns, you can't rely on any content of the buffer preceding the end
250       of the string.
251
252       If the string being scanned is not well formed (has no closing
253       delimiter), "toke_scan_str" returns "undef".  In this case you cannot
254       rely on the contents of the buffer.
255
256       "get_lex_stuff"
257
258       This builtin returns what was matched by "toke_scan_str".  To avoid
259       segfaults, you should call "clear_lex_stuff" immediately afterwards.
260
261   Munging the subroutine
262       Let's look at what we need to do in detail.
263
264       "make_proto_unwrap"
265
266       We may have defined our method in different ways, which will result in
267       a different value for our prototype, as parsed above.  For example:
268
269           method foo         {  # undefined
270           method foo ()      {  # ''
271           method foo ($arg1) {  # '$arg1'
272
273       We deal with them as follows, and return the appropriate "my ($self,
274       ...) = @_;" string.
275
276           sub make_proto_unwrap {
277             my ($proto) = @_;
278             my $inject = 'my ($self';
279             if (defined $proto) {
280               $inject .= ", $proto" if length($proto);
281               $inject .= ') = @_; ';
282             } else {
283               $inject .= ') = shift;';
284             }
285             return $inject;
286           }
287
288       "inject_if_block"
289
290       Now we need to inject it after the opening '{' of the method body.  We
291       can do this with the building blocks we defined above like "skipspace"
292       and "get_linestr".
293
294           sub inject_if_block {
295             my $inject = shift;
296             skipspace;
297             my $linestr = Devel::Declare::get_linestr;
298             if (substr($linestr, $Offset, 1) eq '{') {
299               substr($linestr, $Offset+1, 0) = $inject;
300               Devel::Declare::set_linestr($linestr);
301             }
302           }
303
304       "scope_injector_call"
305
306       We want to be able to handle both named and anonymous methods.  i.e.
307
308           method foo () { ... }
309           my $meth = method () { ... };
310
311       These will then get rewritten as
312
313           method { ... }
314           my $meth = method { ... };
315
316       where 'method' is a subroutine that takes a code block.  Spot the
317       problem?  The first one doesn't have a semicolon at the end of it!
318       Unlike 'sub' which is a builtin, this is just a normal statement, so we
319       need to terminate it.  Luckily, using "B::Hooks::EndOfScope", we can do
320       this!
321
322         use B::Hooks::EndOfScope;
323
324       We'll add this to what gets 'injected' at the beginning of the method
325       source.
326
327         sub scope_injector_call {
328           return ' BEGIN { MethodHandlers::inject_scope }; ';
329         }
330
331       So at the beginning of every method, we are passing a callback that
332       will get invoked at the end of the method's compilation... i.e. exactly
333       then the closing '}' is compiled.
334
335         sub inject_scope {
336           on_scope_end {
337             my $linestr = Devel::Declare::get_linestr;
338             my $offset = Devel::Declare::get_linestr_offset;
339             substr($linestr, $offset, 0) = ';';
340             Devel::Declare::set_linestr($linestr);
341           };
342         }
343
344   Shadowing each method.
345       "shadow"
346
347       We override the current definition of 'method' using "shadow".
348
349           sub shadow {
350             my $pack = Devel::Declare::get_curstash_name;
351             Devel::Declare::shadow_sub("${pack}::${Declarator}", $_[0]);
352           }
353
354       For a named method we invoked like this:
355
356           shadow(sub (&) { no strict 'refs'; *{$name} = shift; });
357
358       So in the case of a "method foo { ... }", this call would redefine
359       "method" to be a subroutine that exports 'sub foo' as the (munged)
360       contents of "{...}".
361
362       The case of an anonymous method is also cute:
363
364           shadow(sub (&) { shift });
365
366       This means that
367
368           my $meth = method () { ... };
369
370       is rewritten with "method" taking the codeblock, and returning it as is
371       to become the value of $meth.
372
373       "get_curstash_name"
374
375       This returns the package name currently being compiled.
376
377       "shadow_sub"
378
379       Handles the details of redefining the subroutine.
380

SEE ALSO

382       One of the best ways to learn "Devel::Declare" is still to look at
383       modules that use it:
384
385       http://cpants.perl.org/dist/used_by/Devel-Declare
386       <http://cpants.perl.org/dist/used_by/Devel-Declare>.
387

AUTHORS

389       Matt S Trout - <mst@shadowcat.co.uk> - original author
390
391       Company: http://www.shadowcat.co.uk/ Blog:
392       http://chainsawblues.vox.com/
393
394       Florian Ragwitz <rafl@debian.org> - maintainer
395
396       osfameron <osfameron@cpan.org> - first draft of documentation
397
399       This library is free software under the same terms as perl itself
400
401       Copyright (c) 2007, 2008, 2009  Matt S Trout
402
403       Copyright (c) 2008, 2009  Florian Ragwitz
404
405       stolen_chunk_of_toke.c based on toke.c from the perl core, which is
406
407       Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
408       2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
409
410
411
412perl v5.12.4                      2011-09-12                 Devel::Declare(3)
Impressum