File Coverage

blib/lib/Optree/Generate.pm
Criterion Covered Total %
statement 45 46 97.8
branch 8 8 100.0
condition 5 7 71.4
subroutine 11 12 91.6
pod 1 1 100.0
total 70 74 94.5


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