File Coverage

blib/lib/XS/Parse/Sublike.pm
Criterion Covered Total %
statement 5 5 100.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 7 7 100.0


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2020-2021 -- leonerd@leonerd.org.uk
5              
6             package XS::Parse::Sublike 0.21;
7              
8 22     22   4657081 use v5.14;
  22         197  
9 22     22   123 use warnings;
  22         55  
  22         2460  
10              
11             require XSLoader;
12             XSLoader::load( __PACKAGE__, our $VERSION );
13              
14             =encoding UTF-8
15              
16             =head1 NAME
17              
18             C<XS::Parse::Sublike> - XS functions to assist in parsing C<sub>-like syntax
19              
20             =head1 DESCRIPTION
21              
22             This module provides some XS functions to assist in writing parsers for
23             C<sub>-like syntax, primarily for authors of keyword plugins using the
24             C<PL_keyword_plugin> hook mechanism. It is unlikely to be of much use to
25             anyone else; and highly unlikely to be any use when writing perl code using
26             these. Unless you are writing a keyword plugin using XS, this module is not
27             for you.
28              
29             This module is also currently experimental, and the design is still evolving
30             and subject to change. Later versions may break ABI compatibility, requiring
31             changes or at least a rebuild of any module that depends on it.
32              
33             =head1 XS FUNCTIONS
34              
35             =head2 boot_xs_parse_sublike
36              
37             void boot_xs_parse_sublike(double ver)
38              
39             Call this function from your C<BOOT> section in order to initialise the module
40             and parsing hooks.
41              
42             I<ver> should either be 0 or a decimal number for the module version
43             requirement; e.g.
44              
45             boot_xs_parse_sublike(0.04);
46              
47             =head2 xs_parse_sublike
48              
49             int xs_parse_sublike(const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr)
50              
51             This function performs the actual parsing of a C<sub>-like keyword. It expects
52             the lexer to be at a position just after the introduction keyword has been
53             consumed, and will proceed to parse an optional name, list of attributes,
54             signature (if enabled by C<use feature 'signatures'>), and code body. The
55             return value and C<op_ptr> can be used directly from the keyword plugin
56             function. It is intended this function be invoked from it, and the result
57             returned directly.
58              
59             For a more automated handling of keywords, see L</register_xs_parse_sublike>.
60              
61             I<hooks> should be a structure that can provide optional function pointers
62             used to customise the parsing process at various stages. I<hookdata> is an
63             opaque pointer which is passed through to each of the hook stage functions.
64              
65             =head2 register_xs_parse_sublike
66              
67             void register_xs_parse_sublike(const char *keyword,
68             const struct XSParseSublikeHooks *hooks, void *hookdata)
69              
70             This function installs a set of parsing hooks to be associated with the given
71             keyword. Such a keyword will then be handled automatically by a keyword parser
72             installed by C<XS::Parse::Sublike> itself.
73              
74             When the keyword is encountered, the hook's C<permit> function is first tested
75             to see if the keyword is permitted at this point. If the function returns true
76             then the keyword is consumed and parsed as per L</xs_parse_sublike>.
77              
78             I<hookdata> is an opaque pointer which is passed through to each of the hook
79             stage functions when they are invoked.
80              
81             =head2 xs_parse_sublike_any
82              
83             int xs_parse_sublike_any(const struct XSParseSublikeHooks *hooks, void *hookdata,
84             OP **op_ptr)
85              
86             This function expects to consume an introduction keyword at the lexer position
87             which is either C<sub> or the name of another C<sub>-like keyword, which has
88             been previously registered using L</register_xs_parse_sublike>. It then
89             proceeds to parse the subsequent syntax similar to how it would have parsed if
90             encountered by the module's own keyword parser plugin, except that the second
91             set of hooks given here also take effect.
92              
93             If a regular C<sub> is encountered, then this is parsed using the I<hooks> in
94             a similar way to C<xs_parse_sublike()>.
95              
96             If a different registered C<sub>-like keyword is encountered, then parsing is
97             performed using B<both> sets of hooks - the ones given to this function as
98             well as the ones registered with the keyword. This allows their effects to
99             combined. The hooks given by the I<hooks> argument are considered to be on the
100             "outside" from those of the registered keyword "inside". The outside ones run
101             first for all stages, except C<pre_blockend> which runs them inside-out.
102              
103             I<hookdata> is an opaque pointer which is passed through to each of the hook
104             stage functions when they are invoked.
105              
106             Note that this function is now vaguely discouraged, in favour of using a
107             prefixing keyword instead, by using the C<XS_PARSE_SUBLIKE_FLAG_PREFIX> flag.
108              
109             =head1 PARSE CONTEXT
110              
111             The various hook stages all share state about the ongoing parse process using
112             various fields of the C<XSParseSublikeContext> structure.
113              
114             struct XSParseSublikeContext {
115             SV *name;
116             OP *attrs;
117             OP *body;
118             CV *cv;
119             U32 actions;
120             HV *moddata;
121             }
122              
123             The C<actions> field will contain a bitmask of action flags that control the
124             various steps that C<XS::Parse::Sublike> might take inbetween invoking hook
125             stages. The initial value of this field is set after the name-parsing stage,
126             depending on whether or not a name is found. Stage hook functions may modify
127             the field to adjust the subsequent behaviour.
128              
129             At the current ABI version, a module will have to set the
130             C<XS_PARSE_SUBLIKE_COMPAT_FLAG_DYNAMIC_ACTIONS> bit of the C<flags> field in
131             order to make use of the I<actions> field. A future ABI version may remove
132             this restriction.
133              
134             =over 4
135              
136             =item XS_PARSE_SUBLIKE_ACTION_CVf_ANON
137              
138             If set, the C<start_subparse()> call will be set up for an anonymous function
139             protosub; if not it will be set for a named function. This is set by default
140             if a name was not found.
141              
142             =item XS_PARSE_SUBLIKE_ACTION_SET_CVNAME
143              
144             If set, the newly-constructed CV will have the given name set on it. This is
145             set by default if a name was found.
146              
147             On Perl versions 5.22 and above, this flag can be set even if
148             C<XS_PARSE_SUBLIKE_ACTION_INSTALL_SYMBOL> is not. In this case, the CV will
149             not be reachable via the symbol table, even though it knows its own name and
150             pretends that it is. On earlier versions of perl this flag will be ignored in
151             that case.
152              
153             =item XS_PARSE_SUBLIKE_ACTION_INSTALL_SYMBOL
154              
155             If set, the newly-constructed CV will be installed into the symbol table at
156             its given name. Note that it is not possible to enable this flag without also
157             enabling C<XS_PARSE_SUBLIKE_ACTION_SET_CVNAME>. This is set by default if a
158             name was found.
159              
160             =item XS_PARSE_SUBLIKE_ACTION_REFGEN_ANONCODE
161              
162             If set, the syntax will yield the C<OP_REFGEN> / C<OP_ANONCODE> optree
163             fragment typical of anonymous code expressions; if not it will be C<OP_NULL>.
164             This is set by default if a name was not found.
165              
166             =item XS_PARSE_SUBLIKE_ACTION_RET_EXPR
167              
168             If set, the syntax will parse like an expression; if not it will parse like a
169             statement. This is set by default if a name was not found.
170              
171             =back
172              
173             The I<moddata> field will point towards an HV that modules can used to store
174             extra data between stages. As a naming convention a module should prefix its
175             keys with its own module name and a slash character, C<"Some::Module/field">.
176             The field will point to a newly-created HV for every parse invocation, and
177             will be released when each parse is complete.
178              
179             =head1 PARSE HOOKS
180              
181             The C<XSParseSublikeHooks> structure provides the following hook stages, which
182             are invoked in the given order.
183              
184             The structure has a I<flags> field, which controls various optional parts of
185             operation. The following flags are defined.
186              
187             =over 4
188              
189             =item XS_PARSE_SUBLIKE_FLAG_FILTERATTRS
190              
191             If set, the optional C<filter_attr> stage will be invoked.
192              
193             =item XS_PARSE_SUBLIKE_FLAG_BODY_OPTIONAL
194              
195             If B<not> set, the I<require_parts> field will imply the
196             C<XS_PARSE_SUBLIKE_PART_BODY> flag, making the body part required. By setting
197             this flag this will no longer happen. If all hooks agree, then the body will
198             become optional.
199              
200             =item XS_PARSE_SUBLIKE_FLAG_PREFIX
201              
202             If set, the keyword is considered to be a prefix that can be placed in front
203             of C<sub> or another sub-like keyword, to add its set of hooks in addition to
204             those of the following keyword. These prefices may be further stacked.
205              
206             =back
207              
208             In addition there are two C<U8> fields named I<require_parts> and
209             I<skip_parts> which control the behaviour of various parts of the syntax which
210             are usually optional. Any parts with bits set in I<require_parts> become
211             non-optional, and an error if they are missing. Any parts with bits set in
212             I<skip_parts> will skip the relevant part of the parsing process.
213              
214             When multiple sets of hooks are combined by the C<xs_parse_sublike_any>
215             function, or as part of parsing prefixing keywords, these bitmasks are
216             accumulated together with inclusive or. Any part required by any set of hooks
217             will still be required; any step skipped by either will be skipped entirely.
218              
219             If the same bit is set in both fields then the relevant parsing step will not
220             be performed but it will still be an error for that section to be missing.
221             This is likely not useful.
222              
223             Note that for skipped parts, only the actual parsing steps are skipped. A hook
224             function can still set the relevant fields in the context structure anyway to
225             force a particular value for those parts.
226              
227             =over 4
228              
229             =item XS_PARSE_SUBLIKE_PART_NAME
230              
231             The name of the function.
232              
233             =item XS_PARSE_SUBLIKE_PART_ATTRS
234              
235             The attributes of the function.
236              
237             This part can be skipped, but the bit is ignored when in I<require_parts>. It
238             is always permitted to not provide any additional attributes to a function
239             definition.
240              
241             =item XS_PARSE_SUBLIKE_PART_SIGNATURE
242              
243             The parameter signature of the function.
244              
245             This part can be skipped, but it is always permitted not to provide a
246             signature for a function definition even if the bit it set in
247             I<require_parts>. This is because such syntax only applies when
248             C<use feature 'signatures'> is in effect, and only on supporting perl
249             versions.
250              
251             However, setting the bit in I<require_parts> instead has the effect of
252             enabling C<use feature 'signatures'> (at least on supporting perl versions),
253             thus permitting the syntax to use a signature even if the signatures feature
254             was not previously enabled.
255              
256             =item XS_PARSE_SUBLIKE_PART_BODY
257              
258             The actual body of the function, expressed as a brace-delimited block.
259              
260             This part cannot be skipped, but it can be made optional by omitting it from
261             the I<require_parts> field. Instead of the block, it is permitted to place a
262             single semicolon (C<;>) to act as a statement terminator; thus giving the same
263             syntax as a subroutine forward declaration.
264              
265             In this case, the C<body> and C<cv> fields of the context structure will
266             remain C<NULL>.
267              
268             This flag is currently implied on the I<require_parts> field if the hook does
269             not supply the C<XS_PARSE_SUBLIKE_FLAG_BODY_OPTIONAL> flag; meaning that most
270             use-cases will make it a required part.
271              
272             =back
273              
274             =head2 The C<permit> Stage
275              
276             const char *permit_hintkey
277             bool (*permit)(pTHX_ void *hookdata)
278              
279             Called by the installed keyword parser hook which is used to handle keywords
280             registered by L</register_xs_parse_sublike>.
281              
282             As a shortcut for the common case, the C<permit_hintkey> may point to a string
283             to look up from the hints hash. If the given key name is not found in the
284             hints hash then the keyword is not permitted. If the key is present then the
285             C<permit> function is invoked as normal.
286              
287             If not rejected by a hint key that was not found in the hints hash, the
288             function part of the stage is called next and should inspect whether the
289             keyword is permitted at this time perhaps by inspecting other lexical clues,
290             and return true only if the keyword is permitted.
291              
292             Both the string and the function are optional. Either or both may be present.
293             If neither is present then the keyword is always permitted - which is likely
294             not what you wanted to do.
295              
296             =head2 Parse Name
297              
298             At this point, the optional name is parsed and filled into the C<name> field
299             of the context.
300              
301             =head2 The C<pre_subparse> Stage
302              
303             void (*pre_subparse)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata)
304              
305             Invoked just before C<start_subparse()> is called.
306              
307             =head2 Parse Attrs
308              
309             At this point the optional sub attributes are parsed and filled into the
310             C<attrs> field of the context, then C<block_start()> is called.
311              
312             =head2 The optional C<filter_attr> Stage
313              
314             bool (*filter_attr)(pTHX_ struct XSParseSublikeContext *ctx,
315             SV *attr, SV *val, void *hookdata);
316              
317             If the I<flags> field includes C<XS_PARSE_SUBLIKE_FLAG_FILTERATTRS> then each
318             individual attribute is passed through this optional filter function
319             immediately as each is parsed. I<attr> will be a string SV containing the name
320             of the attribute, and I<val> will either be C<NULL>, or a string SV containing
321             the contents of the parens after its name (without the parens themselves).
322              
323             If the filter returns C<true>, it indicates that it has in some way handled
324             the attribute and it should not be added to the list given to C<newATTRSUB()>.
325             If the filter returns C<false> it will be handled in the usual way; equivalent
326             to the case where the filter function did not exist.
327              
328             =head2 The C<post_blockstart> Stage
329              
330             void (*post_blockstart)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata)
331              
332             Invoked after the C<block_start()> function has been called. This hook stage
333             may wish to perform any alterations of C<PL_compcv> or related, inspect or
334             alter the lexical pad, provide hints hash values, or any other tasks before
335             the signature and code body are parsed.
336              
337             =head2 Parse Body
338              
339             At this point, the main body of the function is parsed and the optree is
340             stored in the C<body> field of the context. If the perl version supports sub
341             signatures and they are enabled and found, the body will be prefixed with the
342             signature ops as well.
343              
344             =head2 The C<pre_blockend> Stage
345              
346             void (*pre_blockend)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata)
347              
348             Invoked just before the C<block_end()> function is invoked. The hook stage may
349             wish to inspect or alter the optree stored in the C<body> context field.
350              
351             =head2 The C<post_newcv> Stage
352              
353             void (*post_newcv)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata)
354              
355             Invoked just after C<newATTRSUB()> has been invoked on the optree. The hook
356             stage may wish to inspect or alter the CV stored in the C<cv> context field.
357              
358             =cut
359              
360             =head1 AUTHOR
361              
362             Paul Evans <leonerd@leonerd.org.uk>
363              
364             =cut
365              
366             0x55AA;