File Coverage

blib/lib/Optree/Generate.pm
Criterion Covered Total %
statement 19 31 61.2
branch 1 6 16.6
condition 0 7 0.0
subroutine 7 8 87.5
pod 1 1 100.0
total 28 53 52.8


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, 2023 -- leonerd@leonerd.org.uk
5              
6             package Optree::Generate 0.07;
7              
8 11     11   1689 use v5.26; # XS code needs op_class() and the OPclass_* constants
  11         38  
9 11     11   64 use warnings;
  11         20  
  11         567  
10              
11             BEGIN {
12 11     11   63 require XSLoader;
13 11         6469 XSLoader::load( __PACKAGE__, our $VERSION );
14             }
15              
16             BEGIN {
17 11 50   11   270 if( $^V ge v5.36 ) {
18 0         0 warnings->unimport(qw( experimental::builtin ));
19 0         0 builtin->import(qw( blessed reftype ));
20             }
21             else {
22 11         67 require Scalar::Util;
23 11         929 Scalar::Util->import(qw( blessed reftype ));
24             }
25             }
26              
27             require B; # for the B::OP classes
28              
29 11     11   125 use Exporter 'import';
  11         34  
  11         1437  
30             push our @EXPORT_OK, qw(
31             opcode
32             op_contextualize
33             op_scope
34             newOP
35             newASSIGNOP
36             newBINOP
37             newCONDOP
38             newFOROP
39             newGVOP
40             newLISTOP
41             newLOGOP
42             newPADxVOP
43             newSVOP
44             newUNOP
45             make_entersub_op
46             );
47              
48             =head1 NAME
49              
50             C - helper functions for creating optree fragments from Perl
51              
52             =head1 DESCRIPTION
53              
54             This module provides helper functions to allow Perl code to get access to
55             various parts of the C-level API that would be useful when building optrees,
56             such as when parsing and implementing code behind custom keywords. It is
57             mostly intended for use with L and
58             L.
59              
60             =cut
61              
62             =head1 FUNCTIONS
63              
64             =head2 opcode
65              
66             $type = opcode( $opname );
67              
68             Returns an opcode integer corresponding to the given op name, which should be
69             lowercase and without the leading C prefix. As this involves a linear
70             search across the entire C array you may wish to perform this just
71             once and store the result, perhaps using C for convenience.
72              
73             use constant OP_CONST => opcode("const");
74              
75             =head2 op_contextualize
76              
77             $op = op_contextualize( $op, $context );
78              
79             Applies a syntactic context to an optree representing an expression.
80             C<$context> must be one of the exported constants C, C, or
81             C.
82              
83             =head2 op_scope
84              
85             $op = op_scope( $op );
86              
87             Wraps an optree with some additional ops so that a runtime dynamic scope will
88             created.
89              
90             =head2 new*OP
91              
92             This family of functions return a new OP of the given class, for the type,
93             flags, and other arguments specified.
94              
95             A suitable C<$type> can be obtained by using the L function.
96              
97             C<$flags> contains the opflags; a bitmask of the following constants.
98              
99             OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST
100             OPf_KIDS
101             OPf_PARENS
102             OPf_REF
103             OPf_MOD
104             OPf_STACKED
105             OPf_SPECIAL
106              
107             The op is returned as a C instance or a subclass thereof.
108              
109             These functions can only be called during the compilation time of a perl
110             subroutine. This is unlikely to be happening most of the time, except during
111             the C phase of a keyword registered using C or the
112             C phase of an infix operator registered using C.
113              
114             =head3 newOP
115              
116             $op = newOP( $type, $flags );
117              
118             Returns a new base OP for the given type and flags.
119              
120             =head3 newASSIGNOP
121              
122             $op = newASSIGNOP( $flags, $left, $optype, $right );
123              
124             Returns a new op representing an assignment operation from the right to the
125             left OP child of the given type. Note the odd order of arguments.
126              
127             =head3 newBINOP
128              
129             $op = newBINOP( $type, $flags, $first, $last );
130              
131             Returns a new BINOP for the given type, flags, and first and last OP child.
132              
133             =head3 newCONDOP
134              
135             $op = newCONDOP( $flags, $first, $trueop, $falseop );
136              
137             Returns a new conditional expression op for the given condition expression and
138             true and false alternatives, all as OP instances.
139              
140             =head3 newFOROP
141              
142             $op = newFOROP( $flags, $svop, $expr, $block, $cont );
143              
144             Returns a new optree representing a heavyweight C loop, given the
145             optional iterator SV op, the list expression, the block, and the optional
146             continue block, all as OP instances.
147              
148             =head3 newGVOP
149              
150             $op = newGVOP( $type, $flags, $gvref );
151              
152             Returns a new SVOP for the given type, flags, and GV given by a GLOB
153             reference. The referred-to GLOB will be stored in the SVOP itself.
154              
155             =head3 newLISTOP
156              
157             $op = newLISTOP( $type, $flags, @children );
158              
159             Returns a new LISTOP for the given type, flags, and child SVs.
160              
161             Note that an arbitrary number of child SVs can be passed here. This wrapper
162             function will automatically perform the C conversion from a
163             plain C if required.
164              
165             =head3 newLOGOP
166              
167             $op = newLOGOP( $type, $flags, $first, $other );
168              
169             Returns a new LOGOP for the given type, flags, and first and other OP child.
170              
171             =head3 newPADxVOP
172              
173             $op = newPADxVOP( $type, $flags, $padoffset );
174              
175             Returns a new op for the given type, flags, and pad offset. C<$type> must be
176             one of C, C, C or C.
177              
178             =head3 newSVOP
179              
180             $op = newSVOP( $type, $flags, $sv );
181              
182             Returns a new SVOP for the given type, flags, and SV. A copy of the given
183             scalar will be stored in the SVOP itself.
184              
185             =head3 newUNOP
186              
187             $op = newUNOP( $type, $flags, $first );
188              
189             Returns a new UNOP for the given type, flags, and first OP child.
190              
191             =cut
192              
193             =head2 make_entersub_op
194              
195             $op = make_entersub_op( $cv, $argops, ... );
196              
197             A handy wrapper function around calling C to create an
198             C op that will invoke a code reference (which may be known at
199             compiletime), with a given list of argument-generating optree framents. This
200             in effect creates a function call.
201              
202             I<$cv> must be one of:
203              
204             =over 2
205              
206             =item *
207              
208             An optree fragment as a C instance, which will be invoked directly to
209             yield the required CV
210              
211             =item *
212              
213             A CODE reference, which will be stored in a C
214              
215             =item *
216              
217             A plain string, which will be used to look up a GLOB in the symbol table and
218             stored as a C + C pair.
219              
220             =back
221              
222             I<$argops> should be an ARRAY reference containing optree fragments that
223             generate the arguments to the function.
224              
225             Takes the following additional optional named arguments:
226              
227             =over 4
228              
229             =item flags => INT
230              
231             Additional flags to set on the returned C. The C
232             flag will always be set.
233              
234             =back
235              
236             =cut
237              
238             use constant {
239 11         2340 OP_CONST => opcode("const"),
240             OP_ENTERSUB => opcode("entersub"),
241             OP_GV => opcode("gv"),
242             OP_RV2CV => opcode("rv2cv"),
243 11     11   94 };
  11         23  
