File Coverage

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