244              
245             sub make_entersub_op
246             {
247 0     0 1   my ( $cv, $argops, %args ) = @_;
248              
249 0           my $cvop;
250 0 0 0       if( blessed $cv and $cv->isa( "B::OP" ) ) {
    0 0        
251 0           $cvop = $cv;
252             }
253             elsif( ( reftype $cv // "" ) eq "CODE" ) {
254 0           $cvop = newSVOP(OP_CONST, 0, $cv);
255             }
256             else {
257 11     11   93 my $gv = do { no strict 'refs'; \*$cv };
  11         25  
  11         1592  
  0            
  0            
258 0           $cvop = newUNOP(OP_RV2CV, 0, newGVOP(OP_GV, 0, $gv));
259             }
260              
261 0   0       my $flags = $args{flags} // 0;
262 0           return newLISTOP(OP_ENTERSUB, $flags | OPf_STACKED, @$argops, $cvop);
263             }
264              
265             =head1 TODO
266              
267             =over 4
268              
269             =item *
270              
271             More C wrapper functions.
272              
273             =item *
274              
275             More optree-mangling functions. At least, some way to set the TARG might be
276             handy.
277              
278             =back
279              
280             =cut
281              
282             =head1 AUTHOR
283              
284             Paul Evans
285              
286             =cut
287              
288             0x55AA;